~ubuntu-branches/ubuntu/precise/alltray/precise

« back to all changes in this revision

Viewing changes to src/utils.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
#include "common.h"
 
43
#include "utils.h"
 
44
#include "trayicon.h"
 
45
#include "xmms.h"
 
46
#include "balloon_message.h"
 
47
#include "grab.h"
 
48
#include "shortcut.h"
 
49
#include "eventfilter.h"
 
50
#include "inlinepixbufs.h"
 
51
#include "config.h"
 
52
 
 
53
char *event_names[] = {
 
54
   "",
 
55
   "",
 
56
   "KeyPress",
 
57
   "KeyRelease",
 
58
   "ButtonPress",
 
59
   "ButtonRelease",
 
60
   "MotionNotify",
 
61
   "EnterNotify",
 
62
   "LeaveNotify",
 
63
   "FocusIn",
 
64
   "FocusOut",
 
65
   "KeymapNotify",
 
66
   "Expose",
 
67
   "GraphicsExpose",
 
68
   "NoExpose",
 
69
   "VisibilityNotify",
 
70
   "CreateNotify",
 
71
   "DestroyNotify",
 
72
   "UnmapNotify",
 
73
   "MapNotify",
 
74
   "MapRequest",
 
75
   "ReparentNotify",
 
76
   "ConfigureNotify",
 
77
   "ConfigureRequest",
 
78
   "GravityNotify",
 
79
   "ResizeRequest",
 
80
   "CirculateNotify",
 
81
   "CirculateRequest",
 
82
   "PropertyNotify",
 
83
   "SelectionClear",
 
84
   "SelectionRequest",
 
85
   "SelectionNotify",
 
86
   "ColormapNotify",
 
87
   "ClientMessage",
 
88
   "MappingNotify"
 
89
};
 
90
 
 
91
gboolean assert_window (Window window)
 
92
{
 
93
 
 
94
  XWindowAttributes wa;
 
95
  
 
96
  gdk_error_trap_push();
 
97
  XGetWindowAttributes (GDK_DISPLAY(), window, &wa);
 
98
  
 
99
  if (gdk_error_trap_pop())
 
100
    return FALSE;
 
101
  
 
102
  return TRUE;
 
103
}
 
104
 
 
105
void atom_init (void)
 
106
{
 
107
 
 
108
  wm_name_atom = XInternAtom(GDK_DISPLAY(), "WM_NAME", False);
 
109
  wm_icon_atom = XInternAtom(GDK_DISPLAY(), "WM_ICON", False);
 
110
  net_wm_icon = XInternAtom(GDK_DISPLAY(), "_NET_WM_ICON", False);
 
111
  net_wm_name= XInternAtom(GDK_DISPLAY(), "_NET_WM_NAME", False);
 
112
  net_close_window=XInternAtom(GDK_DISPLAY(), "_NET_CLOSE_WINDOW", False);
 
113
  net_number_of_desktops=XInternAtom(GDK_DISPLAY(),
 
114
    "_NET_NUMBER_OF_DESKTOPS",False);
 
115
  net_current_desktop = XInternAtom(GDK_DISPLAY(), "_NET_CURRENT_DESKTOP", False);
 
116
  wm_delete_window = XInternAtom (GDK_DISPLAY(), "WM_DELETE_WINDOW", False);
 
117
  wm_take_focus = XInternAtom (GDK_DISPLAY(), "WM_TAKE_FOCUS", False);
 
118
  net_wm_pid=XInternAtom(GDK_DISPLAY(), "_NET_WM_PID", False);
 
119
  net_wm_ping = XInternAtom (GDK_DISPLAY(), "_NET_WM_PING", False);
 
120
  net_wm_state_skip_pager= XInternAtom (GDK_DISPLAY(), "_NET_WM_STATE_SKIP_PAGER", False);
 
121
  net_wm_state_skip_taskbar=XInternAtom (GDK_DISPLAY(), "_NET_WM_STATE_SKIP_TASKBAR", False);
 
122
  net_wm_state = XInternAtom (GDK_DISPLAY(), "_NET_WM_STATE", False);
 
123
  wm_state = XInternAtom (GDK_DISPLAY(), "WM_STATE", False);
 
124
  net_wm_state_sticky= XInternAtom (GDK_DISPLAY(), "_NET_WM_STATE_STICKY", False);
 
125
  net_wm_desktop= XInternAtom (GDK_DISPLAY(), "_NET_WM_DESKTOP", False);
 
126
  net_active_window= XInternAtom(GDK_DISPLAY(), "_NET_ACTIVE_WINDOW", False);
 
127
  net_wm_window_type= XInternAtom(GDK_DISPLAY(), "_NET_WM_WINDOW_TYPE", False);
 
128
  net_wm_window_type_normal= XInternAtom(GDK_DISPLAY(), "_NET_WM_WINDOW_TYPE_NORMAL", False);
 
129
  gdk_timestamp_prop=XInternAtom(GDK_DISPLAY(),"GDK_TIMESTAMP_PROP", False);
 
130
  net_client_list_stacking=XInternAtom(GDK_DISPLAY(),"_NET_CLIENT_LIST_STACKING",False);
 
131
  net_client_list=XInternAtom(GDK_DISPLAY(),"_NET_CLIENT_LIST",False);
 
132
  utf8_string = XInternAtom(GDK_DISPLAY(),"UTF8_STRING", False);
 
133
  net_wm_visible_name=XInternAtom(GDK_DISPLAY(),"_NET_WM_VISIBLE_NAME", False);
 
134
  alltray_found_window=XInternAtom (GDK_DISPLAY(), "_ALLTRAY_FOUND_WINDOW", False);
 
135
  
 
136
    
 
137
  char temp[50];
 
138
  Screen *screen = XDefaultScreenOfDisplay(GDK_DISPLAY());
 
139
 
 
140
  sprintf(temp, "_NET_SYSTEM_TRAY_S%i", XScreenNumberOfScreen(screen));
 
141
  selection_atom = XInternAtom(GDK_DISPLAY(), temp, False);
 
142
 
 
143
  manager_atom = XInternAtom (GDK_DISPLAY(), "MANAGER", False);
 
144
  system_tray_opcode_atom = XInternAtom (GDK_DISPLAY(), 
 
145
      "_NET_SYSTEM_TRAY_OPCODE", False);
 
146
 
 
147
}
 
148
 
 
149
void xprop (Window window)
 
150
{
 
151
 
 
152
  gchar *tmp=g_strdup_printf ("xprop -id %d &", (int) window);
 
153
  system (tmp);
 
154
  g_free (tmp);
 
155
}
 
156
 
 
157
gboolean gtk_sleep_function (gpointer data)
 
158
{
 
159
  gtk_main_quit ();
 
160
  return FALSE;
 
161
}
 
162
 
 
163
void gtk_sleep (gint millisec) 
 
164
{
 
165
 
 
166
  g_timeout_add (millisec, gtk_sleep_function, NULL);
 
167
  gtk_main();
 
168
  
 
169
}
 
170
 
 
171
Window get_active_window (void)
 
172
{
 
173
  Atom type;
 
174
  int format;
 
175
  unsigned long nitems;
 
176
  unsigned long bytes_after;
 
177
  unsigned char *data;
 
178
  int result;
 
179
  Window win=None;
 
180
  gint err;
 
181
    
 
182
  type = None;
 
183
  
 
184
  gdk_error_trap_push();
 
185
  result = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
 
186
         net_active_window,
 
187
         0,  0x7fffffff, False,XA_WINDOW, &type, &format, &nitems,
 
188
         &bytes_after, &data); 
 
189
  
 
190
  err=gdk_error_trap_pop();
 
191
   
 
192
  if (err!=0 || result != Success)
 
193
     return None;
 
194
        
 
195
  if (type != XA_WINDOW) {
 
196
      XFree (data);
 
197
      return None;
 
198
  }
 
199
  
 
200
  if (data) {
 
201
    win= *((Window *) data);
 
202
    if (debug) printf ("active window id %d\n", (int) win);
 
203
    XFree (data);
 
204
  }
 
205
  
 
206
  return win;
 
207
}
 
208
 
 
209
gint get_current_desktop(void)
 
210
{
 
211
  Atom type;
 
212
  int format;
 
213
  unsigned long nitems;
 
214
  unsigned long bytes_after;
 
215
  unsigned char *data;
 
216
  int result;
 
217
  gint err;
 
218
  gint number=1;
 
219
            
 
220
  type = None;
 
221
  
 
222
  gdk_error_trap_push();
 
223
  result = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
 
224
         net_current_desktop,
 
225
         0,  1l, False,XA_CARDINAL, &type, &format, &nitems,
 
226
         &bytes_after, &data); 
 
227
  
 
228
  err=gdk_error_trap_pop();
 
229
   
 
230
  if (err!=0 || result != Success)
 
