~blackskad/gnomeradio/dev-vol-button

« back to all changes in this revision

Viewing changes to src/eggtrayicon.c

  • Committer: mfcn
  • Date: 2008-09-13 14:54:30 UTC
  • Revision ID: svn-v3-trunk0:ba97a3d1-ec25-0410-b1c6-e06ad936ea6c:trunk:205
        * src/Makefile.am:
        * src/eggtrayicon.c:
        * src/eggtrayicon.h:
        * src/gui.c (adj_value_changed_cb):
        * src/trayicon.c (tray_activate_cb), (tray_popup_menu),
        (create_tray_icon):
        * src/trayicon.h:
        Apply patch by Daniel Garcia to use GtkStatusIcon instead of egg-tray-icon (#417240)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
21
 
#include <string.h>
22
 
#include <gdk/gdkx.h>
23
 
#include "eggtrayicon.h"
24
 
 
25
 
#define SYSTEM_TRAY_REQUEST_DOCK    0
26
 
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
27
 
#define SYSTEM_TRAY_CANCEL_MESSAGE  2
28
 
         
29
 
static GtkPlugClass *parent_class = NULL;
30
 
 
31
 
static void egg_tray_icon_init (EggTrayIcon *icon);
32
 
static void egg_tray_icon_class_init (EggTrayIconClass *klass);
33
 
 
34
 
static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
35
 
 
36
 
GType
37
 
egg_tray_icon_get_type (void)
38
 
{
39
 
  static GType our_type = 0;
40
 
 
41
 
  if (our_type == 0)
42
 
    {
43
 
      static const GTypeInfo our_info =
44
 
      {
45
 
        sizeof (EggTrayIconClass),
46
 
        (GBaseInitFunc) NULL,
47
 
        (GBaseFinalizeFunc) NULL,
48
 
        (GClassInitFunc) egg_tray_icon_class_init,
49
 
        NULL, /* class_finalize */
50
 
        NULL, /* class_data */
51
 
        sizeof (EggTrayIcon),
52
 
        0,    /* n_preallocs */
53
 
        (GInstanceInitFunc) egg_tray_icon_init
54
 
      };
55
 
 
56
 
      our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
57
 
    }
58
 
 
59
 
  return our_type;
60
 
}
61
 
 
62
 
static void
63
 
egg_tray_icon_init (EggTrayIcon *icon)
64
 
{
65
 
  icon->stamp = 1;
66
 
  
67
 
  gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
68
 
}
69
 
 
70
 
static void
71
 
egg_tray_icon_class_init (EggTrayIconClass *klass)
72
 
{
73
 
  parent_class = g_type_class_peek_parent (klass);
74
 
}
75
 
 
76
 
static GdkFilterReturn
77
 
egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
78
 
{
79
 
  EggTrayIcon *icon = user_data;
80
 
  XEvent *xev = (XEvent *)xevent;
81
 
 
82
 
  if (xev->xany.type == ClientMessage &&
83
 
      xev->xclient.message_type == icon->manager_atom &&
84
 
      xev->xclient.data.l[1] == icon->selection_atom)
85
 
    {
86
 
      egg_tray_icon_update_manager_window (icon);
87
 
    }
88
 
  else if (xev->xany.window == icon->manager_window)
89
 
    {
90
 
      if (xev->xany.type == DestroyNotify)
91
 
        {
92
 
          egg_tray_icon_update_manager_window (icon);
93
 
        }
94
 
    }
95
 
  
96
 
  return GDK_FILTER_CONTINUE;
97
 
}
98
 
 
99
 
static void
100
 
egg_tray_icon_send_manager_message (EggTrayIcon *icon,
101
 
                                    long         message,
102
 
                                    Window       window,
103
 
                                    long         data1,
104
 
                                    long         data2,
105
 
                                    long         data3)
106
 
{
107
 
  XClientMessageEvent ev;
108
 
  Display *display;
109
 
  
110
 
  ev.type = ClientMessage;
111
 
  ev.window = window;
112
 
  ev.message_type = icon->system_tray_opcode_atom;
113
 
  ev.format = 32;
114
 
  ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
115
 
  ev.data.l[1] = message;
116
 
  ev.data.l[2] = data1;
117
 
  ev.data.l[3] = data2;
118
 
  ev.data.l[4] = data3;
119
 
 
120
 
#if HAVE_GTK_MULTIHEAD
121
 
  display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
122
 
#else
123
 
  display = gdk_display;
124
 
#endif
125
 
  
126
 
  gdk_error_trap_push ();
127
 
  XSendEvent (display,
128
 
              icon->manager_window, False, NoEventMask, (XEvent *)&ev);
129
 
  XSync (display, False);
130
 
  gdk_error_trap_pop ();
131
 
}
132
 
 
133
 
static void
134
 
egg_tray_icon_send_dock_request (EggTrayIcon *icon)
135
 
{
136
 
  egg_tray_icon_send_manager_message (icon,
137
 
                                      SYSTEM_TRAY_REQUEST_DOCK,
138
 
                                      icon->manager_window,
139
 
                                      gtk_plug_get_id (GTK_PLUG (icon)),
140
 
                                      0, 0);
141
 
}
142
 
 
143
 
static void
144
 
egg_tray_icon_update_manager_window (EggTrayIcon *icon)
145
 
{
146
 
  Display *xdisplay;
147
 
  
148
 
#if HAVE_GTK_MULTIHEAD
149
 
  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
150
 
#else
151
 
  xdisplay = gdk_display;
152
 
#endif
153
 
  
154
 
  if (icon->manager_window != None)
155
 
    {
156
 
      GdkWindow *gdkwin;
157
 
 
158
 
#if HAVE_GTK_MULTIHEAD
159
 
      gdkwin = gdk_window_lookup_for_display (display,
160
 
                                              icon->manager_window);
161
 
#else
162
 
      gdkwin = gdk_window_lookup (icon->manager_window);
163
 
#endif
164
 
      
165
 
      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
166
 
    }
167
 
  
168
 
  XGrabServer (xdisplay);
169
 
  
170
 
  icon->manager_window = XGetSelectionOwner (xdisplay,
171
 
                                             icon->selection_atom);
172
 
 
173
 
  if (icon->manager_window != None)
174
 
    XSelectInput (xdisplay,
175
 
                  icon->manager_window, StructureNotifyMask);
176
 
 
177
 
  XUngrabServer (xdisplay);
178
 
  XFlush (xdisplay);
179
 
  
180
 
  if (icon->manager_window != None)
181
 
    {
182
 
      GdkWindow *gdkwin;
183
 
 
184
 
#if HAVE_GTK_MULTIHEAD
185
 
      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
186
 
                                              icon->manager_window);
187
 
#else
188
 
      gdkwin = gdk_window_lookup (icon->manager_window);
189
 
#endif
190
 
      
191
 
      gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
192
 
 
193
 
      /* Send a request that we'd like to dock */
194
 
      egg_tray_icon_send_dock_request (icon);
195
 
    }
196
 
}
197
 
 
198
 
