Statistics
| Revision:

root / src / eggtrayicon.c @ 3049

History | View | Annotate | Download (14.9 kB)

1 501 hiro
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 501 hiro
/* eggtrayicon.c
3 501 hiro
 * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
4 501 hiro
 *
5 501 hiro
 * This library is free software; you can redistribute it and/or
6 501 hiro
 * modify it under the terms of the GNU Lesser General Public
7 501 hiro
 * License as published by the Free Software Foundation; either
8 501 hiro
 * version 2 of the License, or (at your option) any later version.
9 501 hiro
 *
10 501 hiro
 * This library is distributed in the hope that it will be useful,
11 501 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 501 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 501 hiro
 * Lesser General Public License for more details.
14 501 hiro
 *
15 501 hiro
 * You should have received a copy of the GNU Lesser General Public
16 501 hiro
 * License along with this library; if not, write to the
17 501 hiro
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 501 hiro
 * Boston, MA 02111-1307, USA.
19 501 hiro
 */
20 501 hiro
/* Added WINDOWING ifdef  2005-07-09 by Yoichi Imai <yoichi@silver-forest.com> */
21 501 hiro
22 501 hiro
#include <config.h>
23 501 hiro
24 501 hiro
#include "eggtrayicon.h"
25 501 hiro
26 1288 hiro
#if !GTK_CHECK_VERSION(2, 10, 0) && defined(GDK_WINDOWING_X11)
27 1288 hiro
#include <string.h>
28 1288 hiro
#include <libintl.h>
29 501 hiro
#include <gdk/gdkx.h>
30 501 hiro
#include <X11/Xatom.h>
31 501 hiro
32 501 hiro
#ifndef EGG_COMPILATION
33 501 hiro
#ifndef _
34 501 hiro
#define _(x) dgettext (GETTEXT_PACKAGE, x)
35 501 hiro
#define N_(x) x
36 501 hiro
#endif
37 501 hiro
#else
38 501 hiro
#define _(x) x
39 501 hiro
#define N_(x) x
40 501 hiro
#endif
41 501 hiro
42 501 hiro
#define SYSTEM_TRAY_REQUEST_DOCK    0
43 501 hiro
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
44 501 hiro
#define SYSTEM_TRAY_CANCEL_MESSAGE  2
45 501 hiro
46 501 hiro
#define SYSTEM_TRAY_ORIENTATION_HORZ 0
47 501 hiro
#define SYSTEM_TRAY_ORIENTATION_VERT 1
48 501 hiro
49 501 hiro
enum {
50 501 hiro
  PROP_0,
51 501 hiro
  PROP_ORIENTATION
52 501 hiro
};
53 501 hiro
54 501 hiro
static GtkPlugClass *parent_class = NULL;
55 501 hiro
56 501 hiro
static void egg_tray_icon_init (EggTrayIcon *icon);
57 501 hiro
static void egg_tray_icon_class_init (EggTrayIconClass *klass);
58 501 hiro
59 501 hiro
static void egg_tray_icon_get_property (GObject    *object,
60 501 hiro
                                        guint       prop_id,
61 501 hiro
                                        GValue     *value,
62 501 hiro
                                        GParamSpec *pspec);
63 501 hiro
64 501 hiro
static void egg_tray_icon_realize   (GtkWidget *widget);
65 501 hiro
static void egg_tray_icon_unrealize (GtkWidget *widget);
66 501 hiro
67 1138 hiro
static void egg_tray_icon_add (GtkContainer *container,
68 1138 hiro
                               GtkWidget    *widget);
69 501 hiro
70 1138 hiro
static void egg_tray_icon_update_manager_window    (EggTrayIcon *icon,
71 1138 hiro
                                                    gboolean     dock_if_realized);
