1 /* Skippy - Seduces Kids Into Perversion
3 * Copyright (C) 2004 Hyriand <hyriand@thegraveyard.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define WM_PERSONALITY_NETWM 0
23 #define WM_PERSONALITY_GNOME 1
25 /* From WindowMaker's gnome.c */
26 #define WIN_HINTS_SKIP_FOCUS (1<<0) /*"alt-tab" skips this win*/
27 #define WIN_HINTS_SKIP_WINLIST (1<<1) /*do not show in window list*/
28 #define WIN_HINTS_SKIP_TASKBAR (1<<2) /*do not show on taskbar*/
29 #define WIN_HINTS_GROUP_TRANSIENT (1<<3) /*Reserved - definition is unclear*/
30 #define WIN_HINTS_FOCUS_ON_CLICK (1<<4) /*app only accepts focus if clicked*/
31 #define WIN_HINTS_DO_NOT_COVER (1<<5) /* attempt to not cover this window */
34 #define WIN_STATE_STICKY (1<<0) /*everyone knows sticky*/
35 #define WIN_STATE_MINIMIZED (1<<1) /*Reserved - definition is unclear*/
36 #define WIN_STATE_MAXIMIZED_VERT (1<<2) /*window in maximized V state*/
37 #define WIN_STATE_MAXIMIZED_HORIZ (1<<3) /*window in maximized H state*/
38 #define WIN_STATE_HIDDEN (1<<4) /*not on taskbar but window visible*/
39 #define WIN_STATE_SHADED (1<<5) /*shaded (MacOS / Afterstep style)*/
40 /* these are bogus states defined in "the spec" */
41 #define WIN_STATE_HID_WORKSPACE (1<<6) /*not on current desktop*/
42 #define WIN_STATE_HID_TRANSIENT (1<<7) /*owner of transient is hidden*/
43 #define WIN_STATE_FIXED_POSITION (1<<8) /*window is fixed in position even*/
44 #define WIN_STATE_ARRANGE_IGNORE (1<<9) /*ignore for auto arranging*/
47 static int WM_PERSONALITY = WM_PERSONALITY_NETWM,
48 NETWM_HAS_FULLSCREEN = 0,
49 IGNORE_SKIP_TASKBAR = 0;
52 wm_get_atoms(Display *dpy)
54 XA_WM_STATE = XInternAtom(dpy, "WM_STATE", 0);
55 WM_CLIENT_LEADER = XInternAtom(dpy, "WM_CLIENT_LEADER", 0);
56 XA_UTF8_STRING = XInternAtom(dpy, "UTF8_STRING", 0);
58 _XROOTPMAP_ID = XInternAtom(dpy, "_XROOTPMAP_ID", 0);
59 ESETROOT_PMAP_ID = XInternAtom(dpy, "ESETROOT_PMAP_ID", 0);
61 _NET_SUPPORTING_WM_CHECK = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", 0);
62 _NET_SUPPORTED = XInternAtom(dpy, "_NET_SUPPORTED", 0);
63 _NET_NUMBER_OF_DESKTOPS = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", 0);
64 _NET_CLIENT_LIST = XInternAtom(dpy, "_NET_CLIENT_LIST", 0);
65 _NET_CLIENT_LIST_STACKING = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", 0);
66 _NET_CURRENT_DESKTOP = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", 0);
67 _NET_WM_DESKTOP = XInternAtom(dpy, "_NET_WM_DESKTOP", 0);
68 _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", 0);
69 _NET_WM_STATE_HIDDEN = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", 0);
70 _NET_WM_STATE_SKIP_TASKBAR = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", 0);
71 _NET_WM_STATE_SKIP_PAGER = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", 0);
72 _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", 0);
73 _NET_WM_STATE_SHADED = XInternAtom(dpy, "_NET_WM_STATE_SHADED", 0);
74 _NET_WM_STATE_ABOVE = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", 0);
75 _NET_WM_STATE_STICKY = XInternAtom(dpy, "_NET_WM_STATE_STICKY", 0);
76 _NET_WM_WINDOW_TYPE = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", 0);
77 _NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", 0);
78 _NET_WM_WINDOW_TYPE_DOCK = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", 0);
79 _NET_WM_VISIBLE_NAME = XInternAtom(dpy, "_NET_WM_VISIBLE_NAME", 0);
80 _NET_WM_NAME = XInternAtom(dpy, "_NET_WM_VISIBLE_NAME", 0);
82 _WIN_SUPPORTING_WM_CHECK = XInternAtom(dpy, "_WIN_SUPPORTING_WM_CHECK", 0);
83 _WIN_WORKSPACE = XInternAtom(dpy, "_WIN_WORKSPACE", 0);
84 _WIN_WORKSPACE_COUNT = XInternAtom(dpy, "_WIN_WORKSPACE_COUNT", 0);
85 _WIN_PROTOCOLS = XInternAtom(dpy, "_WIN_PROTOCOLS", 0);
86 _WIN_CLIENT_LIST = XInternAtom(dpy, "_WIN_CLIENT_LIST", 0);
87 _WIN_STATE = XInternAtom(dpy, "_WIN_STATE", 0);
88 _WIN_HINTS = XInternAtom(dpy, "_WIN_HINTS", 0);
92 wm_check_netwm(Display *dpy)
95 unsigned char *data, *data2;
97 int status, real_format;
99 unsigned long items_read, items_left, i;
103 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTING_WM_CHECK,
104 0L, 1L, False, XA_WINDOW, &real_type, &real_format,
105 &items_read, &items_left, &data);
106 if(status != Success || ! items_read) {
107 if(status == Success)
112 wm_check = ((Window*)data)[0];
115 status = XGetWindowProperty(dpy, wm_check, _NET_SUPPORTING_WM_CHECK,
116 0L, 1L, False, XA_WINDOW, &real_type, &real_format,
117 &items_read, &items_left, &data);
119 if(status != Success && ! items_read) {
120 if(status == Success)
125 if(wm_check != ((Window*)data)[0]) {
132 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTED,
133 0L, 8192L, False, XA_ATOM, &real_type, &real_format,
134 &items_read, &items_left, &data2);
136 if(status != Success || ! items_read) {
137 if(status == Success)
142 for(i = 0; i < items_read; i++) {
143 if(((Atom*)data2)[i] == _NET_NUMBER_OF_DESKTOPS)
145 else if(((Atom*)data2)[i] == _NET_CURRENT_DESKTOP)
147 else if(((Atom*)data2)[i] == _NET_WM_STATE)
149 else if(((Atom*)data2)[i] == _NET_CLIENT_LIST)
151 else if(((Atom*)data2)[i] == _NET_CLIENT_LIST_STACKING)
153 else if(((Atom*)data2)[i] == _NET_WM_STATE_FULLSCREEN)
154 NETWM_HAS_FULLSCREEN = 1;
159 _NET_CLIENT_LIST = _NET_CLIENT_LIST_STACKING;
162 return ((req & 15) == 15);
166 wm_check_gnome(Display *dpy)
169 unsigned char *data, *data2;
171 int status, real_format;
173 unsigned long items_read, items_left, i;
177 WM_PERSONALITY = WM_PERSONALITY_GNOME;
179 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _WIN_SUPPORTING_WM_CHECK,
180 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
181 &items_read, &items_left, &data);
182 if(status != Success || ! items_read) {
183 if(status == Success)
188 wm_check = ((Window*)data)[0];
191 status = XGetWindowProperty(dpy, wm_check, _WIN_SUPPORTING_WM_CHECK,
192 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
193 &items_read, &items_left, &data);
195 if(status != Success && ! items_read) {
196 if(status == Success)
201 if(wm_check != ((Window*)data)[0]) {
208 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _WIN_PROTOCOLS,
209 0L, 8192L, False, XA_ATOM, &real_type, &real_format,
210 &items_read, &items_left, &data2);
212 if(status != Success || ! items_read) {
213 if(status == Success)
218 for(i = 0; i < items_read; i++) {
219 if(((Atom*)data2)[i] == _WIN_WORKSPACE)
221 else if(((Atom*)data2)[i] == _WIN_WORKSPACE_COUNT)
223 else if(((Atom*)data2)[i] == _WIN_STATE)
225 else if(((Atom*)data2)[i] == _WIN_CLIENT_LIST)
230 return ((req & 15) == 15);
234 wm_check(Display *dpy)
236 return wm_check_netwm(dpy) || wm_check_gnome(dpy);
240 wm_get_stack(Display *dpy)
244 int status, real_format;
246 unsigned long items_read, items_left, i;
248 if(WM_PERSONALITY == WM_PERSONALITY_NETWM)
249 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_CLIENT_LIST,
250 0L, 8192L, False, XA_WINDOW, &real_type, &real_format,
251 &items_read, &items_left, &data);
253 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _WIN_CLIENT_LIST,
254 0L, 8192L, False, XA_CARDINAL, &real_type, &real_format,
255 &items_read, &items_left, &data);
257 if(status != Success)
260 for(i = 0; i < items_read; i++)
261 l = dlist_add(l, (void*)((CARD32*)data)[i]);
269 wm_get_root_pmap(Display *dpy)
271 Pixmap rootpmap = None;
273 int status, real_format;
275 unsigned long items_read, items_left;
277 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _XROOTPMAP_ID,
278 0L, 1L, False, XA_PIXMAP, &real_type, &real_format,
279 &items_read, &items_left, &data);
280 if(status != Success) {
281 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy), ESETROOT_PMAP_ID,
282 0L, 1L, False, XA_PIXMAP, &real_type, &real_format,
283 &items_read, &items_left, &data);
284 if(status != Success)
289 rootpmap = ((Pixmap*)data)[0];
297 wm_get_current_desktop(Display *dpy)
300 /*unsigned char *data;
301 int status, real_format;
303 unsigned long items_read, items_left;
305 status = XGetWindowProperty(dpy, DefaultRootWindow(dpy),
306 (WM_PERSONALITY == WM_PERSONALITY_NETWM) ? _NET_CURRENT_DESKTOP : _WIN_WORKSPACE,
307 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
308 &items_read, &items_left, &data);
309 if(status != Success)
312 desktop = ((CARD32*)data)[0];
319 wm_get_window_title(Display *dpy, Window window, int *length_return)
323 int status, real_format;
325 unsigned long items_read, items_left;
329 status = XGetWindowProperty(dpy, window, _NET_WM_VISIBLE_NAME,
330 0, 8192, False, XA_UTF8_STRING, &real_type, &real_format,
331 &items_read, &items_left, &data);
332 if(status != Success || items_read == 0)
334 if(status == Success)
336 status = XGetWindowProperty(dpy, window, _NET_WM_NAME,
337 0, 8192, False, XA_UTF8_STRING, &real_type, &real_format,
338 &items_read, &items_left, &data);
340 if(status != Success || items_read == 0)
342 if(status == Success)
344 status = XGetWindowProperty(dpy, window, XA_WM_NAME,
345 0, 8192, False, XA_STRING, &real_type, &real_format,
346 &items_read, &items_left, &data);
348 if(status != Success)
353 ret = (FcChar8 *)malloc(items_read);
354 memcpy(ret, data, items_read);
355 *length_return = items_read;
364 wm_get_group_leader(Display *dpy, Window window)
367 int status, real_format;
369 unsigned long items_read, items_left;
370 Window leader = None;
372 status = XGetWindowProperty(dpy, window, WM_CLIENT_LEADER,
373 0, 1, False, XA_WINDOW, &real_type, &real_format,
374 &items_read, &items_left, &data);
376 if(status != Success)
378 XWMHints *hints = XGetWMHints(dpy, window);
382 if(hints->flags & WindowGroupHint)
383 leader = hints->window_group;
389 leader = ((Window*)data)[0];
397 wm_use_netwm_fullscreen(Bool b)
399 NETWM_HAS_FULLSCREEN = b ? NETWM_HAS_FULLSCREEN : False;
403 wm_ignore_skip_taskbar(Bool b)
405 IGNORE_SKIP_TASKBAR = b;
409 wm_set_fullscreen(Display *dpy, Window window, int x, int y, unsigned int width, unsigned int height)
411 if(WM_PERSONALITY == WM_PERSONALITY_NETWM && NETWM_HAS_FULLSCREEN)
414 CARD32 desktop = (CARD32)0;
416 props[0] = _NET_WM_STATE_FULLSCREEN;
417 props[1] = _NET_WM_STATE_SKIP_TASKBAR;
418 props[2] = _NET_WM_STATE_SKIP_PAGER;
419 props[3] = _NET_WM_STATE_ABOVE;
420 props[4] = _NET_WM_STATE_STICKY;
422 XChangeProperty(dpy, window, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char*)props, 5);
423 XChangeProperty(dpy, window, _NET_WM_DESKTOP, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&desktop, 1);
427 XSetWindowAttributes wattr;
428 wattr.override_redirect = True;
429 XChangeWindowAttributes(dpy, window, CWOverrideRedirect, &wattr);
430 XMoveResizeWindow(dpy, window, x, y, width, height);
435 wm_validate_window(Display *dpy, Window win)
439 int status, real_format;
441 unsigned long items_read, items_left, i;
444 if(WM_PERSONALITY == WM_PERSONALITY_NETWM)
446 status = XGetWindowProperty(dpy, win, _NET_WM_STATE,
447 0L, 8192L, False, XA_ATOM, &real_type, &real_format,
448 &items_read, &items_left, &data);
450 if(status != Success)
453 atoms = (Atom *)data;
455 for(i = 0; result && i < items_read; i++) {
456 if(atoms[i] == _NET_WM_STATE_HIDDEN)
458 else if(! IGNORE_SKIP_TASKBAR && atoms[i] == _NET_WM_STATE_SKIP_TASKBAR)
460 else if(atoms[i] == _NET_WM_STATE_SHADED)
470 status = XGetWindowProperty(dpy, win, _NET_WM_WINDOW_TYPE,
471 0L, 1L, False, XA_ATOM, &real_type, &real_format,
472 &items_read, &items_left, &data);
473 if(status != Success)
476 atoms = (Atom *)data;
478 if(items_read && (atoms[0] == _NET_WM_WINDOW_TYPE_DESKTOP || atoms[0] == _NET_WM_WINDOW_TYPE_DOCK))
487 status = XGetWindowProperty(dpy, win, _WIN_STATE,
488 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
489 &items_read, &items_left, &data);
490 if(status != Success || ! items_read)
492 if(status == Success)
496 attr = (((CARD32*)data)[0]) & (WIN_STATE_MINIMIZED |
505 if(! IGNORE_SKIP_TASKBAR)
507 status = XGetWindowProperty(dpy, win, _WIN_HINTS,
508 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
509 &items_read, &items_left, &data);
510 if(status != Success || ! items_read)
512 if(status == Success)
514 return 1; /* If there's no _WIN_HINTS, assume it's 0, thus valid */
516 attr = ((CARD32*)data)[0];
517 if(attr & WIN_HINTS_SKIP_TASKBAR)
527 wm_get_window_desktop(Display *dpy, Window win)
529 int status, real_format;
531 unsigned long items_read, items_left;
535 if(WM_PERSONALITY == WM_PERSONALITY_GNOME)
537 status = XGetWindowProperty(dpy, win, _WIN_STATE,
538 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
539 &items_read, &items_left, &data);
540 if(status == Success)
543 desktop = (((CARD32*)data)[0] & WIN_STATE_STICKY) ? (CARD32)-1 : 0;
552 status = XGetWindowProperty(dpy, win,
553 (WM_PERSONALITY == WM_PERSONALITY_NETWM) ? _NET_WM_DESKTOP : _WIN_WORKSPACE,
554 0L, 1L, False, XA_CARDINAL, &real_type, &real_format,
555 &items_read, &items_left, &data);
557 if(status != Success)
558 return wm_get_current_desktop(dpy);
561 desktop = ((CARD32*)data)[0];
563 desktop = wm_get_current_desktop(dpy);
570 /* Get focused window and traverse towards the root window until a window with WM_STATE is found */
572 wm_get_focused(Display *dpy)
574 Window focused = None, root = None, *children;
576 int revert_to, status, real_format;
578 unsigned long items_read, items_left;
581 XGetInputFocus(dpy, &focused, &revert_to);
583 /*printf("%x\n",focused);*/
585 while(focused != None && focused != root)
587 status = XGetWindowProperty(dpy, focused, XA_WM_STATE,
588 0L, 1L, False, XA_WM_STATE, &real_type, &real_format,
589 &items_read, &items_left, &data);
590 if(status == Success)
596 XQueryTree(dpy, focused, &root, &focused, &children, &tmp_u);