231
    return 1;
 
232
  
 
233
  if (type == XA_CARDINAL && format == 32 && nitems == 1)
 
234
   number = *((long *) data);
 
235
  
 
236
  if (data)
 
237
    XFree (data);
 
238
  
 
239
  return number;
 
240
  
 
241
}
 
242
 
 
243
gboolean get_window_list (Window   xwindow,
 
244
   Atom     atom,
 
245
   Window **windows,
 
246
   int     *len)
 
247
{
 
248
  Atom type;
 
249
  int format;
 
250
  gulong nitems;
 
251
  gulong bytes_after;
 
252
  unsigned char *data;
 
253
  int err, result;
 
254
  
 
255
  *windows = NULL;
 
256
  *len = 0;
 
257
  
 
258
  gdk_error_trap_push();
 
259
  type = None;
 
260
  result = XGetWindowProperty (GDK_DISPLAY(), xwindow,
 
261
    atom, 0, G_MAXLONG, False, XA_WINDOW, &type,
 
262
    &format, &nitems, &bytes_after, &data);  
 
263
  err = gdk_error_trap_pop ();
 
264
 
 
265
  if (err != Success || result != Success)
 
266
    return FALSE;
 
267
    
 
268
  if (type != XA_WINDOW) {
 
269
    XFree (data);
 
270
    return FALSE;
 
271
  }
 
272
 
 
273
  *windows = g_new (Window, nitems);
 
274
  memcpy (*windows, (Window*) data, sizeof (Window) * nitems);
 
275
  *len = nitems;
 
276
 
 
277
  XFree (data);
 
278
 
 
279
  return TRUE;  
 
280
}
 
281
 
 
282
gint get_pid (Window w)
 
283
{
 
284
  
 
285
  Atom actual_type;
 
286
  int actual_format;
 
287
  unsigned long nitems, leftover;
 
288
  unsigned char *pid_return;
 
289
  gint pid=0;
 
290
  int status;
 
291
  gint err;
 
292
    
 
293
  gdk_error_trap_push();
 
294
  
 
295
  status=XGetWindowProperty(GDK_DISPLAY(), w,
 
296
      net_wm_pid, 0,
 
297
      1, False, XA_CARDINAL, &actual_type,
 
298
      &actual_format, &nitems, &leftover, &pid_return);
 
299
  
 
300
  err=gdk_error_trap_pop();
 
301
    
 
302
  if (err!=0 || status != Success)
 
303
    return 0;
 
304
     
 
305
  if (pid_return) {
 
306
    pid=*(gint *) pid_return;
 
307
    XFree(pid_return);
 
308
  }
 
309
 
 
310
  return pid;
 
311
}
 
312
 
 
313
gboolean window_type_is_normal (Window win)
 
314
{
 
315
 
 
316
  Atom type;
 
317
  unsigned long nitems, bytes_after;
 
318
  unsigned char *data = 0;
 
319
  gint format;
 
320
  gboolean normal=TRUE;
 
321
  gint result =0;
 
322
  gint err;
 
323
     
 
324
  type = None;
 
325
  
 
326
  gdk_error_trap_push();
 
327
    
 
328
  result = XGetWindowProperty (GDK_DISPLAY(), win,
 
329
    net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM,
 
330
    &type, &format, &nitems, &bytes_after, &data);
 
331
  
 
332
  err=gdk_error_trap_pop();
 
333
 
 
334
  if (err || result != Success) {
 
335
   return FALSE;
 
336
  }
 
337
 
 
338
  if (data) {
 
339
  
 
340
    Atom *atoms = (unsigned long *)data;
 
341
    unsigned long l;
 
342
    for (l=0; l<nitems; ++l) {
 
343
    
 
344
      if (atoms[l] != net_wm_window_type_normal) {
 
345
        normal=FALSE;
 
346
        break;
 
347
      }
 
348
    
 
349
    }
 
350
    
 
351
    XFree(data);    
 
352
  }
 
353
  
 
354
  return normal;
 
355
            
 
356
}
 
357
 
 
358
void skip_pager (Window window, gboolean add)
 
359
{
 
360
  
 
361
  XEvent xev;
 
362
  
 
363
  xev.xclient.type = ClientMessage;
 
364
  xev.xclient.serial = 0;
 
365
  xev.xclient.send_event = True;
 
366
  xev.xclient.window = window;
 
367
  xev.xclient.message_type = net_wm_state;
 
368
  xev.xclient.format = 32;
 
369
  xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
 
370
  xev.xclient.data.l[1] = net_wm_state_skip_pager;
 
371
  xev.xclient.data.l[2] = 0;
 
372
  xev.xclient.data.l[3] = 0;
 
373
  xev.xclient.data.l[4] = 0;
 
374
  
 
375
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
 
376
     SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
377
}
 
378
 
 
379
void sticky (Window window)
 
380
{
 
381
  
 
382
  XEvent xev;
 
383
  
 
384
  xev.xclient.type = ClientMessage;
 
385
  xev.xclient.serial = 0;
 
386
  xev.xclient.send_event = True;
 
387
  xev.xclient.window = window;
 
388
  xev.xclient.message_type = net_wm_state;
 
389
  xev.xclient.format = 32;
 
390
  xev.xclient.data.l[0] = 1;
 
391
  xev.xclient.data.l[1] = net_wm_state_sticky;
 
392
  xev.xclient.data.l[2] = 0;
 
393
  xev.xclient.data.l[3] = 0;
 
394
  xev.xclient.data.l[4] = 0;
 
395
  
 
396
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
 
397
     SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
398
 
 
399
  /* Request desktop 0xFFFFFFFF */
 
400
  xev.xclient.type = ClientMessage;
 
401
  xev.xclient.serial = 0;
 
402
  xev.xclient.send_event = True;
 
403
  xev.xclient.window = window;
 
404
  xev.xclient.display = GDK_DISPLAY();
 
405
  xev.xclient.message_type =net_wm_desktop;
 
406
  xev.xclient.format = 32;
 
407
  
 
408
  xev.xclient.data.l[0] = 0xFFFFFFFF;
 
409
  xev.xclient.data.l[1] = 0;
 
410
  xev.xclient.data.l[2] = 0;
 
411
  xev.xclient.data.l[3] = 0;
 
412
  xev.xclient.data.l[4] = 0;
 
413
  
 
414
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
 
415
            SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
416
 
 
417
}
 
418
 
 
419
void to_desktop (Window window, gint num)
 
420
{
 
421
 
 
422
  XEvent xev;
 
423
 
 
424
 
 
425
  xev.xclient.type = ClientMessage;
 
426
  xev.xclient.serial = 0;
 
427
  xev.xclient.send_event = True;
 
428
  xev.xclient.window = window;
 
429
  xev.xclient.display = GDK_DISPLAY();
 
430
  xev.xclient.message_type =net_wm_desktop;
 
431
  xev.xclient.format = 32;
 
432
  
 
433
  xev.xclient.data.l[0] = num;
 
434
  xev.xclient.data.l[1] = 0;
 
435
  xev.xclient.data.l[2] = 0;
 
436
  xev.xclient.data.l[3] = 0;
 
437
  xev.xclient.data.l[4] = 0;
 
438
  
 
439
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
 
440
            SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
441
 
 
442
}
 
443
 
 
444
void rm_sticky (Window window)
 
445
{
 
446
  
 
447
  XEvent xev;
 
448
 
 
449
  xev.xclient.type = ClientMessage;
 
450
  xev.xclient.serial = 0;
 
451
  xev.xclient.send_event = True;
 
452
  xev.xclient.window = window;
 
453
  xev.xclient.display = GDK_DISPLAY();
 
454
  xev.xclient.message_type =net_wm_desktop;
 
455
  xev.xclient.format = 32;
 
456
  xev.xclient.data.l[0] = get_current_desktop();
 
457
  xev.xclient.data.l[1] = 0;
 
458
  xev.xclient.data.l[2] = 0;
 
459
  xev.xclient.data.l[3] = 0;
 
460
  xev.xclient.data.l[4] = 0;
 
461
  
 
462
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
 
463
            SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
464
 
 
465
}
 
466
 
 
467
/*for debug...*/
 
468
void show_pixbuf (GdkPixbuf *buf)
 
469
{
 
470
 
 
471
  GtkWidget *window1;
 
472
  GtkWidget *image1;
 
473
  
 
474
  window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
475
  image1=gtk_image_new_from_pixbuf(buf);
 
476
  gtk_widget_show (image1);
 
477
  gtk_container_add (GTK_CONTAINER (window1), image1);
 
478
  gtk_widget_show (window1);
 
479
 
 
480
}
 
481
 
 
482
void display_window_id(Display *display, Window window)
 