72 1138 hiro
static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon);
73 1138 hiro
74 501 hiro
GType
75 501 hiro
egg_tray_icon_get_type (void)
76 501 hiro
{
77 501 hiro
  static GType our_type = 0;
78 501 hiro
79 501 hiro
  if (our_type == 0)
80 501 hiro
    {
81 1138 hiro
      our_type = g_type_from_name("EggTrayIcon");
82 1138 hiro
83 1138 hiro
      if (our_type == 0)
84 1138 hiro
        {
85 501 hiro
      static const GTypeInfo our_info =
86 501 hiro
      {
87 501 hiro
        sizeof (EggTrayIconClass),
88 501 hiro
        (GBaseInitFunc) NULL,
89 501 hiro
        (GBaseFinalizeFunc) NULL,
90 501 hiro
        (GClassInitFunc) egg_tray_icon_class_init,
91 501 hiro
        NULL, /* class_finalize */
92 501 hiro
        NULL, /* class_data */
93 501 hiro
        sizeof (EggTrayIcon),
94 501 hiro
        0,    /* n_preallocs */
95 1138 hiro
        (GInstanceInitFunc) egg_tray_icon_init,
96 1138 hiro
        NULL /* value_table */
97 501 hiro
      };
98 501 hiro
99 501 hiro
      our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
100 1138 hiro
        }
101 1138 hiro
      else if (parent_class == NULL)
102 1138 hiro
        {
103 1138 hiro
          /* we're reheating the old class from a previous instance -  engage ugly hack =( */
104 1138 hiro
          egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type));
105 1138 hiro
        }
106 501 hiro
    }
107 501 hiro
108 501 hiro
  return our_type;
109 501 hiro
}
110 501 hiro
111 501 hiro
static void
112 501 hiro
egg_tray_icon_init (EggTrayIcon *icon)
113 501 hiro
{
114 501 hiro
  icon->stamp = 1;
115 501 hiro
  icon->orientation = GTK_ORIENTATION_HORIZONTAL;
116 501 hiro
117 501 hiro
  gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
118 501 hiro
}
119 501 hiro
120 501 hiro
static void
121 501 hiro
egg_tray_icon_class_init (EggTrayIconClass *klass)
122 501 hiro
{
123 501 hiro
  GObjectClass *gobject_class = (GObjectClass *)klass;
124 501 hiro
  GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
125 1138 hiro
  GtkContainerClass *container_class = (GtkContainerClass *)klass;
126 501 hiro
127 501 hiro
  parent_class = g_type_class_peek_parent (klass);
128 501 hiro
129 501 hiro
  gobject_class->get_property = egg_tray_icon_get_property;
130 501 hiro
131 501 hiro
  widget_class->realize   = egg_tray_icon_realize;
132 501 hiro
  widget_class->unrealize = egg_tray_icon_unrealize;
133 501 hiro
134 1138 hiro
  container_class->add = egg_tray_icon_add;
135 1138 hiro
136 501 hiro
  g_object_class_install_property (gobject_class,
137 501 hiro
                                   PROP_ORIENTATION,
138 501 hiro
                                   g_param_spec_enum ("orientation",
139 501 hiro
                                                      _("Orientation"),
140 501 hiro
                                                      _("The orientation of the tray."),
141 501 hiro
                                                      GTK_TYPE_ORIENTATION,
142 501 hiro
                                                      GTK_ORIENTATION_HORIZONTAL,
143 501 hiro
                                                      G_PARAM_READABLE));
144 501 hiro
}
145 501 hiro
146 501 hiro
static void
147 501 hiro
egg_tray_icon_get_property (GObject    *object,
148 501 hiro
                            guint       prop_id,
149 501 hiro
                            GValue     *value,
150 501 hiro
                            GParamSpec *pspec)
