~ubuntu-branches/debian/experimental/xfce4-panel/experimental

« back to all changes in this revision

Viewing changes to plugins/systray/systray-socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Yves-Alexis Perez, Lionel Le Folgoc, Yves-Alexis Perez
  • Date: 2011-02-06 18:10:07 UTC
  • mfrom: (1.3.13 upstream) (5.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110206181007-vpw5z3xnm3hdvybx
Tags: 4.8.1-1
[ Lionel Le Folgoc ]
* New upstream bugfix release.
* debian/control:
  - refreshed (b-)deps for this new major release
  - add myself to Uploaders
  - bump Standards-Version to 3.9.1.
* debian/NEWS: dropped, unneeded.
* debian/xfce4-panel.shlibs: refreshed, bump to (>= 4.7.2).
* debian/xfce4-panel.lintian-overrides: refreshed, new lib name.
* debian/xfce4-panel.preinst: added, handles removal of old conffiles.
* debian/xfce4-panel.postinst: explicitly set -e.
* debian/*.install: refreshed.
* debian/rules:
  - call dpkg-buildflags
  - dropped rc files mangling as they don't exist anymore
  - updated removal of *.{l,}a files.
  - drop overrides for dh_auto_{configure,clean}, obsolete.
* debian/xfce4-panel.{preinst,postinst,prerm}: use dpkg-maintscript-helper
  to remove pre-xfconf config files.
* Bugs fixed by 4.7.x/4.8.x series:
  - rgba support                                                  lp: #586012
  - disappearing menus                                             lp: #53897
  - xrandr support                               lp: #176174, Closes: #432914
  - Fails to reap children, creating zombies                      lp: #420187
  - DND of desktop-files on the panel to create new launchers Closes: #480380
* Bumped shlibs to >= 4.7.7, abi break for external plugins.

[ Yves-Alexis Perez ]
* New upstream development release
* debian/xfce4-panel.install:
  - install wrapper and migrate tools in xfce4-panel package
  - update plugins paths
* debian/rules:
  - update path when removing .a/.la files for plugins.
  - add hardening flags to {C,LD}FLAGS
* debian/control:
  - add build-dep on hardening-includes
  - update build-dep on garcon to 0.1.4.
* debian/copyright updated for new release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2002      Anders Carlsson <andersca@gnu.org>
 
3
 * Copyright (c) 2003-2006 Vincent Untz
 
4
 * Copyright (c) 2008      Red Hat, Inc.
 
5
 * Copyright (c) 2009-2010 Nick Schermer <nick@xfce.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or modify it
 
8
 * under the terms of the GNU General Public License as published by the Free
 
9
 * Software Foundation; either version 2 of the License, or (at your option)
 
10
 * any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful, but WITHOUT
 
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
15
 * more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public License
 
18
 * along with this library; if not, write to the Free Software Foundation,
 
19
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#ifdef HAVE_STRING_H
 
27
#include <string.h>
 
28
#endif
 
29
 
 
30
#include <X11/Xlib.h>
 
31
#include <X11/Xatom.h>
 
32
 
 
33
#include <gdk/gdk.h>
 
34
#include <gdk/gdkx.h>
 
35
#include <gtk/gtk.h>
 
36
 
 
37
#include <libxfce4panel/libxfce4panel.h>
 
38
 
 
39
#include <common/panel-private.h>
 
40
#include <common/panel-debug.h>
 
41
 
 
42
#include "systray-socket.h"
 
43
 
 
44
 
 
45
 
 
46
struct _SystraySocketClass
 
47
{
 
48
  GtkSocketClass __parent__;
 
49
};
 
50
 
 
51
struct _SystraySocket
 
52
{
 
53
  GtkSocket __parent__;
 
54
 
 
55
  /* plug window */
 
56
  GdkNativeWindow window;
 
57
 
 
58
  gchar           *name;
 
59
 
 
60
  guint            is_composited : 1;
 
61
  guint            parent_relative_bg : 1;
 
62
  guint            hidden : 1;
 
63
};
 
