~ubuntu-branches/ubuntu/vivid/mate-applets/vivid-proposed

« back to all changes in this revision

Viewing changes to trashapplet/src/xstuff.c

  • Committer: Package Import Robot
  • Author(s): Mike Gabriel
  • Date: 2014-04-21 13:57:07 UTC
  • Revision ID: package-import@ubuntu.com-20140421135707-hh4arlnzglq9xxfo
Tags: upstream-1.8.0+dfsg1
ImportĀ upstreamĀ versionĀ 1.8.0+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MATE panel x stuff
 
3
 *
 
4
 * Copyright (C) 2000, 2001 Eazel, Inc.
 
5
 *               2002 Sun Microsystems Inc.
 
6
 *
 
7
 * Authors: George Lebl <jirka@5z.com>
 
8
 *          Mark McLoughlin <mark@skynet.ie>
 
9
 *
 
10
 *  Contains code from the Window Maker window manager
 
11
 *
 
12
 *  Copyright (c) 1997-2002 Alfredo K. Kojima
 
13
 
 
14
 */
 
15
#include <config.h>
 
16
#include <string.h>
 
17
#include <unistd.h>
 
18
 
 
19
#include <gdk/gdk.h>
 
20
#include <gdk/gdkx.h>
 
21
 
 
22
#include <X11/Xlib.h>
 
23
#include <X11/Xatom.h>
 
24
 
 
25
#include "xstuff.h"
 
26
 
 
27
#if GTK_CHECK_VERSION (3, 0, 0)
 
28
#define GDK_WINDOW_XWINDOW(x) GDK_WINDOW_XID(x)
 
29
#define gdk_x11_drawable_get_xid(x) GDK_WINDOW_XID(x)
 
30
#endif
 
31
 
 
32
static Atom
 
33
panel_atom_get (const char *atom_name)
 
34
{
 
35
        static GHashTable *atom_hash;
 
36
        Display           *xdisplay;
 
37
        Atom               retval;
 
38
 
 
39
        g_return_val_if_fail (atom_name != NULL, None);
 
40
 
 
41
        xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
42
 
 
43
        if (!atom_hash)
 
44
                atom_hash = g_hash_table_new_full (
 
45
                                g_str_hash, g_str_equal, g_free, NULL);
 
46
 
 
47
        retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
 
48
        if (!retval) {
 
49
                retval = XInternAtom (xdisplay, atom_name, FALSE);
 
50
 
 
51
                if (retval != None)
 
52
                        g_hash_table_insert (atom_hash, g_strdup (atom_name),
 
53
                                             GUINT_TO_POINTER (retval));
 
54
        }
 
55
 
 
56
        return retval;
 
57
}
 
58
 
 
59
/* Stolen from deskguide */
 
60
static gpointer
 
61
get_typed_property_data (Display *xdisplay,
 
62
                         Window   xwindow,
 
63
                         Atom     property,
 
64
                         Atom     requested_type,
 
65
                         gint    *size_p,
 
66
                         guint    expected_format)
 
