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