~ubuntu-branches/ubuntu/maverick/uim/maverick

« back to all changes in this revision

Viewing changes to helper/eggtrayicon.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2006-11-23 15:10:53 UTC
  • mfrom: (3.1.8 edgy)
  • Revision ID: james.westby@ubuntu.com-20061123151053-q42sk1lvks41xpfx
Tags: 1:1.2.1-9
uim-gtk2.0.postinst: Don't call update-gtk-immodules on purge.
(closes: Bug#398530)

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * Boston, MA 02111-1307, USA.
19
19
 */
20
20
 
 
21
#include <config.h>
 
22
 
 
23
#include "uim/gettext.h"
21
24
#include <string.h>
 
25
 
 
26
#include "eggtrayicon.h"
 
27
 
 
28
#include <gdkconfig.h>
 
29
#if defined (GDK_WINDOWING_X11)
22
30
#include <gdk/gdkx.h>
23
 
#include "eggtrayicon.h"
 
31
#include <X11/Xatom.h>
 
32
#elif defined (GDK_WINDOWING_WIN32)
 
33
#include <gdk/gdkwin32.h>
 
34
#endif
24
35
 
25
36
#define SYSTEM_TRAY_REQUEST_DOCK    0
26
37
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
27
38
#define SYSTEM_TRAY_CANCEL_MESSAGE  2
28
 
         
 
39
 
 
40
#define SYSTEM_TRAY_ORIENTATION_HORZ 0
 
41
#define SYSTEM_TRAY_ORIENTATION_VERT 1
 
42
 
 
43
enum {
 
44
  PROP_0,
 
45
  PROP_ORIENTATION
 
46
};
 
47
 
29
48
static GtkPlugClass *parent_class = NULL;
30
49
 
31
50
static void egg_tray_icon_init (EggTrayIcon *icon);
32
51
static void egg_tray_icon_class_init (EggTrayIconClass *klass);
33
52
 
 
53
static void egg_tray_icon_get_property (GObject    *object,
 
54
                                        guint       prop_id,
 
55
                                        GValue     *value,
 
56
                                        GParamSpec *pspec);
 
57
 
 
58
static void egg_tray_icon_realize   (GtkWidget *widget);
34
59
static void egg_tray_icon_unrealize (GtkWidget *widget);
35
60
 
36
 
static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
 
61
#ifdef GDK_WINDOWING_X11
 
62
static void egg_tray_icon_update_manager_window    (EggTrayIcon *icon,
 
63
                                                    gboolean     dock_if_realized);
 
64
static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon);
 
65
#endif
37
66
 
38
67
GType
39
68
egg_tray_icon_get_type (void)
40
69
{
41
70
  static GType our_type = 0;
42
71
 
43
 
  our_type = g_type_from_name("EggTrayIcon");
44
 
 
45
72
  if (our_type == 0)
46
73
    {
47
74
      static const GTypeInfo our_info =
59
86
 
60
87
      our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
61
88
    }
62
 
  else if (parent_class == NULL) {
63
 
    /* we're reheating the old class from a previous instance -  engage ugly hack =( */
64
 
    egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type));
65
 
  }
66
89
 
67
90
  return our_type;
68
91
}
71
94
egg_tray_icon_init (EggTrayIcon *icon)
72
95
{
73
96
  icon->stamp = 1;
74
 
  
 
97
  icon->orientation = GTK_ORIENTATION_HORIZONTAL;
 
98
 
75
99
  gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
76
100
}
77
101
 
78
102
static void
79
103
egg_tray_icon_class_init (EggTrayIconClass *klass)
80
104
{
 
105
  GObjectClass *gobject_class = (GObjectClass *)klass;
81
106
  GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
82
107
 
83
108
  parent_class = g_type_class_peek_parent (klass);
84
109
 
 
110
  gobject_class->get_property = egg_tray_icon_get_property;
 
111
 
 
112
  widget_class->realize   = egg_tray_icon_realize;
85
113
  widget_class->unrealize = egg_tray_icon_unrealize;
 
114
 
 
115
  g_object_class_install_property (gobject_class,
 
116
                                   PROP_ORIENTATION,
 
117
                                   g_param_spec_enum ("orientation",
 
118
                                                      _("Orientation"),
 
119
                                                      _("The orientation of the tray."),
 
120
                                                      GTK_TYPE_ORIENTATION,
 
121
                                                      GTK_ORIENTATION_HORIZONTAL,
 
122
                                                      G_PARAM_READABLE));
 
123
 
 
124
#if defined (GDK_WINDOWING_X11)
 
125
  /* Nothing */
 
126
#elif defined (GDK_WINDOWING_WIN32)
 
127
  g_warning ("Port eggtrayicon to Win32");
 
128
#else
 
129
  g_warning ("Port eggtrayicon to this GTK+ backend");
 
130
#endif
 
131
}
 