64
 
 
65
 
 
66
 
 
67
static void     systray_socket_finalize      (GObject        *object);
 
68
static void     systray_socket_realize       (GtkWidget      *widget);
 
69
static void     systray_socket_size_allocate (GtkWidget      *widget,
 
70
                                              GtkAllocation  *allocation);
 
71
static gboolean systray_socket_expose_event  (GtkWidget      *widget,
 
72
                                              GdkEventExpose *event);
 
73
static void     systray_socket_style_set     (GtkWidget      *widget,
 
74
                                              GtkStyle       *previous_style);
 
75
 
 
76
 
 
77
 
 
78
XFCE_PANEL_DEFINE_TYPE (SystraySocket, systray_socket, GTK_TYPE_SOCKET)
 
79
 
 
80
 
 
81
 
 
82
static void
 
83
systray_socket_class_init (SystraySocketClass *klass)
 
84
{
 
85
  GtkWidgetClass *gtkwidget_class;
 
86
  GObjectClass   *gobject_class;
 
87
 
 
88
  gobject_class = G_OBJECT_CLASS (klass);
 
89
  gobject_class->finalize = systray_socket_finalize;
 
90
 
 
91
  gtkwidget_class = GTK_WIDGET_CLASS (klass);
 
92
  gtkwidget_class->realize = systray_socket_realize;
 
93
  gtkwidget_class->size_allocate = systray_socket_size_allocate;
 
94
  gtkwidget_class->expose_event = systray_socket_expose_event;
 
95
  gtkwidget_class->style_set = systray_socket_style_set;
 
96
}
 
97
 
 
98
 
 
99
 
 
100
static void
 
101
systray_socket_init (SystraySocket *socket)
 
102
{
 
103
  socket->hidden = FALSE;
 
104
  socket->name = NULL;
 
105
}
 
106
 
 
107
 
 
108
 
 
109
static void
 
110
systray_socket_finalize (GObject *object)
 
111
{
 
112
  SystraySocket *socket = XFCE_SYSTRAY_SOCKET (object);
 
113
 
 
114
  g_free (socket->name);
 
115
 
 
116
  G_OBJECT_CLASS (systray_socket_parent_class)->finalize (object);
 
117
}
 
118
 
 
119
 
 
120
 
 
121
static void
 
122
systray_socket_realize (GtkWidget *widget)
 
123
{
 
124
  SystraySocket *socket = XFCE_SYSTRAY_SOCKET (widget);
 
125
  GdkColor       transparent = { 0, 0, 0, 0 };
 
126
  GdkWindow     *window;
 
127
 
 
128
  GTK_WIDGET_CLASS (systray_socket_parent_class)->realize (widget);
 
129
 
 
130
  window = gtk_widget_get_window (widget);
 
131
 
 
132
  if (socket->is_composited)
 
133
    {
 
134
      gdk_window_set_background (window, &transparent);
 
135
      gdk_window_set_composited (window, TRUE);
 
136
 
 
137
      socket->parent_relative_bg = FALSE;
 
138
    }
 
139
  else if (gtk_widget_get_visual (widget) ==
 
140
           gdk_drawable_get_visual (GDK_DRAWABLE (gdk_window_get_parent (window))))
 
141
    {
 
142
      gdk_window_set_back_pixmap (window, NULL, TRUE);
 
143
 
 
144
      socket->parent_relative_bg = TRUE;
 
145
    }
 
146
  else
 
147
    {
 
148
      socket->parent_relative_bg = FALSE;
 
149
    }
 
150
 
 
151
  gdk_window_set_composited (window, socket->is_composited);
 
152
 
 
153
  gtk_widget_set_app_paintable (widget,
 
154
      socket->parent_relative_bg || socket->is_composited);
 
155
 
 
156
  gtk_widget_set_double_buffered (widget, socket->parent_relative_bg);
 
157
 
 
158
  panel_debug_filtered (PANEL_DEBUG_SYSTRAY,
 
159
      "socket %s[%p] (composited=%s, relative-bg=%s",
 
160
      systray_socket_get_name (socket), socket,
 
161
      PANEL_DEBUG_BOOL (socket->is_composited),
 
162
      PANEL_DEBUG_BOOL (socket->parent_relative_bg));
 
163
}
 