67
{
 
68
  static const guint prop_buffer_lengh = 1024 * 1024;
 
69
  unsigned char *prop_data = NULL;
 
70
  Atom type_returned = 0;
 
71
  unsigned long nitems_return = 0, bytes_after_return = 0;
 
72
  int format_returned = 0;
 
73
  gpointer data = NULL;
 
74
  gboolean abort = FALSE;
 
75
 
 
76
  g_return_val_if_fail (size_p != NULL, NULL);
 
77
  *size_p = 0;
 
78
 
 
79
  gdk_error_trap_push ();
 
80
 
 
81
  abort = XGetWindowProperty (xdisplay,
 
82
                              xwindow,
 
83
                              property,
 
84
                              0, prop_buffer_lengh,
 
85
                              False,
 
86
                              requested_type,
 
87
                              &type_returned, &format_returned,
 
88
                              &nitems_return,
 
89
                              &bytes_after_return,
 
90
                              &prop_data) != Success;
 
91
  if (gdk_error_trap_pop () ||
 
92
      type_returned == None)
 
93
    abort++;
 
94
  if (!abort &&
 
95
      requested_type != AnyPropertyType &&
 
96
      requested_type != type_returned)
 
97
    {
 
98
      g_warning ("%s(): Property has wrong type, probably on crack", G_STRFUNC);
 
99
      abort++;
 
100
    }
 
101
  if (!abort && bytes_after_return)
 
102
    {
 
103
      g_warning ("%s(): Eeek, property has more than %u bytes, stored on harddisk?",
 
104
                 G_STRFUNC, prop_buffer_lengh);
 
105
      abort++;
 
106
    }
 
107
  if (!abort && expected_format && expected_format != format_returned)
 
108
    {
 
109
      g_warning ("%s(): Expected format (%u) unmatched (%d), programmer was drunk?",
 
110
                 G_STRFUNC, expected_format, format_returned);
 
111
      abort++;
 
112
    }
 
113
  if (!abort && prop_data && nitems_return && format_returned)
 
114
    {
 
115
      switch (format_returned)
 
116
        {
 
117
        case 32:
 
118
          *size_p = nitems_return * 4;
 
119
          if (sizeof (gulong) == 8)
 
120
            {
 
121
              guint32 i, *mem = g_malloc0 (*size_p + 1);
 
122
              gulong *prop_longs = (gulong*) prop_data;
 
123
 
 
124
              for (i = 0; i < *size_p / 4; i++)
 
125
                mem[i] = prop_longs[i];
 
126
              data = mem;
 
127
            }
 
128
          break;
 
129
        case 16:
 
130
          *size_p = nitems_return * 2;
 
131
          break;
 
132
        case 8:
 
133
          *size_p = nitems_return;
 
134
          break;
 
135
        default:
 
136
          g_warning ("Unknown property data format with %d bits (extraterrestrial?)",
 
137
                     format_returned);
 
138
          break;
 
139
        }
 
140
      if (!data && *size_p)
 
141
        {
 
142
          guint8 *mem = g_malloc (*size_p + 1);
 
143
 
 
144
          memcpy (mem, prop_data, *size_p);
 
145
          mem[*size_p] = 0;
 
146
          data = mem;
 
147
        }
 
148
    }
 
149
 
 
150
  if (prop_data)
 
151
    XFree (prop_data);
 
152
  
 
153
  return data;
 
154
}
 
155
 
 
156
gboolean
 
157
xstuff_is_compliant_wm (void)
 
158
{
 
159
        Display  *xdisplay;
 
160
        Window    root_window;
 
161
        gpointer  data;
 
162
        int       size;
 
163
 
 
164
        xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
165
        root_window = GDK_WINDOW_XWINDOW (
 
166
                                gdk_get_default_root_window ());
 
167
 
 
168
        /* FIXME this is totally broken; should be using
 
169
         * gdk_net_wm_supports() on particular hints when we rely
 
170
         * on those particular hints
 
171
         */
 
172
        data = get_typed_property_data (
 
173
                        xdisplay, root_window,
 
174
                        panel_atom_get ("_NET_SUPPORTED"),
 
175
                        XA_ATOM, &size, 32);
 
176
 
 
177
        if (!data)
 
178
                return FALSE;
 
179
 
 
180
        /* Actually checks for some of these */
 
181
        g_free (data);
 
182
        return TRUE;
 
183
}
 
184
 
 
185
#if !GTK_CHECK_VERSION (3, 0, 0)
 
186
gboolean
 
187
xstuff_net_wm_supports (const char *hint)
 
188
{
 
189
        return gdk_net_wm_supports (gdk_atom_intern (hint, FALSE));
 
190
}
 
191
#endif
 
192
 
 
193
void
 
194
xstuff_set_no_group (GdkWindow *win)
 
