~ubuntu-branches/ubuntu/karmic/alltray/karmic

« back to all changes in this revision

Viewing changes to src/trayicon.c

  • Committer: Bazaar Package Importer
  • Author(s): Raphael Hertzog
  • Date: 2007-01-14 18:36:56 UTC
  • Revision ID: james.westby@ubuntu.com-20070114183656-tutd3t7x0kifep7a
Tags: upstream-0.69
ImportĀ upstreamĀ versionĀ 0.69

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * GPL Notice:
 
3
 *
 
4
 *    This program is free software; you can redistribute it and/or modify
 
5
 *    it under the terms of the GNU General Public License as published by
 
6
 *    the Free Software Foundation; either version 2 of the License, or
 
7
 *    (at your option) any later version.
 
8
 *
 
9
 *    This program is distributed in the hope that it will be useful,
 
10
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *    GNU Library General Public License for more details.
 
13
 *
 
14
 *    You should have received a copy of the GNU General Public License
 
15
 *    along with this program; if not, write to the Free Software
 
16
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 *
 
18
 *
 
19
 * Name:
 
20
 *
 
21
 *    alltray
 
22
 *
 
23
 *
 
24
 * Copyright:
 
25
 * 
 
26
 *    Jochen Baier, 2004, 2005, 2006 (email@Jochen-Baier.de)
 
27
 *
 
28
 *
 
29
 * Based on code from:
 
30
 *
 
31
 *    steal-xwin.c (acano@systec.com)
 
32
 *    xswallow (Caolan McNamara ?)
 
33
 *    kdocker (Girish Ramakrishnan)
 
34
 *    libwnck (Havoc Pennington <hp@redhat.com>)
 
35
 *    eggtrayicon (Anders Carlsson <andersca@gnu.org>)
 
36
 *    dsimple.c ("The Open Group")
 
37
 *    xfwm4 (Olivier Fourdan <fourdan@xfce.org>)
 
38
 *    .....lot more, THANX !!!
 
39
 *    
 
40
*/
 
41
 
 
42
 
 
43
#include "common.h"
 
44
#include "utils.h"
 
45
#include "trayicon.h"
 
46
#include "balloon_message.h"
 
47
#include "xmms.h"
 
48
 
 
49
#define SYSTEM_TRAY_REQUEST_DOCK 0
 
50
 
 
51
GtkWidget *menu = NULL;
 
52
GtkWidget *show_item;
 
53
GtkWidget *exit_item;
 
54
GtkWidget *undock_item;
 
55
 
 
56
void tray_done (win_struct *win)
 
57
{
 
58
  
 
59
  gdk_window_remove_filter (win->root_gdk, manager_filter, (gpointer) win);
 
60
  gdk_window_remove_filter (win->manager_window_gdk, manager_filter, NULL);
 
61
 
 
62
  if (menu)
 
63
    gtk_widget_destroy (menu);
 
64
  
 
65
  if (win->plug)
 
66
    gtk_widget_destroy (win->plug);
 
67
  
 
68
}
 
69
 
 
70
void exit_call(GtkWidget * button, gpointer user_data)
 
71
{
 
72
 
 
73
  win_struct *win= (win_struct*) user_data;
 
74
  
 
75
  if (debug) printf ("exit_call\n");
 
76
 
 
77
  destroy_all_and_exit (win, TRUE);
 
78
 
 
79
}
 
80
 
 
81
void undock_call(GtkWidget * button, gpointer user_data)
 
82
{
 
83
 
 
84
  win_struct *win= (win_struct*) user_data;
 
85
  
 
86
  if (debug) printf ("undock_call\n");
 
87
 
 
88
  destroy_all_and_exit (win, FALSE);
 
89
 
 
90
}
 
91
 
 
92
void show_hide_call (GtkWidget * button, gpointer user_data)
 
93
{
 
94
 
 
95
  win_struct *win= (win_struct*) user_data;
 
96
 
 
97
  show_hide_window (win, force_disabled, FALSE);
 
98
}
 
