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