483
{
 
484
  char *win_name;
 
485
  static char *window_id_format = "0x%lx";
 
486
   
 
487
  if (!debug)
 
488
    return;
 
489
  
 
490
  if (!assert_window (window))
 
491
    return;
 
492
    
 
493
  printf(window_id_format, window);         /* print id # in hex/dec */
 
494
  
 
495
  if (!window) {
 
496
    printf(" (none)");
 
497
  } else {
 
498
  if (window == DefaultRootWindow (display)) {
 
499
    printf(" (the root window)");
 
500
  }
 
501
 
 
502
  if (!XFetchName(display, window, &win_name)) { /* Get window name if any */
 
503
    printf(" (has no name)");
 
504
  } else if (win_name) {
 
505
    printf(" \"%s\"", win_name);
 
506
    XFree(win_name);
 
507
  } else
 
508
    printf(" (has no name)");
 
509
  }
 
510
 
 
511
  printf ("window int: %d\n", (int) window);
 
512
  
 
513
  printf("\n");
 
514
 
 
515
}
 
516
 
 
517
/*from gdk-pixbuf-xlib-drawabel.c*/
 
518
gboolean xlib_window_is_viewable (Window w)
 
519
{
 
520
  XWindowAttributes wa;
 
521
  gint err;
 
522
  
 
523
  
 
524
  while (w != 0) {
 
525
    Window parent, root, *children;
 
526
    int nchildren;
 
527
    
 
528
    gdk_error_trap_push();
 
529
    XGetWindowAttributes (GDK_DISPLAY(), w, &wa);
 
530
    err=gdk_error_trap_pop();
 
531
  
 
532
    if (err)
 
533
      return FALSE;
 
534
        
 
535
    if (wa.map_state != IsViewable) {
 
536
      return FALSE;
 
537
    }
 
538
     
 
539
    if (!XQueryTree (GDK_DISPLAY(), w, &root, &parent, &children, (unsigned int *) &nchildren))
 
540
      return 0;
 
541
    
 
542
    if (nchildren > 0)
 
543
      XFree (children);
 
544
    
 
545
    if ((parent == root) || (w == root))
 
546
      return TRUE;
 
547
    
 
548
    w = parent;
 
549
  }
 
550
  return TRUE;
 
551
}
 
552
 
 
553
void get_window_position (Window window, gint *x, gint *y)
 
554
{
 
555
 
 
556
  Window  root_return;
 
557
  unsigned int width_return, height_return, border, depth;
 
558
 
 
559
  Window our=one_under_root(GDK_DISPLAY(), window);
 
560
 
 
561
  if (debug) printf ("get_window_position: window normal: %d, window our: %d\n", 
 
562
    (int) window, (int)our);
 
563
  
 
564
  XGetGeometry (GDK_DISPLAY(), our,
 
565
    &root_return, x, y, &height_return, &width_return, &border, &depth);
 
566
 
 
567
}
 
568
 
 
569
GPid exec_command (gchar *command)
 
570
{
 
571
 
 
572
  gchar **child_vector=NULL;
 
573
  gint num;
 
574
  GError *error=NULL;
 
575
  GPid pid=0;
 
576
  gboolean success_parse;
 
577
  gboolean success_spawn;
 
578
 
 
579
  success_parse=g_shell_parse_argv (command, &num, &child_vector, NULL);
 
580
    
 
581
  if (success_parse) {
 
582
    success_spawn=g_spawn_async (NULL,child_vector, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL |
 
583
        G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &pid, &error);
 
584
  
 
585
  if (!success_spawn)
 
586
    printf ("AllTray: %s\n", error->message);
 
587
    
 
588
    g_strfreev (child_vector);
 
589
  }
 
590
   
 
591
  return pid;
 
592
 
 
593
}
 
594
 
 
595
Window one_under_root (Display *display, Window window)
 
596
{
 
597
  
 
598
  Window root_return=None;
 
599
  Window parent=None;
 
600
  Window *kids;
 
601
  Window runner=None;
 
602
  
 
603
  int nkids;
 
604
  
 
605
  runner=window;
 
606
 
 
607
  if (debug) printf ("one under root function\n");
 
608
 
 
609
    while (1) {
 
610
    
 
611
      if (debug) printf ("current runner: %d\n", (int) runner);
 
612
   
 
613
       if (! XQueryTree (display, runner, &root_return, &parent, &kids, (unsigned int *) &nkids))
 
614
         {  continue;  }
 
615
       if (kids) XFree ((char *)kids);
 
616
         
 
617
       if (parent == DefaultRootWindow (display))
 
618
         break;
 
619
       
 
620
       runner=parent;
 
621
          
 
622
     }
 
623
    
 
624
  return runner;
 
625
}   
 
626
 
 
627
GdkColormap*
 
628
get_cmap (GdkPixmap *pixmap)
 
629
{
 
630
  GdkColormap *cmap;
 
631
 
 
632
  cmap = gdk_drawable_get_colormap (pixmap);
 
633
  if (cmap)
 
634
    g_object_ref (G_OBJECT (cmap));
 
635
 
 
636
  if (cmap == NULL)
 
637
    {
 
638
      if (gdk_drawable_get_depth (pixmap) == 1)
 
639
        {
 
640
          /* try null cmap */
 
641
          cmap = NULL;
 
642
        }
 
643
      else
 
644
        {
 
645
          /* Try system cmap */
 
646
          GdkScreen *screen = gdk_drawable_get_screen (GDK_DRAWABLE (pixmap));
 
647
          cmap = gdk_screen_get_system_colormap (screen);
 
648
          g_object_ref (G_OBJECT (cmap));
 
649
        }
 
650
    }
 
651
 
 
652
  /* Be sure we aren't going to blow up due to visual mismatch */
 
653
  if (cmap &&
 
654
      (gdk_colormap_get_visual (cmap)->depth !=
 
655
       gdk_drawable_get_depth (pixmap)))
 
656
    cmap = NULL;
 
657
  
 
658
  return cmap;
 
659
}
 
660
 
 
661
gboolean get_window_pixmap (Window window, Pixmap *pix, Pixmap *mask)
 
662
{
 
663
 
 
664
  XWMHints *wm_hints;
 
665
  
 
666
  gdk_error_trap_push();
 
667
  
 
668
  wm_hints= XGetWMHints(GDK_DISPLAY(), window);
 
669
  
 
670
  if (gdk_error_trap_pop()) {
 
671
    if (wm_hints)
 
672
      XFree (wm_hints);
 
673
      return FALSE;
 
674
  }
 
675
    
 
676
  if (wm_hints != NULL) {
 
677
    if (!(wm_hints->flags & IconMaskHint))
 
678
      wm_hints->icon_mask = None;
 
679
      
 
680
    if ((wm_hints->flags & IconPixmapHint) && (wm_hints->icon_pixmap)) {
 
681
      *pix=wm_hints->icon_pixmap;
 
682
      *mask=wm_hints->icon_mask;
 
683
    }
 
684
  
 
685
    XFree (wm_hints);
 
686
   return TRUE;
 
687
  }
 
688
 
 
689
  return FALSE;
 
690
}
 
691
 
 
692
static void free_pixels (guchar *pixels, gpointer data)
 
693
{
 
694
  g_free (pixels);
 
695
}
 
696
 
 
697
static void get_pixmap_geometry (Pixmap       pixmap,
 
698
                     int         *w,
 
699
                     int         *h,
 
700
                     int         *d)
 
701
{
 
702
  Window root_ignored;
 
703
  int x_ignored, y_ignored;
 
704
  guint width, height;
 
705
  guint border_width_ignored;
 
706
  guint depth;
 
707
 
 
708
  if (w)
 
709
    *w = 1;
 
710
  if (h)
 
711
    *h = 1;
 
712
  if (d)
 
713
    *d = 1;
 
714
  
 
715
  XGetGeometry (GDK_DISPLAY(),
 
716
                pixmap, &root_ignored, &x_ignored, &y_ignored,
 
717
                &width, &height, &border_width_ignored, &depth);
 
718
 
 
719
  if (w)
 
720
    *w = width;
 
721
  if (h)
 
722
    *h = height;
 
723
  if (d)
 
724
    *d = depth;
 
725
}
 
726
 
 
727
GdkPixbuf* _wnck_gdk_pixbuf_get_from_pixmap (GdkPixbuf   *dest,
 
728
                                  Pixmap       xpixmap,
 
729
                                  int          src_x,
 
730
                                  int          src_y,
 
731
                                  int          dest_x,
 
732
                                  int          dest_y,
 
733
                                  int          width,
 
734
                                  int          height)
 