99
 
 
100
void command_menu_call (GtkWidget * button, gpointer user_data)
 
101
{
 
102
 
 
103
  gchar *command= (gchar*) user_data;
 
104
  
 
105
  if (debug) printf ("command_menu_call: %s\n", command);
 
106
    
 
107
  if (!strcmp (command, "xmmsnext"))
 
108
    system ("xmms -f && xmms -p &");
 
109
  else
 
110
    exec_command (command);
 
111
  
 
112
}
 
113
 
 
114
void menu_init (win_struct *win)
 
115
{
 
116
  
 
117
  menu = gtk_menu_new();
 
118
  
 
119
  command_menu_struct command;
 
120
  gint i;
 
121
     
 
122
  
 
123
  GtkWidget *title = gtk_menu_item_new_with_label("   AllTray");
 
124
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), title);
 
125
  gtk_widget_set_sensitive(title, FALSE);
 
126
 
 
127
  GtkWidget *separator1 = gtk_menu_item_new();
 
128
  gtk_widget_show(separator1);
 
129
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), separator1);
 
130
  
 
131
  
 
132
  if (debug) printf ("command_menu->len: %d\n", win->command_menu->len);
 
133
  
 
134
  if (win->command_menu->len >0) {
 
135
  
 
136
    for (i=0; i < win->command_menu->len; i++) {
 
137
      
 
138
      command=g_array_index (win->command_menu, command_menu_struct, i);
 
139
      
 
140
      if (debug) printf ("found command.entry: %s\n", command.entry);
 
141
      
 
142
      GtkWidget *item = gtk_menu_item_new_with_label(command.entry);
 
143
      g_signal_connect(G_OBJECT(item), "activate",
 
144
        G_CALLBACK(command_menu_call), (gpointer) command.command);
 
145
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
 
146
  
 
147
    }
 
148
    
 
149
    GtkWidget *separator2 = gtk_menu_item_new();
 
150
    gtk_widget_show(separator2);
 
151
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), separator2);
 
152
    gtk_widget_set_sensitive(separator2, FALSE);
 
153
  
 
154
  }
 
155
 
 
156
  show_item = gtk_menu_item_new_with_label("Show/Hide");
 
157
  g_signal_connect(G_OBJECT(show_item), "activate",
 
158
      G_CALLBACK(show_hide_call), (gpointer) win);
 
159
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), show_item);
 
160
 
 
161
  GtkWidget *separator4 = gtk_menu_item_new();
 
162
  gtk_widget_show(separator4);
 
163
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), separator4);
 
164
  gtk_widget_set_sensitive(separator4, FALSE);
 
165
 
 
166
  undock_item = gtk_menu_item_new_with_label("Undock");
 
167
  g_signal_connect(G_OBJECT(undock_item), "activate",
 
168
      G_CALLBACK(undock_call), (gpointer) win);
 
169
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), undock_item);
 
170
 
 
171
  GtkWidget *separator3 = gtk_menu_item_new();
 
172
  gtk_widget_show(separator3);
 
173
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), separator3);
 
174
  gtk_widget_set_sensitive(separator3, FALSE);
 
175
 
 
176
  exit_item = gtk_menu_item_new_with_label("Exit");
 
177
  g_signal_connect(G_OBJECT(exit_item), "activate",
 
178
      G_CALLBACK(exit_call), (gpointer) win);
 
179
  gtk_menu_shell_append(GTK_MENU_SHELL(menu), exit_item);
 
180
 
 
181
 
 
182
  gtk_widget_show_all(menu);
 
183
}
 
184
 
 
185
void update_tray_icon(win_struct *win)
 
