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