132
 
 
133
static void
 
134
egg_tray_icon_get_property (GObject    *object,
 
135
                            guint       prop_id,
 
136
                            GValue     *value,
 
137
                            GParamSpec *pspec)
 
138
{
 
139
  EggTrayIcon *icon = EGG_TRAY_ICON (object);
 
140
 
 
141
  switch (prop_id)
 
142
    {
 
143
    case PROP_ORIENTATION:
 
144
      g_value_set_enum (value, icon->orientation);
 
145
      break;
 
146
    default:
 
147
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
148
      break;
 
149
    }
 
150
}
 
151
 
 
152
#ifdef GDK_WINDOWING_X11
 
153
 
 
154
static void
 
155
egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
 
156
{
 
157
  Display *xdisplay;
 
158
  Atom type;
 
159
  int format;
 
160
  union {
 
161
        gulong *prop;
 
162
        guchar *prop_ch;
 
163
  } prop = { NULL };
 
164
  gulong nitems;
 
165
  gulong bytes_after;
 
166
  int error, result;
 
167
 
 
168
  g_assert (icon->manager_window != None);
 
169
 
 
170
  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
 
171
 
 
172
  gdk_error_trap_push ();
 
173
  type = None;
 
174
  result = XGetWindowProperty (xdisplay,
 
175
                               icon->manager_window,
 
176
                               icon->orientation_atom,
 
177
                               0, G_MAXLONG, FALSE,
 
178
                               XA_CARDINAL,
 
179
                               &type, &format, &nitems,
 
180
                               &bytes_after, &(prop.prop_ch));
 
181
  error = gdk_error_trap_pop ();
 
182
 
 
183
  if (error || result != Success)
 
184
    return;
 
185
 
 
186
  if (type == XA_CARDINAL)
 
187
    {
 
188
      GtkOrientation orientation;
 
189
 
 
190
      orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
 
191
                                        GTK_ORIENTATION_HORIZONTAL :
 
192
                                        GTK_ORIENTATION_VERTICAL;
 
193
 
 
194
      if (icon->orientation != orientation)
 
195
        {
 
196
          icon->orientation = orientation;
 
197
 
 
198
          g_object_notify (G_OBJECT (icon), "orientation");
 
199
        }
 
200
    }
 
201
 
 
202
  if (prop.prop)
 
203
    XFree (prop.prop);
86
204
}
87
205
 
88
206
static GdkFilterReturn
93
211
 
94
212
  if (xev->xany.type == ClientMessage &&
95
213
      xev->xclient.message_type == icon->manager_atom &&
96
 
      xev->xclient.data.l[1] == icon->selection_atom)
 
214
      xev->xclient.data.l[1] == (int)icon->selection_atom)
97
215
    {
98
 
      egg_tray_icon_update_manager_window (icon);
 
216
      egg_tray_icon_update_manager_window (icon, TRUE);
99
217
    }
100
218
  else if (xev->xany.window == icon->manager_window)
101
219
    {
 
220
      if (xev->xany.type == PropertyNotify &&
 
221
          xev->xproperty.atom == icon->orientation_atom)
 
222
        {
 
223
          egg_tray_icon_get_orientation_property (icon);
 
224
        }
102
225
      if (xev->xany.type == DestroyNotify)
103
226
        {
104
 
          egg_tray_icon_update_manager_window (icon);
 
227
          egg_tray_icon_manager_window_destroyed (icon);
105
228
        }
106
229
    }
107
 
  
108
230
  return GDK_FILTER_CONTINUE;
109
231
}
110
232
 
 
233
#endif
 
234
 
111
235
static void
112
236
egg_tray_icon_unrealize (GtkWidget *widget)
113
237
{
 
238
#ifdef GDK_WINDOWING_X11
114
239
  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
115
240
  GdkWindow *root_window;
116
241
 
118
243
    {
119
244
      GdkWindow *gdkwin;
120
245
 
121
 
#if HAVE_GTK_MULTIHEAD
122
246
      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
123
247
                                              icon->manager_window);
124
 
#else
125
 
      gdkwin = gdk_window_lookup (icon->manager_window);
126
 
#endif
127
248
 
128
249
      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
129
250
    }
130
251
 
131
 
#if HAVE_GTK_MULTIHEAD
132
252
  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
133
 
#else
134
 
  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
135
 
#endif
136
253
 
137
254
  gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
138
255
 
139
256
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
140
257
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 
258
#endif
141
259
}
142
260
 
 
261
#ifdef GDK_WINDOWING_X11
 
262
 