151 501 hiro
{
152 501 hiro
  EggTrayIcon *icon = EGG_TRAY_ICON (object);
153 501 hiro
154 501 hiro
  switch (prop_id)
155 501 hiro
    {
156 501 hiro
    case PROP_ORIENTATION:
157 501 hiro
      g_value_set_enum (value, icon->orientation);
158 501 hiro
      break;
159 501 hiro
    default:
160 501 hiro
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
161 501 hiro
      break;
162 501 hiro
    }
163 501 hiro
}
164 501 hiro
165 501 hiro
static void
166 501 hiro
egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
167 501 hiro
{
168 501 hiro
  Display *xdisplay;
169 501 hiro
  Atom type;
170 501 hiro
  int format;
171 501 hiro
  union {
172 501 hiro
        gulong *prop;
173 501 hiro
        guchar *prop_ch;
174 501 hiro
  } prop = { NULL };
175 501 hiro
  gulong nitems;
176 501 hiro
  gulong bytes_after;
177 501 hiro
  int error, result;
178 501 hiro
179 1138 hiro
  g_return_if_fail(icon->manager_window != None);
180 1138 hiro
181 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
182 501 hiro
  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
183 1138 hiro
#else
184 1138 hiro
  xdisplay = gdk_display;
185 1138 hiro
#endif
186 501 hiro
187 501 hiro
  gdk_error_trap_push ();
188 501 hiro
  type = None;
189 501 hiro
  result = XGetWindowProperty (xdisplay,
190 501 hiro
                               icon->manager_window,
191 501 hiro
                               icon->orientation_atom,
192 501 hiro
                               0, G_MAXLONG, FALSE,
193 501 hiro
                               XA_CARDINAL,
194 501 hiro
                               &type, &format, &nitems,
195 501 hiro
                               &bytes_after, &(prop.prop_ch));
196 501 hiro
  error = gdk_error_trap_pop ();
197 501 hiro
198 501 hiro
  if (error || result != Success)
199 501 hiro
    return;
200 501 hiro
201 501 hiro
  if (type == XA_CARDINAL)
202 501 hiro
    {
203 501 hiro
      GtkOrientation orientation;
204 501 hiro
205 501 hiro
      orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
206 501 hiro
                                        GTK_ORIENTATION_HORIZONTAL :
207 501 hiro
                                        GTK_ORIENTATION_VERTICAL;
208 501 hiro
209 501 hiro
      if (icon->orientation != orientation)
210 501 hiro
        {
211 501 hiro
          icon->orientation = orientation;
212 501 hiro
213 501 hiro
          g_object_notify (G_OBJECT (icon), "orientation");
214 501 hiro
        }
215 501 hiro
    }
216 501 hiro
217 501 hiro
  if (prop.prop)
218 501 hiro
    XFree (prop.prop);
219 501 hiro
}
220 501 hiro
221 501 hiro
static GdkFilterReturn
222 501 hiro
egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
223 501 hiro
{
224 501 hiro
  EggTrayIcon *icon = user_data;
225 501 hiro
  XEvent *xev = (XEvent *)xevent;
226 501 hiro
227 501 hiro
  if (xev->xany.type == ClientMessage &&
228 501 hiro
      xev->xclient.message_type == icon->manager_atom &&
229 501 hiro
      xev->xclient.data.l[1] == icon->selection_atom)
230 501 hiro
    {
231 1138 hiro
      egg_tray_icon_update_manager_window (icon, TRUE);
232 501 hiro
    }
233 501 hiro
  else if (xev->xany.window == icon->manager_window)
234 501 hiro
    {
235 501 hiro
      if (xev->xany.type == PropertyNotify &&
236 501 hiro
          xev->xproperty.atom == icon->orientation_atom)
237 501 hiro
        {
238 501 hiro
          egg_tray_icon_get_orientation_property (icon);
239 501 hiro
        }
240 501 hiro
      if (xev->xany.type == DestroyNotify)
241 501 hiro
        {
242 1138 hiro
          egg_tray_icon_manager_window_destroyed (icon);
243 501 hiro
        }
244 501 hiro
    }
245 501 hiro
246 501 hiro
  return GDK_FILTER_CONTINUE;
247 501 hiro
}
248 501 hiro
249 501 hiro
static void
250 501 hiro
egg_tray_icon_unrealize (GtkWidget *widget)
251 501 hiro
{
252 501 hiro
  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
253 501 hiro
  GdkWindow *root_window;
254 501 hiro
255 501 hiro
  if (icon->manager_window != None)
256 501 hiro
    {
257 501 hiro
      GdkWindow *gdkwin;
258 501 hiro
259 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
260 501 hiro
      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
261 501 hiro
                                              icon->manager_window);
262 1138 hiro
#else
263 1138 hiro
      gdkwin = gdk_window_lookup (icon->manager_window);
264 1138 hiro
#endif
265 501 hiro
266 501 hiro
      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
267 501 hiro
    }
268 501 hiro
269 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
270 501 hiro
  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
271 1138 hiro
#else
272 1138 hiro
  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
273 1138 hiro
#endif
274 501 hiro
275 501 hiro
  gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
276 501 hiro
277 501 hiro
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
278 501 hiro
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
279 501 hiro
}
280 501 hiro
281 501 hiro
static void
282 501 hiro
egg_tray_icon_send_manager_message (EggTrayIcon *icon,
283 501 hiro
                                    long         message,
284 501 hiro
                                    Window       window,
285 501 hiro
                                    long         data1,
286 501 hiro
                                    long         data2,
287 501 hiro
                                    long         data3)
