Sun, 09 Nov 2008 20:55:10 +0000
Added menu items to buddy list context menu to start voice and video sessions
After discussing the matter with Maiku, we decided to have two choises.
"Audio call" which will show up if audio sessions is possible with a buddy and
the other item is either "Audio/Video" or "Video" depending on if the buddy
supports both at the same time or not
| 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 | |
|
19859
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
18709
diff
changeset
|
17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
18709
diff
changeset
|
18 | * Boston, MA 02111-1301, USA. |
| 3510 | 19 | */ |
| 20 | ||
| 10779 | 21 | #include <config.h> |
| 3510 | 22 | #include <string.h> |
| 10779 | 23 | |
| 24 | #include "eggtrayicon.h" | |
| 25 | ||
| 26 | #include <X11/Xatom.h> | |
| 27 | ||
| 28 | #define _(x) x | |
| 29 | #define N_(x) x | |
| 3510 | 30 | |
| 31 | #define SYSTEM_TRAY_REQUEST_DOCK 0 | |
| 32 | #define SYSTEM_TRAY_BEGIN_MESSAGE 1 | |
| 33 | #define SYSTEM_TRAY_CANCEL_MESSAGE 2 | |
| 10779 | 34 | |
| 35 | #define SYSTEM_TRAY_ORIENTATION_HORZ 0 | |
| 36 | #define SYSTEM_TRAY_ORIENTATION_VERT 1 | |
| 37 | ||
| 38 | enum { | |
| 39 | PROP_0, | |
| 40 | PROP_ORIENTATION | |
| 41 | }; | |
| 3510 | 42 | |
| 43 | static GtkPlugClass *parent_class = NULL; | |
| 44 | ||
| 45 | static void egg_tray_icon_init (EggTrayIcon *icon); | |
| 46 | static void egg_tray_icon_class_init (EggTrayIconClass *klass); | |
| 47 | ||
| 10779 | 48 | static void egg_tray_icon_get_property (GObject *object, |
| 49 | guint prop_id, | |
| 50 | GValue *value, | |
| 51 | GParamSpec *pspec); | |
| 52 | ||
| 53 | static void egg_tray_icon_realize (GtkWidget *widget); | |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
54 | static void egg_tray_icon_unrealize (GtkWidget *widget); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
55 | |
| 14231 | 56 | static void egg_tray_icon_add (GtkContainer *container, |
| 57 | GtkWidget *widget); | |
| 58 | ||
| 10779 | 59 | static void egg_tray_icon_update_manager_window (EggTrayIcon *icon, |
| 60 | gboolean dock_if_realized); | |
| 61 | static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon); | |
| 3510 | 62 | |
| 63 | GType | |
| 64 | egg_tray_icon_get_type (void) | |
| 65 | { | |
| 66 | static GType our_type = 0; | |
| 67 | ||
| 68 | if (our_type == 0) | |
| 69 | { | |
| 10779 | 70 | our_type = g_type_from_name("EggTrayIcon"); |
| 71 | ||
| 72 | if (our_type == 0) | |
| 73 | { | |
| 3510 | 74 | static const GTypeInfo our_info = |
| 75 | { | |
| 76 | sizeof (EggTrayIconClass), | |
| 77 | (GBaseInitFunc) NULL, | |
| 78 | (GBaseFinalizeFunc) NULL, | |
| 79 | (GClassInitFunc) egg_tray_icon_class_init, | |
| 80 | NULL, /* class_finalize */ | |
| 81 | NULL, /* class_data */ | |
| 82 | sizeof (EggTrayIcon), | |
| 83 | 0, /* n_preallocs */ | |
|
12600
7ecd4441fdc7
[gaim-migrate @ 14934]
Richard Laager <rlaager@pidgin.im>
parents:
11291
diff
changeset
|
84 | (GInstanceInitFunc) egg_tray_icon_init, |
|
7ecd4441fdc7
[gaim-migrate @ 14934]
Richard Laager <rlaager@pidgin.im>
parents:
11291
diff
changeset
|
85 | NULL /* value_table */ |
| 3510 | 86 | }; |
| 87 | ||
| 88 | our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0); | |
| 10779 | 89 | } |
| 90 | else if (parent_class == NULL) | |
| 91 | { | |
| 92 | /* we're reheating the old class from a previous instance - engage ugly hack =( */ | |
| 93 | egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type)); | |
| 94 | } | |
| 3510 | 95 | } |
| 96 | ||
| 97 | return our_type; | |
| 98 | } | |
| 99 | ||
| 100 | static void | |
| 101 | egg_tray_icon_init (EggTrayIcon *icon) | |
| 102 | { | |
| 103 | icon->stamp = 1; | |
| 10779 | 104 | icon->orientation = GTK_ORIENTATION_HORIZONTAL; |
| 3510 | 105 | |
| 106 | gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); | |
| 107 | } | |
| 108 | ||
| 109 | static void | |
| 110 | egg_tray_icon_class_init (EggTrayIconClass *klass) | |
| 111 | { | |
| 10779 | 112 | GObjectClass *gobject_class = (GObjectClass *)klass; |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
113 | GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; |
| 14231 | 114 | GtkContainerClass *container_class = (GtkContainerClass *)klass; |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
115 | |
| 3510 | 116 | parent_class = g_type_class_peek_parent (klass); |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
117 | |
| 10779 | 118 | gobject_class->get_property = egg_tray_icon_get_property; |
| 119 | ||
| 120 | widget_class->realize = egg_tray_icon_realize; | |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
121 | widget_class->unrealize = egg_tray_icon_unrealize; |
| 10779 | 122 | |
| 14231 | 123 | container_class->add = egg_tray_icon_add; |
| 124 | ||
| 10779 | 125 | g_object_class_install_property (gobject_class, |
| 126 | PROP_ORIENTATION, | |
| 127 | g_param_spec_enum ("orientation", | |
| 128 | _("Orientation"), | |
| 129 | _("The orientation of the tray."), | |
| 130 | GTK_TYPE_ORIENTATION, | |
| 131 | GTK_ORIENTATION_HORIZONTAL, | |
| 132 | G_PARAM_READABLE)); | |
| 133 | } | |
| 134 | ||
| 135 | static void | |
| 136 | egg_tray_icon_get_property (GObject *object, | |
| 137 | guint prop_id, | |
| 138 | GValue *value, | |
| 139 | GParamSpec *pspec) | |
| 140 | { | |
| 141 | EggTrayIcon *icon = EGG_TRAY_ICON (object); | |
| 142 | ||
| 143 | switch (prop_id) | |
| 144 | { | |
| 145 | case PROP_ORIENTATION: | |
| 146 | g_value_set_enum (value, icon->orientation); | |
| 147 | break; | |
| 148 | default: | |
| 149 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
| 150 | break; | |
| 151 | } | |
| 152 | } | |
| 153 | ||
|
18346
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
154 | static Display * |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
155 | egg_tray_icon_get_x_display(EggTrayIcon *icon) |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
156 | { |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
157 | Display *xdisplay = NULL; |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
158 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
159 | #if GTK_CHECK_VERSION(2,1,0) |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
160 | { |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
161 | GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (icon)); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
162 | if (!GDK_IS_DISPLAY (display)) |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
163 | display = gdk_display_get_default (); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
164 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
165 | xdisplay = GDK_DISPLAY_XDISPLAY (display); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
166 | } |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
167 | #else |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
168 | xdisplay = gdk_display; |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
169 | #endif |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
170 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
171 | return xdisplay; |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
172 | } |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
173 | |
| 10779 | 174 | static void |
| 175 | egg_tray_icon_get_orientation_property (EggTrayIcon *icon) | |
| 176 | { | |
| 177 | Display *xdisplay; | |
| 178 | Atom type; | |
| 179 | int format; | |
| 180 | union { | |
| 181 | gulong *prop; | |
| 182 | guchar *prop_ch; | |
| 183 | } prop = { NULL }; | |
| 184 | gulong nitems; | |
| 185 | gulong bytes_after; | |
| 186 | int error, result; | |
| 187 | ||
|
11291
5441d2419942
[gaim-migrate @ 13491]
Mark Doliner <markdoliner@pidgin.im>
parents:
10779
diff
changeset
|
188 | g_return_if_fail(icon->manager_window != None); |
| 10779 | 189 | |
|
18346
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
190 | xdisplay = egg_tray_icon_get_x_display(icon); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
191 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
192 | if (xdisplay == NULL) |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
193 | return; |
| 10779 | 194 | |
| 195 | gdk_error_trap_push (); | |
| 196 | type = None; | |
| 197 | result = XGetWindowProperty (xdisplay, | |
| 198 | icon->manager_window, | |
| 199 | icon->orientation_atom, | |
| 200 | 0, G_MAXLONG, FALSE, | |
| 201 | XA_CARDINAL, | |
| 202 | &type, &format, &nitems, | |
| 203 | &bytes_after, &(prop.prop_ch)); | |
| 204 | error = gdk_error_trap_pop (); | |
| 205 | ||
| 206 | if (error || result != Success) | |
| 207 | return; | |
| 208 | ||
| 209 | if (type == XA_CARDINAL) | |
| 210 | { | |
| 211 | GtkOrientation orientation; | |
| 212 | ||
| 213 | orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ? | |
| 214 | GTK_ORIENTATION_HORIZONTAL : | |
| 215 | GTK_ORIENTATION_VERTICAL; | |
| 216 | ||
| 217 | if (icon->orientation != orientation) | |
| 218 | { | |
| 219 | icon->orientation = orientation; | |
| 220 | ||
| 221 | g_object_notify (G_OBJECT (icon), "orientation"); | |
| 222 | } | |
| 223 | } | |
| 224 | ||
| 225 | if (prop.prop) | |
| 226 | XFree (prop.prop); | |
| 3510 | 227 | } |
| 228 | ||
| 229 | static GdkFilterReturn | |
| 230 | egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data) | |
| 231 | { | |
| 232 | EggTrayIcon *icon = user_data; | |
| 233 | XEvent *xev = (XEvent *)xevent; | |
| 234 | ||
| 235 | if (xev->xany.type == ClientMessage && | |
| 236 | xev->xclient.message_type == icon->manager_atom && | |
| 237 | xev->xclient.data.l[1] == icon->selection_atom) | |
| 238 | { | |
| 10779 | 239 | egg_tray_icon_update_manager_window (icon, TRUE); |
| 3510 | 240 | } |
| 241 | else if (xev->xany.window == icon->manager_window) | |
| 242 | { | |
| 10779 | 243 | if (xev->xany.type == PropertyNotify && |
| 244 | xev->xproperty.atom == icon->orientation_atom) | |
| 245 | { | |
| 246 | egg_tray_icon_get_orientation_property (icon); | |
| 247 | } | |
| 3510 | 248 | if (xev->xany.type == DestroyNotify) |
| 249 | { | |
| 10779 | 250 | egg_tray_icon_manager_window_destroyed (icon); |
| 3510 | 251 | } |
| 252 | } | |
| 253 | ||
| 254 | return GDK_FILTER_CONTINUE; | |
| 255 | } | |
| 256 | ||
| 257 | static void | |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
258 | egg_tray_icon_unrealize (GtkWidget *widget) |
|
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 | EggTrayIcon *icon = EGG_TRAY_ICON (widget); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
261 | GdkWindow *root_window; |
|
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 | if (icon->manager_window != None) |
|
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 | GdkWindow *gdkwin; |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
266 | |
| 10779 | 267 | #if GTK_CHECK_VERSION(2,1,0) |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
268 | gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget), |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
269 | icon->manager_window); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
270 | #else |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
271 | gdkwin = gdk_window_lookup (icon->manager_window); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
272 | #endif |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
273 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
274 | gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
275 | } |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
276 | |
| 10779 | 277 | #if GTK_CHECK_VERSION(2,1,0) |
|
4261
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
278 | 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
|
279 | #else |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
280 | root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
281 | #endif |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
282 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
283 | 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
|
284 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
285 | if (GTK_WIDGET_CLASS (parent_class)->unrealize) |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
286 | (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
287 | } |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
288 | |
|
cc35d7c0582f
<Robot101> commit message:
Robert McQueen <robot101@debian.org>
parents:
3510
diff
changeset
|
289 | static void |
| 3510 | 290 | egg_tray_icon_send_manager_message (EggTrayIcon *icon, |
| 291 | long message, | |
| 292 | Window window, | |
| 293 | long data1, | |
| 294 | long data2, | |
| 295 | long data3) | |
| 296 | { | |
| 297 | XClientMessageEvent ev; | |
| 298 | Display *display; | |
| 299 | ||
| 300 | ev.type = ClientMessage; | |
| 301 | ev.window = window; | |
| 302 | ev.message_type = icon->system_tray_opcode_atom; | |
| 303 | ev.format = 32; | |
| 304 | ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window); | |
| 305 | ev.data.l[1] = message; | |
| 306 | ev.data.l[2] = data1; | |
| 307 | ev.data.l[3] = data2; | |
| 308 | ev.data.l[4] = data3; | |
| 309 | ||
| 10779 | 310 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 311 | display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); |
| 312 | #else | |
| 313 | display = gdk_display; | |
| 314 | #endif | |
| 10779 | 315 | |
| 3510 | 316 | gdk_error_trap_push (); |
| 317 | XSendEvent (display, | |
| 318 | icon->manager_window, False, NoEventMask, (XEvent *)&ev); | |
| 319 | XSync (display, False); | |
| 320 | gdk_error_trap_pop (); | |
| 321 | } | |
| 322 | ||
| 323 | static void | |
| 324 | egg_tray_icon_send_dock_request (EggTrayIcon *icon) | |
| 325 | { | |
| 326 | egg_tray_icon_send_manager_message (icon, | |
| 327 | SYSTEM_TRAY_REQUEST_DOCK, | |
| 328 | icon->manager_window, | |
| 329 | gtk_plug_get_id (GTK_PLUG (icon)), | |
| 330 | 0, 0); | |
| 331 | } | |
| 332 | ||
| 333 | static void | |
| 10779 | 334 | egg_tray_icon_update_manager_window (EggTrayIcon *icon, |
| 335 | gboolean dock_if_realized) | |
| 3510 | 336 | { |
| 337 | Display *xdisplay; | |
| 338 | ||
| 10779 | 339 | if (icon->manager_window != None) |
| 340 | return; | |
| 341 | ||
|
18346
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
342 | xdisplay = egg_tray_icon_get_x_display(icon); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
343 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
344 | if (xdisplay == NULL) |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
345 | return; |
| 3510 | 346 | |
| 347 | XGrabServer (xdisplay); | |
| 348 | ||
| 349 | icon->manager_window = XGetSelectionOwner (xdisplay, | |
| 350 | icon->selection_atom); | |
| 351 | ||
| 352 | if (icon->manager_window != None) | |
| 353 | XSelectInput (xdisplay, | |
| 10779 | 354 | icon->manager_window, StructureNotifyMask|PropertyChangeMask); |
| 3510 | 355 | |
| 356 | XUngrabServer (xdisplay); | |
| 357 | XFlush (xdisplay); | |
| 358 | ||
| 359 | if (icon->manager_window != None) | |
| 360 | { | |
| 361 | GdkWindow *gdkwin; | |
| 362 | ||
| 10779 | 363 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 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 | |
| 10779 | 369 | |
| 3510 | 370 | gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); |
| 371 | ||
| 10779 | 372 | if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) |
| 373 | egg_tray_icon_send_dock_request (icon); | |
| 374 | ||
| 375 | egg_tray_icon_get_orientation_property (icon); | |
| 3510 | 376 | } |
| 377 | } | |
| 378 | ||
| 10779 | 379 | static void |
| 380 | egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon) | |
| 3510 | 381 | { |
| 10779 | 382 | GdkWindow *gdkwin; |
| 383 | ||
| 384 | g_return_if_fail (icon->manager_window != None); | |
| 385 | ||
| 386 | #if GTK_CHECK_VERSION(2,1,0) | |
| 387 | gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), | |
| 388 | icon->manager_window); | |
| 389 | #else | |
| 390 | gdkwin = gdk_window_lookup (icon->manager_window); | |
| 391 | #endif | |
| 392 | ||
| 393 | gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); | |
| 394 | ||
| 395 | icon->manager_window = None; | |
| 396 | ||
| 397 | egg_tray_icon_update_manager_window (icon, TRUE); | |
| 398 | } | |
| 399 | ||
| 14231 | 400 | static gboolean |
| 401 | transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) | |
| 402 | { | |
| 403 | gdk_window_clear_area (widget->window, event->area.x, event->area.y, | |
| 404 | event->area.width, event->area.height); | |
| 405 | return FALSE; | |
| 406 | } | |
| 407 | ||
| 408 | static void | |
| 409 | make_transparent_again (GtkWidget *widget, GtkStyle *previous_style, | |
| 410 | gpointer user_data) | |
| 411 | { | |
| 412 | gdk_window_set_back_pixmap(widget->window, NULL, TRUE); | |
| 413 | } | |
| 414 | ||
| 415 | static void | |
| 416 | make_transparent (GtkWidget *widget, gpointer user_data) | |
| 417 | { | |
| 418 | if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget)) | |
| 419 | return; | |
| 420 | ||
| 421 | gtk_widget_set_app_paintable (widget, TRUE); | |
| 422 | gtk_widget_set_double_buffered (widget, FALSE); | |
| 423 | gdk_window_set_back_pixmap (widget->window, NULL, TRUE); | |
| 424 | g_signal_connect (widget, "expose_event", | |
| 425 | G_CALLBACK (transparent_expose_event), NULL); | |
| 426 | g_signal_connect_after (widget, "style_set", | |
| 427 | G_CALLBACK (make_transparent_again), NULL); | |
| 428 | } | |
| 429 | ||
| 10779 | 430 | static void |
| 431 | egg_tray_icon_realize (GtkWidget *widget) | |
| 432 | { | |
| 433 | EggTrayIcon *icon = EGG_TRAY_ICON (widget); | |
| 434 | gint screen; | |
| 435 | Display *xdisplay; | |
| 3510 | 436 | char buffer[256]; |
| 437 | GdkWindow *root_window; | |
| 438 | ||
| 10779 | 439 | if (GTK_WIDGET_CLASS (parent_class)->realize) |
| 440 | GTK_WIDGET_CLASS (parent_class)->realize (widget); | |
| 3510 | 441 | |
| 14231 | 442 | make_transparent (widget, NULL); |
| 443 | ||
|
18346
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
444 | xdisplay = egg_tray_icon_get_x_display(icon); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
445 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
446 | if (xdisplay == NULL) |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
447 | return; |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
448 | |
| 10779 | 449 | #if GTK_CHECK_VERSION(2,1,0) |
| 450 | screen = gdk_screen_get_number (gtk_widget_get_screen (widget)); | |
| 3510 | 451 | #else |
| 10779 | 452 | screen = XScreenNumberOfScreen (DefaultScreenOfDisplay (gdk_display)); |
| 3510 | 453 | #endif |
| 454 | ||
| 455 | /* Now see if there's a manager window around */ | |
| 456 | g_snprintf (buffer, sizeof (buffer), | |
| 457 | "_NET_SYSTEM_TRAY_S%d", | |
| 10779 | 458 | screen); |
| 459 | ||
| 460 | icon->selection_atom = XInternAtom (xdisplay, buffer, False); | |
| 3510 | 461 | |
| 10779 | 462 | icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False); |
| 3510 | 463 | |
| 10779 | 464 | icon->system_tray_opcode_atom = XInternAtom (xdisplay, |
| 465 | "_NET_SYSTEM_TRAY_OPCODE", | |
| 466 | False); | |
| 3510 | 467 | |
| 10779 | 468 | icon->orientation_atom = XInternAtom (xdisplay, |
| 469 | "_NET_SYSTEM_TRAY_ORIENTATION", | |
| 470 | False); | |
| 3510 | 471 | |
| 10779 | 472 | egg_tray_icon_update_manager_window (icon, FALSE); |
| 473 | egg_tray_icon_send_dock_request (icon); | |
| 474 | ||
| 475 | #if GTK_CHECK_VERSION(2,1,0) | |
| 476 | root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); | |
| 3510 | 477 | #else |
| 478 | root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); | |
| 479 | #endif | |
| 10779 | 480 | |
| 3510 | 481 | /* Add a root window filter so that we get changes on MANAGER */ |
| 482 | gdk_window_add_filter (root_window, | |
| 483 | egg_tray_icon_manager_filter, icon); | |
| 484 | } | |
| 485 | ||
| 14231 | 486 | static void |
| 487 | egg_tray_icon_add (GtkContainer *container, GtkWidget *widget) | |
| 488 | { | |
| 489 | g_signal_connect (widget, "realize", | |
| 490 | G_CALLBACK (make_transparent), NULL); | |
| 491 | GTK_CONTAINER_CLASS (parent_class)->add (container, widget); | |
| 492 | } | |
| 493 | ||
| 10779 | 494 | #if GTK_CHECK_VERSION(2,1,0) |
| 3510 | 495 | EggTrayIcon * |
| 496 | egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) | |
| 497 | { | |
| 498 | g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); | |
| 499 | ||
| 10779 | 500 | return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL); |
| 3510 | 501 | } |
| 502 | #endif | |
| 503 | ||
| 504 | EggTrayIcon* | |
| 505 | egg_tray_icon_new (const gchar *name) | |
| 506 | { | |
| 10779 | 507 | return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL); |
| 3510 | 508 | } |
| 509 | ||
| 510 | guint | |
| 511 | egg_tray_icon_send_message (EggTrayIcon *icon, | |
| 512 | gint timeout, | |
| 513 | const gchar *message, | |
| 514 | gint len) | |
| 515 | { | |
| 516 | guint stamp; | |
| 517 | ||
| 518 | g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); | |
| 519 | g_return_val_if_fail (timeout >= 0, 0); | |
| 520 | g_return_val_if_fail (message != NULL, 0); | |
| 521 | ||
| 522 | if (icon->manager_window == None) | |
| 523 | return 0; | |
| 524 | ||
| 525 | if (len < 0) | |
| 526 | len = strlen (message); | |
| 527 | ||
| 528 | stamp = icon->stamp++; | |
| 529 | ||
| 530 | /* Get ready to send the message */ | |
| 531 | egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, | |
| 532 | (Window)gtk_plug_get_id (GTK_PLUG (icon)), | |
| 533 | timeout, len, stamp); | |
| 534 | ||
| 535 | /* Now to send the actual message */ | |
| 536 | gdk_error_trap_push (); | |
| 537 | while (len > 0) | |
| 538 | { | |
| 539 | XClientMessageEvent ev; | |
| 540 | Display *xdisplay; | |
| 541 | ||
|
18346
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
542 | xdisplay = egg_tray_icon_get_x_display(icon); |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
543 | |
|
8a6dfdd516d4
Guard against passing NULL to GDK_DISPLAY_XDISPLAY. This resolves a crash
Casey Harkins <charkins@pidgin.im>
parents:
15435
diff
changeset
|
544 | if (xdisplay == NULL) |
|
18709
e93e7776283e
Return 0 to silence the following warning
Mark Doliner <markdoliner@pidgin.im>
parents:
18346
diff
changeset
|
545 | return 0; |
| 10779 | 546 | |
| 3510 | 547 | ev.type = ClientMessage; |
| 548 | ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); | |
| 549 | ev.format = 8; | |
| 550 | ev.message_type = XInternAtom (xdisplay, | |
| 551 | "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); | |
| 552 | if (len > 20) | |
| 553 | { | |
| 554 | memcpy (&ev.data, message, 20); | |
| 555 | len -= 20; | |
| 556 | message += 20; | |
| 557 | } | |
| 558 | else | |
| 559 | { | |
| 560 | memcpy (&ev.data, message, len); | |
| 561 | len = 0; | |
| 562 | } | |
| 563 | ||
| 564 | XSendEvent (xdisplay, | |
| 565 | icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev); | |
| 566 | XSync (xdisplay, False); | |
| 567 | } | |
| 568 | gdk_error_trap_pop (); | |
| 569 | ||
| 570 | return stamp; | |
| 571 | } | |
| 572 | ||
| 573 | void | |
| 574 | egg_tray_icon_cancel_message (EggTrayIcon *icon, | |
| 575 | guint id) | |
| 576 | { | |
| 577 | g_return_if_fail (EGG_IS_TRAY_ICON (icon)); | |
| 578 | g_return_if_fail (id > 0); | |
| 579 | ||
| 580 | egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, | |
| 581 | (Window)gtk_plug_get_id (GTK_PLUG (icon)), | |
| 582 | id, 0, 0); | |
| 583 | } | |
| 10779 | 584 | |
| 585 | GtkOrientation | |
| 586 | egg_tray_icon_get_orientation (EggTrayIcon *icon) | |
| 587 | { | |
| 588 | g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL); | |
| 589 | ||
| 590 | return icon->orientation; | |
| 591 | } |