143
263
static void
144
264
egg_tray_icon_send_manager_message (EggTrayIcon *icon,
145
265
                                    long         message,
150
270
{
151
271
  XClientMessageEvent ev;
152
272
  Display *display;
153
 
  
 
273
 
154
274
  ev.type = ClientMessage;
155
275
  ev.window = window;
156
276
  ev.message_type = icon->system_tray_opcode_atom;
161
281
  ev.data.l[3] = data2;
162
282
  ev.data.l[4] = data3;
163
283
 
164
 
#if HAVE_GTK_MULTIHEAD
165
284
  display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
166
 
#else
167
 
  display = gdk_display;
168
 
#endif
169
 
  
 
285
 
170
286
  gdk_error_trap_push ();
171
287
  XSendEvent (display,
172
288
              icon->manager_window, False, NoEventMask, (XEvent *)&ev);
185
301
}
186
302
 
187
303
static void
188
 
egg_tray_icon_update_manager_window (EggTrayIcon *icon)
 
304
egg_tray_icon_update_manager_window (EggTrayIcon *icon,
 
305
                                     gboolean     dock_if_realized)
189
306
{
190
307
  Display *xdisplay;
191
 
  
192
 
#if HAVE_GTK_MULTIHEAD
 
308
 
 
309
  if (icon->manager_window != None)
 
310
    return;
 
311
 
193
312
  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
194
 
#else
195
 
  xdisplay = gdk_display;
196
 
#endif
197
 
  
198
 
  if (icon->manager_window != None)
199
 
    {
200
 
      GdkWindow *gdkwin;
201
313
 
202
 
#if HAVE_GTK_MULTIHEAD
203
 
      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
204
 
                                              icon->manager_window);
205
 
#else
206
 
      gdkwin = gdk_window_lookup (icon->manager_window);
207
 
#endif
208
 
      
209
 
      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
210
 
    }
211
 
  
212
314
  XGrabServer (xdisplay);
213
 
  
 
315
 
214
316
  icon->manager_window = XGetSelectionOwner (xdisplay,
215
317
                                             icon->selection_atom);
216
318
 
217
319
  if (icon->manager_window != None)
218
320
    XSelectInput (xdisplay,
219
 
                  icon->manager_window, StructureNotifyMask);
 
321
                  icon->manager_window, StructureNotifyMask|PropertyChangeMask);
220
322
 
221
323
  XUngrabServer (xdisplay);
222
324
  XFlush (xdisplay);
223
 
  
 
325
 
224
326
  if (icon->manager_window != None)
225
327
    {
226
328
      GdkWindow *gdkwin;
227
329
 
228
 
#if HAVE_GTK_MULTIHEAD
229
330
      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
230
331
                                              icon->manager_window);
231
 
#else
232
 
      gdkwin = gdk_window_lookup (icon->manager_window);
233
 
#endif
234
 
      
 
332
 
235
333
      gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
236
334
 
237
 
      /* Send a request that we'd like to dock */
238
 
      egg_tray_icon_send_dock_request (icon);
 
335
      if (dock_if_realized && GTK_WIDGET_REALIZED (icon))
 
336
        egg_tray_icon_send_dock_request (icon);
 
337
 
 
338
      egg_tray_icon_get_orientation_property (icon);
239
339
    }
240
340
}
241
341
 
242
 
EggTrayIcon *
243
 
egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
244
 
{
245
 
  EggTrayIcon *icon;
 
342
static void
 
343
egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon)
 
344
{
 
345
  GdkWindow *gdkwin;
 
346
 
 
347
  g_return_if_fail (icon->manager_window != None);
 
348
 
 
349
  gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
 
350
                                          icon->manager_window);
 
351
 
 
352
  gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
 
353
 
 
354
  icon->manager_window = None;
 
355
 
 
356
  egg_tray_icon_update_manager_window (icon, TRUE);
 
357
}
 
358
 
 
359
#endif
 
360
 
 
361
static void
 
362
egg_tray_icon_realize (GtkWidget *widget)
 
363
{
 
364
#ifdef GDK_WINDOWING_X11
 
365
  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
 
366
  GdkScreen *screen;
 
367
  GdkDisplay *display;
 
368
  Display *xdisplay;
246
369
  char buffer[256];
247
370
  GdkWindow *root_window;
248
371
 
249
 
  g_return_val_if_fail (xscreen != NULL, NULL);
250
 
  
251
 
  icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL);
252
 
  gtk_window_set_title (GTK_WINDOW (icon), name);
 
372
  if (GTK_WIDGET_CLASS (parent_class)->realize)
 
373
    GTK_WIDGET_CLASS (parent_class)->realize (widget);
253
374
 
254
 
#if HAVE_GTK_MULTIHEAD
255
 
  /* FIXME: this code does not compile, screen is undefined. Now try
256
 
   * getting the GdkScreen from xscreen (:. Dunno how to solve this
257
 
   * (there is prolly some easy way I cant think of right now)
258
 
   */
259
 
  gtk_plug_construct_for_display (GTK_PLUG (icon),
260
 
                                  gdk_screen_get_display (screen), 0);