735
{
 
736
  GdkDrawable *drawable;
 
737
  GdkPixbuf *retval;
 
738
  GdkColormap *cmap;
 
739
  
 
740
  retval = NULL;
 
741
  
 
742
  drawable = gdk_xid_table_lookup (xpixmap);
 
743
 
 
744
  if (drawable)
 
745
    g_object_ref (G_OBJECT (drawable));
 
746
  else
 
747
    drawable = gdk_pixmap_foreign_new (xpixmap);
 
748
 
 
749
  cmap = get_cmap (drawable);
 
750
 
 
751
  /* GDK is supposed to do this but doesn't in GTK 2.0.2,
 
752
   * fixed in 2.0.3
 
753
   */
 
754
  if (width < 0)
 
755
    gdk_drawable_get_size (drawable, &width, NULL);
 
756
  if (height < 0)
 
757
    gdk_drawable_get_size (drawable, NULL, &height);
 
758
  
 
759
  retval = gdk_pixbuf_get_from_drawable (dest,
 
760
                                         drawable,
 
761
                                         cmap,
 
762
                                         src_x, src_y,
 
763
                                         dest_x, dest_y,
 
764
                                         width, height);
 
765
 
 
766
  if (cmap)
 
767
    g_object_unref (G_OBJECT (cmap));
 
768
  g_object_unref (G_OBJECT (drawable));
 
769
 
 
770
  return retval;
 
771
}
 
772
 
 
773
static GdkPixbuf* apply_mask (GdkPixbuf *pixbuf,
 
774
            GdkPixbuf *mask)
 
775
{
 
776
  int w, h;
 
777
  int i, j;
 
778
  GdkPixbuf *with_alpha;
 
779
  guchar *src;
 
780
  guchar *dest;
 
781
  int src_stride;
 
782
  int dest_stride;
 
783
  
 
784
  w = MIN (gdk_pixbuf_get_width (mask), gdk_pixbuf_get_width (pixbuf));
 
785
  h = MIN (gdk_pixbuf_get_height (mask), gdk_pixbuf_get_height (pixbuf));
 
786
  
 
787
  with_alpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
 
788
 
 
789
  dest = gdk_pixbuf_get_pixels (with_alpha);
 
790
  src = gdk_pixbuf_get_pixels (mask);
 
791
 
 
792
  dest_stride = gdk_pixbuf_get_rowstride (with_alpha);
 
793
  src_stride = gdk_pixbuf_get_rowstride (mask);
 
794
  
 
795
  i = 0;
 
796
  while (i < h)
 
797
    {
 
798
      j = 0;
 
799
      while (j < w)
 
800
        {
 
801
          guchar *s = src + i * src_stride + j * 3;
 
802
          guchar *d = dest + i * dest_stride + j * 4;
 
803
          
 
804
          /* s[0] == s[1] == s[2], they are 255 if the bit was set, 0
 
805
           * otherwise
 
806
           */
 
807
          if (s[0] == 0)
 
808
            d[3] = 0;   /* transparent */
 
809
          else
 
810
            d[3] = 255; /* opaque */
 
811
          
 
812
          ++j;
 
813
        }
 
814
      
 
815
      ++i;
 
816
    }
 
817
 
 
818
  return with_alpha;
 
819
}
 
820
 
 
821
static GdkPixbuf* scaled_from_pixdata (guchar *pixdata,
 
822
                     int     w,
 
823
                     int     h,
 
824
                     int     new_w,
 
825
                     int     new_h)
 
826
{
 
827
  GdkPixbuf *src;
 
828
  GdkPixbuf *dest;
 
829
  
 
830
  src = gdk_pixbuf_new_from_data (pixdata,
 
831
                                  GDK_COLORSPACE_RGB,
 
832
                                  TRUE,
 
833
                                  8,
 
834
                                  w, h, w * 4,
 
835
                                  free_pixels, 
 
836
                                  NULL);
 
837
 
 
838
  if (src == NULL)
 
839
    return NULL;
 
840
 
 
841
  if (w != h)
 
842
    {
 
843
      GdkPixbuf *tmp;
 
844
      int size;
 
845
      
 
846
      size = MAX (w, h);
 
847
      
 
848
      tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
 
849
      
 
850
      if (tmp != NULL) {
 
851
       gdk_pixbuf_fill (tmp, 0);
 
852
       gdk_pixbuf_copy_area (src, 0, 0, w, h, tmp, (size - w) / 2, (size - h) / 2);
 
853
      
 
854
       g_object_unref (src);
 
855
       src = tmp;
 
856
      }
 
857
    }
 
858
  
 
859
  if (w != new_w || h != new_h)
 
860
    {
 
861
      dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR);
 
862
      
 
863
      g_object_unref (G_OBJECT (src));
 
864
    }
 
865
  else
 
866
    {
 
867
      dest = src;
 
868
    }
 
869
 
 
870
  return dest;
 
871
}
 
872
 
 
873
gboolean try_wm_hints (Window xwindow, GdkPixbuf **iconp, 
 
874
  gint width, gint height)
 
875
{
 
876
  GdkPixbuf *unscaled = NULL;
 
877
  GdkPixbuf *mask = NULL;
 
878
  int w, h;
 
879
 
 
880
  Pixmap src_pixmap=None;
 
881
  Pixmap src_mask=None;
 
882
 
 
883
  if (!get_window_pixmap (xwindow, &src_pixmap, &src_mask))
 
884
    return FALSE;
 
885
 
 
886
  if (src_pixmap==None) {
 
887
    if (debug) printf ("src_pixmap is none\n");
 
888
    return FALSE;
 
889
  }
 
890
  
 
891
            
 
892
  gdk_error_trap_push();
 
893
 
 
894
  get_pixmap_geometry (src_pixmap, &w, &h, NULL);
 
895
      
 
896
  unscaled = _wnck_gdk_pixbuf_get_from_pixmap (NULL,
 
897
                                               src_pixmap,
 
898
                                               0, 0, 0, 0,
 
899
                                               w, h);
 
900
 
 
901
  if (unscaled && src_mask != None) {
 
902
      get_pixmap_geometry (src_mask, &w, &h, NULL);
 
903
      mask = _wnck_gdk_pixbuf_get_from_pixmap (NULL,
 
904
                                               src_mask,
 
905
                                               0, 0, 0, 0,
 
906
                                               w, h);
 
907
    }
 
908
  
 
909
   if (gdk_error_trap_pop ()) {
 
910
       if (unscaled)
 
911
         g_object_unref (unscaled);
 
912
       
 
913
       if (mask)
 
914
         g_object_unref (mask);
 
915
       
 
916
       return FALSE;
 
917
    }
 
918
 
 
919
  if (mask) {
 
920
      GdkPixbuf *masked;
 
921
      
 
922
      masked = apply_mask (unscaled, mask);
 
923
      g_object_unref (G_OBJECT (unscaled));
 
924
      unscaled = masked;
 
925
 
 
926
      g_object_unref (G_OBJECT (mask));
 
927
      mask = NULL;
 
928
    }
 
929
  
 
930
  if (unscaled) {
 
931
      *iconp =
 
932
        gdk_pixbuf_scale_simple (unscaled, width, height, GDK_INTERP_HYPER);
 
933
      
 
934
      
 
935
      g_object_unref (G_OBJECT (unscaled));
 
936
      return TRUE;
 
937
    }
 
938
  else
 
939
    return FALSE;
 
940
}
 
941
 
 
942
/* The icon-reading code is copied
 
943
 * from metacity, please sync bugfixes
 
944
 */
 
945
static gboolean find_largest_sizes (gulong *data,
 
946
                    gulong  nitems,
 
947
                    int    *width,
 
948
                    int    *height)
 
949
{
 
950
  *width = 0;
 
951
  *height = 0;
 
952
  
 
953
  while (nitems > 0)
 
954
    {
 
955
      int w, h;
 
956
      gboolean replace;
 
957
 
 
958
      replace = FALSE;
 
959
      
 
960
      if (nitems < 3)
 
961
        return FALSE; /* no space for w, h */
 
962
      
 
963
      w = data[0];
 
964
      h = data[1];
 
965
      
 
966
      if (nitems < ((w * h) + 2))
 
967
        return FALSE; /* not enough data */
 
968
 
 
969
      *width = MAX (w, *width);
 
970
      *height = MAX (h, *height);
 
971
      
 
972
      data += (w * h) + 2;
 
973
      nitems -= (w * h) + 2;
 
974
    }
 
975
 
 
976
  return TRUE;
 
977
}
 
978
 
 
979
static gboolean find_best_size (gulong  *data,
 
980
                gulong   nitems,
 
981
                int      ideal_width,
 
982
                int      ideal_height,
 
983
                int     *width,
 
984
                int     *height,
 
985
                gulong **start)
 