164
 
 
165
 
 
166
 
 
167
static void
 
168
systray_socket_size_allocate (GtkWidget     *widget,
 
169
                              GtkAllocation *allocation)
 
170
{
 
171
  SystraySocket *socket = XFCE_SYSTRAY_SOCKET (widget);
 
172
  gboolean       moved = allocation->x != widget->allocation.x
 
173
                         || allocation->y != widget->allocation.y;
 
174
  gboolean       resized = allocation->width != widget->allocation.width
 
175
                           ||allocation->height != widget->allocation.height;
 
176
 
 
177
  if ((moved || resized)
 
178
      && GTK_WIDGET_MAPPED (widget))
 
179
    {
 
180
      if (socket->is_composited)
 
181
        gdk_window_invalidate_rect (gdk_window_get_parent (widget->window),
 
182
                                    &widget->allocation, FALSE);
 
183
    }
 
184
 
 
185
  GTK_WIDGET_CLASS (systray_socket_parent_class)->size_allocate (widget, allocation);
 
186
 
 
187
  if ((moved || resized)
 
188
      && GTK_WIDGET_MAPPED (widget))
 
189
    {
 
190
      if (socket->is_composited)
 
191
        gdk_window_invalidate_rect (gdk_window_get_parent (widget->window),
 
192
                                    &widget->allocation, FALSE);
 
193
      else if (moved && socket->parent_relative_bg)
 
194
        systray_socket_force_redraw (socket);
 
195
    }
 
196
}
 
197
 
 
198
 
 
199
 
 
200
static gboolean
 
201
systray_socket_expose_event (GtkWidget      *widget,
 
202
                             GdkEventExpose *event)
 
203
{
 
204
  SystraySocket *socket = XFCE_SYSTRAY_SOCKET (widget);
 
205
  cairo_t       *cr;
 
206
 
 
207
  if (socket->is_composited)
 
208
    {
 
209
      /* clear to transparent */
 
210
      cr = gdk_cairo_create (widget->window);
 
211
      cairo_set_source_rgba (cr, 0, 0, 0, 0);
 
212
      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
213
      gdk_cairo_region (cr, event->region);
 
214
      cairo_fill (cr);
 
215
      cairo_destroy (cr);
 
216
    }
 
217
  else if (socket->parent_relative_bg)
 
218
    {
 
219
      /* clear to parent-relative pixmap */
 
220
      gdk_window_clear_area (widget->window,
 
221
                             event->area.x,
 
222
                             event->area.y,
 
223
                             event->area.width,
 
224
                             event->area.height);
 
225
    }
 
226
 
 
227
  return FALSE;
 
228
}
 
229
 
 
230
 
 
231
 
 
232
static void
 
233
systray_socket_style_set (GtkWidget *widget,
 
234
                          GtkStyle  *previous_style)
 
235
{
 
236
}
 
237
 
 
238
 
 
239
 
 
240
GtkWidget *
 
241
systray_socket_new (GdkScreen       *screen,
 
242
                    GdkNativeWindow  window)
 