288 501 hiro
{
289 501 hiro
  XClientMessageEvent ev;
290 501 hiro
  Display *display;
291 501 hiro
292 501 hiro
  ev.type = ClientMessage;
293 501 hiro
  ev.window = window;
294 501 hiro
  ev.message_type = icon->system_tray_opcode_atom;
295 501 hiro
  ev.format = 32;
296 501 hiro
  ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
297 501 hiro
  ev.data.l[1] = message;
298 501 hiro
  ev.data.l[2] = data1;
299 501 hiro
  ev.data.l[3] = data2;
300 501 hiro
  ev.data.l[4] = data3;
301 501 hiro
302 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
303 501 hiro
  display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
304 1138 hiro
#else
305 1138 hiro
  display = gdk_display;
306 1138 hiro
#endif
307 1138 hiro
308 501 hiro
  gdk_error_trap_push ();
309 501 hiro
  XSendEvent (display,
310 501 hiro
              icon->manager_window, False, NoEventMask, (XEvent *)&ev);
311 501 hiro
  XSync (display, False);
312 501 hiro
  gdk_error_trap_pop ();
313 501 hiro
}
314 501 hiro
315 501 hiro
static void
316 501 hiro
egg_tray_icon_send_dock_request (EggTrayIcon *icon)
317 501 hiro
{
318 501 hiro
  egg_tray_icon_send_manager_message (icon,
319 501 hiro
                                      SYSTEM_TRAY_REQUEST_DOCK,
320 501 hiro
                                      icon->manager_window,
321 501 hiro
                                      gtk_plug_get_id (GTK_PLUG (icon)),
322 501 hiro
                                      0, 0);
323 501 hiro
}
324 501 hiro
325 501 hiro
static void
326 1138 hiro
egg_tray_icon_update_manager_window (EggTrayIcon *icon,
327 1138 hiro
                                     gboolean     dock_if_realized)
328 501 hiro
{
329 501 hiro
  Display *xdisplay;
330 501 hiro
331 501 hiro
  if (icon->manager_window != None)
332 1138 hiro
    return;
333 501 hiro
334 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
335 1138 hiro
  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
336 1138 hiro
#else
337 1138 hiro
  xdisplay = gdk_display;
338 1138 hiro
#endif
339 1138 hiro
340 501 hiro
  XGrabServer (xdisplay);
341 501 hiro
342 501 hiro
  icon->manager_window = XGetSelectionOwner (xdisplay,
343 501 hiro
                                             icon->selection_atom);
344 501 hiro
345 501 hiro
  if (icon->manager_window != None)
346 501 hiro
    XSelectInput (xdisplay,
347 501 hiro
                  icon->manager_window, StructureNotifyMask|PropertyChangeMask);
348 501 hiro
349 501 hiro
  XUngrabServer (xdisplay);
350 501 hiro
  XFlush (xdisplay);
351 501 hiro
352 501 hiro
  if (icon->manager_window != None)
353 501 hiro
    {
354 501 hiro
      GdkWindow *gdkwin;
355 501 hiro
356 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
357 501 hiro
      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
358 501 hiro
                                              icon->manager_window);
359 1138 hiro
#else
360 1138 hiro
      gdkwin = gdk_window_lookup (icon->manager_window);
361 1138 hiro
#endif
362 1138 hiro
363 501 hiro
      gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
364 501 hiro
365 1138 hiro
      if (dock_if_realized && GTK_WIDGET_REALIZED (icon))
366 1138 hiro
        egg_tray_icon_send_dock_request (icon);
367 501 hiro
368 501 hiro
      egg_tray_icon_get_orientation_property (icon);
369 501 hiro
    }
370 501 hiro
}
371 501 hiro
372 1138 hiro
static gboolean
373 1138 hiro
transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
374 1138 hiro
{
375 1138 hiro
  gdk_window_clear_area (widget->window, event->area.x, event->area.y,
376 1138 hiro
                         event->area.width, event->area.height);
377 1138 hiro
  return FALSE;
378 1138 hiro
}
379 1138 hiro
380 501 hiro
static void
381 1138 hiro
make_transparent_again (GtkWidget *widget, GtkStyle *previous_style,
382 1138 hiro
                        gpointer user_data)