986
{
 
987
  int best_w;
 
988
  int best_h;
 
989
  gulong *best_start;
 
990
  int max_width, max_height;
 
991
  
 
992
  *width = 0;
 
993
  *height = 0;
 
994
  *start = NULL;
 
995
 
 
996
  if (!find_largest_sizes (data, nitems, &max_width, &max_height))
 
997
    return FALSE;
 
998
 
 
999
  if (ideal_width < 0)
 
1000
    ideal_width = max_width;
 
1001
  if (ideal_height < 0)
 
1002
    ideal_height = max_height;
 
1003
  
 
1004
  best_w = 0;
 
1005
  best_h = 0;
 
1006
  best_start = NULL;
 
1007
  
 
1008
  while (nitems > 0)
 
1009
    {
 
1010
      int w, h;
 
1011
      gboolean replace;
 
1012
 
 
1013
      replace = FALSE;
 
1014
      
 
1015
      if (nitems < 3)
 
1016
        return FALSE; /* no space for w, h */
 
1017
      
 
1018
      w = data[0];
 
1019
      h = data[1];
 
1020
      
 
1021
      if (nitems < ((w * h) + 2))
 
1022
        break; /* not enough data */
 
1023
 
 
1024
      if (best_start == NULL)
 
1025
        {
 
1026
          replace = TRUE;
 
1027
        }
 
1028
      else
 
1029
        {
 
1030
          /* work with averages */
 
1031
          const int ideal_size = (ideal_width + ideal_height) / 2;
 
1032
          int best_size = (best_w + best_h) / 2;
 
1033
          int this_size = (w + h) / 2;
 
1034
          
 
1035
          /* larger than desired is always better than smaller */
 
1036
          if (best_size < ideal_size &&
 
1037
              this_size >= ideal_size)
 
1038
            replace = TRUE;
 
1039
          /* if we have too small, pick anything bigger */
 
1040
          else if (best_size < ideal_size &&
 
1041
                   this_size > best_size)
 
1042
            replace = TRUE;
 
1043
          /* if we have too large, pick anything smaller
 
1044
           * but still >= the ideal
 
1045
           */
 
1046
          else if (best_size > ideal_size &&
 
1047
                   this_size >= ideal_size &&
 
1048
                   this_size < best_size)
 
1049
            replace = TRUE;
 
1050
        }
 
1051
 
 
1052
      if (replace)
 
1053
        {
 
1054
          best_start = data + 2;
 
1055
          best_w = w;
 
1056
          best_h = h;
 
1057
        }
 
1058
 
 
1059
      data += (w * h) + 2;
 
1060
      nitems -= (w * h) + 2;
 
1061
    }
 
1062
 
 
1063
  if (best_start)
 
1064
    {
 
1065
      *start = best_start;
 
1066
      *width = best_w;
 
1067
      *height = best_h;
 
1068
      return TRUE;
 
1069
    }
 
1070
  else
 
1071
    return FALSE;
 
1072
}
 
1073
 
 
1074
static void argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata)
 
1075
{
 
1076
  guchar *p;
 
1077
  int i;
 
1078
  
 
1079
  *pixdata = g_new (guchar, len * 4);
 
1080
  p = *pixdata;
 
1081
 
 
1082
  /* One could speed this up a lot. */
 
1083
  i = 0;
 
1084
  while (i < len)
 
1085
    {
 
1086
      guint argb;
 
1087
      guint rgba;
 
1088
      
 
1089
      argb = argb_data[i];
 
1090
      rgba = (argb << 8) | (argb >> 24);
 
1091
      
 
1092
      *p = rgba >> 24;
 
1093
      ++p;
 
1094
      *p = (rgba >> 16) & 0xff;
 
1095
      ++p;
 
1096
      *p = (rgba >> 8) & 0xff;
 
1097
      ++p;
 
1098
      *p = rgba & 0xff;
 
1099
      ++p;
 
1100
      
 
1101
      ++i;
 
1102
    }
 
1103
}
 
1104
 
 
1105
static gboolean read_rgb_icon (Window         xwindow,
 
1106
               int            ideal_width,
 
1107
               int            ideal_height,
 
1108
               int           *width,
 
1109
               int           *height,
 
1110
               guchar       **pixdata)
 
1111
         
 
1112
{
 
1113
  Atom type;
 
1114
  int format;
 
1115
  gulong nitems;
 
1116
  gulong bytes_after;
 
1117
  int result, err;
 
1118
  unsigned char *data;
 
1119
  gulong *best;
 
1120
  int w, h;
 
1121
   
 
1122
  gdk_error_trap_push();
 
1123
  type = None;
 
1124
  data = NULL;
 
1125
  result = XGetWindowProperty (GDK_DISPLAY(), xwindow,
 
1126
    net_wm_icon, 0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems,
 
1127
     &bytes_after, &data);
 
1128
  
 
1129
  err=gdk_error_trap_pop();
 
1130
      
 
1131
  if (result != Success || err || !data || type != XA_CARDINAL) {
 
1132
    if (debug) printf ("ERROR in read_rgb_icon\n");
 
1133
    return FALSE;
 
1134
  }
 
1135
 
 
1136
  if (!find_best_size ((gulong*)data, nitems,
 
1137
                       ideal_width, ideal_height,
 
1138
                       &w, &h, &best)) {
 
1139
      XFree (data);
 
1140
      return FALSE;
 
1141
  }
 
1142
  
 
1143
  *width = w;
 
1144
  *height = h;
 
1145
 
 
1146
  argbdata_to_pixdata (best, w * h, pixdata);
 
1147
 
 
1148
  XFree (data);
 
1149
  
 
1150
  return TRUE;
 
1151
}
 
1152
 
 
1153
GdkPixbuf *get_window_icon (Window xwindow, gint width, gint height)
 
1154
{
 
1155
 
 
1156
  guchar *pixdata;
 
1157
  int w, h;
 
1158
  GdkPixbuf *icon=NULL;
 
1159
  
 
1160
  if (debug) printf ("get_window_icon with size request: %dx%d\n", width, height);
 
1161
  
 
1162
  pixdata = NULL;
 
1163
  
 
1164
  if (read_rgb_icon (xwindow, width, height, &w, &h, &pixdata))   {
 
1165
  
 
1166
    if (debug) printf ("read_rgb_icon  --> ok\n");
 
1167
      
 
1168
    icon= scaled_from_pixdata (pixdata, w, h, width, height);
 
1169
  
 
1170
    if (icon)
 
1171
      return icon;
 
1172
  }
 
1173
  
 
1174
  if (debug) printf ("rgb failed\n");
 
1175
    
 
1176
  if (try_wm_hints (xwindow, &icon, width, height)) {
 
1177
    return icon;
 
1178
  }
 
1179
  
 
1180
  if (debug) printf ("need fallback icon\n");
 
1181
    
 
1182
  GdkPixbuf *fallback=NULL;
 
1183
  GdkPixbuf *fallback_scaled=NULL;
 
1184
    
 
1185
  fallback = gdk_pixbuf_new_from_inline (-1, fallback_icon,
 
1186
                                     FALSE,
 
1187
                                     NULL);
 
1188
  
 
1189
  if (fallback) {
 
1190
    fallback_scaled=gdk_pixbuf_scale_simple (fallback, 
 
1191
        width, height, GDK_INTERP_HYPER);
 
1192
    
 
1193
    g_object_unref (fallback);
 
1194
  }
 
1195
      
 
1196
  
 
1197
  g_assert (fallback_scaled);
 
1198
 
 
1199
  return fallback_scaled;
 
1200
 
 
1201
}
 
1202
 
 
1203
GdkPixbuf *get_user_icon (gchar *path, gint width, gint height)
 
1204
{
 
1205
  
 
1206
  GdkPixbuf *pix_return=NULL;
 
1207
  GdkPixbuf *pix_return_tmp=NULL;
 
1208
    
 
1209
  if (debug) printf ("get_user_icon: path: %s\n", path);
 
1210
    
 
1211
    if (g_file_test (path, G_FILE_TEST_EXISTS)) {
 
1212
    
 
1213
      GError *error=NULL;
 
1214
    
 
1215
      pix_return_tmp=gdk_pixbuf_new_from_file (path, &error);
 
1216
    
 
1217
      if (!pix_return_tmp)
 
1218
        printf ("%s\n", error->message);
 
1219
      else {
 
1220
         
 
1221
        pix_return=gdk_pixbuf_scale_simple (pix_return_tmp,
 
1222
           width, height, GDK_INTERP_HYPER);
 
1223
        g_object_unref (pix_return_tmp);
 
1224
      }
 
1225
      
 
1226
    } else {
 
1227
      
 
1228
      printf ("Alltray: Icon file %s do not exist !\n", path);
 
1229
    }
 
1230
 
 
1231
  return pix_return;
 
1232
}
 
1233
 
 
1234
void update_window_icon(win_struct *win)
 