243
{
 
244
  SystraySocket     *socket;
 
245
  GdkDisplay        *display;
 
246
  XWindowAttributes  attr;
 
247
  gint               result;
 
248
  GdkVisual         *visual;
 
249
  GdkColormap       *colormap;
 
250
  gboolean           release_colormap = FALSE;
 
251
 
 
252
  panel_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 
253
 
 
254
  /* get the window attributes */
 
255
  display = gdk_screen_get_display (screen);
 
256
  gdk_error_trap_push ();
 
257
  result = XGetWindowAttributes (GDK_DISPLAY_XDISPLAY (display),
 
258
                                 window, &attr);
 
259
 
 
260
  /* leave on an error or if the window does not exist */
 
261
  if (gdk_error_trap_pop () != 0 || result == 0)
 
262
    return NULL;
 
263
 
 
264
  /* get the windows visual */
 
265
  visual = gdk_x11_screen_lookup_visual (screen, attr.visual->visualid);
 
266
  panel_return_val_if_fail (visual == NULL || GDK_IS_VISUAL (visual), NULL);
 
267
  if (G_UNLIKELY (visual == NULL))
 
268
    return NULL;
 
269
 
 
270
  /* get the correct colormap */
 
271
  if (visual == gdk_screen_get_rgb_visual (screen))
 
272
    colormap = gdk_screen_get_rgb_colormap (screen);
 
273
  else if (visual == gdk_screen_get_rgba_visual (screen))
 
274
    colormap = gdk_screen_get_rgba_colormap (screen);
 
275
  else if (visual == gdk_screen_get_system_visual (screen))
 
276
    colormap = gdk_screen_get_system_colormap (screen);
 
277
  else
 
278
    {
 
279
      /* create custom colormap */
 
280
      colormap = gdk_colormap_new (visual, FALSE);
 
281
      release_colormap = TRUE;
 
282
    }
 
283
 
 
284
  /* create a new socket */
 
285
  socket = g_object_new (XFCE_TYPE_SYSTRAY_SOCKET, NULL);
 
286
  socket->window = window;
 
287
  socket->is_composited = FALSE;
 
288
  gtk_widget_set_colormap (GTK_WIDGET (socket), colormap);
 
289
 
 
290
  /* release the custom colormap */
 
291
  if (release_colormap)
 
292
    g_object_unref (G_OBJECT (colormap));
 
293
 
 
294
  /* check if there is an alpha channel in the visual */
 
295
  if (visual->red_prec + visual->blue_prec + visual->green_prec < visual->depth
 
296
      && gdk_display_supports_composite (gdk_screen_get_display (screen)))
 
297
    socket->is_composited = TRUE;
 
298
 
 
299
  return GTK_WIDGET (socket);
 
300
}
 
301
 
 
302
 
 
303
 
 
304
void
 
305
systray_socket_force_redraw (SystraySocket *socket)
 
306
{
 
307
  GtkWidget  *widget = GTK_WIDGET (socket);
 
308
  XEvent      xev;
 
309
  GdkDisplay *display;
 
310
 
 
311
  panel_return_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket));
 
312
 
 
313
  if (GTK_WIDGET_MAPPED (socket) && socket->parent_relative_bg)
 
314
    {
 
315
      display = gtk_widget_get_display (widget);
 
316
 
 
317
      xev.xexpose.type = Expose;
 
318
      xev.xexpose.window = GDK_WINDOW_XWINDOW (GTK_SOCKET (socket)->plug_window);
 
319
      xev.xexpose.x = 0;
 
320
      xev.xexpose.y = 0;
 
321
      xev.xexpose.width = widget->allocation.width;
 
322
      xev.xexpose.height = widget->allocation.height;
 
323
      xev.xexpose.count = 0;
 
324
 
 
325
      gdk_error_trap_push ();
 
326
      XSendEvent (GDK_DISPLAY_XDISPLAY (display),
 
327
                  xev.xexpose.window,
 
328
                  False, ExposureMask,
 
329
                  &xev);
 
330
      /* We have to sync to reliably catch errors from the XSendEvent(),
 
331
       * since that is asynchronous.
 
332
       */
 
333
      XSync (GDK_DISPLAY_XDISPLAY (display), False);
 
334
      gdk_error_trap_pop ();
 
335
    }
 
336
}
 