EggTrayIcon *
199
 
egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
200
 
{
201
 
  EggTrayIcon *icon;
202
 
  char buffer[256];
203
 
  GdkWindow *root_window;
204
 
 
205
 
  g_return_val_if_fail (xscreen != NULL, NULL);
206
 
  
207
 
  icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL);
208
 
  gtk_window_set_title (GTK_WINDOW (icon), name);
209
 
 
210
 
#if HAVE_GTK_MULTIHEAD
211
 
  gtk_plug_construct_for_display (GTK_PLUG (icon),
212
 
                                  gdk_screen_get_display (screen), 0);
213
 
#else
214
 
  gtk_plug_construct (GTK_PLUG (icon), 0);
215
 
#endif
216
 
  
217
 
  gtk_widget_realize (GTK_WIDGET (icon));
218
 
 
219
 
  /* Now see if there's a manager window around */
220
 
  g_snprintf (buffer, sizeof (buffer),
221
 
              "_NET_SYSTEM_TRAY_S%d",
222
 
              XScreenNumberOfScreen (xscreen));
223
 
  
224
 
  icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen),
225
 
                                      buffer, False);
226
 
  
227
 
  icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen),
228
 
                                    "MANAGER", False);
229
 
  
230
 
  icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen),
231
 
                                               "_NET_SYSTEM_TRAY_OPCODE", False);