195
{
 
196
        XWMHints *old_wmhints;
 
197
        XWMHints wmhints = {0};
 
198
 
 
199
        XDeleteProperty (GDK_WINDOW_XDISPLAY (win),
 
200
                         GDK_WINDOW_XWINDOW (win),
 
201
                         panel_atom_get ("WM_CLIENT_LEADER"));
 
202
 
 
203
        old_wmhints = XGetWMHints (GDK_WINDOW_XDISPLAY (win),
 
204
                                   GDK_WINDOW_XWINDOW (win));
 
205
        /* General paranoia */
 
206
        if (old_wmhints != NULL) {
 
207
                memcpy (&wmhints, old_wmhints, sizeof (XWMHints));
 
208
                XFree (old_wmhints);
 
209
 
 
210
                wmhints.flags &= ~WindowGroupHint;
 
211
                wmhints.window_group = 0;
 
212
        } else {
 
213
                /* General paranoia */
 
214
                wmhints.flags = StateHint;
 
215
                wmhints.window_group = 0;
 
216
                wmhints.initial_state = NormalState;
 
217
        }
 
218
 
 
219
        XSetWMHints (GDK_WINDOW_XDISPLAY (win),
 
220
                     GDK_WINDOW_XWINDOW (win),
 
221
                     &wmhints);
 
222
}
 
223
 
 
224
/* This is such a broken stupid function. */   
 
225
void
 
226
xstuff_set_pos_size (GdkWindow *window, int x, int y, int w, int h)
 
227
{
 
228
        XSizeHints size_hints;
 
229
        int old_x, old_y, old_w, old_h;
 
230
 
 
231
        old_x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-x"));
 
232
        old_y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-y"));
 
233
        old_w = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-w"));
 
234
        old_h = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-h"));
 
235
 
 
236
        if (x == old_x && y == old_y && w == old_w && h == old_h)
 
237
                return;
 
238
 
 
239
        /* Do not add USPosition / USSize here, fix the damn WM */
 
240
        size_hints.flags = PPosition | PSize | PMaxSize | PMinSize;
 
241
        size_hints.x = 0; /* window managers aren't supposed to and  */
 
242
        size_hints.y = 0; /* don't use these fields */
 
243
        size_hints.width = w;
 
244
        size_hints.height = h;
 
245
        size_hints.min_width = w;
 
246
        size_hints.min_height = h;
 
247
        size_hints.max_width = w;
 
248
        size_hints.max_height = h;
 
249
  
 
250
        gdk_error_trap_push ();
 
251
 
 
252
        XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
 
253
                           GDK_WINDOW_XWINDOW (window),
 
254
                           &size_hints);
 
255
 
 
256
        gdk_window_move_resize (window, x, y, w, h);
 
257
 
 
258
        gdk_flush ();
 
259
        gdk_error_trap_pop ();
 
260
 
 
261
        g_object_set_data (G_OBJECT (window), "xstuff-cached-x", GINT_TO_POINTER (x));
 
262
        g_object_set_data (G_OBJECT (window), "xstuff-cached-y", GINT_TO_POINTER (y));
 
263
        g_object_set_data (G_OBJECT (window), "xstuff-cached-w", GINT_TO_POINTER (w));
 
264
        g_object_set_data (G_OBJECT (window), "xstuff-cached-h", GINT_TO_POINTER (h));
 
265
}
 
266
 
 
267
void
 
268
xstuff_set_wmspec_dock_hints (GdkWindow *window,
 
269
                              gboolean autohide)
 
270
{
 
271
        Atom atoms [2] = { None, None };
 
272
        
 
273
        if (!autohide)
 
274
                atoms [0] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
 
275
        else {
 
276
                atoms [0] = panel_atom_get ("_MATE_WINDOW_TYPE_AUTOHIDE_PANEL");
 
277
                atoms [1] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
 
278
        }
 
279
 
 
280
        XChangeProperty (GDK_WINDOW_XDISPLAY (window),
 
281
                         GDK_WINDOW_XWINDOW (window),
 
282
                         panel_atom_get ("_NET_WM_WINDOW_TYPE"),
 
283
                         XA_ATOM, 32, PropModeReplace,
 
284
                         (unsigned char *) atoms, 
 
285
                         autohide ? 2 : 1);
 
286
}
 