1235
{
 
1236
 
 
1237
  GdkPixbuf *icon_return; 
 
1238
  static gboolean dont_update=FALSE;
 
1239
 
 
1240
  if (dont_update)
 
1241
    return;
 
1242
 
 
1243
  if (win->user_icon) {
 
1244
    icon_return=win->user_icon;
 
1245
    dont_update=TRUE;
 
1246
  }  else {
 
1247
    
 
1248
    if (win->xmms) {
 
1249
      icon_return=get_xmms_icon (30, 30);
 
1250
      dont_update=TRUE;
 
1251
    } else {
 
1252
      icon_return =get_window_icon (win->child_xlib, 30, 30);
 
1253
    }
 
1254
    
 
1255
  }
 
1256
  
 
1257
  if (icon_return) {
 
1258
   
 
1259
    if (win->window_icon) {
 
1260
      g_object_unref (win->window_icon);
 
1261
    }
 
1262
    win->window_icon=icon_return;
 
1263
  
 
1264
  }
 
1265
  
 
1266
  GList *icons=NULL;
 
1267
  
 
1268
  icons = g_list_append (icons, (gpointer) win->window_icon);
 
1269
  
 
1270
  if (win->xmms)
 
1271
    gdk_window_set_icon_list (win->xmms_main_window_gdk, icons);
 
1272
  else {
 
1273
 
 
1274
    if (win->no_reparent)
 
1275
      gdk_window_set_icon_list (win->child_gdk, icons);
 
1276
   else
 
1277
      gdk_window_set_icon_list (win->parent_gdk, icons);
 
1278
 
 
1279
  }
 
1280
  
 
1281
  g_list_free(icons);
 
1282
 
 
1283
}
 
1284
 
 
1285
void send_skip_message (Window win, gboolean add)
 
1286
{
 
1287
 
 
1288
  XEvent xev;
 
1289
 
 
1290
  xev.xclient.type = ClientMessage;
 
1291
  xev.xclient.serial = 0;
 
1292
  xev.xclient.send_event = True;
 
1293
  xev.xclient.window = win;
 
1294
  xev.xclient.message_type = net_wm_state;
 
1295
  xev.xclient.format = 32;
 
1296
  xev.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
 
1297
  xev.xclient.data.l[1] = net_wm_state_skip_taskbar;
 
1298
  xev.xclient.data.l[2] = 0;
 
1299
  xev.xclient.data.l[3] = 0;
 
1300
  xev.xclient.data.l[4] = 0;
 
1301
  
 
1302
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
 
1303
     SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
1304
  
 
1305
  XSync (GDK_DISPLAY(), False);
 
1306
 
 
1307
}
 
1308
 
 
1309
void skip_taskbar (win_struct *win, gboolean add)
 
1310
{
 
1311
  
 
1312
  Window parent_xlib;
 
1313
  GdkWindow *parent_gdk;
 
1314
 
 
1315
  do {
 
1316
 
 
1317
    if (win->xmms) {
 
1318
      parent_xlib=win->xmms_main_window_xlib;
 
1319
      parent_gdk=win->xmms_main_window_gdk;
 
1320
      break;
 
1321
    }
 
1322
  
 
1323
    if (win->no_reparent) {
 
1324
      parent_xlib=win->child_xlib;
 
1325
      parent_gdk=win->child_gdk;
 
1326
      break;
 
1327
    }
 
1328
  
 
1329
    parent_xlib=win->parent_xlib;
 
1330
    parent_gdk=win->parent_gdk;
 
1331
 
 
1332
  } until;
 
1333
 
 
1334
  
 
1335
  send_skip_message (parent_xlib, add);
 
1336
 
 
1337
}
 
1338
 
 
1339
char*
 
1340
_wnck_get_utf8_property (Window  xwindow,
 
1341
                         Atom    atom)
 
1342
{
 
1343
  Atom type;
 
1344
  int format;
 
1345
  gulong nitems;
 
1346
  gulong bytes_after;
 
1347
  guchar *val;
 
1348
  int err, result;
 
1349
  char *retval;
 
1350
 
 
1351
  gdk_error_trap_push();
 
1352
  type = None;
 
1353
  val = NULL;
 
1354
  result = XGetWindowProperty (GDK_DISPLAY(),
 
1355
     xwindow, atom, 0, G_MAXLONG, False, utf8_string,
 
1356
     &type, &format, &nitems, &bytes_after, (guchar **)&val);
 
1357
  err = gdk_error_trap_pop ();
 
1358
 
 
1359
  if (err != Success || result != Success)
 
1360
    return NULL;
 
1361
  
 
1362
  if (type != utf8_string || format != 8 || nitems == 0) {
 
1363
    if (val)
 
1364
      XFree (val);
 
1365
    return NULL;
 
1366
  }
 
1367
 
 
1368
  if (!g_utf8_validate (val, nitems, NULL)) {
 
1369
    printf ("Property contained invalid UTF-8\n");
 
1370
    XFree (val);
 
1371
    return NULL;
 
1372
  }
 
1373
  
 
1374
  retval = g_strndup (val, nitems);
 
1375
  
 
1376
  XFree (val);
 
1377
  
 
1378
  return retval;
 
1379
}
 
1380
 
 
1381
static char*
 
1382
text_property_to_utf8 (const XTextProperty *prop)
 
1383
{
 
1384
  char **list;
 
1385
  int count;
 
1386
  char *retval;
 
1387
  
 
1388
  list = NULL;
 
1389
 
 
1390
  count = gdk_text_property_to_utf8_list
 
1391
    (gdk_x11_xatom_to_atom (prop->encoding), prop->format,
 
1392
     prop->value, prop->nitems, &list);
 
1393
 
 
1394
  if (count == 0)
 
1395
    return NULL;
 
1396
 
 
1397
  retval = list[0];
 
1398
  list[0] = g_strdup (""); /* something to free */
 
1399
  
 
1400
  g_strfreev (list);
 
1401
 
 
1402
  return retval;
 
1403
}
 
1404
 
 
1405
char*
 
1406
_wnck_get_text_property (Window  xwindow,
 
1407
                         Atom    atom)
 
1408
{
 
1409
  XTextProperty text;
 
1410
  char *retval;
 
1411
  
 
1412
  gdk_error_trap_push ();
 
1413
 
 
1414
  text.nitems = 0;
 
1415
 
 
1416
  if (XGetTextProperty (GDK_DISPLAY(), xwindow, &text, atom)){
 
1417
    retval = text_property_to_utf8 (&text);
 
1418
    if (text.nitems > 0)
 
1419
      XFree (text.value);
 
1420
  } else {
 
1421
    retval = NULL;
 
1422
  }
 
1423
  
 
1424
  gdk_error_trap_pop ();
 
1425
 
 
1426
  return retval;
 
1427
}
 
1428
 
 
1429
char*
 
1430
wnck_get_name (Window xwindow)
 
1431
{
 
1432
  char *name;
 
1433
  
 
1434
  name = _wnck_get_utf8_property (xwindow, net_wm_visible_name);
 
1435
 
 
1436
  if (name == NULL) {
 
1437
    if (debug) printf ("net_wm_visible_name failed\n");
 
1438
    name = _wnck_get_utf8_property (xwindow, net_wm_name);
 
1439
  }
 
1440
 
 
1441
  if (name == NULL) {
 
1442
    if (debug) printf ("net_wm_name failed\n");
 
1443
    name = _wnck_get_text_property (xwindow, XA_WM_NAME);
 
1444
  }
 
1445
 
 
1446
  return name;
 
1447
}
 
1448
 
 
1449
void update_window_title(win_struct *win)
 
1450
{
 
1451
 
 
1452
  char *title = NULL;
 
1453
  gchar *title_string=NULL;
 
1454
  
 
1455
  Window child=None;
 
1456
   
 
1457
  if (debug) printf ("update window title\n");
 
1458
  
 
1459
  if (win->xmms)
 
1460
    child=win->xmms_main_window_xlib;
 
1461
  else
 
1462
    child=win->child_xlib;
 
1463
    
 
1464
  if (!assert_window(child))
 
1465
    return;
 
1466
  
 
1467
  title= wnck_get_name (child);
 
1468
 
 
1469
  if (title) {
 
1470
    
 
1471
    if (debug) printf ("title: %s\n", title);
 
1472
 
 
1473
    if (!win->xmms && win->no_reparent && g_str_has_suffix (title,"(AllTray)")) {
 
1474
      g_free (title);
 
1475
      return;
 
1476
    }
 
1477
 
 
1478
    if (!win->xmms) {
 
1479
      title_string=g_strconcat (title, " (AllTray)", NULL);
 
1480
 
 
1481
    if (!win->no_title) {
 
1482
      
 
1483
      if (win->no_reparent)
 
1484
        gdk_window_set_title (win->child_gdk, title_string);
 
1485
      else
 
1486
        gdk_window_set_title (win->parent_gdk, title_string);
 
1487
    }
 
1488
 
 
1489
      g_free (title_string);
 
1490
    }
 
1491
 
 
1492
    if (win->title)
 
1493
      g_free (win->title);
 
1494
    
 
1495
    if (win->xmms) {
 
1496
      if (!strcmp (title, "XMMS"))
 
1497
        win->title = g_strdup ("no title");
 
1498
      else
 
1499
        win->title = g_strdup (title+7*sizeof(char));
 
1500
    }
 
1501
    else
 
1502
      win->title=g_strdup (title);
 
1503
    
 
1504
    if (debug) printf ("win->title: %s\n", win->title);
 
1505
        
 
1506
    g_free(title);
 
1507
    
 
1508
    if (win->title_time)
 
1509
      show_balloon (win, win->title, win->title_time);
 
1510
 
 
1511
  }
 
1512
 
 
1513
}
 