232
 
 
233
 
  egg_tray_icon_update_manager_window (icon);
234
 
 
235
 
#if HAVE_GTK_MULTIHEAD
236
 
  root_window = gdk_screen_get_root_window (screen);
237
 
#else
238
 
  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
239
 
#endif
240
 
  
241
 
  /* Add a root window filter so that we get changes on MANAGER */
242
 
  gdk_window_add_filter (root_window,
243
 
                         egg_tray_icon_manager_filter, icon);
244
 
                      
245
 
  return icon;
246
 
}
247
 
 
248
 
#if HAVE_GTK_MULTIHEAD
249
 
EggTrayIcon *
250
 
egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
251
 
{
252
 
  EggTrayIcon *icon;
253
 
  char buffer[256];
254
 
 
255
 
  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
256
 
 
257
 
  return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name);
258
 
}
259
 
#endif
260
 
 
261
 
EggTrayIcon*
262
 
egg_tray_icon_new (const gchar *name)
263
 
{
264
 
  return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name);
265
 
}
266
 
 
267
 
guint
268
 
egg_tray_icon_send_message (EggTrayIcon *icon,
269
 
                            gint         timeout,
270
 
                            const gchar *message,
271
 
                            gint         len)
272
 
{
273
 
  guint stamp;
274
 
  
275
 
  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
276
 
  g_return_val_if_fail (timeout >= 0, 0);
277
 
  g_return_val_if_fail (message != NULL, 0);
278
 
                     
279
 
  if (icon->manager_window == None)
280
 
    return 0;
281
 
 
282
 
  if (len < 0)
283
 
    len = strlen (message);
284
 
 
285
 
  stamp = icon->stamp++;
286
 
  
287
 
  /* Get ready to send the message */
288
 
  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
289
 
                                      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
290
 
                                      timeout, len, stamp);
291
 
 
292
 
  /* Now to send the actual message */
293
 
  gdk_error_trap_push ();
294
 
  while (len > 0)
295
 
    {
296
 
      XClientMessageEvent ev;
297
 
      Display *xdisplay;
298
 
 
299
 
#if HAVE_GTK_MULTIHEAD
300
 
      xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
301
 
#else
302
 
      xdisplay = gdk_display;
303
 
#endif
304
 
      
305
 
      ev.type = ClientMessage;
306
 
      ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
307
 
      ev.format = 8;
308
 
      ev.message_type = XInternAtom (xdisplay,
309
 
                                     "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
310
 
      if (len > 20)
311
 
        {
312
 
          memcpy (&ev.data, message, 20);
313
 
          len -= 20;
314
 
          message += 20;
315
 
        }
316
 
      else
317
 
        {
318
 
          memcpy (&ev.data, message, len);
319
 
          len = 0;
320
 
        }
321
 
 
322
 
      XSendEvent (xdisplay,
323
 
                  icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
324
 
      XSync (xdisplay, False);
325
 
    }
326
 
  gdk_error_trap_pop ();
327
 
 
328
 
  return stamp;
329
 
}
330
 
 
331
 
void
332
 
egg_tray_icon_cancel_message (EggTrayIcon *icon,
333
 
                              guint        id)
334
 
{
335
 
  g_return_if_fail (EGG_IS_TRAY_ICON (icon));
336
 
  g_return_if_fail (id > 0);
337
 
  
338
 
  egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
339
 
                                      (Window)gtk_plug_get_id (GTK_PLUG (icon)),
340
 
                                      id, 0, 0);
341
 
}