4
* Copyright (C) 2000, 2001 Eazel, Inc.
5
* 2002 Sun Microsystems Inc.
7
* Authors: George Lebl <jirka@5z.com>
8
* Mark McLoughlin <mark@skynet.ie>
10
* Contains code from the Window Maker window manager
12
* Copyright (c) 1997-2002 Alfredo K. Kojima
23
#include <X11/Xatom.h>
27
#if GTK_CHECK_VERSION (3, 0, 0)
28
#define GDK_WINDOW_XWINDOW(x) GDK_WINDOW_XID(x)
29
#define gdk_x11_drawable_get_xid(x) GDK_WINDOW_XID(x)
33
panel_atom_get (const char *atom_name)
35
static GHashTable *atom_hash;
39
g_return_val_if_fail (atom_name != NULL, None);
41
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
44
atom_hash = g_hash_table_new_full (
45
g_str_hash, g_str_equal, g_free, NULL);
47
retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
49
retval = XInternAtom (xdisplay, atom_name, FALSE);
52
g_hash_table_insert (atom_hash, g_strdup (atom_name),
53
GUINT_TO_POINTER (retval));
59
/* Stolen from deskguide */
61
get_typed_property_data (Display *xdisplay,
66
guint expected_format)
68
static const guint prop_buffer_lengh = 1024 * 1024;
69
unsigned char *prop_data = NULL;
70
Atom type_returned = 0;
71
unsigned long nitems_return = 0, bytes_after_return = 0;
72
int format_returned = 0;
74
gboolean abort = FALSE;
76
g_return_val_if_fail (size_p != NULL, NULL);
79
gdk_error_trap_push ();
81
abort = XGetWindowProperty (xdisplay,
87
&type_returned, &format_returned,
90
&prop_data) != Success;
91
if (gdk_error_trap_pop () ||
92
type_returned == None)
95
requested_type != AnyPropertyType &&
96
requested_type != type_returned)
98
g_warning ("%s(): Property has wrong type, probably on crack", G_STRFUNC);
101
if (!abort && bytes_after_return)
103
g_warning ("%s(): Eeek, property has more than %u bytes, stored on harddisk?",
104
G_STRFUNC, prop_buffer_lengh);
107
if (!abort && expected_format && expected_format != format_returned)
109
g_warning ("%s(): Expected format (%u) unmatched (%d), programmer was drunk?",
110
G_STRFUNC, expected_format, format_returned);
113
if (!abort && prop_data && nitems_return && format_returned)
115
switch (format_returned)
118
*size_p = nitems_return * 4;
119
if (sizeof (gulong) == 8)
121
guint32 i, *mem = g_malloc0 (*size_p + 1);
122
gulong *prop_longs = (gulong*) prop_data;
124
for (i = 0; i < *size_p / 4; i++)
125
mem[i] = prop_longs[i];
130
*size_p = nitems_return * 2;
133
*size_p = nitems_return;
136
g_warning ("Unknown property data format with %d bits (extraterrestrial?)",
140
if (!data && *size_p)
142
guint8 *mem = g_malloc (*size_p + 1);
144
memcpy (mem, prop_data, *size_p);
157
xstuff_is_compliant_wm (void)
164
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
165
root_window = GDK_WINDOW_XWINDOW (
166
gdk_get_default_root_window ());
168
/* FIXME this is totally broken; should be using
169
* gdk_net_wm_supports() on particular hints when we rely
170
* on those particular hints
172
data = get_typed_property_data (
173
xdisplay, root_window,
174
panel_atom_get ("_NET_SUPPORTED"),
180
/* Actually checks for some of these */
185
#if !GTK_CHECK_VERSION (3, 0, 0)
187
xstuff_net_wm_supports (const char *hint)
189
return gdk_net_wm_supports (gdk_atom_intern (hint, FALSE));
194
xstuff_set_no_group (GdkWindow *win)
196
XWMHints *old_wmhints;
197
XWMHints wmhints = {0};
199
XDeleteProperty (GDK_WINDOW_XDISPLAY (win),
200
GDK_WINDOW_XWINDOW (win),
201
panel_atom_get ("WM_CLIENT_LEADER"));
203
old_wmhints = XGetWMHints (GDK_WINDOW_XDISPLAY (win),
204
GDK_WINDOW_XWINDOW (win));
205
/* General paranoia */
206
if (old_wmhints != NULL) {
207
memcpy (&wmhints, old_wmhints, sizeof (XWMHints));
210
wmhints.flags &= ~WindowGroupHint;
211
wmhints.window_group = 0;
213
/* General paranoia */
214
wmhints.flags = StateHint;
215
wmhints.window_group = 0;
216
wmhints.initial_state = NormalState;
219
XSetWMHints (GDK_WINDOW_XDISPLAY (win),
220
GDK_WINDOW_XWINDOW (win),
224
/* This is such a broken stupid function. */
226
xstuff_set_pos_size (GdkWindow *window, int x, int y, int w, int h)
228
XSizeHints size_hints;
229
int old_x, old_y, old_w, old_h;
231
old_x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-x"));
232
old_y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-y"));
233
old_w = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-w"));
234
old_h = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "xstuff-cached-h"));
236
if (x == old_x && y == old_y && w == old_w && h == old_h)
239
/* Do not add USPosition / USSize here, fix the damn WM */
240
size_hints.flags = PPosition | PSize | PMaxSize | PMinSize;
241
size_hints.x = 0; /* window managers aren't supposed to and */
242
size_hints.y = 0; /* don't use these fields */
243
size_hints.width = w;
244
size_hints.height = h;
245
size_hints.min_width = w;
246
size_hints.min_height = h;
247
size_hints.max_width = w;
248
size_hints.max_height = h;
250
gdk_error_trap_push ();
252
XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
253
GDK_WINDOW_XWINDOW (window),
256
gdk_window_move_resize (window, x, y, w, h);
259
gdk_error_trap_pop ();
261
g_object_set_data (G_OBJECT (window), "xstuff-cached-x", GINT_TO_POINTER (x));
262
g_object_set_data (G_OBJECT (window), "xstuff-cached-y", GINT_TO_POINTER (y));
263
g_object_set_data (G_OBJECT (window), "xstuff-cached-w", GINT_TO_POINTER (w));
264
g_object_set_data (G_OBJECT (window), "xstuff-cached-h", GINT_TO_POINTER (h));
268
xstuff_set_wmspec_dock_hints (GdkWindow *window,
271
Atom atoms [2] = { None, None };
274
atoms [0] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
276
atoms [0] = panel_atom_get ("_MATE_WINDOW_TYPE_AUTOHIDE_PANEL");
277
atoms [1] = panel_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
280
XChangeProperty (GDK_WINDOW_XDISPLAY (window),
281
GDK_WINDOW_XWINDOW (window),
282
panel_atom_get ("_NET_WM_WINDOW_TYPE"),
283
XA_ATOM, 32, PropModeReplace,
284
(unsigned char *) atoms,
289
xstuff_set_wmspec_strut (GdkWindow *window,
302
XChangeProperty (GDK_WINDOW_XDISPLAY (window),
303
GDK_WINDOW_XWINDOW (window),
304
panel_atom_get ("_NET_WM_STRUT"),
305
XA_CARDINAL, 32, PropModeReplace,
306
(unsigned char *) vals, 4);
310
xstuff_delete_property (GdkWindow *window, const char *name)
312
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
313
Window xwindow = GDK_WINDOW_XWINDOW (window);
315
XDeleteProperty (xdisplay, xwindow,
316
panel_atom_get (name));
320
#define MINIATURIZE_ANIMATION_FRAMES_Z 1
321
#define MINIATURIZE_ANIMATION_STEPS_Z 6
322
/* the delay per draw */
323
#define MINIATURIZE_ANIMATION_DELAY_Z 10
326
draw_zoom_animation (GdkScreen *gscreen,
327
int x, int y, int w, int h,
328
int fx, int fy, int fw, int fh,
331
#define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
332
float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
333
int cxi[FRAMES], cyi[FRAMES], cwi[FRAMES], chi[FRAMES];
334
float xstep, ystep, wstep, hstep;
338
GdkColor color = { 65535, 65535, 65535 };
344
dpy = gdk_x11_display_get_xdisplay (gdk_screen_get_display (gscreen));
345
root_win = gdk_x11_drawable_get_xid (gdk_screen_get_root_window (gscreen));
346
screen = gdk_screen_get_number (gscreen);
347
#if GTK_CHECK_VERSION (3, 0, 0)
348
depth = DefaultDepth(dpy,screen);
350
depth = gdk_drawable_get_depth (gdk_screen_get_root_window (gscreen));
354
#if !GTK_CHECK_VERSION (3, 0, 0)
355
gdk_colormap_alloc_color (
356
gdk_screen_get_system_colormap (gscreen), &color, FALSE, TRUE);
358
gcv.function = GXxor;
359
/* this will raise the probability of the XORed color being different
360
* of the original color in PseudoColor when not all color cells are
362
if (DefaultVisual(dpy, screen)->class==PseudoColor)
363
gcv.plane_mask = (1<<(depth-1))|1;
365
gcv.plane_mask = AllPlanes;
366
gcv.foreground = color.pixel;
367
if (gcv.foreground == 0)
370
gcv.subwindow_mode = IncludeInferiors;
371
gcv.graphics_exposures = False;
373
frame_gc = XCreateGC(dpy, root_win, GCForeground|GCGraphicsExposures
374
|GCFunction|GCSubwindowMode|GCLineWidth
377
xstep = (float)(fx-x)/steps;
378
ystep = (float)(fy-y)/steps;
379
wstep = (float)(fw-w)/steps;
380
hstep = (float)(fh-h)/steps;
382
for (j=0; j<FRAMES; j++) {
393
for (i=0; i<steps; i++) {
394
for (j=0; j<FRAMES; j++) {
395
XDrawRectangle(dpy, root_win, frame_gc, cxi[j], cyi[j], cwi[j], chi[j]);
398
#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
399
usleep(MINIATURIZE_ANIMATION_DELAY_Z);
403
for (j=0; j<FRAMES; j++) {
404
XDrawRectangle(dpy, root_win, frame_gc,
405
cxi[j], cyi[j], cwi[j], chi[j]);
431
for (j=0; j<FRAMES; j++) {
432
XDrawRectangle(dpy, root_win, frame_gc,
433
cxi[j], cyi[j], cwi[j], chi[j]);
436
#if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
437
usleep(MINIATURIZE_ANIMATION_DELAY_Z);
441
for (j=0; j<FRAMES; j++) {
442
XDrawRectangle(dpy, root_win, frame_gc,
443
cxi[j], cyi[j], cwi[j], chi[j]);
447
XFreeGC (dpy, frame_gc);
448
#if !GTK_CHECK_VERSION (3, 0, 0)
449
gdk_colormap_free_colors (gdk_screen_get_system_colormap (gscreen),
456
xstuff_zoom_animate (GtkWidget *widget, GdkRectangle *opt_rect)
459
GdkRectangle rect, dest;
460
GtkAllocation allocation;
466
gdk_window_get_origin (gtk_widget_get_window (widget), &rect.x, &rect.y);
467
gtk_widget_get_allocation (widget, &allocation);
468
if (!gtk_widget_get_has_window (widget)) {
469
rect.x += allocation.x;
470
rect.y += allocation.y;
472
rect.height = allocation.height;
473
rect.width = allocation.width;
476
gscreen = gtk_widget_get_screen (widget);
477
monitor = gdk_screen_get_monitor_at_window (gscreen, gtk_widget_get_window (widget));
478
gdk_screen_get_monitor_geometry (gscreen, monitor, &dest);
480
draw_zoom_animation (gscreen,
481
rect.x, rect.y, rect.width, rect.height,
482
dest.x, dest.y, dest.width, dest.height,
483
MINIATURIZE_ANIMATION_STEPS_Z);
487
xstuff_get_current_workspace (GdkScreen *screen)
498
root_window = gdk_x11_drawable_get_xid (
499
gdk_screen_get_root_window (screen));
501
gdk_error_trap_push ();
502
#if GTK_CHECK_VERSION (3, 0, 0)
503
result = XGetWindowProperty (GDK_SCREEN_XDISPLAY (screen),
505
result = XGetWindowProperty (gdk_display,
508
panel_atom_get ("_NET_CURRENT_DESKTOP"),
510
False, XA_CARDINAL, &type, &format, &nitems,
511
&bytes_after, (gpointer) &num);
512
if (gdk_error_trap_pop () || result != Success)
515
if (type != XA_CARDINAL) {
528
xstuff_grab_key_on_all_screens (int keycode,
536
display = gdk_display_get_default ();
537
n_screens = gdk_display_get_n_screens (display);
539
for (i = 0; i < n_screens; i++) {
542
root = gdk_screen_get_root_window (
543
gdk_display_get_screen (display, i));
546
XGrabKey (gdk_x11_display_get_xdisplay (display),
548
gdk_x11_drawable_get_xid (root),
549
True, GrabModeAsync, GrabModeAsync);
551
XUngrabKey (gdk_x11_display_get_xdisplay (display),
553
gdk_x11_drawable_get_xid (root));