337
 
 
338
 
 
339
 
 
340
gboolean
 
341
systray_socket_is_composited (SystraySocket *socket)
 
342
{
 
343
  panel_return_val_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket), FALSE);
 
344
 
 
345
  return socket->is_composited;
 
346
}
 
347
 
 
348
 
 
349
 
 
350
static gchar *
 
351
systray_socket_get_name_prop (SystraySocket *socket,
 
352
                              const gchar   *prop_name,
 
353
                              const gchar   *type_name)
 
354
{
 
355
  GdkDisplay *display;
 
356
  Atom        req_type, type;
 
357
  gint        result;
 
358
  gchar      *val;
 
359
  gint        format;
 
360
  gulong      nitems;
 
361
  gulong      bytes_after;
 
362
  gchar      *name = NULL;
 
363
 
 
364
  panel_return_val_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket), NULL);
 
365
  panel_return_val_if_fail (type_name != NULL && prop_name != NULL, NULL);
 
366
 
 
367
  display = gtk_widget_get_display (GTK_WIDGET (socket));
 
368
 
 
369
  req_type = gdk_x11_get_xatom_by_name_for_display (display, type_name);
 
370
 
 
371
  gdk_error_trap_push ();
 
372
 
 
373
  result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
 
374
                               socket->window,
 
375
                               gdk_x11_get_xatom_by_name_for_display (display, prop_name),
 
376
                               0, G_MAXLONG, False,
 
377
                               req_type,
 
378
                               &type, &format, &nitems,
 
379
                               &bytes_after,
 
380
                               (guchar **) &val);
 
381
 
 
382
  /* check if everything went fine */
 
383
  if (gdk_error_trap_pop () != 0
 
384
      || result != Success
 
385
      || val == NULL)
 
386
    return NULL;
 
387
 
 
388
  /* check the returned data */
 
389
  if (type == req_type
 
390
      && format == 8
 
391
      && nitems > 0
 
392
      && g_utf8_validate (val, nitems, NULL))
 
393
   {
 
394
     /* lowercase the result */
 
395
     name = g_utf8_strdown (val, nitems);
 
396
   }
 
397
 
 
398
  XFree (val);
 
399
 
 
400
  return name;
 
401
}
 
402
 
 
403
 
 
404
 
 
405
const gchar *
 
406
systray_socket_get_name (SystraySocket *socket)
 
407
{
 
408
  panel_return_val_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket), NULL);
 
409
 
 
410
  if (G_LIKELY (socket->name != NULL))
 
411
    return socket->name;
 
412
 
 
413
  /* try _NET_WM_NAME first, for gtk icon implementations, fall back to
 
414
   * WM_NAME for qt icons */
 
415
  socket->name = systray_socket_get_name_prop (socket, "_NET_WM_NAME", "UTF8_STRING");
 
416
  if (G_UNLIKELY (socket->name == NULL))
 
417
    socket->name = systray_socket_get_name_prop (socket, "WM_NAME", "STRING");
 
418
 
 
419
  return socket->name;
 
420
}
 
421
 
 
422
 
 
423
 
 
424
GdkNativeWindow *
 
425
systray_socket_get_window (SystraySocket *socket)
 
426
{
 
427
  panel_return_val_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket), NULL);
 
428
 
 
429
  return &socket->window;
 
430
}
 
431
 
 
432
 
 
433
 
 
434
gboolean
 
435
systray_socket_get_hidden (SystraySocket *socket)
 
436
{
 
437
  panel_return_val_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket), FALSE);
 
438
 
 
439
  return socket->hidden;
 
440
}
 
441
 
 
442
 
 
443
 
 
444
void
 
445
systray_socket_set_hidden (SystraySocket *socket,
 
446
                           gboolean       hidden)
 
447
{
 
448
  panel_return_if_fail (XFCE_IS_SYSTRAY_SOCKET (socket));
 
449
 
 
450
  socket->hidden = hidden;
 
451
}