186
{
 
187
 
 
188
 
 
189
  
 
190
  GdkPixbuf *tmp=NULL;
 
191
  XWindowAttributes wa;
 
192
  gboolean resize=FALSE;
 
193
  
 
194
  gint req_h, req_w;
 
195
 
 
196
  if (win->notray)
 
197
    return;    
 
198
   
 
199
  gdk_error_trap_push();
 
200
  XGetWindowAttributes (GDK_DISPLAY(), win->plug_xlib, &wa);
 
201
  if (gdk_error_trap_pop())
 
202
    return;
 
203
   
 
204
  if (debug) printf ("update_tray_icon: real plug size: %dx%d\n", wa.width, wa.height);
 
205
    
 
206
  if (wa.width <=1 || wa.height <= 1)
 
207
    return;
 
208
 
 
209
  if ((wa.height > 24 && win->large_icons) || wa.height < 24 ) {
 
210
    resize=TRUE;
 
211
    if (debug) printf ("resize = TRUE\n");
 
212
  }
 
213
  
 
214
  if (resize) {
 
215
    req_w=wa.height;
 
216
    req_h=wa.height;
 
217
  } else {
 
218
    req_w=24;
 
219
    req_h=24;
 
220
  }
 
221
 
 
222
  if (win->user_icon_path)
 
223
    tmp=get_user_icon (win->user_icon_path, req_w, req_h);
 
224
  
 
225
  if (!tmp) {
 
226
    
 
227
     if (win->xmms)
 
228
        tmp=get_xmms_icon (req_w, req_h);
 
229
      else
 
230
        tmp=get_window_icon (win->child_xlib, req_w, req_h);
 
231
  }
 
232
  
 
233
  if (win->tray_icon)
 
234
    g_object_unref(win->tray_icon);
 
235
  
 
236
  win->tray_icon=tmp;
 
237
  
 
238
  if (GTK_IS_WIDGET (win->image_icon))
 
239
    gtk_image_set_from_pixbuf(GTK_IMAGE(win->image_icon), win->tray_icon);
 
240
 
 
241
}
 
242
 
 
243
void dock_window(Window manager_window, Window window)
 
244
{
 
245
 
 
246
  XClientMessageEvent ev;
 
247
  
 
248
  ev.type = ClientMessage;
 
249
  ev.window = manager_window;
 
250
  ev.message_type =system_tray_opcode_atom;
 
251
  ev.format = 32;
 
252
  ev.data.l[0] = CurrentTime;
 
253
  ev.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
 
254
  ev.data.l[2] = window;
 
255
  ev.data.l[3] =0;
 
256
  ev.data.l[4] = 0;
 
257
 
 
258
  gdk_error_trap_push ();
 
259
    XSendEvent (GDK_DISPLAY(), manager_window, False, NoEventMask, (XEvent *)&ev);
 
260
    XSync (GDK_DISPLAY(), False);
 
261
  gdk_error_trap_pop ();
 
262
 
 
263
}
 
264
 
 
265
Window get_manager_window (void)
 
266
{
 
267
 
 
268
  Window manager_window=None;
 
269
 
 
270
  gdk_error_trap_push();
 
271
 
 
272
  XGrabServer (GDK_DISPLAY());
 
273
  
 
274
  manager_window = XGetSelectionOwner (GDK_DISPLAY(), selection_atom);
 
275
     
 
276
  XUngrabServer (GDK_DISPLAY());
 
277
  XFlush (GDK_DISPLAY());
 
278
 
 
279
  if (gdk_error_trap_pop())
 
280
    return None;
 
281
    
 
282
 // display_window_id(GDK_DISPLAY(), manager_window);
 
283
    
 
284
  return manager_window;
 
285
}
 
286
 
 
287
GdkFilterReturn
 
288
manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
 