1514
 
 
1515
void close_window (Window window)
 
1516
{
 
1517
 
 
1518
  XClientMessageEvent ev;
 
1519
 
 
1520
 
 
1521
  if (debug) printf ("close window\n");
 
1522
 
 
1523
  ev.type = ClientMessage;
 
1524
 
 
1525
  ev.window = window;
 
1526
  ev.message_type =net_close_window;
 
1527
  ev.format = 32;
 
1528
  ev.data.l[0] = 0;
 
1529
  ev.data.l[1] = 0;
 
1530
  ev.data.l[2] = 0;
 
1531
  ev.data.l[3] =0;
 
1532
  ev.data.l[4] = 0;
 
1533
  
 
1534
  gdk_error_trap_push ();
 
1535
  XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False, 
 
1536
  SubstructureNotifyMask | SubstructureRedirectMask, (XEvent *)&ev);
 
1537
  gdk_error_trap_pop ();
 
1538
    
 
1539
}
 
1540
 
 
1541
void free_command_menu (GArray *command_menu)
 
1542
{
 
1543
  
 
1544
  gint i;
 
1545
  command_menu_struct command;
 
1546
 
 
1547
  if (command_menu->len >0) {
 
1548
  
 
1549
    for (i=0; i < command_menu->len; i++) {
 
1550
      command=g_array_index (command_menu, command_menu_struct, i);
 
1551
      g_free (command.entry);
 
1552
      g_free (command.command);
 
1553
    }
 
1554
  
 
1555
  }
 
1556
 
 
1557
  g_array_free (command_menu, TRUE);
 
1558
}
 
1559
 
 
1560
void destroy_all_and_exit (win_struct *win, gboolean kill_child)
 
1561
{
 
1562
 
 
1563
  if (debug) printf ("destroy_all_and_exit\n");
 
1564
 
 
1565
  Window child;
 
1566
  gboolean child_dead=FALSE;
 
1567
    
 
1568
  if (win->xmms)
 
1569
    child=win->xmms_main_window_xlib;
 
1570
  else
 
1571
    child=win->child_xlib;
 
1572
 
 
1573
  child_dead=!assert_window (child);
 
1574
 
 
1575
  if (child_dead) {
 
1576
    if (debug) printf ("child already dead\n");
 
1577
    win->xmms_main_window_gdk=NULL;
 
1578
    win->child_gdk=NULL;
 
1579
  }
 
1580
 
 
1581
 
 
1582
  do {
 
1583
 
 
1584
    if (win->xmms) {
 
1585
      gdk_window_remove_filter (win->xmms_main_window_gdk, motion_filter_xmms, (gpointer) win);
 
1586
      gdk_window_remove_filter(win->xmms_main_window_gdk, event_filter, (gpointer) win);
 
1587
      break;
 
1588
    }
 
1589
 
 
1590
    if (win->no_reparent) {
 
1591
      gdk_window_remove_filter (win->child_gdk, motion_filter_gnome, (gpointer) win);
 
1592
      gdk_window_remove_filter(win->child_gdk, event_filter, (gpointer) win);
 
1593
      break;
 
1594
    }
 
1595
 
 
1596
    gdk_window_remove_filter(win->parent_gdk, parent_window_filter, (gpointer) win);
 
1597
    gdk_window_remove_filter(win->child_gdk, child_window_filter, (gpointer) win);
 
1598
    
 
1599
 
 
1600
  } until;
 
1601
 
 
1602
  if (!child_dead) {
 
1603
  
 
1604
    {
 
1605
      XWMHints *wm_hints;
 
1606
      
 
1607
      gdk_error_trap_push();
 
1608
      wm_hints= XGetWMHints(GDK_DISPLAY(), child);
 
1609
      if (!gdk_error_trap_pop() && wm_hints!=NULL) {
 
1610
        wm_hints->initial_state=NormalState;
 
1611
        XSetWMHints(GDK_DISPLAY(), child, wm_hints);
 
1612
        XFree(wm_hints);
 
1613
      }
 
1614
    }  
 
1615
  
 
1616
    if (!win->no_reparent) {
 
1617
          
 
1618
      get_window_position (win->parent_xlib, &win->parent_window_x, &win->parent_window_y);
 
1619
      XSelectInput(GDK_DISPLAY(), win->child_xlib, StructureNotifyMask);
 
1620
      XReparentWindow (GDK_DISPLAY(), win->child_xlib, GDK_ROOT_WINDOW(), 0,0);
 
1621
      XMoveWindow (win->display, win->child_xlib, win->parent_window_x, win->parent_window_y);
 
1622
      
 
1623
      for(;;) {
 
1624
        XEvent e;
 
1625
        XNextEvent(GDK_DISPLAY(), &e);
 
1626
        if (e.type == ReparentNotify)
 
1627
         break;
 
1628
      }
 
1629
    
 
1630
    } else {
 
1631
  
 
1632
      XWindowAttributes wa;
 
1633
  
 
1634
      gdk_error_trap_push();
 
1635
      XGetWindowAttributes (GDK_DISPLAY(), child, &wa);
 
1636
      gint err=gdk_error_trap_pop();
 
1637
    
 
1638
      if (!err && wa.map_state != IsViewable)
 
1639
     {
 
1640
  
 
1641
        XMapWindow (GDK_DISPLAY(), child);
 
1642
        XSync (GDK_DISPLAY(), False);
 
1643
  
 
1644
        for(;;) {
 
1645
          XEvent e;
 
1646
          XNextEvent(GDK_DISPLAY(), &e);
 
1647
          if (e.type == MapNotify) {
 
1648
            break;
 
1649
          }
 
1650
        }
 
1651
      
 
1652
      }
 
1653
    
 
1654
    }
 
1655
  
 
1656
    if (!win->xmms)
 
1657
      gdk_window_set_decorations (win->child_gdk, GDK_DECOR_ALL);
 
1658
    
 
1659
    skip_taskbar (win, FALSE);
 
1660
    skip_pager (win->child_xlib, FALSE);
 
1661
    rm_sticky (win->child_xlib);
 
1662
  
 
1663
  
 
1664
    if (kill_child)
 
1665
      close_window (child);
 
1666
 
 
1667
  }
 
1668
 
 
1669
  if (!win->notray)
 
1670
    tray_done(win);
 
1671
 
 
1672
  shortcut_done (win);
 
1673
 
 
1674
  if (win->no_reparent && !kill_child && !child_dead && !win->xmms)
 
1675
    gdk_window_set_title (win->child_gdk, win->title);
 
1676
 
 
1677
  g_free (win->title);
 
1678
 
 
1679
  if (win->user_icon_path)
 
1680
        g_free (win->user_icon_path);
 
1681
  
 
1682
  if (!win->xmms)
 
1683
    g_object_unref (win->window_icon);
 
1684
  
 
1685
  if (!win->notray)
 
1686
    g_object_unref (win->tray_icon);
 
1687
 
 
1688
  if (win->command_menu) 
 
1689
     free_command_menu (win->command_menu);
 
1690
  
 
1691
  if (!win->no_reparent)  
 
1692
    XDestroyWindow(win->display, win->parent_xlib);
 
1693
  
 
1694
  if (win->command)
 
1695
    g_free(win->command);
 
1696
  if (win->command_only)
 
1697
    g_free(win->command_only);
 
1698
  
 
1699
  g_free (win);
 
1700
 
 
1701
  gtk_main_quit ();
 
1702
 
 
1703
}
 
1704
 
 
1705
static GdkFilterReturn parent_filter_map (GdkXEvent *xevent, 
 
1706
    GdkEvent *event, gpointer user_data)
 
1707
{
 
1708
  XEvent *xev = (XEvent *)xevent;
 
1709
   
 
1710
  if (xev->xany.type == MapNotify) {
 
1711
  
 
1712
   if (debug) printf ("map notify\n");
 
1713
       
 
1714
   gtk_main_quit();
 
1715
 
 
1716
  }
 
1717
  
 
1718
  return GDK_FILTER_CONTINUE;
 
1719
}
 
1720
 
 
1721
void deiconify_window (Window window)
 