287
 
 
288
void
 
289
xstuff_set_wmspec_strut (GdkWindow *window,
 
290
                         int        left,
 
291
                         int        right,
 
292
                         int        top,
 
293
                         int        bottom)
 
294
{
 
295
        long vals [4];
 
296
        
 
297
        vals [0] = left;
 
298
        vals [1] = right;
 
299
        vals [2] = top;
 
300
        vals [3] = bottom;
 
301
 
 
302
        XChangeProperty (GDK_WINDOW_XDISPLAY (window),
 
303
                         GDK_WINDOW_XWINDOW (window),
 
304
                         panel_atom_get ("_NET_WM_STRUT"),
 
305
                         XA_CARDINAL, 32, PropModeReplace,
 
306
                         (unsigned char *) vals, 4);
 
307
}
 
308
 
 
309
void
 
310
xstuff_delete_property (GdkWindow *window, const char *name)
 
311
{
 
312
        Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
 
313
        Window   xwindow  = GDK_WINDOW_XWINDOW (window);
 
314
 
 
315
        XDeleteProperty (xdisplay, xwindow,
 
316
                         panel_atom_get (name));
 
317
}
 
318
 
 
319
/* Zoom animation */
 
320
#define MINIATURIZE_ANIMATION_FRAMES_Z   1
 
321
#define MINIATURIZE_ANIMATION_STEPS_Z    6
 
322
/* the delay per draw */
 
323
#define MINIATURIZE_ANIMATION_DELAY_Z    10
 
324
 
 
325
static void 
 
326
draw_zoom_animation (GdkScreen *gscreen,
 
327
                     int x, int y, int w, int h,
 
328
                     int fx, int fy, int fw, int fh, 
 
329
                     int steps)
 