383 1138 hiro
{
384 1138 hiro
  gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
385 1138 hiro
}
386 1138 hiro
387 1138 hiro
static void
388 1138 hiro
make_transparent (GtkWidget *widget, gpointer user_data)
389 1138 hiro
{
390 1138 hiro
  if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget))
391 1138 hiro
    return;
392 1138 hiro
393 1138 hiro
  gtk_widget_set_app_paintable (widget, TRUE);
394 1138 hiro
  gtk_widget_set_double_buffered (widget, FALSE);
395 1138 hiro
  gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
396 1138 hiro
  g_signal_connect (widget, "expose_event",
397 1138 hiro
                    G_CALLBACK (transparent_expose_event), NULL);
398 1138 hiro
  g_signal_connect_after (widget, "style_set",
399 1138 hiro
                          G_CALLBACK (make_transparent_again), NULL);
400 1138 hiro
}
401 1138 hiro
402 1138 hiro
static void
403 1138 hiro
egg_tray_icon_add (GtkContainer *container, GtkWidget *widget)
404 1138 hiro
{
405 1138 hiro
   g_signal_connect (widget, "realize",
406 1138 hiro
                     G_CALLBACK (make_transparent), NULL);
407 1138 hiro
   GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
408 1138 hiro
}
409 1138 hiro
410 1138 hiro
static void
411 1138 hiro
egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon)
412 1138 hiro
{
413 1138 hiro
  GdkWindow *gdkwin;
414 1138 hiro
415 1138 hiro
  g_return_if_fail (icon->manager_window != None);
416 1138 hiro
417 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
418 1138 hiro
  gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
419 1138 hiro
                                          icon->manager_window);
420 1138 hiro
#else
421 1138 hiro
  gdkwin = gdk_window_lookup (icon->manager_window);
422 1138 hiro
#endif
423 1138 hiro
424 1138 hiro
  gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
425 1138 hiro
426 1138 hiro
  icon->manager_window = None;
427 1138 hiro
428 1138 hiro
  egg_tray_icon_update_manager_window (icon, TRUE);
429 1138 hiro
}
430 1138 hiro
431 1138 hiro
static void
432 501 hiro
egg_tray_icon_realize (GtkWidget *widget)
433 501 hiro
{
434 501 hiro
  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
435 1138 hiro
  gint screen;
436 501 hiro
  Display *xdisplay;
437 501 hiro
  char buffer[256];
438 501 hiro
  GdkWindow *root_window;
439 501 hiro
440 501 hiro
  if (GTK_WIDGET_CLASS (parent_class)->realize)
441 501 hiro
    GTK_WIDGET_CLASS (parent_class)->realize (widget);
442 501 hiro
443 1138 hiro
  make_transparent (widget, NULL);
444 501 hiro
445 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
446 1138 hiro
  screen = gdk_screen_get_number (gtk_widget_get_screen (widget));
447 1138 hiro
  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget));
448 1138 hiro
#else
449 1138 hiro
  screen = XScreenNumberOfScreen (DefaultScreenOfDisplay (gdk_display));
450 1138 hiro
  xdisplay = gdk_display;
451 1138 hiro
#endif
452 1138 hiro
453 501 hiro
  /* Now see if there's a manager window around */
454 501 hiro
  g_snprintf (buffer, sizeof (buffer),
455 501 hiro
              "_NET_SYSTEM_TRAY_S%d",
456 1138 hiro
              screen);
457 501 hiro
458 501 hiro
  icon->selection_atom = XInternAtom (xdisplay, buffer, False);
459 501 hiro
460 501 hiro
  icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
461 501 hiro
462 501 hiro
  icon->system_tray_opcode_atom = XInternAtom (xdisplay,
463 501 hiro
                                                   "_NET_SYSTEM_TRAY_OPCODE",
464 501 hiro
                                                   False);
465 501 hiro
466 501 hiro
  icon->orientation_atom = XInternAtom (xdisplay,
467 501 hiro
                                        "_NET_SYSTEM_TRAY_ORIENTATION",
468 501 hiro
                                        False);
469 501 hiro
470 1138 hiro
  egg_tray_icon_update_manager_window (icon, FALSE);
471 1138 hiro
  egg_tray_icon_send_dock_request (icon);