1722
{
 
1723
 
 
1724
  XWMHints *wm_hints;
 
1725
  
 
1726
  gdk_error_trap_push();
 
1727
  
 
1728
  wm_hints= XGetWMHints(GDK_DISPLAY(), window);
 
1729
  
 
1730
  if (!gdk_error_trap_pop() && wm_hints!=NULL) {
 
1731
  
 
1732
    wm_hints->initial_state=NormalState;
 
1733
    XSetWMHints(GDK_DISPLAY(), window, wm_hints);
 
1734
    XFree(wm_hints);
 
1735
  }
 
1736
 
 
1737
}
 
1738
 
 
1739
void geo_move (GdkWindow *window, gint screen_width, gint screen_height, 
 
1740
  gint x, gint y, gint w, gint h, int mask)
 
1741
{
 
1742
 
 
1743
  gint tmp_x=x, tmp_y=y, tmp_w=w, tmp_h=h;
 
1744
 
 
1745
   if (debug) {
 
1746
     printf ("geo_move 1: tmp_x: %d, tmp_y: %d\n", tmp_x, tmp_y);
 
1747
     printf ("geo_move 1: w: %d, h: %d\n", w, h);
 
1748
   }
 
1749
 
 
1750
  do {
 
1751
 
 
1752
    if (mask & XNegative) {
 
1753
      if (x < 0)
 
1754
        tmp_x = screen_width + x;
 
1755
      else
 
1756
        tmp_x = screen_width - w;
 
1757
    }
 
1758
    
 
1759
    if (mask & YNegative) {
 
1760
      if (y < 0)
 
1761
        tmp_y = screen_height + y;
 
1762
      else
 
1763
        tmp_y = screen_height - h;
 
1764
    }
 
1765
  
 
1766
   if (debug) {
 
1767
     printf ("geo_move 2: tmp_x: %d, tmp_y: %d, tmp_w: %d, tmp_h: %d\n", tmp_x, tmp_y, tmp_w, tmp_h);
 
1768
     printf ("geo_move 2: w: %d, h: %d\n", w, h);
 
1769
   }
 
1770
  
 
1771
  
 
1772
    if ( !(mask & WidthValue) && !(mask & HeightValue)) {
 
1773
      if (debug) printf ("only move\n");
 
1774
      gdk_window_move (window, tmp_x, tmp_y);
 
1775
      break;
 
1776
    }
 
1777
   
 
1778
    if ( !(mask & XValue) && !(mask & YValue)) {
 
1779
       
 
1780
     if (debug) printf ("only resize\n");
 
1781
       gdk_window_resize (window, tmp_w, tmp_h);
 
1782
       break;
 
1783
    }
 
1784
         
 
1785
    if (debug) printf ("move and resize\n");
 
1786
      gdk_window_move_resize (window, tmp_x, tmp_y, tmp_w, tmp_h);
 
1787
  
 
1788
  } until;
 
1789
 
 
1790
}
 
1791
 
 
1792
void show_hide_window (win_struct *win, gint force_state,
 
1793
  gboolean keep_in_taskbar)
 
1794
{
 
1795
 
 
1796
  gboolean show=TRUE;
 
1797
  static gboolean first_click=TRUE;
 
1798
  
 
1799
  Window parent_xlib;
 
1800
  GdkWindow *parent_gdk;
 
1801
 
 
1802
 
 
1803
  Window  root_return;
 
1804
  unsigned int x_return, y_return, width_return, height_return, border, depth;
 
1805
 
 
1806
  
 
1807
  do {
 
1808
 
 
1809
    if (win->xmms) {
 
1810
      parent_xlib=win->xmms_main_window_xlib;
 
1811
      parent_gdk=win->xmms_main_window_gdk;
 
1812
      break;
 
1813
    }
 
1814
  
 
1815
    if (win->no_reparent) {
 
1816
      parent_xlib=win->child_xlib;
 
1817
      parent_gdk=win->child_gdk;
 
1818
      break;
 
1819
    }
 
1820
  
 
1821
    parent_xlib=win->parent_xlib;
 
1822
    parent_gdk=win->parent_gdk;
 
1823
 
 
1824
  } until;
 
1825
 
 
1826
 
 
1827
  do {
 
1828
  
 
1829
    if (force_state == force_show) {
 
1830
      show=TRUE;
 
1831
      break;
 
1832
    }
 
1833
  
 
1834
    if (force_state == force_hide) {
 
1835
      show=FALSE;
 
1836
      break;
 
1837
    }
 
1838
 
 
1839
    if (win->visibility != VisibilityUnobscured  && 
 
1840
      parent_xlib != get_active_window()) {
 
1841
      show=TRUE;
 
1842
      break;
 
1843
    }
 
1844
    
 
1845
    show=!win->parent_is_visible;
 
1846
      
 
1847
   } until;
 
1848
 
 
1849
 
 
1850
  if (show) {
 
1851
  
 
1852
    if (debug) printf ("show\n");
 
1853
      
 
1854
    /*kwin what you doing all day long ???*/
 
1855
    if (win->kde) {
 
1856
      to_desktop (parent_xlib, get_current_desktop ());
 
1857
    }
 
1858
 
 
1859
    if (first_click) {
 
1860
 
 
1861
      if (debug) printf ("first click\n");
 
1862
      
 
1863
      if (win->xmms)
 
1864
        deiconify_xmms_windows(win);
 
1865
      else if (win->no_reparent && !win->normal_map && !win->click_mode)
 
1866
        deiconify_window (parent_xlib);
 
1867
      
 
1868
      gdk_window_add_filter(parent_gdk, parent_filter_map, (gpointer) win);
 
1869
      
 
1870
      if (!(win->geo_bitmask & WidthValue)) {
 
1871
        XGetGeometry (GDK_DISPLAY(), parent_xlib,
 
1872
        &root_return, &x_return, &y_return,  &win->initial_w, &height_return, &border, &depth);
 
1873
      }
 
1874
      
 
1875
      if (!(win->geo_bitmask & HeightValue)) {
 
1876
        XGetGeometry (GDK_DISPLAY(), parent_xlib,
 
1877
        &root_return, &x_return, &y_return, &width_return, &win->initial_h, &border, &depth);
 
1878
      }
 
1879
      
 
1880
      if (win->click_mode && !win->kde)  //XXX fixme, no focus under kde
 
1881
        gdk_window_focus (parent_gdk, gtk_get_current_event_time());
 
1882
      else
 
1883
        XMapWindow (win->display, parent_xlib);
 
1884
      
 
1885
      if (!win->normal_map && win->geo_bitmask) {
 
1886
        geo_move (parent_gdk, win->screen_width, win->screen_height, win->initial_x,
 
1887
        win->initial_y, win->initial_w, win->initial_h, win->geo_bitmask);
 
1888
      }
 
1889
      
 
1890
      gtk_main ();
 
1891
      
 
1892
      if (debug) printf ("mapped\n");
 
1893
      
 
1894
      gdk_window_remove_filter(parent_gdk, parent_filter_map, (gpointer) win);
 
1895
 
 
1896
      if (win->gnome)
 
1897
        check_if_pointer_is_over_button (win); 
 
1898
      
 
1899
      /*KDE want to rest a little bit after soo much work ;)*/
 
1900
      /*if not the window will not be the top most*/
 
1901
      if (!win->gnome)
 
1902
        gtk_sleep (100);
 
1903
      
 
1904
      if (win->sticky)
 
1905
        sticky (parent_xlib);
 
1906
      
 
1907
      skip_pager(parent_xlib, TRUE);
 
1908
      
 
1909
      if (win->skip_tasklist)
 
1910
        skip_taskbar (win, TRUE);
 
1911
      
 
1912
      first_click=FALSE;
 
1913
      
 
1914
      return;
 
1915
    
 
1916
    }
 
1917
 
 
1918
    gdk_window_focus (parent_gdk, gtk_get_current_event_time());
 
1919
 
 
1920
    if (win->gnome)
 
1921
        check_if_pointer_is_over_button (win);     
 
1922
 
 
1923
  
 
1924
    if (!win->skip_tasklist)
 
1925
      skip_taskbar (win, FALSE);
 
1926
      
 
1927
    
 
1928
   } else {
 
1929
   
 
1930
      if (debug) printf ("hide\n");
 
1931
         
 
1932
      XIconifyWindow (GDK_DISPLAY(), parent_xlib, DefaultScreen(GDK_DISPLAY()));
 
1933
      if (!win->skip_tasklist)
 
1934
        skip_taskbar (win, !keep_in_taskbar);
 
1935
 
 
1936
   }
 
1937
 
 
1938
}
 
1939
 
 
1940
gchar  *get_window_manager(void) {
 
1941
 
 
1942
  return g_strdup(gdk_x11_screen_get_window_manager_name (gdk_screen_get_default()));
 
1943
}