1 /* -*-c-*- */
2 #include "config.h"
3 
4 #include <stdio.h>
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/Intrinsic.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xproto.h>
11 
12 #include "libs/FEvent.h"
13 
14 Display *dpy;
15 Window  Root, win;
16 int     screen;
17 
18 int has_focus_proto = 0;
19 int has_delete_proto = 1;
20 int input_mode = -1;
21 
22 Atom ATOM_NET_WM_WINDOW_TYPE           = None;
23 Atom ATOM_NET_WM_WINDOW_TYPE_DESKTOP   = None;
24 Atom ATOM_NET_WM_WINDOW_TYPE_DOCK      = None;
25 Atom ATOM_NET_WM_WINDOW_TYPE_TOOLBAR   = None;
26 Atom ATOM_NET_WM_WINDOW_TYPE_MENU      = None;
27 Atom ATOM_NET_WM_WINDOW_TYPE_DIALOG    = None;
28 Atom ATOM_NET_WM_WINDOW_TYPE_NORMAL    = None;
29 Atom ATOM_NET_WM_WINDOW_TYPE_SPLASH       = None;
30 Atom ATOM_NET_WM_WINDOW_TYPE_UTILITY      = None;
31 Atom ATOM_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = None;
32 
33 Atom ATOM_NET_WM_STATE                 = None;
34 Atom ATOM_NET_WM_STATE_MODAL           = None;
35 Atom ATOM_NET_WM_STATE_STICKY          = None;
36 Atom ATOM_NET_WM_STATE_MAXIMIZED_VERT  = None;
37 Atom ATOM_NET_WM_STATE_MAXIMIZED_HORIZ = None;
38 Atom ATOM_NET_WM_STATE_SHADED          = None;
39 Atom ATOM_NET_WM_STATE_SKIP_TASKBAR    = None;
40 Atom ATOM_NET_WM_STATE_SKIP_PAGER      = None;
41 Atom ATOM_NET_WM_STATE_HIDDEN          = None;
42 Atom ATOM_NET_WM_STATE_STAYS_ON_TOP    = None;
43 Atom ATOM_NET_WM_STATE_FULLSCREEN      = None;
44 
45 Atom ATOM_NET_WM_DESKTOP = None;
46 
47 /* wm protocol */
48 Atom ATOM_WM_DELETE_WINDOW = None;
49 Atom ATOM_WM_TAKE_FOCUS = None;
50 
51 /* Motif window hints */
52 Atom ATOM_MOTIF_WM_HINTS = None;
53 
54 #define MWM_HINTS_FUNCTIONS     (1L << 0)
55 #define MWM_HINTS_DECORATIONS   (1L << 1)
56 #define MWM_HINTS_INPUT_MODE    (1L << 2)
57 #define MWM_HINTS_STATUS        (1L << 3) /* ? */
58 
59 /* bit definitions for MwmHints.functions */
60 #define MWM_FUNC_ALL            (1L << 0)
61 #define MWM_FUNC_RESIZE         (1L << 1)
62 #define MWM_FUNC_MOVE           (1L << 2)
63 #define MWM_FUNC_MINIMIZE       (1L << 3)
64 #define MWM_FUNC_MAXIMIZE       (1L << 4)
65 #define MWM_FUNC_CLOSE          (1L << 5)
66 
67 /* values for MwmHints.input_mode */
68 #define MWM_INPUT_MODELESS                      0
69 #define MWM_INPUT_PRIMARY_APPLICATION_MODAL     1
70 #define MWM_INPUT_SYSTEM_MODAL                  2
71 #define MWM_INPUT_FULL_APPLICATION_MODAL        3
72 
73 /* bit definitions for MwmHints.decorations */
74 #define MWM_DECOR_ALL                 (1L << 0)
75 #define MWM_DECOR_BORDER              (1L << 1)
76 #define MWM_DECOR_RESIZEH             (1L << 2)
77 #define MWM_DECOR_TITLE               (1L << 3)
78 #define MWM_DECOR_MENU                (1L << 4)
79 #define MWM_DECOR_MINIMIZE            (1L << 5)
80 #define MWM_DECOR_MAXIMIZE            (1L << 6)
81 
82 /*
83  * _MWM_HINTS property
84  */
85 typedef struct
86 {
87 	long props[4];
88 	/* props[0]: flags */
89 	/* props[1]: functions */
90 	/* props[2]: decorations */
91 	/* props[3]: inputMode */
92 } PropMotifWmHints;
93 
94 typedef PropMotifWmHints PropMwmHints;
95 
96 #define PROP_MOTIF_WM_HINTS_ELEMENTS  4
97 #define PROP_MWM_HINTS_ELEMENTS       PROP_MOTIF_WM_HINTS_ELEMENTS
98 
99 void
Xloop(void)100 Xloop(void)
101 {
102 	while (1)
103 	{
104 		XEvent ev;
105 		XWindowAttributes xatt;
106 
107 		/* Sit and wait for an event to happen */
108 		FNextEvent(dpy,&ev);
109 		switch(ev.type)
110 		{
111 		case ConfigureNotify:
112 			break;
113 		case ClientMessage:
114 			if (has_delete_proto && ev.xclient.format == 32 &&
115 				ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW)
116 			{
117 				exit(0);
118 			}
119 			else if (has_focus_proto &&
120 				ev.xclient.data.l[0] == ATOM_WM_TAKE_FOCUS)
121 			{
122 				printf("WM_TAKE_FOCUS message\n");
123 				if (input_mode == 1)
124 				{
125 					printf ("\t...do nothing\n");
126 				}
127 				else if (input_mode == 0)
128 				{
129 					if (XGetWindowAttributes(dpy, win, &xatt)
130 						&& xatt.map_state == IsViewable)
131 					{
132 						printf ("\t...setting focus on our own: %lu\n",
133 							ev.xclient.data.l[1]);
134 						XSetInputFocus(
135 							dpy, win, RevertToParent,
136 							ev.xclient.data.l[1]);
137 					}
138 					else
139 					{
140 						printf ("\t...but we are not viewable\n");
141 					}
142 				}
143 			}
144 			break;
145 		default:
146 			break;
147 		}
148 	}
149 }
150 
151 #define XIA(a) XInternAtom(dpy,a,False);
InitAtom(void)152 void InitAtom(void)
153 {
154 	ATOM_NET_WM_WINDOW_TYPE           = XIA("_NET_WM_WINDOW_TYPE");
155 	ATOM_NET_WM_WINDOW_TYPE_DESKTOP   = XIA("_NET_WM_WINDOW_TYPE_DESKTOP");
156 	ATOM_NET_WM_WINDOW_TYPE_DOCK      = XIA("_NET_WM_WINDOW_TYPE_DOCK");
157 	ATOM_NET_WM_WINDOW_TYPE_TOOLBAR   = XIA("_NET_WM_WINDOW_TYPE_TOOLBAR");
158 	ATOM_NET_WM_WINDOW_TYPE_MENU      = XIA("_NET_WM_WINDOW_TYPE_MENU");
159 	ATOM_NET_WM_WINDOW_TYPE_DIALOG    = XIA("_NET_WM_WINDOW_TYPE_DIALOG");
160 	ATOM_NET_WM_WINDOW_TYPE_NORMAL    = XIA("_NET_WM_WINDOW_TYPE_NORMAL");
161 	ATOM_NET_WM_WINDOW_TYPE_SPLASH    = XIA("_NET_WM_WINDOW_TYPE_SPLASH");
162 	ATOM_NET_WM_WINDOW_TYPE_UTILITY   = XIA("_NET_WM_WINDOW_TYPE_UTILITY");
163 	ATOM_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = XIA("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
164 
165 	ATOM_NET_WM_STATE                 = XIA("_NET_WM_STATE");
166 	ATOM_NET_WM_STATE_MODAL           = XIA("_NET_WM_STATE_MODAL");
167 	ATOM_NET_WM_STATE_STICKY          = XIA("_NET_WM_STATE_STICKY");
168 	ATOM_NET_WM_STATE_MAXIMIZED_VERT  = XIA("_NET_WM_STATE_MAXIMIZED_VERT");
169 	ATOM_NET_WM_STATE_MAXIMIZED_HORIZ = XIA("_NET_WM_STATE_MAXIMIZED_HORIZ");
170 	ATOM_NET_WM_STATE_SHADED          = XIA("_NET_WM_STATE_SHADED");
171 	ATOM_NET_WM_STATE_SKIP_TASKBAR    = XIA("_NET_WM_STATE_SKIP_TASKBAR");
172 	ATOM_NET_WM_STATE_SKIP_PAGER      = XIA("_NET_WM_STATE_SKIP_PAGER");
173 	ATOM_NET_WM_STATE_HIDDEN          = XIA("_NET_WM_STATE_HIDDEN");
174 	ATOM_NET_WM_STATE_FULLSCREEN      = XIA("_NET_WM_STATE_FULLSCREEN");
175 	ATOM_NET_WM_STATE_STAYS_ON_TOP    = XIA("_NET_WM_STATE_STAYS_ON_TOP");
176 
177 	ATOM_NET_WM_DESKTOP               = XIA("_NET_WM_DESKTOP");
178 
179 	ATOM_WM_DELETE_WINDOW = XIA("WM_DELETE_WINDOW");
180 	ATOM_WM_TAKE_FOCUS    = XIA("WM_TAKE_FOCUS");
181 
182 	ATOM_MOTIF_WM_HINTS = XIA("_MOTIF_WM_HINTS");
183 }
184 
show_usage(void)185 void show_usage(void)
186 {
187 	printf("Usage: hints_test OPTIONS\n");
188 	printf("Options:\n");
189 	printf("  --mwm-func <names>\n");
190 	printf("      all, resize, move, minimize, maximize, close\n");
191 	printf("  --mwm-decor <names>\n");
192 	printf("      all, border, resizeh, title, menu, minimize, maximize\n");
193 	printf("  --ewmh-state <names>\n");
194 	printf("      hidden, shaded, sticky, skippager, skiptaskbar,\n");
195 	printf("      maxhoriz, maxvert, modal, staysontop, fullscreen\n");
196 	printf("  --ewmh-type <names>\n");
197 	printf("      normal, dock, toolbar, desktop, menu, dialog, splash, utility\n");
198 	printf("  --mwm-input { modless, app_modal, sys_modal, full_app_modal}\n");
199 	printf("  --ewmh-desktop\n");
200 	printf("  --wm-state { withdrawn, normal, iconic }\n");
201 	printf("  --wm-urgency\n");
202 	printf("  --wm-group { window, root, <win_id> }\n");
203 	printf("  --min-size <width> <height>\n");
204 	printf("  --max-size <width> <height>\n");
205 	printf("  --inc-size <width> <height>\n");
206 	printf("  --p-geometry <geometry>\n");
207 	printf("  --us-geometry <geometry>\n");
208 	printf("  --input { true, false }\n");
209 	printf("  --delete-proto\n");
210 	printf("  --no-delete-proto\n");
211 	printf("  --transient\n");
212 }
213 
main(int argc,char ** argv)214 int main(int argc, char **argv)
215 {
216 	int state_count = 0;
217 	Atom states[10];
218 	Atom type = 0;
219 	int i,x_r,y_r;
220 	unsigned int h_r,w_r;
221 	int ret;
222 	int ewmh_state_arg = 0;
223 	int ewmh_type_arg = 0;
224 	int mwm_func_arg = 0;
225 	int mwm_decor_arg = 0;
226 	int has_ewmh_desktop = 0;
227 	Atom ewmh_desktop = 0;
228 	XSizeHints hints;
229 	XClassHint classhints;
230 	XWMHints wm_hints;
231 	PropMwmHints mwm_hints;
232 	Window trans_win = 0;
233 
234 	if (!(dpy = XOpenDisplay("")))
235 	{
236 		fprintf(stderr, "can't open display\n");
237 		exit(1);
238 	}
239 
240 	screen = DefaultScreen(dpy);
241 	Root = RootWindow(dpy, screen);
242 	InitAtom();
243 
244 	hints.width = 170;
245 	hints.height = 100;
246 	hints.x = 0;
247 	hints.y = 0;
248 
249 	hints.flags = 0;
250 
251 	wm_hints.flags = 0;
252 	mwm_hints.props[0] = 0;
253 	mwm_hints.props[1] = 0;
254 	mwm_hints.props[2] = 0;
255 	mwm_hints.props[3] = 0;
256 
257 	win = XCreateSimpleWindow(
258 		dpy, Root, 0, 0, hints.width, hints.height, 0, 0, 0);
259 
260 	for (i = 1; i < argc; i++)
261 	{
262 		char *error_arg = NULL;
263 
264 		if (strcasecmp(argv[i], "--help") == 0)
265 		{
266 			show_usage();
267 			exit(0);
268 		}
269 		else if (strcasecmp(argv[i], "--ewmh-state") == 0)
270 		{
271 			ewmh_state_arg = 1;
272 			ewmh_type_arg = 0;
273 			mwm_func_arg = 0;
274 			mwm_decor_arg = 0;
275 		}
276 		else if (strcasecmp(argv[i], "--ewmh-type") == 0)
277 		{
278 			ewmh_state_arg = 0;
279 			ewmh_type_arg = 1;
280 			mwm_func_arg = 0;
281 			mwm_decor_arg = 0;
282 		}
283 		else if (strcasecmp(argv[i], "--mwm-func") == 0)
284 		{
285 			ewmh_state_arg = 0;
286 			ewmh_type_arg = 0;
287 			mwm_func_arg = 1;
288 			mwm_decor_arg = 0;
289 		}
290 		else if (strcasecmp(argv[i], "--mwm-decor") == 0)
291 		{
292 			ewmh_state_arg = 0;
293 			ewmh_type_arg = 0;
294 			mwm_func_arg = 0;
295 			mwm_decor_arg = 1;
296 		}
297 		else if (strcasecmp(argv[i], "--min-size") == 0)
298 		{
299 			i++;
300 			hints.min_width = atoi(argv[i]);
301 			i++;
302 			hints.min_height = atoi(argv[i]);
303 			hints.flags |= PMinSize;
304 		}
305 		else if (strcasecmp(argv[i], "--max-size") == 0)
306 		{
307 			i++;
308 			hints.max_width = atoi(argv[i]);
309 			i++;
310 			hints.max_height = atoi(argv[i]);
311 			hints.flags |= PMaxSize;
312 		}
313 		else if (strcasecmp(argv[i], "--inc-size") == 0)
314 		{
315 			i++;
316 			hints.width_inc = atoi(argv[i]);
317 			i++;
318 			hints.height_inc = atoi(argv[i]);
319 			hints.flags |= PResizeInc;
320 		}
321 		else if (strcasecmp(argv[i], "--p-geometry") == 0)
322 		{
323 			i++;
324 			ret = XParseGeometry(argv[i], &x_r, &y_r, &w_r, &h_r);
325 			if ((ret & WidthValue) && (ret & HeightValue))
326 			{
327 				hints.width = w_r;
328 				hints.height = h_r;
329 				hints.flags |= PSize;
330 			}
331 			if ((ret & XValue) && (ret & YValue))
332 			{
333 				hints.x = x_r;
334 				hints.y = y_r;
335 				hints.win_gravity = NorthWestGravity;
336 				if (ret & XNegative)
337 				{
338 					hints.x += XDisplayWidth(dpy, screen) -
339 						hints.width;
340 					hints.win_gravity = NorthEastGravity;
341 				}
342 				if (ret & YNegative)
343 				{
344 					hints.y += XDisplayHeight(dpy, screen) -
345 						hints.height;
346 					if (ret & XNegative)
347 					{
348 						hints.win_gravity =
349 							SouthEastGravity;
350 					}
351 					else
352 					{
353 						hints.win_gravity =
354 							SouthWestGravity;
355 					}
356 					hints.flags |= PWinGravity;
357 				}
358 				hints.flags |= PPosition;
359 			}
360 		}
361 		else if (strcasecmp(argv[i], "--us-geometry") == 0)
362 		{
363 			i++;
364 			ret = XParseGeometry(argv[i], &x_r, &y_r, &w_r, &h_r);
365 			if ((ret & WidthValue) && (ret & HeightValue))
366 			{
367 				hints.width = w_r;
368 				hints.height = h_r;
369 				hints.flags |= USSize;
370 			}
371 			if ((ret & XValue) && (ret & YValue))
372 			{
373 				hints.x = x_r;
374 				hints.y = y_r;
375 				hints.win_gravity=NorthWestGravity;
376 				if (ret & XNegative)
377 				{
378 					hints.x += XDisplayWidth(dpy,screen) -
379 						hints.width;
380 					hints.win_gravity=NorthEastGravity;
381 				}
382 				if (ret & YNegative)
383 				{
384 					hints.y += XDisplayHeight(dpy,screen) -
385 						hints.height;
386 					if (ret & XNegative)
387 					{
388 						hints.win_gravity =
389 							SouthEastGravity;
390 					}
391 					else
392 					{
393 						hints.win_gravity =
394 							SouthWestGravity;
395 					}
396 				}
397 				hints.flags |= USPosition | PWinGravity;
398 			}
399 		}
400 		else if (strcasecmp(argv[i], "--input") == 0)
401 		{
402 			i++;
403 			if (strcasecmp(argv[i], "true") == 0)
404 			{
405 				wm_hints.input = input_mode = True;
406 				wm_hints.flags |= InputHint;
407 			}
408 			else if (strcasecmp(argv[i], "false") == 0)
409 			{
410 				wm_hints.input = input_mode = False;
411 				wm_hints.flags |= InputHint;
412 			}
413 			else
414 			{
415 				error_arg = "--input";
416 			}
417 		}
418 		else if (strcasecmp(argv[i], "--focus-proto") == 0)
419 		{
420 			has_focus_proto = 1;
421 		}
422 		else if (strcasecmp(argv[i], "--no-delete-proto") == 0)
423 		{
424 			has_delete_proto = 0;
425 		}
426 		else if (strcasecmp(argv[i], "--wm-state") == 0)
427 		{
428 			wm_hints.flags |= StateHint;
429 			i++;
430 			if (strcasecmp(argv[i], "withdrawn") == 0)
431 			{
432 				wm_hints.initial_state = WithdrawnState;
433 			}
434 			else if (strcasecmp(argv[i], "normal") == 0)
435 			{
436 				wm_hints.initial_state = NormalState;
437 			}
438 			else if (strcasecmp(argv[i], "iconic") == 0)
439 			{
440 				wm_hints.initial_state = IconicState;
441 			}
442 			else
443 			{
444 				error_arg = "--wm-state";
445 			}
446 		}
447 		else if (strcasecmp(argv[i], "--wm-urgency") == 0)
448 		{
449 			wm_hints.flags |= XUrgencyHint;
450 		}
451 		else if (strcasecmp(argv[i], "--wm-group") == 0)
452 		{
453 			wm_hints.flags |= WindowGroupHint;
454 			i++;
455 			if (strcasecmp(argv[i], "window") == 0)
456 			{
457 				wm_hints.window_group = win;
458 			}
459 			else if (strcasecmp(argv[i], "root") == 0)
460 			{
461 				wm_hints.window_group = Root;
462 			}
463 			else
464 			{
465 				wm_hints.window_group =
466 					strtoul(argv[i], NULL, 0);
467 			}
468 		}
469 		else if (strcasecmp(argv[i], "--transient") == 0)
470 		{
471 			i++;
472 			if (strcasecmp(argv[i],"root") == 0)
473 			{
474 				trans_win = Root;
475 			}
476 			else
477 			{
478 				trans_win = strtoul(argv[i], NULL, 0);
479 			}
480 		}
481 		else if (strcasecmp(argv[i], "--mwm-input") == 0)
482 		{
483 			mwm_hints.props[0] |= MWM_HINTS_INPUT_MODE;
484 			i++;
485 			if (strcasecmp(argv[i], "modless") == 0)
486 			{
487 				mwm_hints.props[3] = MWM_INPUT_MODELESS;
488 			}
489 			else if (strcasecmp(argv[i], "app_modal") == 0)
490 			{
491 				mwm_hints.props[3] =
492 					MWM_INPUT_PRIMARY_APPLICATION_MODAL;
493 			}
494 			else if (strcasecmp(argv[i], "sys_modal") == 0)
495 			{
496 				mwm_hints.props[3] =
497 					MWM_INPUT_SYSTEM_MODAL;
498 			}
499 			else if (strcasecmp(argv[i], "full_app_modal") == 0)
500 			{
501 				mwm_hints.props[3] =
502 					MWM_INPUT_FULL_APPLICATION_MODAL;
503 			}
504 			else
505 			{
506 				error_arg = "--mwm-input";
507 			}
508 		}
509 		else if (strcasecmp(argv[i], "--ewmh-desktop") == 0)
510 		{
511 			has_ewmh_desktop = 1;
512 			i++;
513 			ewmh_desktop = atol(argv[i]);
514 		}
515 		else if (ewmh_state_arg && state_count < 10)
516 		{
517 			if (strcasecmp(argv[i], "hidden") == 0)
518 			{
519 				states[state_count++] =
520 					ATOM_NET_WM_STATE_HIDDEN;
521 			}
522 			else if (strcasecmp(argv[i], "shaded") == 0)
523 			{
524 				states[state_count++] =
525 					ATOM_NET_WM_STATE_SHADED;
526 			}
527 			else if (strcasecmp(argv[i], "sticky") == 0)
528 			{
529 				states[state_count++] =
530 					ATOM_NET_WM_STATE_STICKY;
531 			}
532 			else if (strcasecmp(argv[i], "skippager") == 0)
533 			{
534 				states[state_count++] =
535 					ATOM_NET_WM_STATE_SKIP_PAGER;
536 			}
537 			else if (strcasecmp(argv[i], "skiptaskbar") == 0)
538 			{
539 				states[state_count++] =
540 					ATOM_NET_WM_STATE_SKIP_TASKBAR;
541 			}
542 			else if (strcasecmp(argv[i], "maxhoriz") == 0)
543 			{
544 				states[state_count++] =
545 					ATOM_NET_WM_STATE_MAXIMIZED_HORIZ;
546 			}
547 			else if (strcasecmp(argv[i], "maxvert") == 0)
548 			{
549 				states[state_count++] =
550 					ATOM_NET_WM_STATE_MAXIMIZED_VERT;
551 			}
552 			else if (strcasecmp(argv[i], "modal") == 0)
553 			{
554 				states[state_count++] =
555 					ATOM_NET_WM_STATE_MODAL;
556 			}
557 			else if (strcasecmp(argv[i], "staysontop") == 0)
558 			{
559 				states[state_count++] =
560 					ATOM_NET_WM_STATE_STAYS_ON_TOP;
561 			}
562 			else if (strcasecmp(argv[i], "fullscreen") == 0)
563 			{
564 				states[state_count++] =
565 					ATOM_NET_WM_STATE_FULLSCREEN;
566 			}
567 			else
568 			{
569 				error_arg = "--ewmh-state";
570 			}
571 		}
572 		else if (ewmh_type_arg)
573 		{
574 			if (strcasecmp(argv[i], "normal") == 0)
575 			{
576 				type = ATOM_NET_WM_WINDOW_TYPE_NORMAL;
577 			}
578 			else if (strcasecmp(argv[i], "dock") == 0)
579 			{
580 				type = ATOM_NET_WM_WINDOW_TYPE_DOCK;
581 			}
582 			else if (strcasecmp(argv[i], "toolbar") == 0)
583 			{
584 				type = ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
585 			}
586 			else if (strcasecmp(argv[i], "desktop") == 0)
587 			{
588 				type = ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
589 			}
590 			else if (strcasecmp(argv[i], "menu") == 0)
591 			{
592 				type = ATOM_NET_WM_WINDOW_TYPE_MENU;
593 			}
594 			else if (strcasecmp(argv[i], "dialog") == 0)
595 			{
596 				type = ATOM_NET_WM_WINDOW_TYPE_DIALOG;
597 			}
598 			else if (strcasecmp(argv[i], "splash") == 0)
599 			{
600 				type = ATOM_NET_WM_WINDOW_TYPE_SPLASH;
601 			}
602 			else if (strcasecmp(argv[i], "utility") == 0)
603 			{
604 				type = ATOM_NET_WM_WINDOW_TYPE_UTILITY;
605 			}
606 			else
607 			{
608 				error_arg = "--ewmh-type";
609 			}
610 		}
611 		else if (mwm_func_arg)
612 		{
613 			mwm_hints.props[0] |= MWM_HINTS_FUNCTIONS;
614 			if (strcasecmp(argv[i], "all") == 0)
615 			{
616 				mwm_hints.props[1] |= MWM_FUNC_ALL;
617 			}
618 			else if (strcasecmp(argv[i], "resize") == 0)
619 			{
620 				mwm_hints.props[1] |= MWM_FUNC_RESIZE;
621 			}
622 			else if (strcasecmp(argv[i], "move") == 0)
623 			{
624 				mwm_hints.props[1] |= MWM_FUNC_MOVE;
625 			}
626 			else if (strcasecmp(argv[i], "minimize") == 0)
627 			{
628 				mwm_hints.props[1] |= MWM_FUNC_MINIMIZE;
629 			}
630 			else if (strcasecmp(argv[i], "maximize") == 0)
631 			{
632 				mwm_hints.props[1] |= MWM_FUNC_MAXIMIZE;
633 			}
634 			else if (strcasecmp(argv[i], "close") == 0)
635 			{
636 				mwm_hints.props[1] |= MWM_FUNC_CLOSE;
637 			}
638 			else
639 			{
640 				error_arg = "--mwm-func";
641 			}
642 		}
643 		else if (mwm_decor_arg)
644 		{
645 			mwm_hints.props[0] |= MWM_HINTS_DECORATIONS;
646 			if (strcasecmp(argv[i], "all") == 0)
647 			{
648 				mwm_hints.props[2] |= MWM_DECOR_ALL;
649 			}
650 			else if (strcasecmp(argv[i], "border") == 0)
651 			{
652 				mwm_hints.props[2] |= MWM_DECOR_BORDER;
653 			}
654 			else if (strcasecmp(argv[i], "resizeh") == 0)
655 			{
656 				mwm_hints.props[2] |= MWM_DECOR_RESIZEH;
657 			}
658 			else if (strcasecmp(argv[i], "title") == 0)
659 			{
660 				mwm_hints.props[2] |= MWM_DECOR_TITLE;
661 			}
662 			else if (strcasecmp(argv[i], "menu") == 0)
663 			{
664 				mwm_hints.props[2] |= MWM_DECOR_MENU;
665 			}
666 			else if (strcasecmp(argv[i], "minimize") == 0)
667 			{
668 				mwm_hints.props[2] |= MWM_DECOR_MINIMIZE;
669 			}
670 			else if (strcasecmp(argv[i], "maximize") == 0)
671 			{
672 				mwm_hints.props[2] |= MWM_DECOR_MAXIMIZE;
673 			}
674 			else
675 			{
676 				error_arg = "--mwm-decor";
677 			}
678 		}
679 		else
680 		{
681 			error_arg = "regular";
682 		}
683 		if (error_arg)
684 		{
685 			show_usage();
686 			printf("Invalid %s argument: %s\n", error_arg, argv[i]);
687 			exit(1);
688 		}
689 	}
690 
691 
692 	XSelectInput(dpy, win, StructureNotifyMask);
693 
694 	if (wm_hints.flags)
695 	{
696 		XSetWMHints(dpy, win, &wm_hints);
697 	}
698 
699 	if (state_count != 0)
700 	{
701 		XChangeProperty(
702 			dpy, win, ATOM_NET_WM_STATE, XA_ATOM, 32,
703 			PropModeReplace, (unsigned char *)states, state_count);
704 	}
705 
706 	if (type != 0)
707 	{
708 		XChangeProperty(
709 			dpy, win, ATOM_NET_WM_WINDOW_TYPE, XA_ATOM, 32,
710 			PropModeReplace, (unsigned char *)&type, 1);
711 	}
712 
713 	if (has_ewmh_desktop)
714 	{
715 		XChangeProperty(
716 			dpy, win, ATOM_NET_WM_DESKTOP, XA_CARDINAL, 32,
717 			PropModeReplace, (unsigned char *)&ewmh_desktop, 1);
718 	}
719 
720 	if (has_delete_proto || has_focus_proto)
721 	{
722 		Atom proto[2];
723 		int j = 0;
724 
725 		if (has_delete_proto)
726 			proto[j++] = ATOM_WM_DELETE_WINDOW;
727 		if (has_focus_proto)
728 			proto[j++] = ATOM_WM_TAKE_FOCUS;
729 
730 		XSetWMProtocols(dpy, win, proto, j);
731 	}
732 
733 	{
734 		XTextProperty nametext;
735 		char *list[] = { NULL, NULL };
736 		list[0] = "Hints Test";
737 
738 		classhints.res_name = strdup("hints_test");
739 		classhints.res_class = strdup("HintsTest");
740 
741 		if (!XStringListToTextProperty(list, 1, &nametext))
742 		{
743 			fprintf(stderr, "Failed to convert name to XText\n");
744 			exit(1);
745 		}
746 		XSetWMProperties(
747 			dpy, win, &nametext, &nametext, NULL, 0, &hints, NULL,
748 			&classhints);
749 		XFree(nametext.value);
750 	}
751 
752 	if (mwm_hints.props[0] != 0)
753 	{
754 		XChangeProperty(
755 			dpy, win, ATOM_MOTIF_WM_HINTS, ATOM_MOTIF_WM_HINTS, 32,
756 			PropModeReplace,(unsigned char *)&mwm_hints,
757 			PROP_MWM_HINTS_ELEMENTS);
758 	}
759 	if (trans_win !=0)
760 		XSetTransientForHint(dpy, win, trans_win);
761 
762 	XMapWindow(dpy, win);
763 	XSetWindowBackground(dpy, win, 0);
764 
765 	Xloop();
766 	return 1;
767 }
768