289
{
 
290
  
 
291
  XEvent *xev = (XEvent *)xevent;
 
292
  XWindowAttributes wa; 
 
293
 
 
294
  win_struct *win= (win_struct *) user_data;
 
295
 
 
296
  if (xev->xany.type == ClientMessage &&
 
297
      xev->xclient.message_type == manager_atom &&
 
298
      xev->xclient.data.l[1] == selection_atom)
 
299
    {
 
300
      
 
301
    
 
302
    if (debug) printf ("manager: here i am\n");
 
303
                          
 
304
    create_tray_and_dock(win);
 
305
    
 
306
    }
 
307
  else if (xev->xany.window == win->manager_window)
 
308
    {
 
309
      if (xev->xany.type == DestroyNotify)
 
310
    {
 
311
    
 
312
       if (debug) printf ("manger destroy notfiy\n");
 
313
      
 
314
      
 
315
      gdk_error_trap_push ();
 
316
          
 
317
      XGetWindowAttributes (GDK_DISPLAY(), win->manager_window, &wa);
 
318
      
 
319
     if (gdk_error_trap_pop()) {
 
320
     
 
321
         gdk_window_remove_filter (win->manager_window_gdk, manager_filter, NULL);
 
322
        
 
323
     
 
324
        if (win->plug) {
 
325
        
 
326
          if (GTK_IS_WIDGET(win->plug))
 
327
            gtk_widget_destroy (win->plug);
 
328
          
 
329
          win->plug=NULL;
 
330
        }
 
331
      }
 
332
  
 
333
    }
 
334
 
 
335
    }
 
336
  
 
337
  return GDK_FILTER_CONTINUE;
 
338
}
 
339
 
 
340
gboolean on_icon_window_press_event(GtkWidget *widget, GdkEventButton * event,
 
341
    gpointer user_data)
 
342
{
 
343
  
 
344
  win_struct *win= (win_struct*) user_data;
 
345
  
 
346
  if (debug) printf ("icon window press event\n");
 
347
    
 
348
  
 
349
  if (win->balloon)
 
350
    destroy_balloon (win);
 
351
 
 
352
  /*right click */
 
353
  if (event->button == 1) {
 
354
  
 
355
    show_hide_window (win, force_disabled, FALSE);
 
356
    return TRUE;
 
357
 
 
358
  }
 
359
 
 
360
  /*left click */
 
361
  if (event->button == 3) {
 
362
  
 
363
  gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0,
 
364
      gtk_get_current_event_time());
 
365
  }
 
366
 
 
367
  return TRUE;
 
368
}
 
369
 
 
370
gboolean icon_window_configure_event (GtkWidget *widget,
 
371
  GdkEventConfigure * event, gpointer user_data)
 
372
{
 
373
 
 
374
  win_struct *win = (win_struct*) user_data;
 
375
 
 
376
  if (debug) printf ("icon_window_configure_event: %dx%d\n",
 
377
    event->width, event->height);
 
378
  
 
379
  if (event->width <= 1 || event->height <= 1)
 
380
    return FALSE;
 
381
 
 
382
  update_tray_icon(win);
 
383
 
 
384
  return FALSE;
 
385
    
 
386
}
 
387
 
 
388
gboolean icon_window_enter_event(GtkWidget *widget, GdkEventButton * event,
 
389
    gpointer user_data)
 
390
{
 
391
  
 
392
  win_struct *win= (win_struct*) user_data;
 
393
  
 
394
  if (debug) printf ("icon window enter event\n");
 
395
    
 
396
  win->balloon_message_allowed=TRUE;
 
397
 
 
398
  show_balloon (win, win->title, 0);
 
399
  
 
400
  return FALSE;
 
401
 
 
402
}
 
403
 
 
404
void create_tray_and_dock (win_struct *win)
 