261
 
#else
262
 
  gtk_plug_construct (GTK_PLUG (icon), 0);
263
 
#endif
264
 
  
265
 
  gtk_widget_realize (GTK_WIDGET (icon));
 
375
  screen = gtk_widget_get_screen (widget);
 
376
  display = gdk_screen_get_display (screen);
 
377
  xdisplay = gdk_x11_display_get_xdisplay (display);
266
378
 
267
379
  /* Now see if there's a manager window around */
268
380
  g_snprintf (buffer, sizeof (buffer),
269
381
              "_NET_SYSTEM_TRAY_S%d",
270
 
              XScreenNumberOfScreen (xscreen));
271
 
  
272
 
  icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen),
273
 
                                      buffer, False);
274
 
  
275
 
  icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen),
276
 
                                    "MANAGER", False);
277
 
  
278
 
  icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen),
279
 
                                               "_NET_SYSTEM_TRAY_OPCODE", False);
280
 
 
281
 
  egg_tray_icon_update_manager_window (icon);
282
 
 
283
 
#if HAVE_GTK_MULTIHEAD
284
 
  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (screen));
285
 
#else
286
 
  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
287
 
#endif
288
 
  
 
382
              gdk_screen_get_number (screen));
 
383
 
 
384
  icon->selection_atom = XInternAtom (xdisplay, buffer, False);
 
385
 
 
386
  icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
 
387
 
 
388
  icon->system_tray_opcode_atom = XInternAtom (xdisplay,
 
389
                                                   "_NET_SYSTEM_TRAY_OPCODE",
 
390
                                                   False);
 
391
 
 
392
  icon->orientation_atom = XInternAtom (xdisplay,
 
393
                                        "_NET_SYSTEM_TRAY_ORIENTATION",
 
394
                                        False);
 
395
 
 
396
  egg_tray_icon_update_manager_window (icon, FALSE);
 
397
  egg_tray_icon_send_dock_request (icon);
 
398
 
 
399
  root_window = gdk_screen_get_root_window (screen);
 
400
 
289
401
  /* Add a root window filter so that we get changes on MANAGER */
290
402
  gdk_window_add_filter (root_window,
291
403
                         egg_tray_icon_manager_filter, icon);
292
 
                      
293
 
  return icon;
 
404
#endif
294
405
}
295
406
 
296
 
#if HAVE_GTK_MULTIHEAD
297
407
EggTrayIcon *
298
408
egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
299
409
{
300
 
  EggTrayIcon *icon;
301
 
  char buffer[256];
302
 
 
303
410
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
304
411
 
305
 
  return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name);
 
412
  return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
306
413
}
307
 
#endif
308
414
 
309
415
EggTrayIcon*
310
416
egg_tray_icon_new (const gchar *name)
311
417
{
312
 
  return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name);
 
418
  return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
313
419
}
314
420
 
315
421
guint
319
425
                            gint         len)
320
426
{
321
427
  guint stamp;
322
 
  
 
428
 
323
429
  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
324
430
  g_return_val_if_fail (timeout >= 0, 0);
325
431
  g_return_val_if_fail (message != NULL, 0);
326
 
                     
 
432
 
 
433
#ifdef GDK_WINDOWING_X11
327
434
  if (icon->manager_window == None)
328
435
    return 0;
 
436
#endif
329
437
 
330
438
  if (len < 0)
331
439
    len = strlen (message);
332
440
 
333
441
  stamp = icon->stamp++;
334
 
  
 
442
 
 
443
#ifdef GDK_WINDOWING_X11
335
444
  /* Get ready to send the message */
336
445
  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
337
446
                                      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
344
453
      XClientMessageEvent ev;
345
454
      Display *xdisplay;
346
455
 
347
 
#if HAVE_GTK_MULTIHEAD
348
456
      xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
349
 
#else
350
 
      xdisplay = gdk_display;
351
 
#endif
352
 
      
 
457
 
353
458
      ev.type = ClientMessage;
354
459
      ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
355
460
      ev.format = 8;
372
477
      XSync (xdisplay, False);
373
478
    }
374
479
  gdk_error_trap_pop ();
 
480
#endif
375
481
 
376
482
  return stamp;
377
483
}
382
488
{
383
489
  g_return_if_fail (EGG_IS_TRAY_ICON (icon));
384
490
  g_return_if_fail (id > 0);
385
 
  
 
491
#ifdef GDK_WINDOWING_X11
386
492
  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
387
493
                                      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
388
494
                                      id, 0, 0);
 
495
#endif
 
496
}
 
497
 
 
498
GtkOrientation
 
499
egg_tray_icon_get_orientation (EggTrayIcon *icon)
 
500
{
 
501
  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
 
502
 
 
503
  return icon->orientation;
389
504
}