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.
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.
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.
26
* Jochen Baier, 2004, 2005, 2006 (email@Jochen-Baier.de)
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 !!!
46
#include "balloon_message.h"
49
#include "eventfilter.h"
50
#include "inlinepixbufs.h"
53
char *event_names[] = {
91
gboolean assert_window (Window window)
96
gdk_error_trap_push();
97
XGetWindowAttributes (GDK_DISPLAY(), window, &wa);
99
if (gdk_error_trap_pop())
105
void atom_init (void)
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);
138
Screen *screen = XDefaultScreenOfDisplay(GDK_DISPLAY());
140
sprintf(temp, "_NET_SYSTEM_TRAY_S%i", XScreenNumberOfScreen(screen));
141
selection_atom = XInternAtom(GDK_DISPLAY(), temp, False);
143
manager_atom = XInternAtom (GDK_DISPLAY(), "MANAGER", False);
144
system_tray_opcode_atom = XInternAtom (GDK_DISPLAY(),
145
"_NET_SYSTEM_TRAY_OPCODE", False);
149
void xprop (Window window)
152
gchar *tmp=g_strdup_printf ("xprop -id %d &", (int) window);
157
gboolean gtk_sleep_function (gpointer data)
163
void gtk_sleep (gint millisec)
166
g_timeout_add (millisec, gtk_sleep_function, NULL);
171
Window get_active_window (void)
175
unsigned long nitems;
176
unsigned long bytes_after;
184
gdk_error_trap_push();
185
result = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
187
0, 0x7fffffff, False,XA_WINDOW, &type, &format, &nitems,
188
&bytes_after, &data);
190
err=gdk_error_trap_pop();
192
if (err!=0 || result != Success)
195
if (type != XA_WINDOW) {
201
win= *((Window *) data);
202
if (debug) printf ("active window id %d\n", (int) win);
209
gint get_current_desktop(void)
213
unsigned long nitems;
214
unsigned long bytes_after;
222
gdk_error_trap_push();
223
result = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
225
0, 1l, False,XA_CARDINAL, &type, &format, &nitems,
226
&bytes_after, &data);
228
err=gdk_error_trap_pop();
230
if (err!=0 || result != Success)
233
if (type == XA_CARDINAL && format == 32 && nitems == 1)
234
number = *((long *) data);
243
gboolean get_window_list (Window xwindow,
258
gdk_error_trap_push();
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 ();
265
if (err != Success || result != Success)
268
if (type != XA_WINDOW) {
273
*windows = g_new (Window, nitems);
274
memcpy (*windows, (Window*) data, sizeof (Window) * nitems);
282
gint get_pid (Window w)
287
unsigned long nitems, leftover;
288
unsigned char *pid_return;
293
gdk_error_trap_push();
295
status=XGetWindowProperty(GDK_DISPLAY(), w,
297
1, False, XA_CARDINAL, &actual_type,
298
&actual_format, &nitems, &leftover, &pid_return);
300
err=gdk_error_trap_pop();
302
if (err!=0 || status != Success)
306
pid=*(gint *) pid_return;
313
gboolean window_type_is_normal (Window win)
317
unsigned long nitems, bytes_after;
318
unsigned char *data = 0;
320
gboolean normal=TRUE;
326
gdk_error_trap_push();
328
result = XGetWindowProperty (GDK_DISPLAY(), win,
329
net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM,
330
&type, &format, &nitems, &bytes_after, &data);
332
err=gdk_error_trap_pop();
334
if (err || result != Success) {
340
Atom *atoms = (unsigned long *)data;
342
for (l=0; l<nitems; ++l) {
344
if (atoms[l] != net_wm_window_type_normal) {
358
void skip_pager (Window window, gboolean add)
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;
375
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
376
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
379
void sticky (Window window)
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;
396
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
397
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
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;
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;
414
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
415
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
419
void to_desktop (Window window, gint num)
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;
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;
439
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
440
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
444
void rm_sticky (Window window)
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;
462
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
463
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
468
void show_pixbuf (GdkPixbuf *buf)
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);
482
void display_window_id(Display *display, Window window)
485
static char *window_id_format = "0x%lx";
490
if (!assert_window (window))
493
printf(window_id_format, window); /* print id # in hex/dec */
498
if (window == DefaultRootWindow (display)) {
499
printf(" (the root window)");
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);
508
printf(" (has no name)");
511
printf ("window int: %d\n", (int) window);
517
/*from gdk-pixbuf-xlib-drawabel.c*/
518
gboolean xlib_window_is_viewable (Window w)
520
XWindowAttributes wa;
525
Window parent, root, *children;
528
gdk_error_trap_push();
529
XGetWindowAttributes (GDK_DISPLAY(), w, &wa);
530
err=gdk_error_trap_pop();
535
if (wa.map_state != IsViewable) {
539
if (!XQueryTree (GDK_DISPLAY(), w, &root, &parent, &children, (unsigned int *) &nchildren))
545
if ((parent == root) || (w == root))
553
void get_window_position (Window window, gint *x, gint *y)
557
unsigned int width_return, height_return, border, depth;
559
Window our=one_under_root(GDK_DISPLAY(), window);
561
if (debug) printf ("get_window_position: window normal: %d, window our: %d\n",
562
(int) window, (int)our);
564
XGetGeometry (GDK_DISPLAY(), our,
565
&root_return, x, y, &height_return, &width_return, &border, &depth);
569
GPid exec_command (gchar *command)
572
gchar **child_vector=NULL;
576
gboolean success_parse;
577
gboolean success_spawn;
579
success_parse=g_shell_parse_argv (command, &num, &child_vector, NULL);
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);
586
printf ("AllTray: %s\n", error->message);
588
g_strfreev (child_vector);
595
Window one_under_root (Display *display, Window window)
598
Window root_return=None;
607
if (debug) printf ("one under root function\n");
611
if (debug) printf ("current runner: %d\n", (int) runner);
613
if (! XQueryTree (display, runner, &root_return, &parent, &kids, (unsigned int *) &nkids))
615
if (kids) XFree ((char *)kids);
617
if (parent == DefaultRootWindow (display))
628
get_cmap (GdkPixmap *pixmap)
632
cmap = gdk_drawable_get_colormap (pixmap);
634
g_object_ref (G_OBJECT (cmap));
638
if (gdk_drawable_get_depth (pixmap) == 1)
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));
652
/* Be sure we aren't going to blow up due to visual mismatch */
654
(gdk_colormap_get_visual (cmap)->depth !=
655
gdk_drawable_get_depth (pixmap)))
661
gboolean get_window_pixmap (Window window, Pixmap *pix, Pixmap *mask)
666
gdk_error_trap_push();
668
wm_hints= XGetWMHints(GDK_DISPLAY(), window);
670
if (gdk_error_trap_pop()) {
676
if (wm_hints != NULL) {
677
if (!(wm_hints->flags & IconMaskHint))
678
wm_hints->icon_mask = None;
680
if ((wm_hints->flags & IconPixmapHint) && (wm_hints->icon_pixmap)) {
681
*pix=wm_hints->icon_pixmap;
682
*mask=wm_hints->icon_mask;
692
static void free_pixels (guchar *pixels, gpointer data)
697
static void get_pixmap_geometry (Pixmap pixmap,
703
int x_ignored, y_ignored;
705
guint border_width_ignored;
715
XGetGeometry (GDK_DISPLAY(),
716
pixmap, &root_ignored, &x_ignored, &y_ignored,
717
&width, &height, &border_width_ignored, &depth);
727
GdkPixbuf* _wnck_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest,
736
GdkDrawable *drawable;
742
drawable = gdk_xid_table_lookup (xpixmap);
745
g_object_ref (G_OBJECT (drawable));
747
drawable = gdk_pixmap_foreign_new (xpixmap);
749
cmap = get_cmap (drawable);
751
/* GDK is supposed to do this but doesn't in GTK 2.0.2,
755
gdk_drawable_get_size (drawable, &width, NULL);
757
gdk_drawable_get_size (drawable, NULL, &height);
759
retval = gdk_pixbuf_get_from_drawable (dest,
767
g_object_unref (G_OBJECT (cmap));
768
g_object_unref (G_OBJECT (drawable));
773
static GdkPixbuf* apply_mask (GdkPixbuf *pixbuf,
778
GdkPixbuf *with_alpha;
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));
787
with_alpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
789
dest = gdk_pixbuf_get_pixels (with_alpha);
790
src = gdk_pixbuf_get_pixels (mask);
792
dest_stride = gdk_pixbuf_get_rowstride (with_alpha);
793
src_stride = gdk_pixbuf_get_rowstride (mask);
801
guchar *s = src + i * src_stride + j * 3;
802
guchar *d = dest + i * dest_stride + j * 4;
804
/* s[0] == s[1] == s[2], they are 255 if the bit was set, 0
808
d[3] = 0; /* transparent */
810
d[3] = 255; /* opaque */
821
static GdkPixbuf* scaled_from_pixdata (guchar *pixdata,
830
src = gdk_pixbuf_new_from_data (pixdata,
848
tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
851
gdk_pixbuf_fill (tmp, 0);
852
gdk_pixbuf_copy_area (src, 0, 0, w, h, tmp, (size - w) / 2, (size - h) / 2);
854
g_object_unref (src);
859
if (w != new_w || h != new_h)
861
dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR);
863
g_object_unref (G_OBJECT (src));
873
gboolean try_wm_hints (Window xwindow, GdkPixbuf **iconp,
874
gint width, gint height)
876
GdkPixbuf *unscaled = NULL;
877
GdkPixbuf *mask = NULL;
880
Pixmap src_pixmap=None;
881
Pixmap src_mask=None;
883
if (!get_window_pixmap (xwindow, &src_pixmap, &src_mask))
886
if (src_pixmap==None) {
887
if (debug) printf ("src_pixmap is none\n");
892
gdk_error_trap_push();
894
get_pixmap_geometry (src_pixmap, &w, &h, NULL);
896
unscaled = _wnck_gdk_pixbuf_get_from_pixmap (NULL,
901
if (unscaled && src_mask != None) {
902
get_pixmap_geometry (src_mask, &w, &h, NULL);
903
mask = _wnck_gdk_pixbuf_get_from_pixmap (NULL,
909
if (gdk_error_trap_pop ()) {
911
g_object_unref (unscaled);
914
g_object_unref (mask);
922
masked = apply_mask (unscaled, mask);
923
g_object_unref (G_OBJECT (unscaled));
926
g_object_unref (G_OBJECT (mask));
932
gdk_pixbuf_scale_simple (unscaled, width, height, GDK_INTERP_HYPER);
935
g_object_unref (G_OBJECT (unscaled));
942
/* The icon-reading code is copied
943
* from metacity, please sync bugfixes
945
static gboolean find_largest_sizes (gulong *data,
961
return FALSE; /* no space for w, h */
966
if (nitems < ((w * h) + 2))
967
return FALSE; /* not enough data */
969
*width = MAX (w, *width);
970
*height = MAX (h, *height);
973
nitems -= (w * h) + 2;
979
static gboolean find_best_size (gulong *data,
990
int max_width, max_height;
996
if (!find_largest_sizes (data, nitems, &max_width, &max_height))
1000
ideal_width = max_width;
1001
if (ideal_height < 0)
1002
ideal_height = max_height;
1016
return FALSE; /* no space for w, h */
1021
if (nitems < ((w * h) + 2))
1022
break; /* not enough data */
1024
if (best_start == NULL)
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;
1035
/* larger than desired is always better than smaller */
1036
if (best_size < ideal_size &&
1037
this_size >= ideal_size)
1039
/* if we have too small, pick anything bigger */
1040
else if (best_size < ideal_size &&
1041
this_size > best_size)
1043
/* if we have too large, pick anything smaller
1044
* but still >= the ideal
1046
else if (best_size > ideal_size &&
1047
this_size >= ideal_size &&
1048
this_size < best_size)
1054
best_start = data + 2;
1059
data += (w * h) + 2;
1060
nitems -= (w * h) + 2;
1065
*start = best_start;
1074
static void argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata)
1079
*pixdata = g_new (guchar, len * 4);
1082
/* One could speed this up a lot. */
1089
argb = argb_data[i];
1090
rgba = (argb << 8) | (argb >> 24);
1094
*p = (rgba >> 16) & 0xff;
1096
*p = (rgba >> 8) & 0xff;
1105
static gboolean read_rgb_icon (Window xwindow,
1118
unsigned char *data;
1122
gdk_error_trap_push();
1125
result = XGetWindowProperty (GDK_DISPLAY(), xwindow,
1126
net_wm_icon, 0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems,
1127
&bytes_after, &data);
1129
err=gdk_error_trap_pop();
1131
if (result != Success || err || !data || type != XA_CARDINAL) {
1132
if (debug) printf ("ERROR in read_rgb_icon\n");
1136
if (!find_best_size ((gulong*)data, nitems,
1137
ideal_width, ideal_height,
1146
argbdata_to_pixdata (best, w * h, pixdata);
1153
GdkPixbuf *get_window_icon (Window xwindow, gint width, gint height)
1158
GdkPixbuf *icon=NULL;
1160
if (debug) printf ("get_window_icon with size request: %dx%d\n", width, height);
1164
if (read_rgb_icon (xwindow, width, height, &w, &h, &pixdata)) {
1166
if (debug) printf ("read_rgb_icon --> ok\n");
1168
icon= scaled_from_pixdata (pixdata, w, h, width, height);
1174
if (debug) printf ("rgb failed\n");
1176
if (try_wm_hints (xwindow, &icon, width, height)) {
1180
if (debug) printf ("need fallback icon\n");
1182
GdkPixbuf *fallback=NULL;
1183
GdkPixbuf *fallback_scaled=NULL;
1185
fallback = gdk_pixbuf_new_from_inline (-1, fallback_icon,
1190
fallback_scaled=gdk_pixbuf_scale_simple (fallback,
1191
width, height, GDK_INTERP_HYPER);
1193
g_object_unref (fallback);
1197
g_assert (fallback_scaled);
1199
return fallback_scaled;
1203
GdkPixbuf *get_user_icon (gchar *path, gint width, gint height)
1206
GdkPixbuf *pix_return=NULL;
1207
GdkPixbuf *pix_return_tmp=NULL;
1209
if (debug) printf ("get_user_icon: path: %s\n", path);
1211
if (g_file_test (path, G_FILE_TEST_EXISTS)) {
1215
pix_return_tmp=gdk_pixbuf_new_from_file (path, &error);
1217
if (!pix_return_tmp)
1218
printf ("%s\n", error->message);
1221
pix_return=gdk_pixbuf_scale_simple (pix_return_tmp,
1222
width, height, GDK_INTERP_HYPER);
1223
g_object_unref (pix_return_tmp);
1228
printf ("Alltray: Icon file %s do not exist !\n", path);
1234
void update_window_icon(win_struct *win)
1237
GdkPixbuf *icon_return;
1238
static gboolean dont_update=FALSE;
1243
if (win->user_icon) {
1244
icon_return=win->user_icon;
1249
icon_return=get_xmms_icon (30, 30);
1252
icon_return =get_window_icon (win->child_xlib, 30, 30);
1259
if (win->window_icon) {
1260
g_object_unref (win->window_icon);
1262
win->window_icon=icon_return;
1268
icons = g_list_append (icons, (gpointer) win->window_icon);
1271
gdk_window_set_icon_list (win->xmms_main_window_gdk, icons);
1274
if (win->no_reparent)
1275
gdk_window_set_icon_list (win->child_gdk, icons);
1277
gdk_window_set_icon_list (win->parent_gdk, icons);
1285
void send_skip_message (Window win, gboolean add)
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;
1302
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
1303
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
1305
XSync (GDK_DISPLAY(), False);
1309
void skip_taskbar (win_struct *win, gboolean add)
1313
GdkWindow *parent_gdk;
1318
parent_xlib=win->xmms_main_window_xlib;
1319
parent_gdk=win->xmms_main_window_gdk;
1323
if (win->no_reparent) {
1324
parent_xlib=win->child_xlib;
1325
parent_gdk=win->child_gdk;
1329
parent_xlib=win->parent_xlib;
1330
parent_gdk=win->parent_gdk;
1335
send_skip_message (parent_xlib, add);
1340
_wnck_get_utf8_property (Window xwindow,
1351
gdk_error_trap_push();
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 ();
1359
if (err != Success || result != Success)
1362
if (type != utf8_string || format != 8 || nitems == 0) {
1368
if (!g_utf8_validate (val, nitems, NULL)) {
1369
printf ("Property contained invalid UTF-8\n");
1374
retval = g_strndup (val, nitems);
1382
text_property_to_utf8 (const XTextProperty *prop)
1390
count = gdk_text_property_to_utf8_list
1391
(gdk_x11_xatom_to_atom (prop->encoding), prop->format,
1392
prop->value, prop->nitems, &list);
1398
list[0] = g_strdup (""); /* something to free */
1406
_wnck_get_text_property (Window xwindow,
1412
gdk_error_trap_push ();
1416
if (XGetTextProperty (GDK_DISPLAY(), xwindow, &text, atom)){
1417
retval = text_property_to_utf8 (&text);
1418
if (text.nitems > 0)
1424
gdk_error_trap_pop ();
1430
wnck_get_name (Window xwindow)
1434
name = _wnck_get_utf8_property (xwindow, net_wm_visible_name);
1437
if (debug) printf ("net_wm_visible_name failed\n");
1438
name = _wnck_get_utf8_property (xwindow, net_wm_name);
1442
if (debug) printf ("net_wm_name failed\n");
1443
name = _wnck_get_text_property (xwindow, XA_WM_NAME);
1449
void update_window_title(win_struct *win)
1453
gchar *title_string=NULL;
1457
if (debug) printf ("update window title\n");
1460
child=win->xmms_main_window_xlib;
1462
child=win->child_xlib;
1464
if (!assert_window(child))
1467
title= wnck_get_name (child);
1471
if (debug) printf ("title: %s\n", title);
1473
if (!win->xmms && win->no_reparent && g_str_has_suffix (title,"(AllTray)")) {
1479
title_string=g_strconcat (title, " (AllTray)", NULL);
1481
if (!win->no_title) {
1483
if (win->no_reparent)
1484
gdk_window_set_title (win->child_gdk, title_string);
1486
gdk_window_set_title (win->parent_gdk, title_string);
1489
g_free (title_string);
1493
g_free (win->title);
1496
if (!strcmp (title, "XMMS"))
1497
win->title = g_strdup ("no title");
1499
win->title = g_strdup (title+7*sizeof(char));
1502
win->title=g_strdup (title);
1504
if (debug) printf ("win->title: %s\n", win->title);
1508
if (win->title_time)
1509
show_balloon (win, win->title, win->title_time);
1515
void close_window (Window window)
1518
XClientMessageEvent ev;
1521
if (debug) printf ("close window\n");
1523
ev.type = ClientMessage;
1526
ev.message_type =net_close_window;
1534
gdk_error_trap_push ();
1535
XSendEvent (GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
1536
SubstructureNotifyMask | SubstructureRedirectMask, (XEvent *)&ev);
1537
gdk_error_trap_pop ();
1541
void free_command_menu (GArray *command_menu)
1545
command_menu_struct command;
1547
if (command_menu->len >0) {
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);
1557
g_array_free (command_menu, TRUE);
1560
void destroy_all_and_exit (win_struct *win, gboolean kill_child)
1563
if (debug) printf ("destroy_all_and_exit\n");
1566
gboolean child_dead=FALSE;
1569
child=win->xmms_main_window_xlib;
1571
child=win->child_xlib;
1573
child_dead=!assert_window (child);
1576
if (debug) printf ("child already dead\n");
1577
win->xmms_main_window_gdk=NULL;
1578
win->child_gdk=NULL;
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);
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);
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);
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);
1616
if (!win->no_reparent) {
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);
1625
XNextEvent(GDK_DISPLAY(), &e);
1626
if (e.type == ReparentNotify)
1632
XWindowAttributes wa;
1634
gdk_error_trap_push();
1635
XGetWindowAttributes (GDK_DISPLAY(), child, &wa);
1636
gint err=gdk_error_trap_pop();
1638
if (!err && wa.map_state != IsViewable)
1641
XMapWindow (GDK_DISPLAY(), child);
1642
XSync (GDK_DISPLAY(), False);
1646
XNextEvent(GDK_DISPLAY(), &e);
1647
if (e.type == MapNotify) {
1657
gdk_window_set_decorations (win->child_gdk, GDK_DECOR_ALL);
1659
skip_taskbar (win, FALSE);
1660
skip_pager (win->child_xlib, FALSE);
1661
rm_sticky (win->child_xlib);
1665
close_window (child);
1672
shortcut_done (win);
1674
if (win->no_reparent && !kill_child && !child_dead && !win->xmms)
1675
gdk_window_set_title (win->child_gdk, win->title);
1677
g_free (win->title);
1679
if (win->user_icon_path)
1680
g_free (win->user_icon_path);
1683
g_object_unref (win->window_icon);
1686
g_object_unref (win->tray_icon);
1688
if (win->command_menu)
1689
free_command_menu (win->command_menu);
1691
if (!win->no_reparent)
1692
XDestroyWindow(win->display, win->parent_xlib);
1695
g_free(win->command);
1696
if (win->command_only)
1697
g_free(win->command_only);
1705
static GdkFilterReturn parent_filter_map (GdkXEvent *xevent,
1706
GdkEvent *event, gpointer user_data)
1708
XEvent *xev = (XEvent *)xevent;
1710
if (xev->xany.type == MapNotify) {
1712
if (debug) printf ("map notify\n");
1718
return GDK_FILTER_CONTINUE;
1721
void deiconify_window (Window window)
1726
gdk_error_trap_push();
1728
wm_hints= XGetWMHints(GDK_DISPLAY(), window);
1730
if (!gdk_error_trap_pop() && wm_hints!=NULL) {
1732
wm_hints->initial_state=NormalState;
1733
XSetWMHints(GDK_DISPLAY(), window, wm_hints);
1739
void geo_move (GdkWindow *window, gint screen_width, gint screen_height,
1740
gint x, gint y, gint w, gint h, int mask)
1743
gint tmp_x=x, tmp_y=y, tmp_w=w, tmp_h=h;
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);
1752
if (mask & XNegative) {
1754
tmp_x = screen_width + x;
1756
tmp_x = screen_width - w;
1759
if (mask & YNegative) {
1761
tmp_y = screen_height + y;
1763
tmp_y = screen_height - h;
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);
1772
if ( !(mask & WidthValue) && !(mask & HeightValue)) {
1773
if (debug) printf ("only move\n");
1774
gdk_window_move (window, tmp_x, tmp_y);
1778
if ( !(mask & XValue) && !(mask & YValue)) {
1780
if (debug) printf ("only resize\n");
1781
gdk_window_resize (window, tmp_w, tmp_h);
1785
if (debug) printf ("move and resize\n");
1786
gdk_window_move_resize (window, tmp_x, tmp_y, tmp_w, tmp_h);
1792
void show_hide_window (win_struct *win, gint force_state,
1793
gboolean keep_in_taskbar)
1797
static gboolean first_click=TRUE;
1800
GdkWindow *parent_gdk;
1804
unsigned int x_return, y_return, width_return, height_return, border, depth;
1810
parent_xlib=win->xmms_main_window_xlib;
1811
parent_gdk=win->xmms_main_window_gdk;
1815
if (win->no_reparent) {
1816
parent_xlib=win->child_xlib;
1817
parent_gdk=win->child_gdk;
1821
parent_xlib=win->parent_xlib;
1822
parent_gdk=win->parent_gdk;
1829
if (force_state == force_show) {
1834
if (force_state == force_hide) {
1839
if (win->visibility != VisibilityUnobscured &&
1840
parent_xlib != get_active_window()) {
1845
show=!win->parent_is_visible;
1852
if (debug) printf ("show\n");
1854
/*kwin what you doing all day long ???*/
1856
to_desktop (parent_xlib, get_current_desktop ());
1861
if (debug) printf ("first click\n");
1864
deiconify_xmms_windows(win);
1865
else if (win->no_reparent && !win->normal_map && !win->click_mode)
1866
deiconify_window (parent_xlib);
1868
gdk_window_add_filter(parent_gdk, parent_filter_map, (gpointer) win);
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);
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);
1880
if (win->click_mode && !win->kde) //XXX fixme, no focus under kde
1881
gdk_window_focus (parent_gdk, gtk_get_current_event_time());
1883
XMapWindow (win->display, parent_xlib);
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);
1892
if (debug) printf ("mapped\n");
1894
gdk_window_remove_filter(parent_gdk, parent_filter_map, (gpointer) win);
1897
check_if_pointer_is_over_button (win);
1899
/*KDE want to rest a little bit after soo much work ;)*/
1900
/*if not the window will not be the top most*/
1905
sticky (parent_xlib);
1907
skip_pager(parent_xlib, TRUE);
1909
if (win->skip_tasklist)
1910
skip_taskbar (win, TRUE);
1918
gdk_window_focus (parent_gdk, gtk_get_current_event_time());
1921
check_if_pointer_is_over_button (win);
1924
if (!win->skip_tasklist)
1925
skip_taskbar (win, FALSE);
1930
if (debug) printf ("hide\n");
1932
XIconifyWindow (GDK_DISPLAY(), parent_xlib, DefaultScreen(GDK_DISPLAY()));
1933
if (!win->skip_tasklist)
1934
skip_taskbar (win, !keep_in_taskbar);
1940
gchar *get_window_manager(void) {
1942
return g_strdup(gdk_x11_screen_get_window_manager_name (gdk_screen_get_default()));