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