1 /* -*-c-*- */
2 /* Copyright (C) 2001  Olivier Chapuis */
3 /* This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, see: <http://www.gnu.org/licenses/>
15  */
16 
17 #include "config.h"
18 
19 #include <stdio.h>
20 
21 #include <X11/Xlib.h>
22 #include <X11/Xmd.h>
23 
24 #include "libs/fvwmlib.h"
25 #include "libs/FScreen.h"
26 #include "libs/Strings.h"
27 #include "fvwm.h"
28 #include "externs.h"
29 #include "execcontext.h"
30 #include "functions.h"
31 #include "misc.h"
32 #include "screen.h"
33 #include "virtual.h"
34 #include "commands.h"
35 #include "update.h"
36 #include "style.h"
37 #include "stack.h"
38 #include "events.h"
39 #include "ewmh.h"
40 #include "ewmh_intern.h"
41 #include "decorations.h"
42 #include "geometry.h"
43 #include "borders.h"
44 
45 extern ewmh_atom ewmh_atom_wm_state[];
46 
47 #define DEBUG_EWMH_INIT_STATE 0
48 /*
49  * root
50  */
ewmh_CurrentDesktop(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)51 int ewmh_CurrentDesktop(
52 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
53 {
54 	if (ev->xclient.data.l[0] < 0 || ev->xclient.data.l[0] > 0x7fffffff)
55 	{
56 		fvwm_msg(
57 			WARN, "ewmh_CurrentDesktop",
58 			"The application window (id %#lx)\n"
59 			"  \"%s\" tried to switch to an invalid desktop (%ld)\n"
60 			"  using an EWMH client message.\n"
61 			"    fvwm is ignoring this request.\n",
62 			fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
63 			ev->xclient.data.l[0]);
64 		fvwm_msg_report_app_and_workers();
65 
66 		return -1;
67 	}
68 	goto_desk(ev->xclient.data.l[0]);
69 
70 	return -1;
71 }
72 
ewmh_DesktopGeometry(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)73 int ewmh_DesktopGeometry(
74 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
75 {
76 	char action[256];
77 	long width = ev->xclient.data.l[0];
78 	long height = ev->xclient.data.l[1];
79 
80 	width = width / Scr.MyDisplayWidth;
81 	height = height / Scr.MyDisplayHeight;
82 
83 	if (width <= 0 || height <= 0)
84 	{
85 		fvwm_msg(
86 			WARN, "ewmh_DesktopGeometry",
87 			"The application window (id %#lx)\n"
88 			"  \"%s\" tried to set an invalid desktop geometry"
89 			" (%ldx%ld)\n"
90 			"  using an EWMH client message.\n"
91 			"    fvwm is ignoring this request.\n",
92 			fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
93 			ev->xclient.data.l[0], ev->xclient.data.l[1]);
94 		fvwm_msg_report_app_and_workers();
95 
96 		return -1;
97 	}
98 	sprintf(action, "DesktopSize %ld %ld", width, height);
99 	execute_function_override_window(NULL, NULL, action, 0, NULL);
100 
101 	return -1;
102 }
103 
ewmh_DesktopViewPort(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)104 int ewmh_DesktopViewPort(
105 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
106 {
107 	if (
108 		ev->xclient.data.l[0] < 0 ||
109 		ev->xclient.data.l[0] > 0x7fffffff ||
110 		ev->xclient.data.l[1] < 0 ||
111 		ev->xclient.data.l[1] > 0x7fffffff)
112 	{
113 		fvwm_msg(
114 			WARN, "ewmh_DesktopViewPort",
115 			"The application window (id %#lx)\n"
116 			"  \"%s\" tried to switch to an invalid page"
117 			" (%ldx%ld)\n"
118 			"  using an EWMH client message.\n"
119 			"    fvwm is ignoring this request.\n",
120 			fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
121 			ev->xclient.data.l[0], ev->xclient.data.l[1]);
122 		fvwm_msg_report_app_and_workers();
123 
124 		return -1;
125 	}
126 	MoveViewport(ev->xclient.data.l[0], ev->xclient.data.l[1], 1);
127 	return -1;
128 }
129 
ewmh_NumberOfDesktops(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)130 int ewmh_NumberOfDesktops(
131 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
132 {
133 	int d = ev->xclient.data.l[0];
134 
135 	/* not a lot of sinification for fvwm */
136 	if (d > 0 && (d <= ewmhc.MaxDesktops || ewmhc.MaxDesktops == 0))
137 	{
138 		ewmhc.NumberOfDesktops = d;
139 		EWMH_SetNumberOfDesktops();
140 	}
141 	else
142 	{
143 		fvwm_msg(
144 			WARN, "ewmh_NumberOfDesktops",
145 			"The application window (id %#lx)\n"
146 			"  \"%s\" tried to set an invalid number of desktops"
147 			" (%ld)\n"
148 			"  using an EWMH client message.\n"
149 			"    fvwm is ignoring this request.\n",
150 			fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
151 			ev->xclient.data.l[0]);
152 		fvwm_msg_report_app_and_workers();
153 	}
154 
155 	return -1;
156 }
157 
158 /*
159  * window
160  */
161 
ewmh_ActiveWindow(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)162 int ewmh_ActiveWindow(
163 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
164 {
165 	if (ev == NULL)
166 	{
167 		return 0;
168 	}
169 	execute_function_override_window(
170 		NULL, NULL, "EWMHActivateWindowFunc", 0, fw);
171 
172 	return 0;
173 }
174 
ewmh_CloseWindow(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)175 int ewmh_CloseWindow(
176 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
177 {
178 	if (ev == NULL)
179 	{
180 		return 0;
181 	}
182 	if (!is_function_allowed(F_CLOSE, NULL, fw, RQORIG_PROGRAM_US, False))
183 	{
184 		return 0;
185 	}
186 	execute_function_override_window(NULL, NULL, "Close", 0, fw);
187 
188 	return 0;
189 }
190 
ewmh_MoveResizeWindow(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)191 int ewmh_MoveResizeWindow(
192 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
193 {
194 	int do_reconfigure;
195 	int win_gravity;
196 	int value_mask;
197 
198 	if (ev == NULL)
199 	{
200 		return 0;
201 	}
202 	win_gravity = ev->xclient.data.l[0] & 0xff;
203 	value_mask = (ev->xclient.data.l[0] >> 8) & 0xf;
204 	if (fw == NULL)
205 	{
206 		/* unmanaged window */
207 		do_reconfigure = 1;
208 	}
209 	else
210 	{
211 		int func;
212 
213 		if (
214 			((value_mask & CWWidth) == 0 ||
215 			 ev->xclient.data.l[3] == fw->g.normal.width) &&
216 			((value_mask & CWHeight) == 0 ||
217 			 ev->xclient.data.l[4] == fw->g.normal.height))
218 		{
219 			func = F_MOVE;
220 		}
221 		else
222 		{
223 			func = F_RESIZE;
224 		}
225 		do_reconfigure = !!is_function_allowed(
226 			func, NULL, fw, RQORIG_PROGRAM, False);
227 	}
228 	if (do_reconfigure == 1)
229 	{
230 		XEvent e;
231 		XConfigureRequestEvent *cre = &e.xconfigurerequest;
232 
233 		cre->value_mask = value_mask;
234 		cre->x = ev->xclient.data.l[1];
235 		cre->y = ev->xclient.data.l[2];
236 		cre->width = ev->xclient.data.l[3];
237 		cre->height = ev->xclient.data.l[4];
238 		cre->window = ev->xclient.window;
239 		events_handle_configure_request(&e, fw, True, win_gravity);
240 	}
241 
242 	return 0;
243 }
244 
ewmh_RestackWindow(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)245 int ewmh_RestackWindow(
246 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
247 {
248 	int do_restack;
249 
250 	if (ev == NULL)
251 	{
252 		return 0;
253 	}
254 	if (fw == NULL)
255 	{
256 		/* unmanaged window */
257 		do_restack = 1;
258 	}
259 	else
260 	{
261 		do_restack = !!DO_EWMH_USE_STACKING_HINTS(fw);
262 	}
263 	if (do_restack == 1)
264 	{
265 		XEvent e;
266 		XConfigureRequestEvent *cre = &e.xconfigurerequest;
267 
268 		cre->value_mask = CWSibling | CWStackMode;
269 		cre->above = ev->xclient.data.l[1];
270 		cre->detail = ev->xclient.data.l[2];
271 		cre->window = ev->xclient.window;
272 		events_handle_configure_request(&e, fw, True, ForgetGravity);
273 	}
274 
275 	return 0;
276 }
277 
ewmh_WMDesktop(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)278 int ewmh_WMDesktop(
279 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
280 {
281 	if (ev != NULL && style == NULL)
282 	{
283 		/* client message */
284 		unsigned long d = (unsigned long)ev->xclient.data.l[0];
285 
286 		/* the spec says that if d = 0xFFFFFFFF then we have to Stick
287 		 * the window however KDE use 0xFFFFFFFE :o) */
288 		if (d == (unsigned long)-2 || d == (unsigned long)-1)
289 		{
290 			execute_function_override_window(
291 				NULL, NULL, "Stick on", 0, fw);
292 		}
293 		else if (d > 0)
294 		{
295 			if (IS_STICKY_ACROSS_PAGES(fw) ||
296 			    IS_STICKY_ACROSS_DESKS(fw))
297 			{
298 				execute_function_override_window(
299 					NULL, NULL, "Stick off", 0, fw);
300 			}
301 			if (fw->Desk != d)
302 			{
303 				do_move_window_to_desk(fw, (int)d);
304 			}
305 		}
306 		else
307 		{
308 			fvwm_msg(
309 				WARN, "ewmh_WMDesktop",
310 				"The application window (id %#lx)\n"
311 				"  \"%s\" tried to move to an invalid desk"
312 				" (%ld)\n"
313 				"  using an EWMH client message.\n"
314 				"    fvwm is ignoring this request.\n",
315 				fw ? FW_W(fw) : 0,
316 				fw ? fw->name.name : "(none)",
317 				ev->xclient.data.l[0]);
318 			fvwm_msg_report_app_and_workers();
319 		}
320 
321 		return 0;
322 	}
323 
324 	if (style != NULL && ev == NULL)
325 	{
326 		/* start on desk */
327 		CARD32 *val;
328 		int size = 0;
329 
330 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
331 		{
332 			SET_HAS_EWMH_INIT_WM_DESKTOP(
333 				fw, EWMH_STATE_UNDEFINED_HINT);
334 
335 			return 0;
336 		}
337 		if (HAS_EWMH_INIT_WM_DESKTOP(fw) != EWMH_STATE_UNDEFINED_HINT)
338 		{
339 			return 0;
340 		}
341 		val = ewmh_AtomGetByName(
342 			FW_W(fw), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN,
343 			&size);
344 		if (val == NULL)
345 		{
346 			SET_HAS_EWMH_INIT_WM_DESKTOP(fw, EWMH_STATE_NO_HINT);
347 
348 			return 0;
349 		}
350 #if DEBUG_EWMH_INIT_STATE
351 		fprintf(
352 			stderr, "ewmh WM_DESKTOP hint for window 0x%lx  "
353 			"(%i,%lu,%u)\n", FW_W(fw),
354 			HAS_EWMH_INIT_WM_DESKTOP(fw),
355 			fw->ewmh_hint_desktop, val[0]);
356 #endif
357 		if (val[0] == (CARD32)-2 || val[0] == (CARD32)-1)
358 		{
359 			S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1);
360 			S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1);
361 			S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1);
362 			S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1);
363 			S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1);
364 			S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1);
365 		}
366 		else if (val[0] < 256)
367 		{
368 			/* prevent crazy hints ?? */
369 			style->flags.use_start_on_desk = 1;
370 			style->flag_mask.use_start_on_desk = 1;
371 			style->change_mask.use_start_on_desk = 1;
372 			SSET_START_DESK(*style, val[0]);
373 		}
374 		SET_HAS_EWMH_INIT_WM_DESKTOP(fw, EWMH_STATE_HAS_HINT);
375 		fw->ewmh_hint_desktop = val[0];
376 		free(val);
377 	}
378 	return 0;
379 }
380 
ewmh_MoveResize(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)381 int ewmh_MoveResize(
382 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
383 {
384 	int dir = -1;
385 	int x_warp = 0;
386 	int y_warp = 0;
387 	Bool move = False;
388 	char cmd[256];
389 
390 	if (ev == NULL)
391 	{
392 		return 0;
393 	}
394 
395 	dir = ev->xclient.data.l[2];
396 	switch(dir)
397 	{
398 	case _NET_WM_MOVERESIZE_SIZE_TOPLEFT:
399 		break;
400 	case _NET_WM_MOVERESIZE_SIZE_TOP:
401 		x_warp = 50;
402 		break;
403 	case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT:
404 		x_warp = 100;
405 		break;
406 	case _NET_WM_MOVERESIZE_SIZE_RIGHT:
407 		x_warp = 100; y_warp = 50;
408 		break;
409 	case _NET_WM_MOVERESIZE_SIZE_KEYBOARD:
410 	case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT:
411 		x_warp = 100; y_warp = 100;
412 		break;
413 	case _NET_WM_MOVERESIZE_SIZE_BOTTOM:
414 		x_warp = 50; y_warp = 100;
415 		break;
416 	case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT:
417 		y_warp = 100;
418 		break;
419 	case _NET_WM_MOVERESIZE_SIZE_LEFT:
420 		y_warp = 50;
421 		break;
422 	case _NET_WM_MOVERESIZE_MOVE_KEYBOARD:
423 	case _NET_WM_MOVERESIZE_MOVE:
424 		move = True;
425 		break;
426 	default:
427 		return 0;
428 	}
429 
430 	if (move)
431 	{
432 		if (
433 			!is_function_allowed(
434 				F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False))
435 		{
436 			return 0;
437 		}
438 	}
439 	else
440 	{
441 		if (
442 			!is_function_allowed(
443 				F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False))
444 		{
445 			return 0;
446 		}
447 	}
448 
449 	if (!move)
450 	{
451 		sprintf(cmd, "WarpToWindow %i %i",x_warp,y_warp);
452 		execute_function_override_window(NULL, NULL, cmd, 0, fw);
453 	}
454 
455 	if (move)
456 	{
457 		execute_function_override_window(
458 			NULL, NULL, "Move", 0, fw);
459 	}
460 	else
461 	{
462 		execute_function_override_window(
463 			NULL, NULL, "Resize", 0, fw);
464 	}
465 
466 	return 0;
467 }
468 
469 /*
470  * WM_STATE*
471  */
ewmh_WMState(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)472 int ewmh_WMState(
473 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
474 {
475 	unsigned long maximize = 0;
476 
477 	if (ev != NULL)
478 	{
479 		ewmh_atom *a1,*a2;
480 
481 		a1 = ewmh_GetEwmhAtomByAtom(
482 			ev->xclient.data.l[1], EWMH_ATOM_LIST_WM_STATE);
483 		a2 = ewmh_GetEwmhAtomByAtom(
484 			ev->xclient.data.l[2], EWMH_ATOM_LIST_WM_STATE);
485 
486 		if (a1 != NULL)
487 		{
488 			maximize |= a1->action(fw, ev, NULL, 0);
489 		}
490 		if (a2 != NULL)
491 		{
492 			maximize |= a2->action(fw, ev, NULL, 0);
493 		}
494 	}
495 	else if (style != NULL)
496 	{
497 		CARD32 *val;
498 		unsigned int nitems;
499 		int size = 0;
500 		int i;
501 		ewmh_atom *list = ewmh_atom_wm_state;
502 		int has_hint = 0;
503 
504 		val = ewmh_AtomGetByName(
505 			FW_W(fw), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN,
506 			&size);
507 
508 		if (val == NULL)
509 		{
510 			size = 0;
511 		}
512 
513 #if DEBUG_EWMH_INIT_STATE
514 		if (size != 0)
515 		{
516 			fprintf(
517 				stderr, "Window 0x%lx has an init"
518 				" _NET_WM_STATE hint\n",FW_W(fw));
519 		}
520 #endif
521 		nitems = size / sizeof(CARD32);
522 		while(list->name != NULL)
523 		{
524 			has_hint = 0;
525 			for(i = 0; i < nitems; i++)
526 			{
527 				if (list->atom == val[i])
528 				{
529 					has_hint = 1;
530 				}
531 			}
532 			list->action(fw, NULL, style, has_hint);
533 			list++;
534 		}
535 		if (val != NULL)
536 		{
537 			free(val);
538 		}
539 		return 0;
540 	}
541 
542 	if (maximize != 0)
543 	{
544 		int max_vert = (maximize & EWMH_MAXIMIZE_VERT)? 100:0;
545 		int max_horiz = (maximize & EWMH_MAXIMIZE_HORIZ)? 100:0;
546 		char cmd[256];
547 
548 		if (maximize & EWMH_MAXIMIZE_REMOVE)
549 		{
550 			sprintf(cmd,"Maximize off");
551 		}
552 		else
553 		{
554 			if (!is_function_allowed(
555 				    F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US,
556 				    False))
557 			{
558 				return 0;
559 			}
560 			sprintf(cmd,"Maximize on %i %i", max_horiz, max_vert);
561 		}
562 		execute_function_override_window(NULL, NULL, cmd, 0, fw);
563 	}
564 	return 0;
565 }
566 
ewmh_WMStateFullScreen(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)567 int ewmh_WMStateFullScreen(
568 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
569 {
570 	if (ev == NULL && style == NULL)
571 	{
572 		return (IS_EWMH_FULLSCREEN(fw));
573 	}
574 
575 	if (ev == NULL && style != NULL)
576 	{
577 		/* start full screen */
578 		unsigned long has_hint = any;
579 
580 #if DEBUG_EWMH_INIT_STATE
581 		if (has_hint)
582 		{
583 			fprintf(stderr,"\tFullscreen\n");
584 		}
585 #endif
586 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
587 		{
588 			SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
589 				fw, EWMH_STATE_UNDEFINED_HINT);
590 			return 0;
591 		}
592 		if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) !=
593 		    EWMH_STATE_UNDEFINED_HINT)
594 		{
595 			return 0;
596 		}
597 		if (!has_hint)
598 		{
599 			SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
600 				fw, EWMH_STATE_NO_HINT);
601 			return 0;
602 		}
603 		SET_EWMH_FULLSCREEN(fw,True);
604 		SET_HAS_EWMH_INIT_FULLSCREEN_STATE(fw, EWMH_STATE_HAS_HINT);
605 		return 0;
606 	}
607 
608 	if (ev != NULL)
609 	{
610 		/* client message */
611 		int bool_arg = ev->xclient.data.l[0];
612 		int is_full_screen;
613 
614 		is_full_screen = IS_EWMH_FULLSCREEN(fw);
615 		if ((bool_arg == NET_WM_STATE_TOGGLE && !is_full_screen) ||
616 		    bool_arg == NET_WM_STATE_ADD)
617 		{
618 			EWMH_fullscreen(fw);
619 		}
620 		else
621 		{
622 			if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) ==
623 			    EWMH_STATE_HAS_HINT)
624 			{
625 				/* the application started fullscreen */
626 				SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
627 					fw, EWMH_STATE_NO_HINT);
628 			}
629 			/* unmaximize will restore is_ewmh_fullscreen,
630 			 * layer and apply_decor_change */
631 			execute_function_override_window(
632 				NULL, NULL, "Maximize off", 0, fw);
633 		}
634 		if ((IS_EWMH_FULLSCREEN(fw) &&
635 		     !DO_EWMH_USE_STACKING_HINTS(fw)) ||
636 		    (!IS_EWMH_FULLSCREEN(fw) &&
637 		     DO_EWMH_USE_STACKING_HINTS(fw)))
638 		{
639 			/* On: if not raised by a layer cmd raise
640 			 * Off: if lowered by a layer cmd raise */
641 			execute_function_override_window(
642 				NULL, NULL, "Raise", 0, fw);
643 		}
644 	}
645 
646 	return 0;
647 }
648 
ewmh_WMStateHidden(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)649 int ewmh_WMStateHidden(
650 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
651 {
652 	if (ev == NULL && style == NULL)
653 	{
654 		unsigned long do_restore = any;
655 
656 		if (do_restore)
657 		{
658 			if (HAS_EWMH_INIT_HIDDEN_STATE(fw) ==
659 			    EWMH_STATE_HAS_HINT)
660 			{
661 				return True;
662 			}
663 			return False;
664 		}
665 		return IS_ICONIFIED(fw);
666 	}
667 
668 	if (ev == NULL && style != NULL)
669 	{
670 		/* start iconified */
671 		unsigned long has_hint = any;
672 
673 #if DEBUG_EWMH_INIT_STATE
674 		if (has_hint)
675 			fprintf(stderr,"\tHidden\n");
676 #endif
677 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
678 		{
679 			SET_HAS_EWMH_INIT_HIDDEN_STATE(
680 				fw, EWMH_STATE_UNDEFINED_HINT);
681 			return 0;
682 		}
683 		if (HAS_EWMH_INIT_HIDDEN_STATE(fw) !=
684 		    EWMH_STATE_UNDEFINED_HINT)
685 		{
686 			return 0;
687 		}
688 		if (!has_hint)
689 		{
690 			SET_HAS_EWMH_INIT_HIDDEN_STATE(fw, EWMH_STATE_NO_HINT);
691 			return 0;
692 		}
693 		style->flags.do_start_iconic = 1;
694 		style->flag_mask.do_start_iconic = 1;
695 		style->change_mask.do_start_iconic = 1;
696 		SET_HAS_EWMH_INIT_HIDDEN_STATE(fw, EWMH_STATE_HAS_HINT);
697 		return 0;
698 	}
699 
700 	if (ev != NULL)
701 	{
702 		/* client message */
703 		char cmd[16];
704 		int bool_arg = ev->xclient.data.l[0];
705 
706 		if ((bool_arg == NET_WM_STATE_TOGGLE && !IS_ICONIFIED(fw)) ||
707 		    bool_arg == NET_WM_STATE_ADD)
708 		{
709 			/* iconify */
710 			if (
711 				!is_function_allowed(
712 					F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US,
713 					False))
714 			{
715 				return 0;
716 			}
717 			sprintf(cmd, "Iconify on");
718 		}
719 		else
720 		{
721 			/* deiconify */
722 			sprintf(cmd, "Iconify off");
723 		}
724 		execute_function_override_window(NULL, NULL, cmd, 0, fw);
725 	}
726 	return 0;
727 }
728 
ewmh_WMStateMaxHoriz(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)729 int ewmh_WMStateMaxHoriz(
730 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
731 {
732 
733 	if (ev == NULL && style == NULL)
734 	{
735 #if 0
736 		return (IS_MAXIMIZED(fw) && !IS_EWMH_FULLSCREEN(fw));
737 #else
738 		/* DV: the notion of vertical/horizontal maximization does not
739 		 * make any sense in fvwm, so just claim we're never maximized
740 		 */
741 		return 0;
742 #endif
743 	}
744 
745 	if (ev == NULL && style != NULL)
746 	{
747 		unsigned long has_hint = any;
748 #if DEBUG_EWMH_INIT_STATE
749 		if (has_hint)
750 		{
751 			fprintf(
752 				stderr, "\t Maxhoriz %i\n",
753 				HAS_EWMH_INIT_MAXHORIZ_STATE(fw));
754 		}
755 #endif
756 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
757 		{
758 			SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
759 				fw, EWMH_STATE_UNDEFINED_HINT);
760 			return 0;
761 		}
762 
763                 /* If the initial state is STATE_NO_HINT we still want to
764                  * override it, since having just one of MAXIMIZED_HORIZ or
765                  * MAXIMIZED_HORZ is enough to make the window maximized.
766                  */
767 		if (HAS_EWMH_INIT_MAXHORIZ_STATE(fw) ==
768 		    EWMH_STATE_HAS_HINT)
769 		{
770 			return 0;
771 		}
772 		if (!has_hint)
773 		{
774 			SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
775 				fw, EWMH_STATE_NO_HINT);
776 			return 0;
777 		}
778 		SET_HAS_EWMH_INIT_MAXHORIZ_STATE(fw, EWMH_STATE_HAS_HINT);
779 		return 0;
780 	}
781 
782 	if (ev != NULL)
783 	{
784 		/* client message */
785 		int cmd_arg = ev->xclient.data.l[0];
786 		if (
787 			!IS_MAXIMIZED(fw) &&
788 			(cmd_arg == NET_WM_STATE_TOGGLE ||
789 			 cmd_arg == NET_WM_STATE_ADD))
790 		{
791 			return EWMH_MAXIMIZE_HORIZ;
792 		}
793 		else if (
794 			IS_MAXIMIZED(fw) &&
795 			(cmd_arg == NET_WM_STATE_TOGGLE ||
796 			 cmd_arg == NET_WM_STATE_REMOVE))
797 		{
798 			return EWMH_MAXIMIZE_REMOVE;
799 		}
800 	}
801 
802 	return 0;
803 }
804 
ewmh_WMStateMaxVert(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)805 int ewmh_WMStateMaxVert(
806 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
807 {
808 
809 	if (ev == NULL && style == NULL)
810 	{
811 #if 0
812 		return (IS_MAXIMIZED(fw) && !IS_EWMH_FULLSCREEN(fw));
813 #else
814 		/* DV: the notion of vertical/horizontal maximization does not
815 		 * make any sense in fvwm, so just claim we're never maximized
816 		 */
817 		return 0;
818 #endif
819 	}
820 
821 	if (ev == NULL && style != NULL)
822 	{
823 		unsigned long has_hint = any;
824 #if DEBUG_EWMH_INIT_STATE
825 		if (has_hint)
826 		{
827 			fprintf(
828 				stderr, "\t Maxvert %i\n",
829 				HAS_EWMH_INIT_MAXVERT_STATE(fw));
830 		}
831 #endif
832 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
833 		{
834 			SET_HAS_EWMH_INIT_MAXVERT_STATE(
835 				fw, EWMH_STATE_UNDEFINED_HINT);
836 			return 0;
837 		}
838 		if (HAS_EWMH_INIT_MAXVERT_STATE(fw) !=
839 		    EWMH_STATE_UNDEFINED_HINT)
840 		{
841 			return 0;
842 		}
843 		if (!has_hint)
844 		{
845 			SET_HAS_EWMH_INIT_MAXVERT_STATE(
846 				fw, EWMH_STATE_NO_HINT);
847 			return 0;
848 		}
849 		SET_HAS_EWMH_INIT_MAXVERT_STATE(fw, EWMH_STATE_HAS_HINT);
850 		return 0;
851 	}
852 
853 	if (ev != NULL)
854 	{
855 		/* client message */
856 		int cmd_arg = ev->xclient.data.l[0];
857 		if (
858 			!IS_MAXIMIZED(fw) &&
859 			(cmd_arg == NET_WM_STATE_TOGGLE ||
860 			 cmd_arg == NET_WM_STATE_ADD))
861 		{
862 			return EWMH_MAXIMIZE_VERT;
863 		}
864 		else if (
865 			IS_MAXIMIZED(fw) &&
866 			(cmd_arg == NET_WM_STATE_TOGGLE ||
867 			 cmd_arg == NET_WM_STATE_REMOVE))
868 		{
869 			return EWMH_MAXIMIZE_REMOVE;
870 		}
871 	}
872 
873 	return 0;
874 }
875 
ewmh_WMStateModal(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)876 int ewmh_WMStateModal(
877 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
878 {
879 	if (ev == NULL && style == NULL)
880 	{
881 		unsigned long do_restore = any;
882 
883 		if (do_restore)
884 		{
885 			if (HAS_EWMH_INIT_MODAL_STATE(fw) ==
886 			    EWMH_STATE_HAS_HINT)
887 			{
888 				return True;
889 			}
890 			return False;
891 		}
892 		return IS_EWMH_MODAL(fw);
893 	}
894 
895 	if (ev == NULL && style != NULL)
896 	{
897 		unsigned long has_hint = any;
898 #if DEBUG_EWMH_INIT_STATE
899 		if (has_hint)
900 		{
901 			fprintf(
902 				stderr, "\t Modal %i\n",
903 				HAS_EWMH_INIT_MODAL_STATE(fw));
904 		}
905 #endif
906 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
907 		{
908 			SET_HAS_EWMH_INIT_MODAL_STATE(
909 				fw, EWMH_STATE_UNDEFINED_HINT);
910 			return 0;
911 		}
912 		if (HAS_EWMH_INIT_MODAL_STATE(fw) != EWMH_STATE_UNDEFINED_HINT)
913 		{
914 			return 0;
915 		}
916 		if (!has_hint)
917 		{
918 			SET_HAS_EWMH_INIT_MODAL_STATE(fw, EWMH_STATE_NO_HINT);
919 			return 0;
920 		}
921 
922 		/* the window map or had mapped with a modal hint */
923 		if (IS_TRANSIENT(fw))
924 		{
925 			SET_EWMH_MODAL(fw, True);
926 			/* the window is a modal transient window so we grab
927 			 * the focus it will be good to raise it but ... */
928 			FPS_GRAB_FOCUS_TRANSIENT(
929 				S_FOCUS_POLICY(SCF(*style)), 1);
930 			FPS_GRAB_FOCUS_TRANSIENT(
931 				S_FOCUS_POLICY(SCM(*style)), 1);
932 			FPS_GRAB_FOCUS_TRANSIENT(
933 				S_FOCUS_POLICY(SCC(*style)), 1);
934 			SET_HAS_EWMH_INIT_MODAL_STATE(
935 				fw, EWMH_STATE_HAS_HINT);
936 		}
937 		else
938 		{
939 			SET_EWMH_MODAL(fw, False);
940 			if (!FP_DO_GRAB_FOCUS_TRANSIENT(
941 				    S_FOCUS_POLICY(SCF(*style))))
942 			{
943 				FPS_GRAB_FOCUS_TRANSIENT(
944 					S_FOCUS_POLICY(SCF(*style)), 0);
945 				FPS_GRAB_FOCUS_TRANSIENT(
946 					S_FOCUS_POLICY(SCM(*style)), 1);
947 				FPS_GRAB_FOCUS_TRANSIENT(
948 					S_FOCUS_POLICY(SCC(*style)), 1);
949 			}
950 		}
951 		return 0;
952 	}
953 
954 	if (ev != NULL && fw != NULL)
955 	{
956 		/* client message: I do not think we can get such message */
957 	    	/* java sends this message */
958 		int cmd_arg = ev->xclient.data.l[0];
959 		if (
960 			!IS_EWMH_MODAL(fw) &&
961 			(cmd_arg == NET_WM_STATE_TOGGLE ||
962 			 cmd_arg == NET_WM_STATE_ADD))
963 		{
964 		    /* ON */
965 		}
966 		else if (
967 			IS_EWMH_MODAL(fw) &&
968 			(cmd_arg == NET_WM_STATE_TOGGLE ||
969 			 cmd_arg == NET_WM_STATE_REMOVE))
970 		{
971 		    /* OFF */
972 		}
973 	/* 			!MODAL			MODAL
974 	 * CMD
975 	 * STATE_ADD		  ON			do nothing
976 	 * STATE_TOGGLE		  ON			  OFF
977 	 * STATE_REMOVE		  do nothing		  OFF
978 	 */
979 	}
980 	return 0;
981 }
982 
ewmh_WMStateShaded(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)983 int ewmh_WMStateShaded(
984 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
985 {
986 
987 	if (ev == NULL && style == NULL)
988 	{
989 		unsigned long do_restore = any;
990 
991 		if (do_restore)
992 		{
993 			if (HAS_EWMH_INIT_SHADED_STATE(fw) ==
994 			    EWMH_STATE_HAS_HINT)
995 			{
996 				return True;
997 			}
998 			return False;
999 		}
1000 		return IS_SHADED(fw);
1001 	}
1002 
1003 	if (ev == NULL && style != NULL)
1004 	{
1005 		/* start shaded */
1006 		unsigned long has_hint = any;
1007 #if DEBUG_EWMH_INIT_STATE
1008 		if (has_hint)
1009 		{
1010 			fprintf(
1011 				stderr, "\t Shaded %i\n",
1012 				HAS_EWMH_INIT_SHADED_STATE(fw));
1013 		}
1014 #endif
1015 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
1016 		{
1017 			SET_HAS_EWMH_INIT_SHADED_STATE(
1018 				fw, EWMH_STATE_UNDEFINED_HINT);
1019 			return 0;
1020 		}
1021 		if (HAS_EWMH_INIT_SHADED_STATE(fw) !=
1022 		    EWMH_STATE_UNDEFINED_HINT)
1023 		{
1024 			return 0;
1025 		}
1026 		if (!has_hint)
1027 		{
1028 			SET_HAS_EWMH_INIT_SHADED_STATE(
1029 				fw, EWMH_STATE_NO_HINT);
1030 			return 0;
1031 		}
1032 
1033 		SET_SHADED(fw, 1);
1034 		SET_SHADED_DIR(fw, GET_TITLE_DIR(fw));
1035 		SET_HAS_EWMH_INIT_SHADED_STATE(fw, EWMH_STATE_HAS_HINT);
1036 		return 0;
1037 	}
1038 
1039 	if (ev != NULL)
1040 	{
1041 		/* client message */
1042 		int cmd_arg = ev->xclient.data.l[0];
1043 		if (
1044 			!IS_SHADED(fw) &&
1045 			(cmd_arg == NET_WM_STATE_TOGGLE ||
1046 			 cmd_arg == NET_WM_STATE_ADD))
1047 		{
1048 			execute_function_override_window(
1049 				NULL, NULL, "Windowshade on", 0, fw);
1050 		}
1051 		else if (
1052 			IS_SHADED(fw) &&
1053 			(cmd_arg == NET_WM_STATE_TOGGLE ||
1054 			 cmd_arg == NET_WM_STATE_REMOVE))
1055 		{
1056 			execute_function_override_window(
1057 				NULL, NULL, "Windowshade off", 0, fw);
1058 		}
1059 	}
1060 	return 0;
1061 }
1062 
ewmh_WMStateSkipPager(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1063 int ewmh_WMStateSkipPager(
1064 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1065 {
1066 	if (ev == NULL && style == NULL)
1067 	{
1068 		unsigned long do_restore = any;
1069 
1070 		if (do_restore)
1071 		{
1072 			if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) ==
1073 			    EWMH_STATE_HAS_HINT)
1074 			{
1075 				return True;
1076 			}
1077 			return False;
1078 		}
1079 		return DO_SKIP_WINDOW_LIST(fw);
1080 	}
1081 
1082 	if (ev == NULL && style != NULL)
1083 	{
1084 		unsigned long has_hint = any;
1085 #if DEBUG_EWMH_INIT_STATE
1086 		/*if (has_hint)*/
1087 		fprintf(
1088 			stderr, "\t Skip_Pager %lu, %i, %i\n", has_hint,
1089 			HAS_EWMH_INIT_SKIP_PAGER_STATE(fw),
1090 			DO_EWMH_IGNORE_STATE_HINTS(style));
1091 #endif
1092 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
1093 		{
1094 			SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(
1095 				fw, EWMH_STATE_UNDEFINED_HINT);
1096 			return 0;
1097 		}
1098 		if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) !=
1099 		    EWMH_STATE_UNDEFINED_HINT)
1100 		{
1101 			return 0;
1102 		}
1103 		if (!has_hint)
1104 		{
1105 			SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(
1106 				fw, EWMH_STATE_NO_HINT);
1107 			return 0;
1108 		}
1109 
1110 		S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1);
1111 		S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1);
1112 		S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1);
1113 		SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(fw, EWMH_STATE_HAS_HINT);
1114 		return 0;
1115 	}
1116 
1117 	if (ev != NULL)
1118 	{
1119 		/* I do not think we can get such client message */
1120 		int bool_arg = ev->xclient.data.l[0];
1121 
1122 		if ((bool_arg == NET_WM_STATE_TOGGLE &&
1123 		     !DO_SKIP_WINDOW_LIST(fw)) ||
1124 		    bool_arg == NET_WM_STATE_ADD)
1125 		{
1126 		}
1127 		else
1128 		{
1129 		}
1130 	}
1131 	return 0;
1132 }
1133 
ewmh_WMStateSkipTaskBar(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1134 int ewmh_WMStateSkipTaskBar(
1135 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1136 {
1137 	if (ev == NULL && style == NULL)
1138 	{
1139 		unsigned long do_restore = any;
1140 
1141 		if (do_restore)
1142 		{
1143 			if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) ==
1144 			    EWMH_STATE_HAS_HINT)
1145 			{
1146 				return True;
1147 			}
1148 			return False;
1149 		}
1150 		return DO_SKIP_WINDOW_LIST(fw);
1151 	}
1152 
1153 	if (ev == NULL && style != NULL)
1154 	{
1155 		unsigned long has_hint = any;
1156 #if DEBUG_EWMH_INIT_STATE
1157 		/*if (has_hint)*/
1158 		fprintf(stderr,"\t Skip_Taskbar %lu, %i, %i\n",
1159 			has_hint,
1160 			HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw),
1161 			DO_EWMH_IGNORE_STATE_HINTS(style));
1162 #endif
1163 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
1164 		{
1165 			SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
1166 				fw, EWMH_STATE_UNDEFINED_HINT);
1167 			return 0;
1168 		}
1169 		if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) !=
1170 		    EWMH_STATE_UNDEFINED_HINT)
1171 		{
1172 			return 0;
1173 		}
1174 		if (!has_hint)
1175 		{
1176 			SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
1177 				fw, EWMH_STATE_NO_HINT);
1178 			return 0;
1179 		}
1180 
1181 		S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1);
1182 		S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1);
1183 		S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1);
1184 		SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
1185 			fw, EWMH_STATE_HAS_HINT);
1186 		return 0;
1187 	}
1188 
1189 	if (ev != NULL)
1190 	{
1191 		/* I do not think we can get such client message */
1192 		int bool_arg = ev->xclient.data.l[0];
1193 
1194 		if ((bool_arg == NET_WM_STATE_TOGGLE &&
1195 		     !DO_SKIP_WINDOW_LIST(fw)) ||
1196 		    bool_arg == NET_WM_STATE_ADD)
1197 		{
1198 		}
1199 		else
1200 		{
1201 		}
1202 	}
1203 	return 0;
1204 }
1205 
ewmh_WMStateStaysOnTop(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1206 int ewmh_WMStateStaysOnTop(
1207 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1208 {
1209 	if (ev == NULL && style == NULL)
1210 	{
1211 		unsigned long do_restore = any;
1212 
1213 		if (do_restore)
1214 		{
1215 			if (fw->ewmh_hint_layer == Scr.TopLayer)
1216 			{
1217 				return True;
1218 			}
1219 			return False;
1220 		}
1221 		if (fw->layer >= Scr.TopLayer)
1222 		{
1223 			return True;
1224 		}
1225 		return False;
1226 	}
1227 
1228 	if (ev == NULL && style != NULL)
1229 	{
1230 		unsigned long has_hint = any;
1231 #if DEBUG_EWMH_INIT_STATE
1232 		if (has_hint)
1233 		{
1234 			fprintf(stderr,"\tStaysOnTop\n");
1235 		}
1236 #endif
1237 		if (!DO_EWMH_USE_STACKING_HINTS(style))
1238 		{
1239 			return 0;
1240 		}
1241 		if (!has_hint && fw->ewmh_hint_layer == 0)
1242 		{
1243 			fw->ewmh_hint_layer = -1;
1244 			return 0;
1245 		}
1246 		if (fw->ewmh_hint_layer == -1)
1247 		{
1248 			return 0;
1249 		}
1250 
1251 		fw->ewmh_hint_layer = Scr.TopLayer;
1252 		SSET_LAYER(*style, Scr.TopLayer);
1253 		style->flags.use_layer = 1;
1254 		style->flag_mask.use_layer = 1;
1255 		style->change_mask.use_layer = 1;
1256 		return 0;
1257 	}
1258 
1259 	if (ev != NULL)
1260 	{
1261 		/* client message */
1262 		int cmd_arg = ev->xclient.data.l[0];
1263 
1264 		if (!DO_EWMH_USE_STACKING_HINTS(fw))
1265 		{
1266 		    	/* if we don't pay attention to the hints,
1267 			 * I don't think we should honor this request also
1268 			 */
1269 			return 0;
1270 		}
1271 		if (fw->layer < Scr.TopLayer &&
1272 		    (cmd_arg == NET_WM_STATE_TOGGLE ||
1273 		     cmd_arg == NET_WM_STATE_ADD))
1274 		{
1275 			new_layer(fw, Scr.TopLayer);
1276 		}
1277 		else if (
1278 			fw->layer == Scr.TopLayer &&
1279 			(cmd_arg == NET_WM_STATE_TOGGLE ||
1280 			 cmd_arg == NET_WM_STATE_REMOVE))
1281 		{
1282 			new_layer(fw, Scr.DefaultLayer);
1283 		}
1284 	/* 			layer < TopLayer	layer == TopLayer
1285 	 * CMD
1286 	 * STATE_ADD		new_layer(TOP)		   do nothing
1287 	 * STATE_TOGGLE		new_layer(TOP)		new_layer(DEFAULT)
1288 	 * STATE_REMOVE		  do nothing		new_layer(DEFAULT)
1289 	 */
1290 	}
1291 	return 0;
1292 }
1293 
ewmh_WMStateStaysOnBottom(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1294 int ewmh_WMStateStaysOnBottom(
1295 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1296 {
1297 	if (ev == NULL && style == NULL)
1298 	{
1299 		unsigned long do_restore = any;
1300 
1301 		if (do_restore)
1302 		{
1303 			if (fw->ewmh_hint_layer == Scr.BottomLayer)
1304 			{
1305 				return True;
1306 			}
1307 			return False;
1308 		}
1309 		if (fw->layer <= Scr.BottomLayer)
1310 		{
1311 			return True;
1312 		}
1313 		return False;
1314 	}
1315 
1316 	if (ev == NULL && style != NULL)
1317 	{
1318 		unsigned long has_hint = any;
1319 #if DEBUG_EWMH_INIT_STATE
1320 		if (has_hint)
1321 			fprintf(stderr,"\tStaysOnBottom\n");
1322 #endif
1323 		if (!DO_EWMH_USE_STACKING_HINTS(style))
1324 		{
1325 			return 0;
1326 		}
1327 		if (!has_hint && fw->ewmh_hint_layer == 0)
1328 		{
1329 			fw->ewmh_hint_layer = -1;
1330 			return 0;
1331 		}
1332 		if (fw->ewmh_hint_layer == -1)
1333 		{
1334 			return 0;
1335 		}
1336 
1337 		fw->ewmh_hint_layer = Scr.BottomLayer;
1338 		SSET_LAYER(*style, Scr.BottomLayer);
1339 		style->flags.use_layer = 1;
1340 		style->flag_mask.use_layer = 1;
1341 		style->change_mask.use_layer = 1;
1342 		return 0;
1343 	}
1344 
1345 	if (ev != NULL)
1346 	{
1347 		/* client message */
1348 		int cmd_arg = ev->xclient.data.l[0];
1349 
1350 		if (!DO_EWMH_USE_STACKING_HINTS(fw))
1351 		{
1352 		    	/* if we don't pay attention to the hints,
1353 			 * I don't think we should honor this request also
1354 			 */
1355 			return 0;
1356 		}
1357 		if (
1358 			fw->layer > Scr.BottomLayer &&
1359 			(cmd_arg == NET_WM_STATE_TOGGLE ||
1360 			 cmd_arg == NET_WM_STATE_ADD))
1361 		{
1362 			new_layer(fw, Scr.BottomLayer);
1363 		}
1364 		else if (
1365 			fw->layer == Scr.BottomLayer &&
1366 			(cmd_arg == NET_WM_STATE_TOGGLE ||
1367 			 cmd_arg == NET_WM_STATE_REMOVE))
1368 		{
1369 			new_layer(fw, Scr.DefaultLayer);
1370 		}
1371 	/* 			layer > BottomLayer	layer == BottomLayer
1372 	 * CMD
1373 	 * STATE_ADD		new_layer(BOTTOM)	   do nothing
1374 	 * STATE_TOGGLE		new_layer(BOTTOM)	new_layer(DEFAULT)
1375 	 * STATE_REMOVE		  do nothing		new_layer(DEFAULT)
1376 	 */
1377 	}
1378 	return 0;
1379 }
1380 
ewmh_WMStateSticky(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1381 int ewmh_WMStateSticky(
1382 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1383 {
1384 
1385 	if (ev == NULL && style == NULL)
1386 	{
1387 		unsigned long do_restore = any;
1388 
1389 		if (do_restore)
1390 		{
1391 			if (HAS_EWMH_INIT_STICKY_STATE(fw) ==
1392 			    EWMH_STATE_HAS_HINT)
1393 			{
1394 				return True;
1395 			}
1396 			return False;
1397 		}
1398 		return (IS_STICKY_ACROSS_PAGES(fw) &&
1399 			IS_STICKY_ACROSS_DESKS(fw));
1400 	}
1401 
1402 	if (ev == NULL && style != NULL)
1403 	{
1404 		/* start sticky */
1405 		unsigned long has_hint = any;
1406 #if DEBUG_EWMH_INIT_STATE
1407 		if (has_hint)
1408 		{
1409 			fprintf(stderr,"\t Sticky\n");
1410 		}
1411 #endif
1412 		if (DO_EWMH_IGNORE_STATE_HINTS(style))
1413 		{
1414 			SET_HAS_EWMH_INIT_STICKY_STATE(
1415 				fw, EWMH_STATE_UNDEFINED_HINT);
1416 			return 0;
1417 		}
1418 		if (HAS_EWMH_INIT_STICKY_STATE(fw) !=
1419 		    EWMH_STATE_UNDEFINED_HINT)
1420 		{
1421 			return 0;
1422 		}
1423 		if (!has_hint)
1424 		{
1425 			SET_HAS_EWMH_INIT_STICKY_STATE(
1426 				fw, EWMH_STATE_NO_HINT);
1427 			return 0;
1428 		}
1429 		S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1);
1430 		S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1);
1431 		S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1);
1432 		S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1);
1433 		S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1);
1434 		S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1);
1435 		SET_HAS_EWMH_INIT_STICKY_STATE(fw, EWMH_STATE_HAS_HINT);
1436 		return 0;
1437 	}
1438 
1439 	if (ev != NULL)
1440 	{
1441 		/* client message */
1442 		int bool_arg = ev->xclient.data.l[0];
1443 		if ((bool_arg == NET_WM_STATE_TOGGLE &&
1444 		     (!IS_STICKY_ACROSS_PAGES(fw) ||
1445 		      !IS_STICKY_ACROSS_DESKS(fw))) ||
1446 		    bool_arg == NET_WM_STATE_ADD)
1447 		{
1448 			execute_function_override_window(
1449 				NULL, NULL, "Stick on", 0, fw);
1450 		}
1451 		else if ((IS_STICKY_ACROSS_PAGES(fw) ||
1452 			  IS_STICKY_ACROSS_DESKS(fw)) &&
1453 			 (bool_arg == NET_WM_STATE_TOGGLE ||
1454 			  bool_arg == NET_WM_STATE_REMOVE))
1455 		{
1456 			execute_function_override_window(
1457 				NULL, NULL, "Stick off", 1, fw);
1458 		}
1459 	}
1460 	return 0;
1461 }
1462 
1463 /*
1464  * Property Notify (_NET_WM_ICON is in ewmh_icon.c, _NET_WM_*NAME are in
1465  * ewmh_name)                        *
1466  */
ewmh_WMIconGeometry(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1467 int ewmh_WMIconGeometry(
1468 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1469 {
1470 	int size;
1471 	CARD32 *val;
1472 
1473 	/* FIXME: After a (un)slide of kicker the geometry are wrong (not
1474 	 * because we set the geometry just after the property notify).  This
1475 	 * does not happen with kwin */
1476 	val = ewmh_AtomGetByName(
1477 		FW_W(fw), "_NET_WM_ICON_GEOMETRY",
1478 		EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size);
1479 
1480 	if (val != NULL && size < 4 * sizeof(CARD32))
1481 	{
1482 		fvwm_msg(
1483 			WARN, "ewmh_WMIconGeometry",
1484 			"The application window (id %#lx)\n"
1485 			"  \"%s\" tried to set to an icon geometry via EWMH\n"
1486 			"  but provided only %d of the 4 values required.\n"
1487 			"    fvwm is ignoring this request.\n",
1488 			fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)",
1489 			(int)(size / sizeof(CARD32)));
1490 		fvwm_msg_report_app_and_workers();
1491 		free(val);
1492 		val = NULL;
1493 	}
1494 	if (val == NULL)
1495 	{
1496 		fw->ewmh_icon_geometry.x = 0;
1497 		fw->ewmh_icon_geometry.y = 0;
1498 		fw->ewmh_icon_geometry.width = 0;
1499 		fw->ewmh_icon_geometry.height = 0;
1500 
1501 		return 0;
1502 	}
1503 	fw->ewmh_icon_geometry.x = val[0];
1504 	fw->ewmh_icon_geometry.y = val[1];
1505 	fw->ewmh_icon_geometry.width = val[2];
1506 	fw->ewmh_icon_geometry.height = val[3];
1507 	free(val);
1508 
1509 	return 0;
1510 }
1511 
1512 /**** for animation ****/
EWMH_GetIconGeometry(FvwmWindow * fw,rectangle * icon_rect)1513 void EWMH_GetIconGeometry(FvwmWindow *fw, rectangle *icon_rect)
1514 {
1515 	if (!IS_ICON_SUPPRESSED(fw) ||
1516 	    (fw->ewmh_icon_geometry.x == 0 &&
1517 	     fw->ewmh_icon_geometry.y == 0 &&
1518 	     fw->ewmh_icon_geometry.width == 0 &&
1519 	     fw->ewmh_icon_geometry.height == 0))
1520 	{
1521 		return;
1522 	}
1523 	icon_rect->x = fw->ewmh_icon_geometry.x;
1524 	icon_rect->y = fw->ewmh_icon_geometry.y;
1525 	icon_rect->width = fw->ewmh_icon_geometry.width;
1526 	icon_rect->height = fw->ewmh_icon_geometry.height;
1527 
1528 	return;
1529 }
1530 
ewmh_WMStrut(FvwmWindow * fw,XEvent * ev,window_style * style,unsigned long any)1531 int ewmh_WMStrut(
1532 	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
1533 {
1534 	int size = 0;
1535 	CARD32 *val;
1536 
1537 	if (ev == NULL)
1538 	{
1539 		fw->dyn_strut.left = fw->strut.left = 0;
1540 		fw->dyn_strut.right = fw->strut.right = 0;
1541 		fw->dyn_strut.top = fw->strut.top = 0;
1542 		fw->dyn_strut.bottom = fw->strut.bottom = 0;
1543 	}
1544 
1545 	val = ewmh_AtomGetByName(
1546 		FW_W(fw), "_NET_WM_STRUT",
1547 		EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size);
1548 
1549 	if (val == NULL)
1550 	{
1551 		return 0;
1552 	}
1553 
1554 	if ((val[0] > 0 || val[1] > 0 || val[2] > 0 || val[3] > 0)
1555 	    &&
1556 	    (val[0] !=  fw->strut.left || val[1] != fw->strut.right ||
1557 	     val[2] != fw->strut.top   || val[3] !=  fw->strut.bottom))
1558 	{
1559 		fw->strut.left   = val[0];
1560 		fw->strut.right  = val[1];
1561 		fw->strut.top    = val[2];
1562 		fw->strut.bottom = val[3];
1563 		ewmh_ComputeAndSetWorkArea();
1564 	}
1565 	if (val[0] !=  fw->dyn_strut.left ||
1566 	    val[1] != fw->dyn_strut.right ||
1567 	    val[2] != fw->dyn_strut.top ||
1568 	    val[3] !=  fw->dyn_strut.bottom)
1569 	{
1570 		fw->dyn_strut.left   = val[0];
1571 		fw->dyn_strut.right  = val[1];
1572 		fw->dyn_strut.top    = val[2];
1573 		fw->dyn_strut.bottom = val[3];
1574 		ewmh_HandleDynamicWorkArea();
1575 	}
1576 	free(val);
1577 
1578 	return 0;
1579 }
1580 
EWMH_ProcessClientMessage(const exec_context_t * exc)1581 Bool EWMH_ProcessClientMessage(const exec_context_t *exc)
1582 {
1583 	ewmh_atom *ewmh_a = NULL;
1584 	FvwmWindow *fw = exc->w.fw;
1585 	XEvent *ev = exc->x.elast;
1586 
1587 	if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
1588 		     ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_ROOT)) !=
1589 	    NULL)
1590 	{
1591 		if (ewmh_a->action != None)
1592 		{
1593 			ewmh_a->action(fw, ev, NULL, 0);
1594 		}
1595 		return True;
1596 	}
1597 
1598 	if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
1599 		     ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_WIN))
1600 	    == NULL)
1601 	{
1602 		return False;
1603 	}
1604 
1605 	if (ev->xclient.window == None)
1606 	{
1607 		return False;
1608 	}
1609 
1610 	/* these one are special: we can get it on an unamaged window */
1611 	if (StrEquals(ewmh_a->name, "_NET_MOVERESIZE_WINDOW") ||
1612 	    StrEquals(ewmh_a->name, "_NET_RESTACK_WINDOW"))
1613 	{
1614 		ewmh_a->action(fw, ev, NULL, 0);
1615 		return True;
1616 	}
1617 
1618 	if (fw == NULL)
1619 	{
1620 		return False;
1621 	}
1622 
1623 
1624 	if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
1625 		     ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_WIN)) !=
1626 	    NULL)
1627 	{
1628 		if (ewmh_a->action != None)
1629 		{
1630 			ewmh_a->action(fw, ev, NULL, 0);
1631 		}
1632 		return True;
1633 	}
1634 
1635 	return False;
1636 }
1637 
EWMH_ProcessPropertyNotify(const exec_context_t * exc)1638 void EWMH_ProcessPropertyNotify(const exec_context_t *exc)
1639 {
1640 	ewmh_atom *ewmh_a = NULL;
1641 	FvwmWindow *fw = exc->w.fw;
1642 	XEvent *ev = exc->x.elast;
1643 
1644 	if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom(
1645 		     ev->xproperty.atom, EWMH_ATOM_LIST_PROPERTY_NOTIFY)) !=
1646 	    NULL)
1647 	{
1648 		if (ewmh_a->action != None)
1649 		{
1650 			flush_property_notify_stop_at_event_type(
1651 				ev->xproperty.atom, FW_W(fw), 0, 0);
1652 			if (XGetGeometry(
1653 				    dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY,
1654 				    (unsigned int*)&JunkWidth,
1655 				    (unsigned int*)&JunkHeight,
1656 				    (unsigned int*)&JunkBW,
1657 				    (unsigned int*)&JunkDepth) == 0)
1658 			{
1659 				/* Window does not exist anymore. */
1660 				return;
1661 			}
1662 			ewmh_a->action(fw, ev, NULL, 0);
1663 		}
1664 	}
1665 
1666 }
1667