Tue, 14 Feb 2006 05:43:43 +0000
[gaim-migrate @ 15646]
Always show a vertical scrollbar on conversations imhtmls. This will solve the shrinking conversation window bug. I chose this approach instead of saving the size of the window (as I had previous talked about), as this prevents the contents of the scrollback from rewrapping when the scrollbars appear or disappear. It also just seems to feel like the right thing to do, but maybe that's me being lazy.
| 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 */ | |
|
12600
7ecd4441fdc7
[gaim-migrate @ 14934]
Richard Laager <rlaager@pidgin.im>
parents:
11291
diff
changeset
|
82 | (GInstanceInitFunc) egg_tray_icon_init, |
|
7ecd4441fdc7
[gaim-migrate @ 14934]
Richard Laager <rlaager@pidgin.im>
parents:
11291
diff
changeset
|
83 | NULL /* value_table */ |
| 3510 | 84 | }; |
| 85 | ||
| 86 | our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0); | |
| 10779 | 87 | } |
| 88 | else if (parent_class == NULL) | |
| 89 | { | |
| 90 | /* we're reheating the old class from a previous instance - engage ugly hack =( */ | |
| 91 | egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type)); | |
| 92 | } | |
| 3510 | 93 | } |
| 94 | ||
| 95 | return our_type; | |
| 96 | } | |
| 97 | ||
| 98 | static void | |
| 99 | egg_tray_icon_init (EggTrayIcon *icon) | |
| 100 | { | |
| 101 | icon->stamp = 1; | |
| 10779 | 102 | icon->orientation = GTK_ORIENTATION_HORIZONTAL; |
| 3510 | 103 | |
| 104 | gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); | |
| 105 | } | |
| 106 | ||
| 107 | static void | |
| 108 | egg_tray_icon_class_init (EggTrayIconClass *klass) | |
| 109 | { | |
| 10779 | 110 | GObjectClass *gobject_class = (GObjectClass *)klass; |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
111 | GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
112 | |
| 3510 | 113 | parent_class = g_type_class_peek_parent (klass); |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
114 | |
| 10779 | 115 | gobject_class->get_property = egg_tray_icon_get_property; |
| 116 | ||
| 117 | widget_class->realize = egg_tray_icon_realize; | |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
118 | widget_class->unrealize = egg_tray_icon_unrealize; |
| 10779 | 119 | |
| 120 | g_object_class_install_property (gobject_class, | |
| 121 | PROP_ORIENTATION, | |
| 122 | g_param_spec_enum ("orientation", | |
| 123 | _("Orientation"), | |
| 124 | _("The orientation of the tray."), | |
| 125 | GTK_TYPE_ORIENTATION, | |
| 126 | GTK_ORIENTATION_HORIZONTAL, | |
| 127 | G_PARAM_READABLE)); | |
| 128 | } | |
| 129 | ||
| 130 | static void | |
| 131 | egg_tray_icon_get_property (GObject *object, | |
| 132 | guint prop_id, | |
| 133 | GValue *value, | |
| 134 | GParamSpec *pspec) | |
| 135 | { | |
| 136 | EggTrayIcon *icon = EGG_TRAY_ICON (object); | |
| 137 | ||
| 138 | switch (prop_id) | |
| 139 | { | |
| 140 | case PROP_ORIENTATION: | |
| 141 | g_value_set_enum (value, icon->orientation); | |
| 142 | break; | |
| 143 | default: | |
| 144 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
| 145 | break; | |
| 146 | } | |
| 147 | } | |
| 148 | ||
| 149 | static void | |
| 150 | egg_tray_icon_get_orientation_property (EggTrayIcon *icon) | |
| 151 | { | |
| 152 | Display *xdisplay; | |
| 153 | Atom type; | |
| 154 | int format; | |
| 155 | union { | |
| 156 | gulong *prop; | |
| 157 | guchar *prop_ch; | |
| 158 | } prop = { NULL }; | |
| 159 | gulong nitems; | |
| 160 | gulong bytes_after; | |
| 161 | int error, result; | |
| 162 | ||
|
11291
5441d2419942
[gaim-migrate @ 13491]
Mark Doliner <markdoliner@pidgin.im>
parents:
10779
diff
changeset
|
163 | g_return_if_fail(icon->manager_window != None); |
| 10779 | 164 | |
| 165 | #if GTK_CHECK_VERSION(2,1,0) | |
| 166 | xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); | |
| 167 | #else | |
| 168 | xdisplay = gdk_display; | |
| 169 | #endif | |
| 170 | ||
| 171 | gdk_error_trap_push (); | |
| 172 | type = None; | |
| 173 | result = XGetWindowProperty (xdisplay, | |
| 174 | icon->manager_window, | |
| 175 | icon->orientation_atom, | |
| 176 | 0, G_MAXLONG, FALSE, | |
| 177 | XA_CARDINAL, | |
| 178 | &type, &format, &nitems, | |
| 179 | &bytes_after, &(prop.prop_ch)); | |
| 180 | error = gdk_error_trap_pop (); | |
| 181 | ||
| 182 | if (error || result != Success) | |
| 183 | return; | |
| 184 | ||
| 185 | if (type == XA_CARDINAL) | |
| 186 | { | |
| 187 | GtkOrientation orientation; | |
| 188 | ||
| 189 | orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ? | |
| 190 | GTK_ORIENTATION_HORIZONTAL : | |
| 191 | GTK_ORIENTATION_VERTICAL; | |
| 192 | ||
| 193 | if (icon->orientation != orientation) | |
| 194 | { | |
| 195 | icon->orientation = orientation; | |
| 196 | ||
| 197 | g_object_notify (G_OBJECT (icon), "orientation"); | |
| 198 | } | |
| 199 | } | |
| 200 | ||
| 201 | if (prop.prop) | |
| 202 | XFree (prop.prop); | |
| 3510 | 203 | } |
| 204 | ||
| 205 | static GdkFilterReturn | |
| 206 | egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data) | |
| 207 | { | |
| 208 | EggTrayIcon *icon = user_data; | |
| 209 | XEvent *xev = (XEvent *)xevent; | |
| 210 | ||
| 211 | if (xev->xany.type == ClientMessage && | |
| 212 | xev->xclient.message_type == icon->manager_atom && | |
| 213 | xev->xclient.data.l[1] == icon->selection_atom) | |
| 214 | { | |
| 10779 | 215 | egg_tray_icon_update_manager_window (icon, TRUE); |
| 3510 | 216 | } |
| 217 | else if (xev->xany.window == icon->manager_window) | |
| 218 | { | |
| 10779 | 219 | if (xev->xany.type == PropertyNotify && |
| 220 | xev->xproperty.atom == icon->orientation_atom) | |
| 221 | { | |
| 222 | egg_tray_icon_get_orientation_property (icon); | |
| 223 | } | |
| 3510 | 224 | if (xev->xany.type == DestroyNotify) |
| 225 | { | |
| 10779 | 226 | egg_tray_icon_manager_window_destroyed (icon); |
| 3510 | 227 | } |
| 228 | } | |
| 229 | ||
| 230 | return GDK_FILTER_CONTINUE; | |
| 231 | } | |
| 232 | ||
| 233 | static void | |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
234 | egg_tray_icon_unrealize (GtkWidget *widget) |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
235 | { |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
236 | EggTrayIcon *icon = EGG_TRAY_ICON (widget); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
237 | GdkWindow *root_window; |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
238 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
239 | if (icon->manager_window != None) |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
240 | { |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
241 | GdkWindow *gdkwin; |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
242 | |
| 10779 | 243 | #if GTK_CHECK_VERSION(2,1,0) |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
244 | gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget), |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
245 | icon->manager_window); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
246 | #else |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
247 | gdkwin = gdk_window_lookup (icon->manager_window); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
248 | #endif |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
249 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
250 | gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
251 | } |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
252 | |
| 10779 | 253 | #if GTK_CHECK_VERSION(2,1,0) |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
254 | 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
|
255 | #else |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
256 | root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
257 | #endif |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
258 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
259 | 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
|
260 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
261 | if (GTK_WIDGET_CLASS (parent_class)->unrealize) |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
262 | (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); |
|
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 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
265 | static void |
| 3510 | 266 | egg_tray_icon_send_manager_message (EggTrayIcon *icon, |
| 267 | long message, | |
| 268 | Window window, | |
| 269 | long data1, | |
| 270 | long data2, | |
| 271 | long data3) | |
| 272 | { | |
| 273 | XClientMessageEvent ev; | |
| 274 | Display *display; | |
| 275 | ||
| 276 | ev.type = ClientMessage; | |
| 277 | ev.window = window; | |
| 278 | ev.message_type = icon->system_tray_opcode_atom; | |
| 279 | ev.format = 32; | |
| 280 | ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window); | |
| 281 | ev.data.l[1] = message; | |
| 282 | ev.data.l[2] = data1; | |
| 283 | ev.data.l[3] = data2; | |
| 284 | ev.data.l[4] = data3; | |
| 285 | ||
| 10779 | 286 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 287 | display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); |
| 288 | #else | |
| 289 | display = gdk_display; | |
| 290 | #endif | |
| 10779 | 291 | |
| 3510 | 292 | gdk_error_trap_push (); |
| 293 | XSendEvent (display, | |
| 294 | icon->manager_window, False, NoEventMask, (XEvent *)&ev); | |
| 295 | XSync (display, False); | |
| 296 | gdk_error_trap_pop (); | |
| 297 | } | |
| 298 | ||
| 299 | static void | |
| 300 | egg_tray_icon_send_dock_request (EggTrayIcon *icon) | |
| 301 | { | |
| 302 | egg_tray_icon_send_manager_message (icon, | |
| 303 | SYSTEM_TRAY_REQUEST_DOCK, | |
| 304 | icon->manager_window, | |
| 305 | gtk_plug_get_id (GTK_PLUG (icon)), | |
| 306 | 0, 0); | |
| 307 | } | |
| 308 | ||
| 309 | static void | |
| 10779 | 310 | egg_tray_icon_update_manager_window (EggTrayIcon *icon, |
| 311 | gboolean dock_if_realized) | |
| 3510 | 312 | { |
| 313 | Display *xdisplay; | |
| 314 | ||
| 10779 | 315 | if (icon->manager_window != None) |
| 316 | return; | |
| 317 | ||
| 318 | #if GTK_CHECK_VERSION(2,1,0) | |
| 3510 | 319 | xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); |
| 320 | #else | |
| 321 | xdisplay = gdk_display; | |
| 322 | #endif | |
| 323 | ||
| 324 | XGrabServer (xdisplay); | |
| 325 | ||
| 326 | icon->manager_window = XGetSelectionOwner (xdisplay, | |
| 327 | icon->selection_atom); | |
| 328 | ||
| 329 | if (icon->manager_window != None) | |
| 330 | XSelectInput (xdisplay, | |
| 10779 | 331 | icon->manager_window, StructureNotifyMask|PropertyChangeMask); |
| 3510 | 332 | |
| 333 | XUngrabServer (xdisplay); | |
| 334 | XFlush (xdisplay); | |
| 335 | ||
| 336 | if (icon->manager_window != None) | |
| 337 | { | |
| 338 | GdkWindow *gdkwin; | |
| 339 | ||
| 10779 | 340 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 341 | gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), |
| 342 | icon->manager_window); | |
| 343 | #else | |
| 344 | gdkwin = gdk_window_lookup (icon->manager_window); | |
| 345 | #endif | |
| 10779 | 346 | |
| 3510 | 347 | gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); |
| 348 | ||
| 10779 | 349 | if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) |
| 350 | egg_tray_icon_send_dock_request (icon); | |
| 351 | ||
| 352 | egg_tray_icon_get_orientation_property (icon); | |
| 3510 | 353 | } |
| 354 | } | |
| 355 | ||
| 10779 | 356 | static void |
| 357 | egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon) | |
| 3510 | 358 | { |
| 10779 | 359 | GdkWindow *gdkwin; |
| 360 | ||
| 361 | g_return_if_fail (icon->manager_window != None); | |
| 362 | ||
| 363 | #if GTK_CHECK_VERSION(2,1,0) | |
| 364 | gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), | |
| 365 | icon->manager_window); | |
| 366 | #else | |
| 367 | gdkwin = gdk_window_lookup (icon->manager_window); | |
| 368 | #endif | |
| 369 | ||
| 370 | gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); | |
| 371 | ||
| 372 | icon->manager_window = None; | |
| 373 | ||
| 374 | egg_tray_icon_update_manager_window (icon, TRUE); | |
| 375 | } | |
| 376 | ||
| 377 | static void | |
| 378 | egg_tray_icon_realize (GtkWidget *widget) | |
| 379 | { | |
| 380 | EggTrayIcon *icon = EGG_TRAY_ICON (widget); | |
| 381 | gint screen; | |
| 382 | Display *xdisplay; | |
| 3510 | 383 | char buffer[256]; |
| 384 | GdkWindow *root_window; | |
| 385 | ||
| 10779 | 386 | if (GTK_WIDGET_CLASS (parent_class)->realize) |
| 387 | GTK_WIDGET_CLASS (parent_class)->realize (widget); | |
| 3510 | 388 | |
| 10779 | 389 | #if GTK_CHECK_VERSION(2,1,0) |
| 390 | screen = gdk_screen_get_number (gtk_widget_get_screen (widget)); | |
| 391 | xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); | |
| 3510 | 392 | #else |
| 10779 | 393 | screen = XScreenNumberOfScreen (DefaultScreenOfDisplay (gdk_display)); |
| 394 | xdisplay = gdk_display; | |
| 3510 | 395 | #endif |
| 396 | ||
| 397 | /* Now see if there's a manager window around */ | |
| 398 | g_snprintf (buffer, sizeof (buffer), | |
| 399 | "_NET_SYSTEM_TRAY_S%d", | |
| 10779 | 400 | screen); |
| 401 | ||
| 402 | icon->selection_atom = XInternAtom (xdisplay, buffer, False); | |
| 3510 | 403 | |
| 10779 | 404 | icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False); |
| 3510 | 405 | |
| 10779 | 406 | icon->system_tray_opcode_atom = XInternAtom (xdisplay, |
| 407 | "_NET_SYSTEM_TRAY_OPCODE", | |
| 408 | False); | |
| 3510 | 409 | |
| 10779 | 410 | icon->orientation_atom = XInternAtom (xdisplay, |
| 411 | "_NET_SYSTEM_TRAY_ORIENTATION", | |
| 412 | False); | |
| 3510 | 413 | |
| 10779 | 414 | egg_tray_icon_update_manager_window (icon, FALSE); |
| 415 | egg_tray_icon_send_dock_request (icon); | |
| 416 | ||
| 417 | #if GTK_CHECK_VERSION(2,1,0) | |
| 418 | root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); | |
| 3510 | 419 | #else |
| 420 | root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); | |
| 421 | #endif | |
| 10779 | 422 | |
| 3510 | 423 | /* Add a root window filter so that we get changes on MANAGER */ |
| 424 | gdk_window_add_filter (root_window, | |
| 425 | egg_tray_icon_manager_filter, icon); | |
| 426 | } | |
| 427 | ||
| 10779 | 428 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 429 | EggTrayIcon * |
| 430 | egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) | |
| 431 | { | |
| 432 | g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); | |
| 433 | ||
| 10779 | 434 | return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL); |
| 3510 | 435 | } |
| 436 | #endif | |
| 437 | ||
| 438 | EggTrayIcon* | |
| 439 | egg_tray_icon_new (const gchar *name) | |
| 440 | { | |
| 10779 | 441 | return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL); |
| 3510 | 442 | } |
| 443 | ||
| 444 | guint | |
| 445 | egg_tray_icon_send_message (EggTrayIcon *icon, | |
| 446 | gint timeout, | |
| 447 | const gchar *message, | |
| 448 | gint len) | |
| 449 | { | |
| 450 | guint stamp; | |
| 451 | ||
| 452 | g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); | |
| 453 | g_return_val_if_fail (timeout >= 0, 0); | |
| 454 | g_return_val_if_fail (message != NULL, 0); | |
| 455 | ||
| 456 | if (icon->manager_window == None) | |
| 457 | return 0; | |
| 458 | ||
| 459 | if (len < 0) | |
| 460 | len = strlen (message); | |
| 461 | ||
| 462 | stamp = icon->stamp++; | |
| 463 | ||
| 464 | /* Get ready to send the message */ | |
| 465 | egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, | |
| 466 | (Window)gtk_plug_get_id (GTK_PLUG (icon)), | |
| 467 | timeout, len, stamp); | |
| 468 | ||
| 469 | /* Now to send the actual message */ | |
| 470 | gdk_error_trap_push (); | |
| 471 | while (len > 0) | |
| 472 | { | |
| 473 | XClientMessageEvent ev; | |
| 474 | Display *xdisplay; | |
| 475 | ||
| 10779 | 476 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 477 | xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); |
| 478 | #else | |
| 479 | xdisplay = gdk_display; | |
| 480 | #endif | |
| 10779 | 481 | |
| 3510 | 482 | ev.type = ClientMessage; |
| 483 | ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); | |
| 484 | ev.format = 8; | |
| 485 | ev.message_type = XInternAtom (xdisplay, | |
| 486 | "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); | |
| 487 | if (len > 20) | |
| 488 | { | |
| 489 | memcpy (&ev.data, message, 20); | |
| 490 | len -= 20; | |
| 491 | message += 20; | |
| 492 | } | |
| 493 | else | |
| 494 | { | |
| 495 | memcpy (&ev.data, message, len); | |
| 496 | len = 0; | |
| 497 | } | |
| 498 | ||
| 499 | XSendEvent (xdisplay, | |
| 500 | icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev); | |
| 501 | XSync (xdisplay, False); | |
| 502 | } | |
| 503 | gdk_error_trap_pop (); | |
| 504 | ||
| 505 | return stamp; | |
| 506 | } | |
| 507 | ||
| 508 | void | |
| 509 | egg_tray_icon_cancel_message (EggTrayIcon *icon, | |
| 510 | guint id) | |
| 511 | { | |
| 512 | g_return_if_fail (EGG_IS_TRAY_ICON (icon)); | |
| 513 | g_return_if_fail (id > 0); | |
| 514 | ||
| 515 | egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, | |
| 516 | (Window)gtk_plug_get_id (GTK_PLUG (icon)), | |
| 517 | id, 0, 0); | |
| 518 | } | |
| 10779 | 519 | |
| 520 | GtkOrientation | |
| 521 | egg_tray_icon_get_orientation (EggTrayIcon *icon) | |
| 522 | { | |
| 523 | g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL); | |
| 524 | ||
| 525 | return icon->orientation; | |
| 526 | } |