1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
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.
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.
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.
23
Permission to use this file under wxWindows license given by
26
From andersca@gnu.org Tue Dec 9 13:01:56 2003
27
Return-path: <andersca@gnu.org>
28
Envelope-to: vasek@localhost
29
Delivery-date: Tue, 09 Dec 2003 13:04:35 +0100
30
Received: from localhost
31
([127.0.0.1] helo=amavis ident=amavis)
32
by armitage with esmtp (Exim 3.35 #1)
34
for vasek@localhost; Tue, 09 Dec 2003 13:04:35 +0100
35
Received: from armitage ([127.0.0.1])
36
by amavis (armitage [127.0.0.1]) (amavisd-new, port 10024) with ESMTP
37
id 04227-09 for <vasek@localhost>;
38
Tue, 9 Dec 2003 13:04:11 +0100 (CET)
39
Received: from localhost ([127.0.0.1] ident=fetchmail)
40
by armitage with esmtp (Exim 3.35 #1)
42
for vasek@localhost; Tue, 09 Dec 2003 13:04:11 +0100
43
Delivered-To: alias-email-slavikvaclav@seznam.cz
44
Received: from pop3.seznam.cz [212.80.76.45]
45
by localhost with POP3 (fetchmail-5.9.11)
46
for vasek@localhost (single-drop); Tue, 09 Dec 2003 13:04:11 +0100 (CET)
47
Received: (qmail 9861 invoked from network); 9 Dec 2003 12:02:17 -0000
48
Received: from unknown (HELO maxipes.logix.cz) (81.0.234.97)
49
by buster.go.seznam.cz with SMTP; 9 Dec 2003 12:02:17 -0000
50
Received: by maxipes.logix.cz (Postfix, from userid 604)
51
id 37E6D29A51; Tue, 9 Dec 2003 13:02:16 +0100 (CET)
52
X-Original-To: vaclav.slavik@matfyz.cz
53
Received: from mail.csbnet.se (glutus.csbnet.se [193.11.248.2])
54
by maxipes.logix.cz (Postfix) with ESMTP id 90D6A29A51
55
for <vaclav.slavik@matfyz.cz>; Tue, 9 Dec 2003 13:02:15 +0100 (CET)
56
Received: by mail.csbnet.se (Postfix, from userid 8)
57
id 7AA7F10A6D7; Tue, 9 Dec 2003 13:02:14 +0100 (CET)
58
Received: from carbon.csbnet.se (carbon.csbnet.se [193.11.248.180])
59
by mail.csbnet.se (Postfix) with ESMTP id A190F10A71D
60
for <vaclav.slavik@matfyz.cz>; Tue, 9 Dec 2003 13:01:56 +0100 (CET)
61
Subject: Re: eggtrayicon.{c,h} licensing
62
From: Anders Carlsson <andersca@gnu.org>
63
To: Vaclav Slavik <vaclav.slavik@matfyz.cz>
64
In-Reply-To: <200312091142.54542.vaclav.slavik@matfyz.cz>
65
References: <200312091142.54542.vaclav.slavik@matfyz.cz>
66
Content-Type: text/plain
67
Message-Id: <1070971316.30989.0.camel@carbon.csbnet.se>
69
X-Mailer: Ximian Evolution 1.5
70
Date: Tue, 09 Dec 2003 13:01:56 +0100
71
Content-Transfer-Encoding: 7bit
72
X-Scanned-By: CLAM (openantivirus DB) antivirus scanner at mail.csbnet.se
73
X-Virus-Scanned: by amavisd-new-20030616-p5 (Debian) at armitage
74
X-Spam-Status: No, hits=-4.9 tagged_above=-999.0 required=6.3 tests=BAYES_00
78
X-KMail-EncryptionState:
79
X-KMail-SignatureState:
81
On tis, 2003-12-09 at 11:42 +0100, Vaclav Slavik wrote:
84
> I'm working on the wxWindows cross-platform GUI toolkit
85
> (http://www.wxwindows.org) which uses GTK+ and it would save me a lot
86
> of time if I could use your eggtrayicon code to implement tray icons
87
> on X11. Unfortunately I can't use it right now because it is not part
88
> of any library we could depend on (as we do depend on GTK+) and would
89
> have to be included in our sources and it is under the LGPL license.
90
> The problem is that wxWindows' license is more permissive (see
91
> http://www.opensource.org/licenses/wxwindows.php for details) and so
92
> I can't take your code and put it under wxWindows License. And I
93
> can't put code that can't be used under the terms of wxWindows
94
> License into wxWindows either. Do you think it would be possible to
95
> get permission to include eggtrayicon under wxWindows license?
101
Sure, that's fine by me.
107
#include "wx/platform.h"
109
#include <gdk/gdkx.h>
112
#include <gtk/gtkversion.h>
113
#if GTK_CHECK_VERSION(2, 1, 0)
116
#include "eggtrayicon.h"
118
#define SYSTEM_TRAY_REQUEST_DOCK 0
119
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
120
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
122
static GtkPlugClass *parent_class = NULL;
124
static void egg_tray_icon_init (EggTrayIcon *icon);
125
static void egg_tray_icon_class_init (EggTrayIconClass *klass);
127
static void egg_tray_icon_unrealize (GtkWidget *widget);
129
static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
132
egg_tray_icon_get_type (void)
134
static GType our_type = 0;
138
static const GTypeInfo our_info =
140
sizeof (EggTrayIconClass),
141
(GBaseInitFunc) NULL,
142
(GBaseFinalizeFunc) NULL,
143
(GClassInitFunc) egg_tray_icon_class_init,
144
NULL, /* class_finalize */
145
NULL, /* class_data */
146
sizeof (EggTrayIcon),
148
(GInstanceInitFunc) egg_tray_icon_init
151
our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
158
egg_tray_icon_init (EggTrayIcon *icon)
162
gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
166
egg_tray_icon_class_init (EggTrayIconClass *klass)
168
GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
170
parent_class = g_type_class_peek_parent (klass);
172
widget_class->unrealize = egg_tray_icon_unrealize;
175
static GdkFilterReturn
176
egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
178
EggTrayIcon *icon = user_data;
179
XEvent *xev = (XEvent *)xevent;
181
if (xev->xany.type == ClientMessage &&
182
xev->xclient.message_type == icon->manager_atom &&
183
xev->xclient.data.l[1] == icon->selection_atom)
185
egg_tray_icon_update_manager_window (icon);
187
else if (xev->xany.window == icon->manager_window)
189
if (xev->xany.type == DestroyNotify)
191
egg_tray_icon_update_manager_window (icon);
195
return GDK_FILTER_CONTINUE;
199
egg_tray_icon_unrealize (GtkWidget *widget)
201
EggTrayIcon *icon = EGG_TRAY_ICON (widget);
202
GdkWindow *root_window;
204
if (icon->manager_window != None)
208
gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
209
icon->manager_window);
211
gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
214
root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
216
gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
218
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
219
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
223
egg_tray_icon_send_manager_message (EggTrayIcon *icon,
230
XClientMessageEvent ev;
233
ev.type = ClientMessage;
235
ev.message_type = icon->system_tray_opcode_atom;
237
ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
238
ev.data.l[1] = message;
239
ev.data.l[2] = data1;
240
ev.data.l[3] = data2;
241
ev.data.l[4] = data3;
243
display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
245
gdk_error_trap_push ();
247
icon->manager_window, False, NoEventMask, (XEvent *)&ev);
248
XSync (display, False);
249
gdk_error_trap_pop ();
253
egg_tray_icon_send_dock_request (EggTrayIcon *icon)
255
egg_tray_icon_send_manager_message (icon,
256
SYSTEM_TRAY_REQUEST_DOCK,
257
icon->manager_window,
258
gtk_plug_get_id (GTK_PLUG (icon)),
263
egg_tray_icon_update_manager_window (EggTrayIcon *icon)
267
xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
269
if (icon->manager_window != None)
273
gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
274
icon->manager_window);
276
gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
279
XGrabServer (xdisplay);
281
icon->manager_window = XGetSelectionOwner (xdisplay,
282
icon->selection_atom);
284
if (icon->manager_window != None)
285
XSelectInput (xdisplay,
286
icon->manager_window, StructureNotifyMask);
288
XUngrabServer (xdisplay);
291
if (icon->manager_window != None)
295
gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
296
icon->manager_window);
298
gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
300
/* Send a request that we'd like to dock */
301
egg_tray_icon_send_dock_request (icon);
306
egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
310
GdkWindow *root_window;
314
g_return_val_if_fail (xscreen != NULL, NULL);
316
icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL);
317
gtk_window_set_title (GTK_WINDOW (icon), name);
319
display = gdk_x11_lookup_xdisplay (DisplayOfScreen (xscreen));
320
screen = gdk_display_get_screen (display, XScreenNumberOfScreen (xscreen));
322
gtk_plug_construct_for_display (GTK_PLUG (icon),
325
gtk_window_set_screen (GTK_WINDOW (icon), screen);
327
gtk_widget_realize (GTK_WIDGET (icon));
329
/* Now see if there's a manager window around */
330
g_snprintf (buffer, sizeof (buffer),
331
"_NET_SYSTEM_TRAY_S%d",
332
XScreenNumberOfScreen (xscreen));
334
icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen),
337
icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen),
340
icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen),
341
"_NET_SYSTEM_TRAY_OPCODE", False);
343
egg_tray_icon_update_manager_window (icon);
345
root_window = gdk_screen_get_root_window (gtk_widget_get_screen (GTK_WIDGET (icon)));
347
/* Add a root window filter so that we get changes on MANAGER */
348
gdk_window_add_filter (root_window,
349
egg_tray_icon_manager_filter, icon);
355
egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
357
g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
359
return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name);
363
egg_tray_icon_new (const gchar *name)
365
return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name);
369
egg_tray_icon_send_message (EggTrayIcon *icon,
371
const gchar *message,
376
g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
377
g_return_val_if_fail (timeout >= 0, 0);
378
g_return_val_if_fail (message != NULL, 0);
380
if (icon->manager_window == None)
384
len = strlen (message);
386
stamp = icon->stamp++;
388
/* Get ready to send the message */
389
egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
390
(Window)gtk_plug_get_id (GTK_PLUG (icon)),
391
timeout, len, stamp);
393
/* Now to send the actual message */
394
gdk_error_trap_push ();
397
XClientMessageEvent ev;
400
xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
402
ev.type = ClientMessage;
403
ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
405
ev.message_type = XInternAtom (xdisplay,
406
"_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
409
memcpy (&ev.data, message, 20);
415
memcpy (&ev.data, message, len);
419
XSendEvent (xdisplay,
420
icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
421
XSync (xdisplay, False);
423
gdk_error_trap_pop ();
429
egg_tray_icon_cancel_message (EggTrayIcon *icon,
432
g_return_if_fail (EGG_IS_TRAY_ICON (icon));
433
g_return_if_fail (id > 0);
435
egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
436
(Window)gtk_plug_get_id (GTK_PLUG (icon)),
440
#endif /* __WXGTK20__ */
441
#endif /* GTK_CHECK_VERSION(2, 1, 0) */