1 /*
2 * Copyright (C) 2000 Sasha Vasko <sasha at aftercode.net>
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 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
20 #define LOCAL_DEBUG
21 #include "../configure.h"
22 #include "asapp.h"
23 #include "screen.h"
24 #include "clientprops.h"
25 #include "hints.h"
26
27 /************************************************************************/
28 /* New hints implementation : */
29 /************************************************************************/
30
31 ASHashTable *hint_handlers = NULL;
32 Bool default_parent_hints_func (Window parent, ASParentHints * dst);
33 static get_parent_hints_func parent_hints_func = default_parent_hints_func;
34
35 Bool as_xrm_initialized = False;
36 XrmDatabase as_xrm_user_db = None;
37
38 /*
39 * these atoms are constants in X11, but we still need pointers to them -
40 * simply defining our own variables to hold those constants :
41 */
42 Atom _XA_WM_NAME = XA_WM_NAME;
43 Atom _XA_WM_ICON_NAME = XA_WM_ICON_NAME;
44 Atom _XA_WM_CLASS = XA_WM_CLASS;
45 Atom _XA_WM_HINTS = XA_WM_HINTS;
46 Atom _XA_WM_NORMAL_HINTS = XA_WM_NORMAL_HINTS;
47 Atom _XA_WM_TRANSIENT_FOR = XA_WM_TRANSIENT_FOR;
48 Atom _XA_WM_COMMAND = XA_WM_COMMAND;
49 Atom _XA_WM_CLIENT_MACHINE = XA_WM_CLIENT_MACHINE;
50
51 /*
52 * rest of the atoms has to be interned by us :
53 */
54 Atom _XA_WM_PROTOCOLS;
55 Atom _XA_WM_TAKE_FOCUS;
56 Atom _XA_WM_DELETE_WINDOW;
57 Atom _XA_WM_COLORMAP_WINDOWS;
58 Atom _XA_WM_STATE;
59 Atom _XA_SM_CLIENT_ID;
60 Atom _XA_WM_WINDOW_ROLE;
61 Atom _XA_WM_CLIENT_LEADER;
62
63 /* Motif hints */
64 Atom _XA_MwmAtom;
65
66 /* Gnome hints */
67 Atom _XA_WIN_LAYER;
68 Atom _XA_WIN_STATE;
69 Atom _XA_WIN_WORKSPACE;
70 Atom _XA_WIN_HINTS;
71
72 /* wm-spec _NET hints : */
73 Atom _XA_NET_WM_NAME;
74 Atom _XA_NET_WM_ICON_NAME;
75
76 Atom _XA_NET_WM_VISIBLE_NAME;
77 Atom _XA_NET_WM_VISIBLE_ICON_NAME;
78
79 Atom _XA_NET_WM_DESKTOP;
80 Atom _XA_NET_WM_WINDOW_TYPE;
81 Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP;
82 Atom _XA_NET_WM_WINDOW_TYPE_DOCK;
83 Atom _XA_NET_WM_WINDOW_TYPE_TOOLBAR;
84 Atom _XA_NET_WM_WINDOW_TYPE_MENU;
85 Atom _XA_NET_WM_WINDOW_TYPE_DIALOG;
86 Atom _XA_NET_WM_WINDOW_TYPE_NORMAL;
87 Atom _XA_NET_WM_WINDOW_TYPE_UTILITY;
88 Atom _XA_NET_WM_WINDOW_TYPE_SPLASH;
89 Atom _XA_AS_WM_WINDOW_TYPE_MODULE;
90
91 Atom _XA_NET_WM_STATE;
92 Atom _XA_NET_WM_STATE_MODAL;
93 Atom _XA_NET_WM_STATE_STICKY;
94 Atom _XA_NET_WM_STATE_MAXIMIZED_VERT;
95 Atom _XA_NET_WM_STATE_MAXIMIZED_HORZ;
96 Atom _XA_NET_WM_STATE_SHADED;
97 Atom _XA_NET_WM_STATE_SKIP_TASKBAR;
98 Atom _XA_NET_WM_STATE_SKIP_PAGER;
99 Atom _XA_NET_WM_STATE_HIDDEN;
100 Atom _XA_NET_WM_STATE_FULLSCREEN;
101 Atom _XA_NET_WM_STATE_ABOVE;
102 Atom _XA_NET_WM_STATE_BELOW;
103 Atom _XA_NET_WM_STATE_DEMANDS_ATTENTION;
104 Atom _XA_NET_WM_STATE_FOCUSED;
105
106 Atom _XA_NET_WM_PID;
107 Atom _XA_NET_WM_ICON;
108 Atom _XA_NET_WM_PING;
109 Atom _XA_NET_WM_WINDOW_OPACITY;
110
111 /* Implements KDE System tray specs:
112 * http://developer.kde.org/documentation/library/kdeqt/kde3arch/protocols-docking.html
113 * https://listman.redhat.com/archives/xdg-list/2002-March/msg00014.html
114 * http://standards.freedesktop.org/systemtray-spec/systemtray-spec-0.2.html#ftn.id2494129
115 *
116 */
117 Atom _XA_KDE_DESKTOP_WINDOW = None;
118 Atom _XA_KDE_NET_SYSTEM_TRAY_WINDOW_FOR = None;
119
120
121 /* Crossreferences of atoms into flag value for
122 different atom list type of properties :*/
123
124 AtomXref MainHints[] = {
125 {"WM_PROTOCOLS", &_XA_WM_PROTOCOLS},
126 {"WM_COLORMAP_WINDOWS", &_XA_WM_COLORMAP_WINDOWS},
127 {"WM_STATE", &_XA_WM_STATE},
128 {"SM_CLIENT_ID", &_XA_SM_CLIENT_ID},
129 {"WM_WINDOW_ROLE", &_XA_WM_WINDOW_ROLE},
130 {"WM_CLIENT_LEADER", &_XA_WM_CLIENT_LEADER},
131 {"_MOTIF_WM_HINTS", &_XA_MwmAtom},
132 {"_WIN_LAYER", &_XA_WIN_LAYER},
133 {"_WIN_STATE", &_XA_WIN_STATE},
134 {"_WIN_WORKSPACE", &_XA_WIN_WORKSPACE},
135 {"_WIN_HINTS", &_XA_WIN_HINTS},
136 {"_NET_WM_NAME", &_XA_NET_WM_NAME},
137 {"_NET_WM_ICON_NAME", &_XA_NET_WM_ICON_NAME},
138 {"_NET_WM_VISIBLE_NAME", &_XA_NET_WM_VISIBLE_NAME},
139 {"_NET_WM_VISIBLE_ICON_NAME", &_XA_NET_WM_VISIBLE_ICON_NAME},
140 {"_NET_WM_DESKTOP", &_XA_NET_WM_DESKTOP},
141 {"_NET_WM_WINDOW_TYPE", &_XA_NET_WM_WINDOW_TYPE},
142 {"_NET_WM_STATE", &_XA_NET_WM_STATE},
143 {"_NET_WM_PID", &_XA_NET_WM_PID},
144 {"_NET_WM_ICON", &_XA_NET_WM_ICON},
145 {"_NET_WM_WINDOW_OPACITY", &_XA_NET_WM_WINDOW_OPACITY},
146 {"_KDE_DESKTOP_WINDOW", &_XA_KDE_DESKTOP_WINDOW},
147 {"_KDE_NET_SYSTEM_TRAY_WINDOW_FOR", &_XA_KDE_NET_SYSTEM_TRAY_WINDOW_FOR},
148 {NULL, NULL, 0, None}
149 };
150
151 AtomXref WM_Protocols[] = {
152 {"WM_TAKE_FOCUS", &_XA_WM_TAKE_FOCUS, AS_DoesWmTakeFocus},
153 {"WM_DELETE_WINDOW", &_XA_WM_DELETE_WINDOW, AS_DoesWmDeleteWindow},
154 {NULL, NULL, 0, None}
155 };
156
157 AtomXref EXTWM_WindowType[] = {
158 {"_NET_WM_WINDOW_TYPE_DESKTOP", &_XA_NET_WM_WINDOW_TYPE_DESKTOP,
159 EXTWM_TypeDesktop},
160 {"_NET_WM_WINDOW_TYPE_DOCK", &_XA_NET_WM_WINDOW_TYPE_DOCK,
161 EXTWM_TypeDock},
162 {"_NET_WM_WINDOW_TYPE_TOOLBAR", &_XA_NET_WM_WINDOW_TYPE_TOOLBAR,
163 EXTWM_TypeToolbar},
164 {"_NET_WM_WINDOW_TYPE_MENU", &_XA_NET_WM_WINDOW_TYPE_MENU,
165 EXTWM_TypeMenu},
166 {"_NET_WM_WINDOW_TYPE_DIALOG", &_XA_NET_WM_WINDOW_TYPE_DIALOG,
167 EXTWM_TypeDialog},
168 {"_NET_WM_WINDOW_TYPE_NORMAL", &_XA_NET_WM_WINDOW_TYPE_NORMAL,
169 EXTWM_TypeNormal},
170 {"_NET_WM_WINDOW_TYPE_UTILITY", &_XA_NET_WM_WINDOW_TYPE_UTILITY,
171 EXTWM_TypeUtility},
172 {"_NET_WM_WINDOW_TYPE_SPLASH", &_XA_NET_WM_WINDOW_TYPE_SPLASH,
173 EXTWM_TypeSplash},
174 {"_AS_WM_WINDOW_TYPE_MODULE", &_XA_AS_WM_WINDOW_TYPE_MODULE,
175 EXTWM_TypeASModule},
176
177 {NULL, NULL, 0, None}
178 };
179
180 AtomXref _EXTWM_State[] = {
181 {"_NET_WM_STATE_MODAL", &_XA_NET_WM_STATE_MODAL, EXTWM_StateModal},
182 {"_NET_WM_STATE_STICKY", &_XA_NET_WM_STATE_STICKY, EXTWM_StateSticky},
183 {"_NET_WM_STATE_MAXIMIZED_VERT", &_XA_NET_WM_STATE_MAXIMIZED_VERT,
184 EXTWM_StateMaximizedV},
185 {"_NET_WM_STATE_MAXIMIZED_HORZ", &_XA_NET_WM_STATE_MAXIMIZED_HORZ,
186 EXTWM_StateMaximizedH},
187 {"_NET_WM_STATE_SHADED", &_XA_NET_WM_STATE_SHADED, EXTWM_StateShaded},
188 {"_NET_WM_STATE_SKIP_TASKBAR", &_XA_NET_WM_STATE_SKIP_TASKBAR,
189 EXTWM_StateSkipTaskbar},
190 {"_NET_WM_STATE_SKIP_PAGER", &_XA_NET_WM_STATE_SKIP_PAGER,
191 EXTWM_StateSkipPager},
192 {"_NET_WM_STATE_HIDDEN", &_XA_NET_WM_STATE_HIDDEN, EXTWM_StateHidden},
193 {"_NET_WM_STATE_FULLSCREEN", &_XA_NET_WM_STATE_FULLSCREEN,
194 EXTWM_StateFullscreen},
195 {"_NET_WM_STATE_ABOVE", &_XA_NET_WM_STATE_ABOVE, EXTWM_StateAbove},
196 {"_NET_WM_STATE_BELOW", &_XA_NET_WM_STATE_BELOW, EXTWM_StateBelow},
197 {"_NET_WM_STATE_DEMANDS_ATTENTION",
198 &_XA_NET_WM_STATE_DEMANDS_ATTENTION, EXTWM_StateDemandsAttention},
199 {"_NET_WM_STATE_FOCUSED", &_XA_NET_WM_STATE_FOCUSED, EXTWM_StateFocused},
200 {NULL, NULL, 0, None}
201 };
202
203 AtomXref *EXTWM_State = &(_EXTWM_State[0]);
204
205 AtomXref EXTWM_Protocols[] = {
206 {"_NET_WM_PING", &_XA_NET_WM_PING, EXTWM_DoesWMPing},
207 {NULL, NULL, 0, None}
208 };
209
210 /*********************** Utility functions ******************************/
211 /* X resources access :*/
init_xrm()212 void init_xrm ()
213 {
214 if (!as_xrm_initialized) {
215 XrmInitialize ();
216 as_xrm_initialized = True;
217 }
218 }
219
220 Bool
read_int_resource(XrmDatabase db,const char * res_name,const char * res_class,int * value)221 read_int_resource (XrmDatabase db, const char *res_name,
222 const char *res_class, int *value)
223 {
224 char *str_type;
225 XrmValue rm_value;
226
227 if (XrmGetResource (db, res_name, res_class, &str_type, &rm_value) != 0)
228 if (rm_value.size > 0) {
229 register char *ptr = rm_value.addr;
230 int val;
231
232 if (*ptr == 'w')
233 ptr++;
234 val = atoi (ptr);
235 while (*ptr)
236 if (!isdigit ((int)*ptr++))
237 break;
238 if (*ptr == '\0') {
239 *value = val;
240 return True;
241 }
242 }
243 return False;
244 }
245
load_user_database()246 void load_user_database ()
247 {
248 if (!as_xrm_initialized)
249 init_xrm ();
250
251 destroy_user_database (); /* just in case */
252
253 if (XResourceManagerString (dpy) == NULL) {
254 char *xdefaults_file = put_file_home ("~/.Xdefaults");
255
256 if (!CheckFile (xdefaults_file)) {
257 char *xenv = getenv ("XENVIRONMENT");
258
259 show_warning ("Can't locate X resources database in \"%s\".",
260 xdefaults_file);
261 free (xdefaults_file);
262 if (xenv == NULL)
263 return;
264 xdefaults_file = put_file_home (xenv);
265 if (!CheckFile (xdefaults_file)) {
266 show_warning ("Can't locate X resources database in \"%s\".",
267 xdefaults_file);
268 free (xdefaults_file);
269 return;
270 }
271 }
272 as_xrm_user_db = XrmGetFileDatabase (xdefaults_file);
273 free (xdefaults_file);
274 }
275 }
276
destroy_user_database()277 void destroy_user_database ()
278 {
279 if (as_xrm_initialized && as_xrm_user_db != NULL) {
280 XrmDestroyDatabase (as_xrm_user_db);
281 as_xrm_user_db = NULL;
282 }
283 }
284
285 /******************** Hints reading functions **************************/
286
read_wm_name(ASRawHints * hints,Window w)287 void read_wm_name (ASRawHints * hints, Window w)
288 {
289 if (hints) {
290 read_text_property (w, XA_WM_NAME, &(hints->wm_name));
291 }
292 }
293
read_wm_icon_name(ASRawHints * hints,Window w)294 void read_wm_icon_name (ASRawHints * hints, Window w)
295 {
296 if (hints) {
297 read_text_property (w, XA_WM_ICON_NAME, &(hints->wm_icon_name));
298 }
299 }
300
read_wm_class(ASRawHints * hints,Window w)301 void read_wm_class (ASRawHints * hints, Window w)
302 {
303 if (hints && w != None) {
304 if (hints->wm_class) {
305 if (hints->wm_class->res_name)
306 XFree (hints->wm_class->res_name);
307 if (hints->wm_class->res_class)
308 XFree (hints->wm_class->res_class);
309 } else
310 hints->wm_class = XAllocClassHint ();
311
312 if (XGetClassHint (dpy, w, hints->wm_class) == 0) {
313 XFree (hints->wm_class);
314 hints->wm_class = NULL;
315 }
316 }
317 }
318
read_wm_hints(ASRawHints * hints,Window w)319 void read_wm_hints (ASRawHints * hints, Window w)
320 {
321 if (hints && w != None) {
322 if (hints->wm_hints)
323 XFree (hints->wm_hints);
324
325 if ((hints->wm_hints = XGetWMHints (dpy, w)) != NULL) {
326 if (get_flags (hints->wm_hints->flags, WindowGroupHint)
327 && hints->wm_hints->window_group != w) {
328 ASParentHints parent_hints;
329
330 if (parent_hints_func
331 (hints->wm_hints->window_group, &parent_hints)) {
332 if (hints->group_leader == NULL)
333 hints->group_leader =
334 (ASParentHints *) safecalloc (1, sizeof (ASParentHints));
335 *(hints->group_leader) = parent_hints;
336 }
337 }
338 if (get_flags (hints->wm_hints->flags, IconWindowHint)) {
339 /* some apps are written by truly insane ppl, most notably those
340 * designed to be docked in Window Maker's dock
341 * So lets bite the bullet and check if it is indeed sane :*/
342 if (hints->wm_hints->icon_window != w) {
343 unsigned int width, height;
344
345 if (!validate_drawable
346 (hints->wm_hints->icon_window, &width, &height))
347 hints->wm_hints->icon_window = None;
348 else if (get_parent_window (hints->wm_hints->icon_window) == w) {
349 if (width == 1 && height == 1) { /* broken wmdock app - icon is animated, yet not properly sized */
350 XMoveResizeWindow (dpy, hints->wm_hints->icon_window, 0, 0,
351 64, 64);
352 }
353 set_flags (hints->wm_hints->flags, IconWindowIsChildHint);
354 hints->wm_hints->icon_window = w;
355 }
356 }
357 /* while merging hints we will disable iconification for the window that
358 * has icon window same as client */
359
360 if (hints->wm_hints->icon_window == None)
361 clear_flags (hints->wm_hints->flags, IconWindowHint);
362 }
363 }
364 }
365 }
366
read_wm_normal_hints(ASRawHints * hints,Window w)367 void read_wm_normal_hints (ASRawHints * hints, Window w)
368 {
369 if (hints && w != None) {
370 long supplied;
371
372 if (hints->wm_normal_hints == NULL)
373 hints->wm_normal_hints = XAllocSizeHints ();
374
375 if (XGetWMNormalHints (dpy, w, hints->wm_normal_hints, &supplied) == 0) {
376 XFree (hints->wm_normal_hints);
377 hints->wm_normal_hints = NULL;
378 }
379 }
380 }
381
read_wm_transient_for(ASRawHints * hints,Window w)382 void read_wm_transient_for (ASRawHints * hints, Window w)
383 {
384 if (hints && w != None) {
385 Window transient_for;
386 ASParentHints parent_hints;
387
388 if (XGetTransientForHint (dpy, w, &transient_for) != 0)
389 if (transient_for != w
390 && parent_hints_func (transient_for, &parent_hints)) {
391 if (hints->transient_for == NULL)
392 hints->transient_for =
393 (ASParentHints *) safecalloc (1, sizeof (ASParentHints));
394 *(hints->transient_for) = parent_hints;
395 }
396 }
397 }
398
read_wm_protocols(ASRawHints * hints,Window w)399 void read_wm_protocols (ASRawHints * hints, Window w)
400 {
401 LOCAL_DEBUG_CALLER_OUT ("window(%lX)", w);
402 if (hints && w != None) {
403 CARD32 *protocols = NULL;
404 long nprotos = 0;
405
406 hints->wm_protocols = 0;
407 if (read_32bit_proplist (w, _XA_WM_PROTOCOLS, 3, &protocols, &nprotos)) {
408 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
409 char *aname = XGetAtomName (dpy, protocols[0]);
410
411 LOCAL_DEBUG_OUT ("nprotos=%ld, protocols[0] = 0x%lX(\"%s\")",
412 nprotos, protocols[0], aname);
413 XFree (aname);
414 #endif
415 translate_atom_list (&(hints->wm_protocols), WM_Protocols, protocols,
416 nprotos);
417 LOCAL_DEBUG_OUT ("translated protocols =0x%lX", hints->wm_protocols);
418 translate_atom_list (&(hints->extwm_hints.flags), EXTWM_Protocols,
419 protocols, nprotos);
420 LOCAL_DEBUG_OUT ("translated NET_ protocols =0x%lX",
421 hints->extwm_hints.flags);
422 free (protocols);
423 }
424 }
425 }
426
read_wm_cmap_windows(ASRawHints * hints,Window w)427 void read_wm_cmap_windows (ASRawHints * hints, Window w)
428 {
429 if (hints && w != None) {
430 if (hints->wm_cmap_windows)
431 free (hints->wm_cmap_windows);
432 if (!read_32bit_proplist
433 (w, _XA_WM_COLORMAP_WINDOWS, 10, &(hints->wm_cmap_windows),
434 &(hints->wm_cmap_win_count)))
435 hints->wm_cmap_win_count = 0;
436 }
437 }
438
read_wm_client_machine(ASRawHints * hints,Window w)439 void read_wm_client_machine (ASRawHints * hints, Window w)
440 {
441 if (hints) {
442 read_text_property (w, _XA_WM_CLIENT_MACHINE,
443 &(hints->wm_client_machine));
444 }
445 }
446
read_wm_command(ASRawHints * hints,Window w)447 void read_wm_command (ASRawHints * hints, Window w)
448 {
449 if (hints) { /* there is some wierd bullshit about this propertie being depreciated and stuff
450 * so we just use standard X function to read it up : */
451 if (hints->wm_cmd_argv)
452 XFreeStringList (hints->wm_cmd_argv);
453 LOCAL_DEBUG_OUT ("Reading WM_COMMAND property from window %lX", w);
454 if (XGetCommand (dpy, w, &(hints->wm_cmd_argv), &(hints->wm_cmd_argc))
455 == 0) {
456 LOCAL_DEBUG_OUT ("XGetCommand returned 0%s", "");
457 hints->wm_cmd_argv = NULL;
458 hints->wm_cmd_argc = 0;
459 }
460 }
461 }
462
read_wm_state(ASRawHints * hints,Window w)463 void read_wm_state (ASRawHints * hints, Window w)
464 {
465 if (hints) {
466 CARD32 *data = NULL;
467 long nitems = 0;
468
469 if (read_32bit_proplist (w, _XA_WM_STATE, 2, &data, &nitems)) {
470 if (nitems > 0) {
471 hints->wm_state = data[0];
472 if (nitems > 1)
473 hints->wm_state_icon_win = data[1];
474 }
475 }
476 if (data)
477 free (data);
478 }
479 }
480
read_motif_hints(ASRawHints * hints,Window w)481 void read_motif_hints (ASRawHints * hints, Window w)
482 {
483 if (hints && w != None) {
484 CARD32 *raw_data = NULL;
485 long nitems = 0;
486
487 if (!read_32bit_proplist (w, _XA_MwmAtom, 4, &raw_data, &nitems))
488 nitems = 0;
489
490 if (hints->motif_hints) {
491 free (hints->motif_hints);
492 hints->motif_hints = NULL;
493 }
494 if (nitems >= 4) {
495 hints->motif_hints = (MwmHints *) raw_data;
496 raw_data = NULL;
497 }
498 if (raw_data)
499 free (raw_data);
500 }
501 }
502
read_gnome_layer(ASRawHints * hints,Window w)503 void read_gnome_layer (ASRawHints * hints, Window w)
504 {
505 if (hints && w != None) {
506 if (read_32bit_property
507 (w, _XA_WIN_LAYER, &(hints->gnome_hints.layer)))
508 set_flags (hints->gnome_hints.flags, GNOME_LAYER);
509 }
510 }
511
read_gnome_state(ASRawHints * hints,Window w)512 void read_gnome_state (ASRawHints * hints, Window w)
513 {
514 if (hints && w != None) {
515 if (read_32bit_property
516 (w, _XA_WIN_STATE, &(hints->gnome_hints.state)))
517 set_flags (hints->gnome_hints.flags, GNOME_STATE);
518 }
519 }
520
read_gnome_workspace(ASRawHints * hints,Window w)521 void read_gnome_workspace (ASRawHints * hints, Window w)
522 {
523 if (hints && w != None) {
524 if (read_32bit_property
525 (w, _XA_WIN_WORKSPACE, &(hints->gnome_hints.workspace)))
526 set_flags (hints->gnome_hints.flags, GNOME_WORKSPACE);
527 }
528 }
529
read_gnome_hints(ASRawHints * hints,Window w)530 void read_gnome_hints (ASRawHints * hints, Window w)
531 {
532 if (hints && w != None) {
533 if (read_32bit_property
534 (w, _XA_WIN_HINTS, &(hints->gnome_hints.hints)))
535 set_flags (hints->gnome_hints.flags, GNOME_HINTS);
536 }
537 }
538
read_extwm_name(ASRawHints * hints,Window w)539 void read_extwm_name (ASRawHints * hints, Window w)
540 {
541 if (hints && w != None) {
542 if (read_text_property
543 (w, _XA_NET_WM_NAME, &(hints->extwm_hints.name)))
544 set_flags (hints->extwm_hints.flags, EXTWM_NAME);
545 }
546 }
547
read_extwm_icon_name(ASRawHints * hints,Window w)548 void read_extwm_icon_name (ASRawHints * hints, Window w)
549 {
550 if (hints && w != None) {
551 if (read_text_property
552 (w, _XA_NET_WM_ICON_NAME, &(hints->extwm_hints.icon_name)))
553 set_flags (hints->extwm_hints.flags, EXTWM_ICON_NAME);
554 }
555 }
556
read_extwm_visible_name(ASRawHints * hints,Window w)557 void read_extwm_visible_name (ASRawHints * hints, Window w)
558 {
559 if (hints && w != None) {
560 if (read_text_property
561 (w, _XA_NET_WM_VISIBLE_NAME, &(hints->extwm_hints.visible_name)))
562 set_flags (hints->extwm_hints.flags, EXTWM_VISIBLE_NAME);
563 }
564 }
565
read_extwm_visible_icon_name(ASRawHints * hints,Window w)566 void read_extwm_visible_icon_name (ASRawHints * hints, Window w)
567 {
568 if (hints && w != None) {
569 if (read_text_property
570 (w, _XA_NET_WM_VISIBLE_ICON_NAME,
571 &(hints->extwm_hints.visible_icon_name)))
572 set_flags (hints->extwm_hints.flags, EXTWM_VISIBLE_ICON_NAME);
573 }
574 }
575
read_extwm_desktop(ASRawHints * hints,Window w)576 void read_extwm_desktop (ASRawHints * hints, Window w)
577 {
578 if (hints && w != None) {
579 if (read_32bit_property
580 (w, _XA_NET_WM_DESKTOP, &(hints->extwm_hints.desktop)))
581 set_flags (hints->extwm_hints.flags, EXTWM_DESKTOP);
582 LOCAL_DEBUG_OUT ("NET_WM_DESKTOP = 0x%X", hints->extwm_hints.desktop);
583 }
584 }
585
read_extwm_desktop_val(Window w)586 CARD32 read_extwm_desktop_val (Window w)
587 {
588 CARD32 val = 0;
589
590 if (w != None)
591 read_32bit_property (w, _XA_NET_WM_DESKTOP, &val);
592 return val;
593 }
594
595
read_extwm_window_type(ASRawHints * hints,Window w)596 void read_extwm_window_type (ASRawHints * hints, Window w)
597 {
598 if (hints && w != None) {
599 CARD32 *protocols;
600 long nprotos = 0;
601
602 if (read_32bit_proplist
603 (w, _XA_NET_WM_WINDOW_TYPE, 6, &protocols, &nprotos)) {
604 translate_atom_list (&(hints->extwm_hints.type_flags),
605 EXTWM_WindowType, protocols, nprotos);
606 set_flags (hints->extwm_hints.flags, EXTWM_TypeSet);
607 free (protocols);
608 }
609 }
610 }
611
read_extwm_state(ASRawHints * hints,Window w)612 void read_extwm_state (ASRawHints * hints, Window w)
613 {
614 if (hints && w != None) {
615 CARD32 *protocols;
616 long nprotos = 0;
617
618 if (read_32bit_proplist (w, _XA_NET_WM_STATE, 6, &protocols, &nprotos)) {
619 translate_atom_list (&(hints->extwm_hints.state_flags), EXTWM_State,
620 protocols, nprotos);
621 set_flags (hints->extwm_hints.flags, EXTWM_StateSet);
622 free (protocols);
623 }
624 }
625 }
626
627
read_extwm_pid(ASRawHints * hints,Window w)628 void read_extwm_pid (ASRawHints * hints, Window w)
629 {
630 if (hints && w != None) {
631 if (read_32bit_property (w, _XA_NET_WM_PID, &(hints->extwm_hints.pid)))
632 set_flags (hints->extwm_hints.flags, EXTWM_PID);
633 }
634 }
635
read_extwm_icon(ASRawHints * hints,Window w)636 void read_extwm_icon (ASRawHints * hints, Window w)
637 {
638 if (hints && w != None) {
639 if (read_32bit_proplist
640 (w, _XA_NET_WM_ICON, 2 + 48 * 48, &(hints->extwm_hints.icon),
641 &(hints->extwm_hints.icon_length)))
642 set_flags (hints->extwm_hints.flags, EXTWM_ICON);
643 }
644 }
645
read_extwm_window_opacity(ASRawHints * hints,Window w)646 void read_extwm_window_opacity (ASRawHints * hints, Window w)
647 {
648 if (hints && w != None) {
649 if (read_32bit_property
650 (w, _XA_NET_WM_WINDOW_OPACITY,
651 &(hints->extwm_hints.window_opacity)))
652 set_flags (hints->extwm_hints.flags, EXTWM_WINDOW_OPACITY);
653 }
654 }
655
read_kde_desktop_window(ASRawHints * hints,Window w)656 void read_kde_desktop_window (ASRawHints * hints, Window w)
657 {
658 if (hints && w != None) {
659 CARD32 dummy;
660
661 if (read_32bit_property (w, _XA_KDE_DESKTOP_WINDOW, &dummy))
662 set_flags (hints->kde_hints.flags, KDE_DesktopWindow);
663 }
664 }
665
read_kde_systray_window_for(ASRawHints * hints,Window w)666 void read_kde_systray_window_for (ASRawHints * hints, Window w)
667 {
668 if (hints && w != None) {
669 if (read_32bit_property
670 (w, _XA_KDE_NET_SYSTEM_TRAY_WINDOW_FOR,
671 (CARD32 *) & hints->kde_hints.systray_window_for))
672 set_flags (hints->kde_hints.flags, KDE_SysTrayWindowFor);
673 }
674 }
675
default_parent_hints_func(Window parent,ASParentHints * dst)676 Bool default_parent_hints_func (Window parent, ASParentHints * dst)
677 {
678 Window root;
679 int dummy;
680 unsigned int udummy;
681
682 if (parent == None && dst == NULL)
683 return False;
684 if (!XGetGeometry
685 (dpy, parent, &root, &dummy, &dummy, &udummy, &udummy, &udummy,
686 &udummy))
687 return False;
688 if (parent != ASDefaultRoot) {
689 CARD32 desktop;
690
691 dst->parent = parent;
692 dst->flags = 0;
693 if (read_32bit_property (parent, _XA_NET_WM_DESKTOP, &desktop)) {
694 set_flags (dst->flags, AS_StartDesktop);
695 dst->desktop = desktop;
696 }
697 /* can't really find out about viewport here - write custom
698 * function for it, and override this deafult
699 */
700 }
701 return True;
702 }
703
704 get_parent_hints_func
set_parent_hints_func(get_parent_hints_func new_func)705 set_parent_hints_func (get_parent_hints_func new_func)
706 {
707 get_parent_hints_func old_func = parent_hints_func;
708
709 if (new_func != NULL)
710 parent_hints_func = new_func;
711 return old_func;
712 }
713
714 /******************** Hints management functions **************************/
715
intern_hint_atoms()716 void intern_hint_atoms ()
717 {
718 intern_atom_list (MainHints);
719 intern_atom_list (WM_Protocols);
720 intern_atom_list (EXTWM_WindowType);
721 intern_atom_list (EXTWM_State);
722 intern_atom_list (EXTWM_Protocols);
723 }
724
725 struct hint_description_struct {
726 Atom *id_variable;
727 void (*read_func) (ASRawHints *, Window);
728 ASFlagType hint_class; /* see HINT_ flags in hints.h */
729 HintsTypes hint_type;
730 } HintsDescriptions[] = {
731 {
732 &_XA_WM_NAME, read_wm_name, HINT_NAME, HINTS_ICCCM}, {
733 &_XA_WM_ICON_NAME, read_wm_icon_name, HINT_NAME, HINTS_ICCCM}, {
734 &_XA_WM_CLASS, read_wm_class, HINT_NAME, HINTS_ICCCM}, {
735 &_XA_WM_HINTS, read_wm_hints, HINT_STARTUP | HINT_GENERAL, HINTS_ICCCM}, {
736 &_XA_WM_NORMAL_HINTS, read_wm_normal_hints,
737 HINT_STARTUP | HINT_GENERAL, HINTS_ICCCM}, {
738 &_XA_WM_TRANSIENT_FOR, read_wm_transient_for,
739 HINT_STARTUP | HINT_GENERAL, HINTS_Transient}, {
740 &_XA_WM_PROTOCOLS, read_wm_protocols, HINT_PROTOCOL,
741 HINTS_ICCCM | HINTS_ExtendedWM}, {
742 &_XA_WM_COLORMAP_WINDOWS, read_wm_cmap_windows, HINT_COLORMAP,
743 HINTS_ICCCM}, {
744 &_XA_WM_CLIENT_MACHINE, read_wm_client_machine, HINT_STARTUP,
745 HINTS_ICCCM}, {
746 &_XA_WM_COMMAND, read_wm_command, HINT_STARTUP, HINTS_ICCCM}, {
747 &_XA_WM_STATE, read_wm_state, HINT_STARTUP, HINTS_ICCCM},
748 /* Motif hints */
749 {
750 &_XA_MwmAtom, read_motif_hints,
751 HINT_GENERAL | HINT_STARTUP | HINT_PROTOCOL, HINTS_Motif},
752 /* Gnome hints */
753 {
754 &_XA_WIN_LAYER, read_gnome_layer, HINT_STARTUP, HINTS_Gnome}, {
755 &_XA_WIN_STATE, read_gnome_state, HINT_STARTUP, HINTS_Gnome}, {
756 &_XA_WIN_WORKSPACE, read_gnome_workspace, HINT_STARTUP, HINTS_Gnome}, {
757 &_XA_WIN_HINTS, read_gnome_hints, HINT_GENERAL, HINTS_Gnome},
758 /* wm-spec _NET hints : */
759 {
760 &_XA_NET_WM_NAME, read_extwm_name, HINT_NAME, HINTS_ExtendedWM}, {
761 &_XA_NET_WM_ICON_NAME, read_extwm_icon_name, HINT_NAME,
762 HINTS_ExtendedWM}, {
763 &_XA_NET_WM_VISIBLE_NAME, read_extwm_visible_name, HINT_NAME,
764 HINTS_ExtendedWM}, {
765 &_XA_NET_WM_VISIBLE_ICON_NAME, read_extwm_visible_icon_name, HINT_NAME,
766 HINTS_ExtendedWM}, {
767 &_XA_NET_WM_DESKTOP, read_extwm_desktop, HINT_STARTUP | HINT_PROTOCOL,
768 HINTS_ExtendedWM}, {
769 &_XA_NET_WM_WINDOW_TYPE, read_extwm_window_type,
770 HINT_STARTUP | HINT_GENERAL, HINTS_ExtendedWM}, {
771 &_XA_NET_WM_STATE, read_extwm_state, HINT_STARTUP | HINT_GENERAL,
772 HINTS_ExtendedWM}, {
773 &_XA_NET_WM_PID, read_extwm_pid, HINT_GENERAL, HINTS_ExtendedWM}, {
774 &_XA_NET_WM_ICON, read_extwm_icon, HINT_GENERAL, HINTS_ExtendedWM}, {
775 &_XA_NET_WM_WINDOW_OPACITY, read_extwm_window_opacity, HINT_GENERAL,
776 HINTS_ExtendedWM}, {
777 &_XA_KDE_DESKTOP_WINDOW, read_kde_desktop_window, HINT_GENERAL,
778 HINTS_KDE}, {
779 &_XA_KDE_NET_SYSTEM_TRAY_WINDOW_FOR, read_kde_systray_window_for,
780 HINT_GENERAL, HINTS_KDE}, {
781 NULL, NULL, 0, HINTS_Supported}
782 };
783
init_hint_handlers()784 void init_hint_handlers ()
785 {
786 register int i;
787
788 if (hint_handlers != NULL)
789 destroy_ashash (&hint_handlers);
790
791 hint_handlers = create_ashash (7, NULL, NULL, NULL);
792
793 for (i = 0; HintsDescriptions[i].id_variable != NULL; i++) {
794 add_hash_item (hint_handlers,
795 (ASHashableValue) * (HintsDescriptions[i].id_variable),
796 &(HintsDescriptions[i]));
797 }
798 }
799
clientprops_cleanup()800 void clientprops_cleanup ()
801 {
802 if (hint_handlers != NULL)
803 destroy_ashash (&hint_handlers);
804 }
805
collect_hints(ScreenInfo * scr,Window w,ASFlagType what,ASRawHints * reusable_memory)806 ASRawHints *collect_hints (ScreenInfo * scr, Window w, ASFlagType what,
807 ASRawHints * reusable_memory)
808 {
809 ASRawHints *hints = NULL;
810
811 if (w != None && what != 0) {
812 Atom *all_props = NULL;
813 int props_num = 0;
814 struct hint_description_struct *descr;
815 Window root;
816 int x = 0, y = 0;
817 unsigned int width = 2, height = 2, bw = 0, depth = 1;
818
819 if (get_flags (what, HINT_STARTUP)) {
820 Status res =
821 XGetGeometry (dpy, w, &root, &x, &y, &width, &height, &bw,
822 &depth);
823
824 if (res == 0)
825 return NULL;
826 }
827
828 if ((all_props = XListProperties (dpy, w, &props_num)) == NULL)
829 return NULL;
830
831 if (reusable_memory == NULL)
832 hints = (ASRawHints *) safecalloc (1, sizeof (ASRawHints));
833 else {
834 hints = reusable_memory;
835 memset (hints, 0x00, sizeof (ASRawHints));
836 }
837
838 hints->scr = scr ? scr : ASDefaultScr;
839
840 if (get_flags (what, HINT_STARTUP)) { /* we also need to get window position, size and border width */
841 hints->placement.x = x;
842 hints->placement.y = y;
843 hints->placement.width = width;
844 hints->placement.height = height;
845 hints->border_width = bw;
846 hints->wm_state = WithdrawnState;
847 }
848
849 if (hint_handlers == NULL)
850 init_hint_handlers ();
851
852 if (all_props) {
853 while (props_num-- > 0) {
854 ASHashData hdata = { 0 };
855 if (get_hash_item
856 (hint_handlers, AS_HASHABLE (all_props[props_num]),
857 &hdata.vptr) == ASH_Success) {
858 if ((descr = hdata.vptr) != NULL)
859 if (get_flags (descr->hint_class, what)
860 && descr->read_func != NULL) {
861 descr->read_func (hints, w);
862 set_flags (hints->hints_types, (0x01 << descr->hint_type));
863 }
864 }
865 }
866 XFree (all_props);
867 }
868 if (hints->group_leader != NULL)
869 set_flags (hints->hints_types, (0x01 << HINTS_GroupLead));
870 }
871 return hints;
872 }
873
destroy_raw_hints(ASRawHints * hints,Bool reusable)874 void destroy_raw_hints (ASRawHints * hints, Bool reusable)
875 {
876 if (hints) {
877 if (hints->wm_name)
878 free_text_property (&(hints->wm_name));
879 if (hints->wm_icon_name)
880 free_text_property (&(hints->wm_icon_name));
881 if (hints->wm_class) {
882 if (hints->wm_class->res_name)
883 XFree (hints->wm_class->res_name);
884 if (hints->wm_class->res_class)
885 XFree (hints->wm_class->res_class);
886 XFree (hints->wm_class);
887 }
888 if (hints->wm_hints)
889 XFree (hints->wm_hints);
890 if (hints->group_leader)
891 free (hints->group_leader);
892 if (hints->wm_normal_hints)
893 XFree (hints->wm_normal_hints);
894
895 if (hints->transient_for)
896 free (hints->transient_for);
897
898 if (hints->wm_cmap_windows)
899 free (hints->wm_cmap_windows);
900
901 if (hints->wm_client_machine)
902 free_text_property (&(hints->wm_client_machine));
903 if (hints->wm_cmd_argv)
904 XFreeStringList (hints->wm_cmd_argv);
905
906 /* Motif Hints : */
907 if (hints->motif_hints)
908 free (hints->motif_hints);
909
910 /* Gnome Hints : */
911 /* nothing to free here */
912
913 /* WM-specs (new Gnome) Hints : */
914 if (hints->extwm_hints.name)
915 free_text_property (&(hints->extwm_hints.name));
916 if (hints->extwm_hints.icon_name)
917 free_text_property (&(hints->extwm_hints.icon_name));
918 if (hints->extwm_hints.icon)
919 free (hints->extwm_hints.icon);
920
921 if (reusable) /* we are being paranoid */
922 memset (hints, 0x00, sizeof (ASRawHints));
923 else
924 free (hints);
925 }
926 }
927
928 /***********************************************************************************
929 * Hints printing functions :
930 ***********************************************************************************/
print_wm_hints(stream_func func,void * stream,XWMHints * hints)931 void print_wm_hints (stream_func func, void *stream, XWMHints * hints)
932 {
933 if (!pre_print_check
934 (&func, &stream, hints, "No ICCCM.WM_HINTS available(NULL)."))
935 return;
936
937 func (stream, "ICCCM.WM_HINTS.flags=0x%lX;\n", hints->flags);
938 if (get_flags (hints->flags, InputHint))
939 func (stream, "ICCCM.WM_HINTS.input = %s;\n",
940 hints->input ? "True" : "False");
941 if (get_flags (hints->flags, StateHint))
942 func (stream, "ICCCM.WM_HINTS.initial_state = %s;\n",
943 (hints->initial_state ==
944 NormalState) ? "Normal" : ((hints->initial_state ==
945 IconicState) ? "Iconic" :
946 "Withdrawn"));
947 if (get_flags (hints->flags, IconPixmapHint))
948 func (stream, "ICCCM.WM_HINTS.icon_pixmap = 0x%lX;\n",
949 hints->icon_pixmap);
950 if (get_flags (hints->flags, IconWindowHint))
951 func (stream, "ICCCM.WM_HINTS.icon_window = 0x%lX;\n",
952 hints->icon_window);
953 if (get_flags (hints->flags, IconMaskHint))
954 func (stream, "ICCCM.WM_HINTS.icon_mask = 0x%lX;\n", hints->icon_mask);
955 if (get_flags (hints->flags, IconPositionHint))
956 func (stream,
957 "ICCCM.WM_HINTS.icon_x = %d;\nICCCM.WM_HINTS.icon_y = %d;\n",
958 hints->icon_x, hints->icon_y);
959 if (get_flags (hints->flags, WindowGroupHint))
960 func (stream, "ICCCM.WM_HINTS.window_group = 0x%lX;\n",
961 hints->window_group);
962 }
963
964 void
print_parent_hints(stream_func func,void * stream,ASParentHints * hints,const char * prompt)965 print_parent_hints (stream_func func, void *stream, ASParentHints * hints,
966 const char *prompt)
967 {
968 if (!pre_print_check (&func, &stream, hints, prompt))
969 return;
970
971 if (hints->parent != ASDefaultRoot)
972 func (stream, "%s.PARENT.parent = 0x%lX;\n", prompt, hints->parent);
973 else
974 func (stream, "%s.PARENT.parent = root;\n", prompt);
975
976 func (stream, "%s.PARENT.flags=0x%lX;\n", prompt, hints->flags);
977 if (get_flags (hints->flags, AS_StartDesktop))
978 func (stream, "%s.PARENT.desktop = %d;\n", prompt, hints->desktop);
979 if (get_flags (hints->flags, AS_StartViewportX))
980 func (stream, "%s.PARENT.viewport_x = %d;\n", prompt,
981 hints->viewport_x);
982 if (get_flags (hints->flags, AS_StartViewportY))
983 func (stream, "%s.PARENT.viewport_y = %d;\n", prompt,
984 hints->viewport_y);
985 }
986
987 void
print_wm_normal_hints(stream_func func,void * stream,XSizeHints * hints)988 print_wm_normal_hints (stream_func func, void *stream, XSizeHints * hints)
989 {
990 if (!pre_print_check
991 (&func, &stream, hints, "No ICCCM.WM_NORMAL_HINTS available(NULL)."))
992 return;
993
994 func (stream, "ICCCM.WM_NORMAL_HINTS.flags = 0x%lX;\n", hints->flags);
995
996 if (get_flags (hints->flags, PMinSize))
997 func (stream,
998 "ICCCM.WM_NORMAL_HINTS.min_width = %d;\nICCCM.WM_NORMAL_HINTS.min_height = %d;\n",
999 hints->min_width, hints->min_height);
1000 if (get_flags (hints->flags, PMaxSize))
1001 func (stream,
1002 "ICCCM.WM_NORMAL_HINTS.max_width = %d;\nICCCM.WM_NORMAL_HINTS.max_height = %d;\n",
1003 hints->max_width, hints->max_height);
1004 if (get_flags (hints->flags, PResizeInc))
1005 func (stream,
1006 "ICCCM.WM_NORMAL_HINTS.width_inc = %d;\nICCCM.WM_NORMAL_HINTS.height_inc = %d;\n",
1007 hints->width_inc, hints->height_inc);
1008 if (get_flags (hints->flags, PAspect)) {
1009 func (stream,
1010 "ICCCM.WM_NORMAL_HINTS.min_aspect.x = %d;\nICCCM.WM_NORMAL_HINTS.min_aspect.y = %d;\n",
1011 hints->min_aspect.x, hints->min_aspect.y);
1012 func (stream,
1013 "ICCCM.WM_NORMAL_HINTS.max_aspect.x = %d;\nICCCM.WM_NORMAL_HINTS.max_aspect.y = %d;\n",
1014 hints->max_aspect.x, hints->max_aspect.y);
1015 }
1016 if (get_flags (hints->flags, PBaseSize))
1017 func (stream,
1018 "ICCCM.WM_NORMAL_HINTS.base_width = %d;\nICCCM.WM_NORMAL_HINTS.base_height = %d;\n",
1019 hints->base_width, hints->base_height);
1020 if (get_flags (hints->flags, PWinGravity))
1021 func (stream, "ICCCM.WM_NORMAL_HINTS.win_gravity = %d;\n",
1022 hints->win_gravity);
1023 }
1024
print_motif_hints(stream_func func,void * stream,MwmHints * hints)1025 void print_motif_hints (stream_func func, void *stream, MwmHints * hints)
1026 {
1027 if (!pre_print_check
1028 (&func, &stream, hints, "No MOTIF_WM_HINTS available(NULL)."))
1029 return;
1030
1031 func (stream, "Motif.MOTIF_WM_HINTS.flags = 0x%lX;\n", hints->flags);
1032
1033 if (get_flags (hints->flags, MWM_HINTS_FUNCTIONS))
1034 func (stream, "Motif.MOTIF_WM_HINTS.functions = 0x%lX;\n",
1035 hints->functions);
1036 if (get_flags (hints->flags, MWM_HINTS_DECORATIONS))
1037 func (stream, "Motif.MOTIF_WM_HINTS.decorations = 0x%lX;\n",
1038 hints->decorations);
1039 if (get_flags (hints->flags, MWM_HINTS_INPUT_MODE))
1040 func (stream, "Motif.MOTIF_WM_HINTS.inputMode = 0x%lX;\n",
1041 hints->inputMode);
1042 }
1043
print_gnome_hints(stream_func func,void * stream,GnomeHints * hints)1044 void print_gnome_hints (stream_func func, void *stream, GnomeHints * hints)
1045 {
1046 if (!pre_print_check
1047 (&func, &stream, hints, "No GNOME hints (_WIN_*) available(NULL)."))
1048 return;
1049
1050 func (stream, "GNOME.flags = 0x%lX;\n", hints->flags);
1051
1052 if (get_flags (hints->flags, GNOME_LAYER))
1053 func (stream, "GNOME._WIN_LAYER = %ld;\n", hints->layer);
1054 if (get_flags (hints->flags, GNOME_STATE))
1055 func (stream, "GNOME._WIN_STATE = 0x%lX;\n", hints->state);
1056 if (get_flags (hints->flags, GNOME_WORKSPACE))
1057 func (stream, "GNOME._WIN_WORKSPACE = %ld;\n", hints->workspace);
1058 if (get_flags (hints->flags, GNOME_HINTS))
1059 func (stream, "GNOME._WIN_HINTS = 0x%lX;\n", hints->hints);
1060 }
1061
1062 void
print_extwm_hints(stream_func func,void * stream,ExtendedWMHints * hints)1063 print_extwm_hints (stream_func func, void *stream, ExtendedWMHints * hints)
1064 {
1065 if (!pre_print_check
1066 (&func, &stream, hints,
1067 "No Extended WM hints (_NET_*) available(NULL)."))
1068 return;
1069
1070 func (stream, "EXTWM.flags = 0x%lX;\n", hints->flags);
1071
1072 if (hints->name && get_flags (hints->flags, EXTWM_NAME))
1073 print_text_property (func, stream, hints->name, "EXTWM._NET_WM_NAME");
1074 if (hints->name && get_flags (hints->flags, EXTWM_ICON_NAME))
1075 print_text_property (func, stream, hints->icon_name,
1076 "EXTWM._NET_WM_ICON_NAME");
1077 if (get_flags (hints->flags, EXTWM_DESKTOP))
1078 func (stream, "EXTWM._NET_WM_DESKTOP = %ld;\n", hints->desktop);
1079 if (get_flags (hints->flags, EXTWM_PID))
1080 func (stream, "EXTWM._NET_WM_PID = %ld;\n", hints->pid);
1081 if (get_flags (hints->flags, EXTWM_ICON)) {
1082 func (stream, "EXTWM._NET_WM_ICON.length = %ld;\n",
1083 hints->icon_length);
1084 if (hints->icon_length > 2 && hints->icon) {
1085 func (stream, "EXTWM._NET_WM_ICON.width = %ld;\n", hints->icon[0]);
1086 func (stream, "EXTWM._NET_WM_ICON.height = %ld;\n", hints->icon[1]);
1087 }
1088 }
1089 if (get_flags (hints->flags, EXTWM_WINDOW_OPACITY))
1090 func (stream, "EXTWM._NET_WM_WINDOW_OPACITY = %ld;\n",
1091 hints->window_opacity);
1092
1093 if (get_flags (hints->flags, EXTWM_TypeSet))
1094 print_list_hints (func, stream, hints->type_flags, EXTWM_WindowType,
1095 "EXTWM._NET_WM_WINDOW_TYPE");
1096 if (get_flags (hints->flags, EXTWM_StateSet))
1097 print_list_hints (func, stream, hints->state_flags, EXTWM_State,
1098 "EXTWM._NET_WM_STATE");
1099 print_list_hints (func, stream, hints->flags, EXTWM_Protocols,
1100 "EXTWM._NET_WM_PROTOCOLS");
1101 }
1102
print_hints(stream_func func,void * stream,ASRawHints * hints)1103 void print_hints (stream_func func, void *stream, ASRawHints * hints)
1104 {
1105 register int i;
1106
1107 if (!pre_print_check
1108 (&func, &stream, hints, "No hints available(NULL)."))
1109 return;
1110
1111 /* ICCCM hints : */
1112 if (hints->wm_name)
1113 print_text_property (func, stream, hints->wm_name, "ICCCM.WM_NAME");
1114 if (hints->wm_icon_name)
1115 print_text_property (func, stream, hints->wm_icon_name,
1116 "ICCCM.WM_ICON_NAME");
1117 if (hints->wm_class)
1118 func (stream,
1119 "ICCCM.WM_CLASS.res_name = \"%s\";\nICCCM.WM_CLASS.res_class = \"%s\";\n",
1120 hints->wm_class->res_name, hints->wm_class->res_class);
1121 if (hints->wm_hints)
1122 print_wm_hints (func, stream, hints->wm_hints);
1123 if (hints->group_leader)
1124 print_parent_hints (func, stream, hints->group_leader,
1125 "ICCCM.WM_HINTS.WINDOW_GROUP");
1126 if (hints->wm_normal_hints)
1127 print_wm_normal_hints (func, stream, hints->wm_normal_hints);
1128
1129 func (stream,
1130 "ICCCM.placement.x = %d;\nICCCM.placement.y = %d;\nICCCM.placement.width = %d;\nICCCM.placement.height = %d;\n",
1131 hints->placement.x, hints->placement.y, hints->placement.width,
1132 hints->placement.height);
1133
1134 if (hints->transient_for)
1135 print_parent_hints (func, stream, hints->transient_for,
1136 "ICCCM.WM_HINTS.TRANSIENT_FOR");
1137
1138 print_list_hints (func, stream, hints->wm_protocols, WM_Protocols,
1139 "ICCCM.WM_PROTOCOLS");
1140
1141 if (hints->wm_client_machine)
1142 print_text_property (func, stream, hints->wm_client_machine,
1143 "ICCCM.WM_CLIENT_MACHINE");
1144
1145 func (stream, "ICCCM.WM_COMMAND.argc = %d;\n", hints->wm_cmd_argc);
1146 if (hints->wm_cmd_argv)
1147 for (i = 0; i < hints->wm_cmd_argc; i++)
1148 func (stream, "ICCCM.WM_COMMAND.argv[%d] = \"%s\";\n", i,
1149 hints->wm_cmd_argv[i] ? hints->wm_cmd_argv[i] : "NULL");
1150
1151 if (hints->wm_cmap_windows)
1152 for (i = 0; i < hints->wm_cmap_win_count; i++)
1153 func (stream, "ICCCM.WM_COLORMAP_WINDOWS[i] = 0x%lX;\n", i,
1154 hints->wm_cmap_windows[i]);
1155
1156 func (stream, "ICCCM.WM_STATE = %d;\n", hints->wm_state);
1157 func (stream, "ICCCM.WM_STATE.icon = 0x%lX;\n",
1158 hints->wm_state_icon_win);
1159
1160 /* Motif Hints : */
1161 if (hints->motif_hints)
1162 print_motif_hints (func, stream, hints->motif_hints);
1163
1164 /* Gnome Hints : */
1165 if (hints->gnome_hints.flags != 0)
1166 print_gnome_hints (func, stream, &(hints->gnome_hints));
1167
1168 /* WM-specs (new Gnome) Hints : */
1169 if (hints->extwm_hints.flags != 0)
1170 print_extwm_hints (func, stream, &(hints->extwm_hints));
1171 }
1172
1173 /**********************************************************************************/
1174 /* This is so that client app could re-read property updated by WM : */
1175
1176 Bool
handle_client_property_update(Window w,Atom property,ASRawHints * raw)1177 handle_client_property_update (Window w, Atom property, ASRawHints * raw)
1178 {
1179 void (*read_func) (ASRawHints * hints, Window w) = NULL;
1180
1181 if (w && property && raw) {
1182 /* Here we are only interested in properties updtaed by the Window Manager : */
1183 if (property == _XA_WM_STATE) /* ICCCM : */
1184 read_func = read_wm_state;
1185 else if (property == _XA_WIN_LAYER) /* GNOME : */
1186 read_func = read_gnome_layer;
1187 else if (property == _XA_WIN_STATE)
1188 read_func = read_gnome_state;
1189 else if (property == _XA_WIN_WORKSPACE)
1190 read_func = read_gnome_workspace;
1191 else if (property == _XA_NET_WM_DESKTOP) /* Extended WM-Hints : */
1192 read_func = read_extwm_desktop;
1193 else if (property == _XA_NET_WM_STATE)
1194 read_func = read_extwm_state;
1195 else
1196 return False;
1197
1198 read_func (raw, w);
1199
1200 return (validate_drawable (w, NULL, NULL) == w);
1201 }
1202 return False;
1203 }
1204
1205 /* This is so that client app could re-read property updated by client : */
1206 Bool
handle_manager_property_update(Window w,Atom property,ASRawHints * raw)1207 handle_manager_property_update (Window w, Atom property, ASRawHints * raw)
1208 {
1209 void (*read_func) (ASRawHints * hints, Window w) = NULL;
1210
1211 if (w && property && raw) {
1212 /* Here we are only interested in properties updtaed by the Window Manager : */
1213 if (IsNameProp (property)) {
1214 read_wm_state (raw, w);
1215 read_wm_icon_name (raw, w);
1216 read_wm_class (raw, w);
1217 read_extwm_name (raw, w);
1218 read_extwm_icon_name (raw, w);
1219 read_extwm_visible_name (raw, w);
1220 read_extwm_visible_icon_name (raw, w);
1221 return (validate_drawable (w, NULL, NULL) == w);
1222 } else if (property == _XA_WM_HINTS)
1223 read_func = read_wm_hints;
1224 else if (property == _XA_WM_NORMAL_HINTS)
1225 read_func = read_wm_normal_hints;
1226 else if (property == _XA_WM_PROTOCOLS)
1227 read_func = read_wm_protocols;
1228 else if (property == _XA_WM_COLORMAP_WINDOWS)
1229 read_func = read_wm_cmap_windows;
1230 else if (property == _XA_WM_STATE)
1231 read_func = read_wm_state;
1232 else if (property == _XA_WM_COMMAND)
1233 read_func = read_wm_command;
1234 else if (property == _XA_WM_CLIENT_MACHINE)
1235 read_func = read_wm_client_machine;
1236 else {
1237 show_debug (__FILE__, __FUNCTION__, __LINE__, "unknown property %X",
1238 property);
1239 return False;
1240 }
1241 read_func (raw, w);
1242 return (validate_drawable (w, NULL, NULL) == w);
1243 } else
1244 show_debug (__FILE__, __FUNCTION__, __LINE__,
1245 "incomplete parameters (%X, %X, %p)", w, property, raw);
1246
1247 return False;
1248 }
1249
get_extwm_state_flags(Window w,ASFlagType * flags)1250 Bool get_extwm_state_flags (Window w, ASFlagType * flags)
1251 {
1252 if (flags && w != None) {
1253 CARD32 *protocols;
1254 long nprotos = 0;
1255
1256 if (read_32bit_proplist
1257 (w, _XA_NET_WM_STATE, MAX_NET_WM_STATES, &protocols, &nprotos)) {
1258 /* LOCAL_DEBUG_OUT( "natoms = %ld", nprotos ); */
1259 translate_atom_list (flags, EXTWM_State, protocols, nprotos);
1260 free (protocols);
1261 return True;
1262 }
1263 }
1264 return False;
1265 }
1266
1267
1268
1269 /**********************************************************************************/
1270 /**********************************************************************************/
1271 /***************** Setting property values here : ********************************/
1272 /**********************************************************************************/
1273
1274 /****************************************************************************
1275 * This is used to tell applications which windows on the screen are
1276 * top level appication windows, and which windows are the icon windows
1277 * that go with them.
1278 ****************************************************************************/
set_client_state(Window w,struct ASStatusHints * status)1279 void set_client_state (Window w, struct ASStatusHints *status)
1280 {
1281 LOCAL_DEBUG_CALLER_OUT ("w = %lX, status->flags = 0x%lX", w,
1282 status ? status->flags : 0);
1283 if (w != None) {
1284 if (status != NULL) {
1285 CARD32 extwm_states[MAX_NET_WM_STATES];
1286 long used = 0;
1287 CARD32 gnome_state = 0;
1288 ASFlagType old_state = 0;
1289
1290 if (get_flags (status->flags, AS_Sticky)) {
1291 extwm_states[used++] = _XA_NET_WM_STATE_STICKY;
1292 gnome_state |= WIN_STATE_STICKY;
1293 }
1294 if (get_flags (status->flags, AS_Shaded)) {
1295 extwm_states[used++] = _XA_NET_WM_STATE_SHADED;
1296 gnome_state |= WIN_STATE_SHADED;
1297 }
1298 if (get_flags (status->flags, AS_Hidden)) {
1299 extwm_states[used++] = _XA_NET_WM_STATE_HIDDEN;
1300 gnome_state |= WIN_STATE_HIDDEN;
1301 }
1302 if (get_flags (status->flags, AS_MaximizedX)) {
1303 extwm_states[used++] = _XA_NET_WM_STATE_MAXIMIZED_HORZ;
1304 gnome_state |= WIN_STATE_MAXIMIZED_HORIZ;
1305 }
1306 if (get_flags (status->flags, AS_MaximizedY)) {
1307 extwm_states[used++] = _XA_NET_WM_STATE_MAXIMIZED_VERT;
1308 gnome_state |= WIN_STATE_MAXIMIZED_VERT;
1309 }
1310 if (get_flags (status->flags, AS_Focused)) {
1311 extwm_states[used++] = _XA_NET_WM_STATE_FOCUSED;
1312 }
1313 /* if (get_flags (status->flags, AS_Urgent))
1314 {
1315 extwm_states[used++] = _XA_NET_WM_STATE_DEMANDS_ATTENTION;
1316 }
1317 */
1318
1319 /* LOCAL_DEBUG_OUT( "window %lX used = %ld", w, used ); */
1320 if (get_extwm_state_flags (w, &old_state)) {
1321 if (get_flags (old_state, EXTWM_StateModal))
1322 extwm_states[used++] = _XA_NET_WM_STATE_MODAL;
1323 if (get_flags (old_state, EXTWM_StateSkipTaskbar))
1324 extwm_states[used++] = _XA_NET_WM_STATE_SKIP_TASKBAR;
1325 if (get_flags (old_state, EXTWM_StateSkipPager))
1326 extwm_states[used++] = _XA_NET_WM_STATE_SKIP_PAGER;
1327 if (get_flags (old_state, EXTWM_StateDemandsAttention))
1328 extwm_states[used++] = _XA_NET_WM_STATE_DEMANDS_ATTENTION;
1329 if (get_flags (old_state, EXTWM_StateHidden))
1330 extwm_states[used++] = _XA_NET_WM_STATE_HIDDEN;
1331 }
1332 LOCAL_DEBUG_OUT ("window %lX old_extwm_state = 0x%lX, used = %ld",
1333 w, old_state, used);
1334
1335 if (used == 0) {
1336 XDeleteProperty (dpy, w, _XA_NET_WM_STATE);
1337 XDeleteProperty (dpy, w, _XA_WIN_STATE);
1338 } else {
1339 set_32bit_proplist (w, _XA_NET_WM_STATE, XA_ATOM,
1340 &(extwm_states[0]), used);
1341 set_32bit_property (w, _XA_WIN_STATE, XA_CARDINAL, gnome_state);
1342 }
1343
1344 if (get_flags (status->flags, AS_Layer))
1345 set_32bit_property (w, _XA_WIN_LAYER, XA_CARDINAL, status->layer);
1346 }
1347 }
1348 }
1349
set_extwm_urgency_state(Window w,Bool set)1350 void set_extwm_urgency_state (Window w, Bool set)
1351 {
1352 LOCAL_DEBUG_CALLER_OUT ("w = %lX, set = %d", w, set);
1353 if (w != None) {
1354 CARD32 *states = NULL;
1355 long nstates = 0;
1356 int i;
1357 Bool changed = False;
1358
1359 read_32bit_proplist (w, _XA_NET_WM_STATE, MAX_NET_WM_STATES, &states,
1360 &nstates);
1361
1362 for (i = 0; i < nstates; ++i)
1363 if (states[i] == _XA_NET_WM_STATE_DEMANDS_ATTENTION)
1364 break;
1365 if (set && i >= nstates) {
1366 ++nstates;
1367 states = realloc (states, sizeof (CARD32) * nstates);
1368 states[nstates - 1] = _XA_NET_WM_STATE_DEMANDS_ATTENTION;
1369 changed = True;
1370 } else if (!set && i < nstates) {
1371 while (++i < nstates)
1372 states[i - 1] = states[i];
1373 --nstates;
1374 changed = True;
1375 }
1376 if (changed) {
1377 if (nstates == 0)
1378 XDeleteProperty (dpy, w, _XA_NET_WM_STATE);
1379 else
1380 set_32bit_proplist (w, _XA_NET_WM_STATE, XA_ATOM, &states[0],
1381 nstates);
1382 }
1383 free (states);
1384 }
1385 }
1386
1387
1388
set_client_desktop(Window w,int ext_desk)1389 void set_client_desktop (Window w, int ext_desk)
1390 {
1391 if (w) {
1392 if (ext_desk >= 0) {
1393 set_32bit_property (w, _XA_WIN_WORKSPACE, XA_CARDINAL, ext_desk);
1394 set_32bit_property (w, _XA_NET_WM_DESKTOP, XA_CARDINAL, ext_desk);
1395 }
1396 }
1397 }
1398
1399 void
set_client_names(Window w,char * name,char * icon_name,char * res_class,char * res_name)1400 set_client_names (Window w, char *name, char *icon_name, char *res_class,
1401 char *res_name)
1402 {
1403 if (w) {
1404 if (name) {
1405 set_text_property (w, _XA_WM_NAME, &name, 1, TPE_String);
1406 /* need to convert string to UTF8 */
1407 set_text_property (w, _XA_NET_WM_NAME, &name, 1, TPE_UTF8);
1408 }
1409 if (icon_name) {
1410 set_text_property (w, _XA_WM_ICON_NAME, &icon_name, 1, TPE_String);
1411 /* need to convert string to UTF8 */
1412 set_text_property (w, _XA_NET_WM_ICON_NAME, &icon_name, 1, TPE_UTF8);
1413 }
1414 if (res_class || res_name) {
1415 XClassHint *class_hint = XAllocClassHint ();
1416
1417 if (class_hint) {
1418 class_hint->res_class = res_class;
1419 class_hint->res_name = res_name;
1420 XSetClassHint (dpy, w, class_hint);
1421 XFree (class_hint);
1422 }
1423 }
1424 }
1425 }
1426
1427 void
set_client_protocols(Window w,ASFlagType protocols,ASFlagType extwm_protocols)1428 set_client_protocols (Window w, ASFlagType protocols,
1429 ASFlagType extwm_protocols)
1430 {
1431 LOCAL_DEBUG_OUT ("protocols=0x%lX", protocols);
1432 if (w && protocols) {
1433 CARD32 *list = NULL, *extwm_list = NULL;
1434 long nitems, extwm_nitems;
1435
1436 encode_atom_list (&(WM_Protocols[0]), &list, &nitems, protocols);
1437 encode_atom_list (&(EXTWM_Protocols[0]), &extwm_list, &extwm_nitems,
1438 extwm_protocols);
1439
1440 LOCAL_DEBUG_OUT ("nitems=%ld, extwm_nitems = %ld", nitems,
1441 extwm_nitems);
1442 if (extwm_nitems > 0) {
1443 int i;
1444
1445 list = realloc (list, sizeof (CARD32) * (nitems + extwm_nitems));
1446 for (i = 0; i < extwm_nitems; ++i)
1447 list[nitems + i] = extwm_list[i];
1448 free (extwm_list);
1449 nitems += extwm_nitems;
1450 }
1451
1452 if (nitems > 0 && list)
1453 set_32bit_proplist (w, _XA_WM_PROTOCOLS, XA_ATOM, list, nitems);
1454 if (list)
1455 free (list);
1456 }
1457 }
1458
set_extwm_hints(Window w,ExtendedWMHints * extwm_hints)1459 void set_extwm_hints (Window w, ExtendedWMHints * extwm_hints)
1460 {
1461 if (w && extwm_hints) {
1462 CARD32 *list;
1463 long nitems;
1464
1465 if (get_flags (extwm_hints->flags, EXTWM_TypeSet)) {
1466 encode_atom_list (&(EXTWM_WindowType[0]), &list, &nitems,
1467 extwm_hints->type_flags);
1468 if (nitems > 0) {
1469 set_32bit_proplist (w, _XA_NET_WM_WINDOW_TYPE, XA_ATOM, list,
1470 nitems);
1471 free (list);
1472 }
1473 }
1474 if (get_flags (extwm_hints->flags, EXTWM_StateSet)) {
1475 encode_atom_list (&(EXTWM_State[0]), &list, &nitems,
1476 extwm_hints->state_flags);
1477 if (nitems > 0) {
1478 set_32bit_proplist (w, _XA_NET_WM_STATE, XA_CARDINAL, list,
1479 nitems);
1480 free (list);
1481 list = NULL;
1482 }
1483 }
1484 if (get_flags (extwm_hints->flags, EXTWM_DESKTOP))
1485 set_32bit_property (w, _XA_NET_WM_DESKTOP, XA_CARDINAL,
1486 extwm_hints->desktop);
1487 if (get_flags (extwm_hints->flags, EXTWM_PID))
1488 set_32bit_property (w, _XA_NET_WM_PID, XA_CARDINAL,
1489 extwm_hints->pid);
1490 if (get_flags (extwm_hints->flags, EXTWM_WINDOW_OPACITY))
1491 set_32bit_property (w, _XA_NET_WM_WINDOW_OPACITY, XA_CARDINAL,
1492 extwm_hints->window_opacity);
1493 if (get_flags (extwm_hints->flags, EXTWM_ICON))
1494 set_32bit_proplist (w, _XA_NET_WM_ICON, XA_CARDINAL,
1495 extwm_hints->icon, extwm_hints->icon_length);
1496 }
1497 }
1498
set_gnome_hints(Window w,GnomeHints * gnome_hints)1499 void set_gnome_hints (Window w, GnomeHints * gnome_hints)
1500 {
1501
1502 }
1503
1504 void
set_client_hints(Window w,XWMHints * hints,XSizeHints * size_hints,ASFlagType protocols,ExtendedWMHints * extwm_hints)1505 set_client_hints (Window w, XWMHints * hints, XSizeHints * size_hints,
1506 ASFlagType protocols, ExtendedWMHints * extwm_hints)
1507 {
1508 if (w) {
1509 if (hints)
1510 XSetWMHints (dpy, w, hints);
1511 if (size_hints)
1512 XSetWMNormalHints (dpy, w, size_hints);
1513 if (protocols)
1514 set_client_protocols (w, protocols, extwm_hints->flags);
1515
1516 if (extwm_hints)
1517 set_extwm_hints (w, extwm_hints);
1518 }
1519 }
1520
set_client_cmd(Window w)1521 void set_client_cmd (Window w)
1522 {
1523 if (w != None && MyArgsPtr->saved_argv && MyArgsPtr->saved_argc > 0) {
1524 XSetCommand (dpy, w, MyArgsPtr->saved_argv, MyArgsPtr->saved_argc);
1525 }
1526 }
1527
1528 /***************************************************************************
1529 * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all
1530 * client messages will have the following form:
1531 *
1532 * event type ClientMessage
1533 * message type _XA_WM_PROTOCOLS
1534 * window client window
1535 * format 32
1536 * data[0] message atom
1537 * data[1] time stamp
1538 ****************************************************************************/
send_wm_protocol_request(Window w,Atom request,Time timestamp)1539 void send_wm_protocol_request (Window w, Atom request, Time timestamp)
1540 {
1541 XClientMessageEvent ev;
1542
1543 ev.type = ClientMessage;
1544 ev.window = w;
1545 ev.message_type = _XA_WM_PROTOCOLS;
1546 ev.format = 32;
1547 ev.data.l[0] = request;
1548 ev.data.l[1] = timestamp;
1549 XSendEvent (dpy, w, False, 0, (XEvent *) & ev);
1550 }
1551