330
{
 
331
#define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
 
332
        float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
 
333
        int cxi[FRAMES], cyi[FRAMES], cwi[FRAMES], chi[FRAMES];
 
334
        float xstep, ystep, wstep, hstep;
 
335
        int i, j;
 
336
        GC frame_gc;
 
337
        XGCValues gcv;
 
338
        GdkColor color = { 65535, 65535, 65535 };
 
339
        Display *dpy;
 
340
        Window root_win;
 
341
        int screen;
 
342
        int depth;
 
343
 
 
344
        dpy = gdk_x11_display_get_xdisplay (gdk_screen_get_display (gscreen));
 
345
        root_win = gdk_x11_drawable_get_xid (gdk_screen_get_root_window (gscreen));
 
346
        screen = gdk_screen_get_number (gscreen);
 
347
#if GTK_CHECK_VERSION (3, 0, 0)
 
348
        depth = DefaultDepth(dpy,screen);
 
349
#else
 
350
        depth = gdk_drawable_get_depth (gdk_screen_get_root_window (gscreen));
 
351
#endif
 
352
 
 
353
        /* frame GC */
 
354
#if !GTK_CHECK_VERSION (3, 0, 0)
 
355
        gdk_colormap_alloc_color (
 
356
                gdk_screen_get_system_colormap (gscreen), &color, FALSE, TRUE);
 
357
#endif
 
358
        gcv.function = GXxor;
 
359
        /* this will raise the probability of the XORed color being different
 
360
         * of the original color in PseudoColor when not all color cells are
 
361
         * initialized */
 
362
        if (DefaultVisual(dpy, screen)->class==PseudoColor)
 
363
                gcv.plane_mask = (1<<(depth-1))|1;
 
364
        else
 
365
                gcv.plane_mask = AllPlanes;
 
366
        gcv.foreground = color.pixel;
 
367
        if (gcv.foreground == 0)
 
368
                gcv.foreground = 1;
 
369
        gcv.line_width = 1;
 
370
        gcv.subwindow_mode = IncludeInferiors;
 
371
        gcv.graphics_exposures = False;
 
372
 
 
373
        frame_gc = XCreateGC(dpy, root_win, GCForeground|GCGraphicsExposures
 
374
                             |GCFunction|GCSubwindowMode|GCLineWidth
 
375
                             |GCPlaneMask, &gcv);
 
376
 
 
377
        xstep = (float)(fx-x)/steps;
 
378
        ystep = (float)(fy-y)/steps;
 
379
        wstep = (float)(fw-w)/steps;
 
380
        hstep = (float)(fh-h)/steps;
 
381
    
 
382
        for (j=0; j<FRAMES; j++) {
 
383
                cx[j] = (float)x;
 
384
                cy[j] = (float)y;
 
385
                cw[j] = (float)w;
 
386
                ch[j] = (float)h;
 
387
                cxi[j] = (int)cx[j];
 
388
                cyi[j] = (int)cy[j];
 
389
                cwi[j] = (int)cw[j];
 
390
                chi[j] = (int)ch[j];
 
391
        }
 
392
        XGrabServer(dpy);
 
393
        for (i=0; i<steps; i++) {
 
394
                for (j=0; j<FRAMES; j++) {
 
395
                        XDrawRectangle(dpy, root_win, frame_gc, cxi[j], cyi[j], cwi[j], chi[j]);
 
396
                }
 
397
                XFlush(dpy);
 
398
#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
 
399
                usleep(MINIATURIZE_ANIMATION_DELAY_Z);
 
400
#else
 
401
                usleep(10);
 
402
#endif
 
403
                for (j=0; j<FRAMES; j++) {
 
404
                        XDrawRectangle(dpy, root_win, frame_gc, 
 
405
                                       cxi[j], cyi[j], cwi[j], chi[j]);
 
406
                        if (j<FRAMES-1) {
 
407
                                cx[j]=cx[j+1];
 
408
                                cy[j]=cy[j+1];
 
409
                                cw[j]=cw[j+1];
 
410
                                ch[j]=ch[j+1];
 
411
                                
 
412
                                cxi[j]=cxi[j+1];
 
413
                                cyi[j]=cyi[j+1];
 
414
                                cwi[j]=cwi[j+1];
 
415
                                chi[j]=chi[j+1];
 
416
                                
 
417
                        } else {
 
418
                                cx[j]+=xstep;
 
419
                                cy[j]+=ystep;
 
420
                                cw[j]+=wstep;
 
421
                                ch[j]+=hstep;
 
422
 
 
423
                                cxi[j] = (int)cx[j];
 
424
                                cyi[j] = (int)cy[j];
 
425
                                cwi[j] = (int)cw[j];
 
426
                                chi[j] = (int)ch[j];
 
427
                        }
 
428
                }
 
429
        }
 
430
 
 
431
        for (j=0; j<FRAMES; j++) {
 
432
                XDrawRectangle(dpy, root_win, frame_gc, 
 
433
                                       cxi[j], cyi[j], cwi[j], chi[j]);
 
434
        }
 
435
        XFlush(dpy);
 
436
#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
 
437
        usleep(MINIATURIZE_ANIMATION_DELAY_Z);
 
438
#else
 
439
        usleep(10);
 
440
#endif
 
441
        for (j=0; j<FRAMES; j++) {
 
442
                XDrawRectangle(dpy, root_win, frame_gc, 
 
443
                                       cxi[j], cyi[j], cwi[j], chi[j]);
 
444
        }
 
445
    
 
446
        XUngrabServer(dpy);
 
447
        XFreeGC (dpy, frame_gc);
 
448
#if !GTK_CHECK_VERSION (3, 0, 0)
 
449
        gdk_colormap_free_colors (gdk_screen_get_system_colormap (gscreen),
 
450
                                  &color, 1);
 
451
#endif
 
452
}
 
453
#undef FRAMES
 
454
 
 
455
void
 
456
xstuff_zoom_animate (GtkWidget *widget, GdkRectangle *opt_rect)
 
