1 /*
2 * Oroborus Window Manager
3 * X11 Hints Utility Library
4 *
5 * Copyright (C) 2001 Ken Lynch
6 * Copyright (C) 2002-2005 Stefan Pfetzing
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/Xmd.h>
30 #include <X11/Xatom.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #ifdef DEBUG
35 #include <stdio.h>
36 #endif
37
38 #include "hints.h"
39
40 Atom wm_state, wm_change_state, wm_delete_window, wm_protocols;
41 Atom motif_wm_hints;
42 Atom win_hints, win_state, win_client_list, win_layer, win_workspace,
43 win_workspace_count, win_desktop_button_proxy, win_supporting_wm_check,
44 gnome_panel_desktop_area;
45 Atom net_atoms[NET_ATOM_COUNT];
46 extern Display *dpy;
47
48 void
initHints(Display * d)49 initHints (Display * d)
50 {
51 dpy = d;
52 initICCCMHints ();
53 initMotifHints ();
54 initGnomeHints ();
55 initNETHints ();
56 }
57
58 void
initICCCMHints()59 initICCCMHints ()
60 {
61 #ifdef DEBUG
62 printf ("entering initICCCMHints\n");
63 #endif
64
65 wm_state = XInternAtom (dpy, "WM_STATE", False);
66 wm_change_state = XInternAtom (dpy, "WM_CHANGE_STATE", False);
67 wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
68 wm_protocols = XInternAtom (dpy, "WM_PROTOCOLS", False);
69 }
70
71 void
initNETHints()72 initNETHints ()
73 {
74 Window root;
75 #ifdef DEBUG
76 printf ("entering initNETHints\n");
77 #endif
78
79 root = XDefaultRootWindow (dpy);
80
81 net_atoms[NET_CLIENT_LIST] = XInternAtom (dpy, "_NET_CLIENT_LIST", False);
82 net_atoms[NET_CLIENT_LIST_STACKING] =
83 XInternAtom (dpy, "_NET_CLIENT_LIST_STACKING", False);
84 net_atoms[NET_WM_WINDOW_TYPE] =
85 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False);
86 net_atoms[NET_WM_WINDOW_TYPE_DESKTOP] =
87 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
88 net_atoms[NET_WM_WINDOW_TYPE_DOCK] =
89 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
90 net_atoms[NET_WM_WINDOW_TYPE_TOOLBAR] =
91 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
92 net_atoms[NET_WM_WINDOW_TYPE_MENU] =
93 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
94 net_atoms[NET_WM_WINDOW_TYPE_UTILITY] =
95 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
96 net_atoms[NET_WM_WINDOW_TYPE_SPLASH] =
97 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
98 net_atoms[NET_WM_WINDOW_TYPE_DIALOG] =
99 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
100 net_atoms[NET_WM_WINDOW_TYPE_NORMAL] =
101 XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
102 net_atoms[NET_WM_STATE] = XInternAtom (dpy, "_NET_WM_STATE", False);
103 net_atoms[NET_WM_STATE_MODAL] =
104 XInternAtom (dpy, "_NET_WM_STATE_MODAL", False);
105 net_atoms[NET_WM_STATE_STICKY] =
106 XInternAtom (dpy, "_NET_WM_STATE_STICKY", False);
107 net_atoms[NET_WM_STATE_SHADED] =
108 XInternAtom (dpy, "_NET_WM_STATE_SHADED", False);
109 net_atoms[NET_WM_STATE_SKIP_TASKBAR] =
110 XInternAtom (dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
111 net_atoms[NET_WM_STATE_SKIP_PAGER] =
112 XInternAtom (dpy, "_NET_WM_STATE_SKIP_PAGER", False);
113 net_atoms[NET_WM_STATE_HIDDEN] =
114 XInternAtom (dpy, "_NET_WM_STATE_HIDDEN", False);
115 net_atoms[NET_WM_STATE_ABOVE] =
116 XInternAtom (dpy, "_NET_WM_STATE_ABOVE", False);
117 net_atoms[NET_WM_STATE_FULLSCREEN] =
118 XInternAtom (dpy, "_NET_WM_STATE_FULLSCREEN", False);
119 net_atoms[NET_WM_NAME] = XInternAtom (dpy, "_NET_WM_NAME", False);
120 net_atoms[NET_WM_DESKTOP] = XInternAtom (dpy, "_NET_WM_DESKTOP", False);
121 net_atoms[NET_NUMBER_OF_DESKTOPS] =
122 XInternAtom (dpy, "_NET_NUMBER_OF_DESKTOPS", False);
123 net_atoms[NET_CURRENT_DESKTOP] =
124 XInternAtom (dpy, "_NET_CURRENT_DESKTOP", False);
125 net_atoms[NET_ACTIVE_WINDOW] =
126 XInternAtom (dpy, "_NET_ACTIVE_WINDOW", False);
127 net_atoms[NET_SUPPORTING_WM_CHECK] =
128 XInternAtom (dpy, "_NET_SUPPORTING_WM_CHECK", False);
129 net_atoms[NET_WORKAREA] = XInternAtom (dpy, "_NET_WORKAREA", False);
130 net_atoms[NET_WM_WORKAREA] = XInternAtom (dpy, "_NET_WM_WORKAREA", False);
131 net_atoms[NET_CLOSE_WINDOW] = XInternAtom (dpy, "_NET_CLOSE_WINDOW", False);
132 net_atoms[NET_WM_PID] = XInternAtom (dpy, "_NET_WM_PID", False);
133 net_atoms[NET_WM_STRUT] = XInternAtom (dpy, "_NET_WM_STRUT", False);
134 XChangeProperty (dpy, root, XInternAtom (dpy, "_NET_SUPPORTED", False),
135 XA_ATOM, 32, PropModeReplace, (unsigned char *) net_atoms,
136 NET_ATOM_COUNT);
137 }
138
139 void
initMotifHints()140 initMotifHints ()
141 {
142 #ifdef DEBUG
143 printf ("entering initMotifHints\n");
144 #endif
145
146 motif_wm_hints = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
147 }
148
149 void
initGnomeHints()150 initGnomeHints ()
151 {
152 Window root;
153
154 #ifdef DEBUG
155 printf ("entering initGnomeHints\n");
156 #endif
157
158 root = XDefaultRootWindow (dpy);
159 win_hints = XInternAtom (dpy, "_WIN_HINTS", False);
160 win_state = XInternAtom (dpy, "_WIN_STATE", False);
161 win_client_list = XInternAtom (dpy, "_WIN_CLIENT_LIST", False);
162 win_layer = XInternAtom (dpy, "_WIN_LAYER", False);
163 win_workspace = XInternAtom (dpy, "_WIN_WORKSPACE", False);
164 win_workspace_count = XInternAtom (dpy, "_WIN_WORKSPACE_COUNT", False);
165 win_desktop_button_proxy =
166 XInternAtom (dpy, "_WIN_DESKTOP_BUTTON_PROXY", False);
167 win_supporting_wm_check =
168 XInternAtom (dpy, "_WIN_SUPPORTING_WM_CHECK", False);
169 gnome_panel_desktop_area =
170 XInternAtom (dpy, "GNOME_PANEL_DESKTOP_AREA", False);
171 }
172
173 long
getWMState(Window w)174 getWMState (Window w)
175 {
176 unsigned long *data = NULL, state = WithdrawnState;
177
178 #ifdef DEBUG
179 printf ("entering getWmState\n");
180 #endif
181
182 data = getPropData (w, wm_state, wm_state, NULL);
183 if (data)
184 {
185 state = *data;
186 XFree (data);
187 }
188 return state;
189 }
190
191 void
setWMState(Window w,long state)192 setWMState (Window w, long state)
193 {
194 CARD32 data[2];
195
196 #ifdef DEBUG
197 printf ("entering setWmState\n");
198 #endif
199
200 data[0] = state;
201 data[1] = None;
202
203 XChangeProperty (dpy, w, wm_state, wm_state, 32, PropModeReplace,
204 (unsigned char *) data, 2);
205 }
206
207 PropMwmHints *
getMotifHints(Window w)208 getMotifHints (Window w)
209 {
210 #ifdef DEBUG
211 printf ("entering getMotifHints\n");
212 #endif
213
214 return getPropData (w, motif_wm_hints, motif_wm_hints, NULL);
215 }
216
217 int
getGnomeHint(Window w,Atom a,long * value)218 getGnomeHint (Window w, Atom a, long *value)
219 {
220 int success = False;
221 long *data = NULL;
222
223 #ifdef DEBUG
224 printf ("entering getGnomeHint\n");
225 #endif
226
227 if (a == win_layer)
228 *value = WIN_LAYER_NORMAL;
229 else
230 *value = 0;
231
232 data = getPropData (w, a, XA_CARDINAL, NULL);
233 if (data)
234 {
235 *value = *data;
236 success = True;
237 XFree (data);
238 }
239 return success;
240 }
241
242 void
setGnomeHint(Window w,Atom a,long value)243 setGnomeHint (Window w, Atom a, long value)
244 {
245 #ifdef DEBUG
246 printf ("entering setGnomeHint\n");
247 #endif
248
249 XChangeProperty (dpy, w, a, XA_CARDINAL, 32, PropModeReplace,
250 (unsigned char *) &value, 1);
251 }
252
253 void
setNetWmName(Window w,Atom a,char * value)254 setNetWmName (Window w, Atom a, char *value)
255 {
256 #ifdef DEBUG
257 printf ("entering setNetWmName\n");
258 #endif
259
260 XChangeProperty (dpy, w, a, XA_STRING, 8, PropModeReplace,
261 (unsigned char *) value, strlen (value));
262 }
263
264 void
setSupportingWmCheck(Window w,Window w2)265 setSupportingWmCheck (Window w, Window w2)
266 {
267 #ifdef DEBUG
268 printf ("entering setSupportingWmCheck\n");
269 #endif
270
271 XChangeProperty (dpy, w, net_atoms[NET_SUPPORTING_WM_CHECK], XA_WINDOW, 32,
272 PropModeReplace, (unsigned char *) &w2, 1);
273 }
274
275 void
getEWMHState(Window w,long * value)276 getEWMHState (Window w, long *value)
277 {
278 unsigned long *data;
279 unsigned long items = 0;
280 unsigned long i;
281
282 data = getPropData (w, net_atoms[NET_WM_STATE], XA_ATOM, &items);
283 if (data)
284 {
285 for (i = 0; i < items; i++)
286 {
287 char *currentName = XGetAtomName (dpy, data[i]);
288 char *configuredName =
289 XGetAtomName (dpy, net_atoms[NET_WM_STATE_STICKY]);
290 if (equals (currentName, configuredName))
291 *value |= WIN_STATE_STICKY;
292 XFree (currentName);
293 XFree (configuredName);
294 }
295 XFree (data);
296 }
297 }
298
299 void
getGnomeDesktopMargins(CARD32 * margins)300 getGnomeDesktopMargins (CARD32 * margins)
301 {
302 unsigned long items_read;
303 CARD32 *data = NULL;
304
305 #ifdef DEBUG
306 printf ("entering getGnomeDesktopMargins\n");
307 #endif
308
309 data =
310 getPropData (XDefaultRootWindow (dpy), gnome_panel_desktop_area,
311 XA_CARDINAL, &items_read);
312 if (data && items_read >= 4)
313 {
314 margins[0] = data[0];
315 margins[1] = data[1];
316 margins[2] = data[2];
317 margins[3] = data[3];
318 XFree (data);
319 }
320 else
321 {
322 margins[0] = 0;
323 margins[1] = 0;
324 margins[2] = 0;
325 margins[3] = 0;
326 }
327 }
328
329 int
getNetWMPid(Window w)330 getNetWMPid (Window w)
331 {
332 int val;
333 int *data = NULL;
334 unsigned long items_read;
335
336 data = getPropData (w, net_atoms[NET_WM_PID], XA_CARDINAL, &items_read);
337
338 if (items_read >= 1)
339 {
340 val = *data;
341 XFree(data);
342
343 return val;
344 }
345 else
346 return 0;
347 }
348
349 void
getNetWMStrut(Window win,CARD32 * margins,CARD32 * window_margins)350 getNetWMStrut (Window win, CARD32 * margins, CARD32 * window_margins)
351 {
352 unsigned long items_read;
353 CARD32 *data = NULL;
354
355 #ifdef DEBUG
356 printf ("entering getGnomeDesktopMargins\n");
357 #endif
358
359 data = getPropData (win, net_atoms[NET_WM_STRUT], XA_CARDINAL, &items_read);
360 if (data && items_read >= 4)
361 {
362 window_margins[0] = data[0];
363 window_margins[1] = data[1];
364 window_margins[2] = data[2];
365 window_margins[3] = data[3];
366 margins[0] += data[0];
367 margins[1] += data[1];
368 margins[2] += data[2];
369 margins[3] += data[3];
370 XFree (data);
371 }
372 else
373 {
374 window_margins[0] = 0;
375 window_margins[1] = 0;
376 window_margins[2] = 0;
377 window_margins[3] = 0;
378 }
379 }
380
381 void
delNetWMStrut(CARD32 * margins,CARD32 * data)382 delNetWMStrut (CARD32 * margins, CARD32 * data)
383 {
384 #ifdef DEBUG
385 printf ("entering delNetWMStrut\n");
386 #endif
387
388 if (data[0] || data[1] || data[2] || data[3])
389 {
390 margins[0] -= data[0];
391 margins[1] -= data[1];
392 margins[2] -= data[2];
393 margins[3] -= data[3];
394 }
395 }
396
397 void
setNetWorkarea(CARD32 * margins,int workspaces)398 setNetWorkarea (CARD32 * margins, int workspaces)
399 {
400 struct workarea
401 {
402 CARD32 left, top, right, bottom;
403 }
404 *workarea;
405 int i;
406
407 if (workspaces <= 0)
408 return;
409
410 workarea = calloc (workspaces, sizeof (struct workarea));
411
412 for (i = 0; i < workspaces; i++)
413 {
414 workarea[i].left = margins[0];
415 workarea[i].top = margins[1];
416 workarea[i].right =
417 XDisplayWidth (dpy, XDefaultScreen (dpy)) - margins[1];
418 workarea[i].bottom =
419 XDisplayHeight (dpy, XDefaultScreen (dpy)) - margins[3];
420 }
421
422 XChangeProperty (dpy, XDefaultRootWindow (dpy),
423 net_atoms[NET_WORKAREA], XA_CARDINAL, 32,
424 PropModeReplace, (unsigned char *) workarea,
425 4 * workspaces);
426 XChangeProperty (dpy, XDefaultRootWindow (dpy), net_atoms[NET_WM_WORKAREA],
427 XA_CARDINAL, 32, PropModeReplace,
428 (unsigned char *) workarea, 4 * workspaces);
429 free (workarea);
430 }
431
432 int
typeDesktop(Window w)433 typeDesktop (Window w)
434 {
435 return typeEWMH (w, "_NET_WM_WINDOW_TYPE_DESKTOP");
436 }
437
438 int
typeDock(Window w)439 typeDock (Window w)
440 {
441 return typeEWMH (w, "_NET_WM_WINDOW_TYPE_DOCK");
442 }
443
444 int
typeAbove(Window w)445 typeAbove (Window w)
446 {
447 return typeEWMH (w, "_NET_WM_STATE_ABOVE");
448 }
449
450 int
typeEWMH(Window w,char * type)451 typeEWMH (Window w, char *type)
452 {
453 unsigned long *data;
454 unsigned long items = 0;
455 unsigned long item = 0;
456 int ret = 0;
457
458 #ifdef DEBUG
459 printf ("entering typeEWMH\n");
460 #endif
461
462 data = getPropData (w, net_atoms[NET_WM_WINDOW_TYPE], XA_ATOM, &items);
463 while (data && items && item < items && !ret)
464 {
465 char *name;
466 name = XGetAtomName (dpy, data[item]);
467 #ifdef DEBUG
468 printf ("%s\n", name);
469 #endif
470 ret = equals (name, type);
471 XFree (name);
472 item++;
473 }
474 if (data)
475 XFree (data);
476
477 return ret;
478 }
479
480 void *
getPropData(Window w,Atom prop,Atom type,unsigned long * items_ret)481 getPropData (Window w, Atom prop, Atom type, unsigned long *items_ret)
482 {
483 Atom type_ret;
484 int format_ret;
485 unsigned long after_ret;
486 unsigned char *prop_data;
487
488 #ifdef DEBUG
489 printf ("entering getPropData\n");
490 #endif
491 prop_data = NULL;
492
493 if (items_ret == NULL)
494 {
495 items_ret = (unsigned long *) malloc (sizeof (unsigned long));
496 XGetWindowProperty (dpy, w, prop, 0, 0x7fffffff, False,
497 type, &type_ret, &format_ret, items_ret,
498 &after_ret, &prop_data);
499 if (prop_data && *items_ret)
500 {
501 free (items_ret);
502 return prop_data;
503 }
504 else
505 {
506 free (items_ret);
507 return NULL;
508 }
509 }
510 else
511 {
512 XGetWindowProperty (dpy, w, prop, 0, 0x7fffffff, False,
513 type, &type_ret, &format_ret, items_ret,
514 &after_ret, &prop_data);
515 if (prop_data && *items_ret)
516 return prop_data;
517 else
518 return NULL;
519 }
520 }
521
522 void
setFocusHint(Window w)523 setFocusHint (Window w)
524 {
525 #ifdef DEBUG
526 printf ("entering setFocusHint\n");
527 #endif
528
529 XChangeProperty (dpy, XDefaultRootWindow (dpy),
530 net_atoms[NET_ACTIVE_WINDOW], XA_WINDOW, 32,
531 PropModeReplace, (unsigned char *) &w, 1);
532 }
533
534 int
equals(char * left,char * right)535 equals (char *left, char *right)
536 {
537 if (left && right && (strcmp (left, right) == 0))
538 return 1;
539 else
540 return 0;
541 }
542
543 /***This must remain at the end of the file.***********************************************
544 * vi:set sw=2 cindent cinoptions={1s,>2s,^-1s,n-1s foldmethod=marker foldmarker=���,���: *
545 * arch-tag: x11_hints handling for oroborus-wm *
546 ******************************************************************************************/
547