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