457
{
 
458
        GdkScreen *gscreen;
 
459
        GdkRectangle rect, dest;
 
460
        GtkAllocation allocation;
 
461
        int monitor;
 
462
 
 
463
        if (opt_rect)
 
464
                rect = *opt_rect;
 
465
        else {
 
466
                gdk_window_get_origin (gtk_widget_get_window (widget), &rect.x, &rect.y);
 
467
                gtk_widget_get_allocation (widget, &allocation);
 
468
                if (!gtk_widget_get_has_window (widget)) {
 
469
                        rect.x += allocation.x;
 
470
                        rect.y += allocation.y;
 
471
                }
 
472
                rect.height = allocation.height;
 
473
                rect.width = allocation.width;
 
474
        }
 
475
 
 
476
        gscreen = gtk_widget_get_screen (widget);
 
477
        monitor = gdk_screen_get_monitor_at_window (gscreen, gtk_widget_get_window (widget));
 
478
        gdk_screen_get_monitor_geometry (gscreen, monitor, &dest);
 
479
 
 
480
        draw_zoom_animation (gscreen,
 
481
                             rect.x, rect.y, rect.width, rect.height,
 
482
                             dest.x, dest.y, dest.width, dest.height,
 
483
                             MINIATURIZE_ANIMATION_STEPS_Z);
 
484
}
 
485
 
 
486
int
 
487
xstuff_get_current_workspace (GdkScreen *screen)
 
488
{
 
489
        Window  root_window;
 
490
        Atom    type = None;
 
491
        gulong  nitems;
 
492
        gulong  bytes_after;
 
493
        gulong *num;
 
494
        int     format;
 
495
        int     result;
 
496
        int     retval;
 
497
 
 
498
        root_window = gdk_x11_drawable_get_xid (
 
499
                                gdk_screen_get_root_window (screen));
 
500
 
 
501
        gdk_error_trap_push ();
 
502
#if GTK_CHECK_VERSION (3, 0, 0)
 
503
        result = XGetWindowProperty (GDK_SCREEN_XDISPLAY (screen),
 
504
#else
 
505
        result = XGetWindowProperty (gdk_display,
 
506
#endif
 
507
                                     root_window,
 
508
                                     panel_atom_get ("_NET_CURRENT_DESKTOP"),
 
509
                                     0, G_MAXLONG,
 
510
                                     False, XA_CARDINAL, &type, &format, &nitems,
 
511
                                     &bytes_after, (gpointer) &num);
 
512
        if (gdk_error_trap_pop () || result != Success)
 
513
                return -1;
 
514
 
 
515
        if (type != XA_CARDINAL) {
 
516
                XFree (num);
 
517
                return -1;
 
518
        }
 
519
 
 
520
        retval = *num;
 
521
 
 
522
        XFree (num);
 
523
 
 
524
        return retval;
 
525
}
 
526
 
 
527
void
 
528
xstuff_grab_key_on_all_screens (int      keycode,
 
529
                                guint    modifiers,
 
530
                                gboolean grab)
 
531
{
 
532
        GdkDisplay *display;
 
533
        int         n_screens;
 
534
        int         i;
 
535
 
 
536
        display   = gdk_display_get_default ();
 
537
        n_screens = gdk_display_get_n_screens (display);
 
538
 
 
539
        for (i = 0; i < n_screens; i++) {
 
540
                GdkWindow *root;
 
541
 
 
542
                root = gdk_screen_get_root_window (
 
543
                                gdk_display_get_screen (display, i));
 
544
 
 
545
                if (grab)
 
546
                        XGrabKey (gdk_x11_display_get_xdisplay (display),
 
547
                                  keycode, modifiers,
 
548
                                  gdk_x11_drawable_get_xid (root),
 
549
                                  True, GrabModeAsync, GrabModeAsync);
 
550
                else
 
551
                        XUngrabKey (gdk_x11_display_get_xdisplay (display),
 
552
                                    keycode, modifiers,
 
553
                                    gdk_x11_drawable_get_xid (root));
 
554
        }
 
555
}