405
{
 
406
  
 
407
  gint icon_width;
 
408
  gint icon_height;
 
409
  GtkStyle *style;
 
410
 
 
411
  if (win->manager_window==None)
 
412
    win->manager_window=get_manager_window();
 
413
  
 
414
  if (win->manager_window==None)
 
415
    return;
 
416
  
 
417
  /*too lazy to fix that now*/
 
418
  if (!assert_window (win->manager_window)) {
 
419
    
 
420
    printf ("Alltray: Can not dock!.\nPlease remove system tray applet\n"\
 
421
    "and add it again.\n");
 
422
    return;
 
423
  }
 
424
  
 
425
  win->manager_window_gdk=NULL;
 
426
  win->manager_window_gdk=gdk_window_foreign_new(win->manager_window);
 
427
     
 
428
  gdk_window_set_events (win->manager_window_gdk, GDK_SUBSTRUCTURE_MASK);
 
429
  gdk_window_add_filter (win->manager_window_gdk, manager_filter, (gpointer) win);
 
430
  
 
431
  if (win->plug && GTK_IS_WIDGET (win->plug)) {
 
432
    if (debug) printf ("plug is still alive\n");
 
433
    gtk_widget_destroy(win->plug);
 
434
  }
 
435
 
 
436
  win->plug= gtk_plug_new (0);
 
437
  gtk_container_set_border_width (GTK_CONTAINER (win->plug), 0);
 
438
  win->image_icon=gtk_image_new ();
 
439
  gtk_container_add (GTK_CONTAINER(win->plug), win->image_icon);
 
440
  gtk_widget_show (win->image_icon);
 
441
  gtk_widget_show (win->plug);
 
442
  gtk_widget_realize (win->plug);
 
443
 
 
444
  gtk_widget_set_double_buffered (win->plug, FALSE);
 
445
  style = gtk_style_copy (win->plug->style);
 
446
  style->bg_pixmap[GTK_STATE_NORMAL] = (GdkPixmap*) GDK_PARENT_RELATIVE;
 
447
  gtk_widget_set_style (win->plug, style);
 
448
  g_object_unref (style);
 
449
  gtk_style_set_background (win->plug->style, win->plug->window, GTK_STATE_NORMAL);
 
450
 
 
451
  win->plug_xlib=gtk_plug_get_id (GTK_PLUG(win->plug));
 
452
  
 
453
  if (win->tray_icon)
 
454
    g_object_unref(win->tray_icon);
 
455
  win->tray_icon=NULL;
 
456
 
 
457
  icon_width=24; icon_height=24;
 
458
 
 
459
  if (win->user_icon_path)
 
460
    win->tray_icon=get_user_icon (win->user_icon_path, icon_width, icon_height);
 
461
  
 
462
  if (!win->tray_icon) {
 
463
    
 
464
    if (win->xmms)
 
465
      win->tray_icon=get_xmms_icon (icon_width, icon_height);
 
466
    else
 
467
      win->tray_icon=get_window_icon (win->child_xlib, icon_width, icon_height);
 
468
  }
 
469
 
 
470
  gtk_image_set_from_pixbuf(GTK_IMAGE(win->image_icon), win->tray_icon);
 
471
 
 
472
  gtk_widget_add_events (win->plug, GDK_BUTTON_PRESS_MASK);
 
473
 
 
474
  g_signal_connect ((gpointer) win->plug, "button_press_event",
 
475
                    G_CALLBACK (on_icon_window_press_event),
 
476
                    (gpointer) win);
 
477
 
 
478
 
 
479
  g_signal_connect ((gpointer) win->plug, "configure_event",
 
480
                    G_CALLBACK (icon_window_configure_event),
 
481
                    (gpointer) win);
 
482
  
 
483
  
 
484
  g_signal_connect ((gpointer) win->plug, "enter_notify_event",
 
485
                    G_CALLBACK (icon_window_enter_event),
 
486
                    (gpointer) win);
 
487
 
 
488
 
 
489
  dock_window (win->manager_window, win->plug_xlib);
 
490
 
 
491
}
 
492
 
 
493
void tray_init (win_struct *win)
 
494
{
 
495
   
 
496
  menu_init(win);
 
497
 
 
498
  win->manager_window=get_manager_window();
 
499
  
 
500
  if (win->manager_window) {
 
501
          
 
502
    if (debug) printf ("have manager window.... now creat_tray.....\n");
 
503
    create_tray_and_dock(win);
 
504
  } else
 
505
  {
 
506
    printf ("Alltray: no system tray/notification area found. I will wait..... I have time....\n");
 
507
  }
 
508
  
 
509
  gdk_window_add_filter (win->root_gdk, manager_filter, (gpointer) win);
 
510
 
 
511
}