472 501 hiro
473 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
474 1138 hiro
  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
475 1138 hiro
#else
476 1138 hiro
  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
477 1138 hiro
#endif
478 1138 hiro
479 501 hiro
  /* Add a root window filter so that we get changes on MANAGER */
480 501 hiro
  gdk_window_add_filter (root_window,
481 501 hiro
                         egg_tray_icon_manager_filter, icon);
482 501 hiro
}
483 501 hiro
484 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
485 501 hiro
EggTrayIcon *
486 501 hiro
egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
487 501 hiro
{
488 501 hiro
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
489 501 hiro
490 501 hiro
  return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
491 501 hiro
}
492 1138 hiro
#endif
493 501 hiro
494 501 hiro
EggTrayIcon*
495 501 hiro
egg_tray_icon_new (const gchar *name)
496 501 hiro
{
497 501 hiro
  return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
498 501 hiro
}
499 501 hiro
500 501 hiro
guint
501 501 hiro
egg_tray_icon_send_message (EggTrayIcon *icon,
502 501 hiro
                            gint         timeout,
503 501 hiro
                            const gchar *message,
504 501 hiro
                            gint         len)
505 501 hiro
{
506 501 hiro
  guint stamp;
507 501 hiro
508 501 hiro
  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
509 501 hiro
  g_return_val_if_fail (timeout >= 0, 0);
510 501 hiro
  g_return_val_if_fail (message != NULL, 0);
511 501 hiro
512 501 hiro
  if (icon->manager_window == None)
513 501 hiro
    return 0;
514 501 hiro
515 501 hiro
  if (len < 0)
516 501 hiro
    len = strlen (message);
517 501 hiro
518 501 hiro
  stamp = icon->stamp++;
519 501 hiro
520 501 hiro
  /* Get ready to send the message */
521 501 hiro
  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
522 501 hiro
                                      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
523 501 hiro
                                      timeout, len, stamp);
524 501 hiro
525 501 hiro
  /* Now to send the actual message */
526 501 hiro
  gdk_error_trap_push ();
527 501 hiro
  while (len > 0)
528 501 hiro
    {
529 501 hiro
      XClientMessageEvent ev;
530 501 hiro
      Display *xdisplay;
531 501 hiro
532 1138 hiro
#if GTK_CHECK_VERSION(2,1,0)
533 501 hiro
      xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
534 1138 hiro
#else
535 1138 hiro
      xdisplay = gdk_display;
536 1138 hiro
#endif
537 1138 hiro
538 501 hiro
      ev.type = ClientMessage;
539 501 hiro
      ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
540 501 hiro
      ev.format = 8;
541 501 hiro
      ev.message_type = XInternAtom (xdisplay,
542 501 hiro
                                     "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
543 501 hiro
      if (len > 20)
544 501 hiro
        {
545 501 hiro
          memcpy (&ev.data, message, 20);
546 501 hiro
          len -= 20;
547 501 hiro
          message += 20;
548 501 hiro
        }
549 501 hiro
      else
550 501 hiro
        {
551 501 hiro
          memcpy (&ev.data, message, len);
552 501 hiro
          len = 0;
553 501 hiro
        }
554 501 hiro
555 501 hiro
      XSendEvent (xdisplay,
556 501 hiro
                  icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
557 501 hiro
      XSync (xdisplay, False);
558 501 hiro
    }
559 501 hiro
  gdk_error_trap_pop ();
560 501 hiro
561 501 hiro
  return stamp;
562 501 hiro
}
563 501 hiro
564 501 hiro
void
565 501 hiro
egg_tray_icon_cancel_message (EggTrayIcon *icon,
566 501 hiro
                              guint        id)
567 501 hiro
{
568 501 hiro
  g_return_if_fail (EGG_IS_TRAY_ICON (icon));
569 501 hiro
  g_return_if_fail (id > 0);
570 501 hiro
571 501 hiro
  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
572 501 hiro
                                      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
573 501 hiro
                                      id, 0, 0);
574 501 hiro
}
575 501 hiro
576 501 hiro
GtkOrientation
577 501 hiro
egg_tray_icon_get_orientation (EggTrayIcon *icon)
578 501 hiro
{
579 501 hiro
  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
580 501 hiro
581 501 hiro
  return icon->orientation;
582 501 hiro
}
583 501 hiro
#endif