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.
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.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "libs/fvwmlib.h"
26 #include "libs/FScreen.h"
27 #include "libs/Strings.h"
29 #include "execcontext.h"
30 #include "functions.h"
40 #include "ewmh_intern.h"
41 #include "decorations.h"
45 extern ewmh_atom ewmh_atom_wm_state
[];
47 #define DEBUG_EWMH_INIT_STATE 0
51 int ewmh_CurrentDesktop(EWMH_CMD_ARGS
)
53 if (ev
->xclient
.data
.l
[0] < 0 || ev
->xclient
.data
.l
[0] > 0x7fffffff)
56 WARN
, "ewmh_CurrentDesktop",
57 "The application window (id %#lx)\n"
58 " \"%s\" tried to switch to an invalid desktop (%ld)\n"
59 " using an EWMH client message.\n"
60 " fvwm is ignoring this request.\n",
61 fw
? FW_W(fw
) : 0, fw
? fw
->name
.name
: "(none)",
62 ev
->xclient
.data
.l
[0]);
63 fvwm_msg_report_app_and_workers();
67 goto_desk(ev
->xclient
.data
.l
[0]);
72 int ewmh_DesktopGeometry(EWMH_CMD_ARGS
)
75 long width
= ev
->xclient
.data
.l
[0];
76 long height
= ev
->xclient
.data
.l
[1];
78 width
= width
/ Scr
.MyDisplayWidth
;
79 height
= height
/ Scr
.MyDisplayHeight
;
81 if (width
<= 0 || height
<= 0)
84 WARN
, "ewmh_DesktopGeometry",
85 "The application window (id %#lx)\n"
86 " \"%s\" tried to set an invalid desktop geometry"
88 " using an EWMH client message.\n"
89 " fvwm is ignoring this request.\n",
90 fw
? FW_W(fw
) : 0, fw
? fw
->name
.name
: "(none)",
91 ev
->xclient
.data
.l
[0], ev
->xclient
.data
.l
[1]);
92 fvwm_msg_report_app_and_workers();
96 sprintf(action
, "DesktopSize %ld %ld", width
, height
);
97 execute_function_override_window(NULL
, NULL
, action
, 0, NULL
);
102 int ewmh_DesktopViewPort(EWMH_CMD_ARGS
)
105 ev
->xclient
.data
.l
[0] < 0 ||
106 ev
->xclient
.data
.l
[0] > 0x7fffffff ||
107 ev
->xclient
.data
.l
[1] < 0 ||
108 ev
->xclient
.data
.l
[1] > 0x7fffffff)
111 WARN
, "ewmh_DesktopViewPort",
112 "The application window (id %#lx)\n"
113 " \"%s\" tried to switch to an invalid page"
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();
123 MoveViewport(ev
->xclient
.data
.l
[0], ev
->xclient
.data
.l
[1], 1);
127 int ewmh_NumberOfDesktops(EWMH_CMD_ARGS
)
129 int d
= ev
->xclient
.data
.l
[0];
131 /* not a lot of sinification for fvwm */
132 if (d
> 0 && (d
<= ewmhc
.MaxDesktops
|| ewmhc
.MaxDesktops
== 0))
134 ewmhc
.NumberOfDesktops
= d
;
135 EWMH_SetNumberOfDesktops();
140 WARN
, "ewmh_NumberOfDesktops",
141 "The application window (id %#lx)\n"
142 " \"%s\" tried to set an invalid number of desktops"
144 " using an EWMH client message.\n"
145 " fvwm is ignoring this request.\n",
146 fw
? FW_W(fw
) : 0, fw
? fw
->name
.name
: "(none)",
147 ev
->xclient
.data
.l
[0]);
148 fvwm_msg_report_app_and_workers();
158 int ewmh_ActiveWindow(EWMH_CMD_ARGS
)
164 execute_function_override_window(
165 NULL
, NULL
, "EWMHActivateWindowFunc", 0, fw
);
170 int ewmh_CloseWindow(EWMH_CMD_ARGS
)
176 if (!is_function_allowed(F_CLOSE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
))
180 execute_function_override_window(NULL
, NULL
, "Close", 0, fw
);
185 int ewmh_MoveResizeWindow(EWMH_CMD_ARGS
)
187 XConfigureRequestEvent cre
;
197 win_gravity
= ev
->xclient
.data
.l
[0] & 0xff;
198 value_mask
= (ev
->xclient
.data
.l
[0] >> 8) & 0xf;
199 source
= (ev
->xclient
.data
.l
[0] >> 12) & 0xf;
202 /* unmanaged window */
210 ((value_mask
& CWWidth
) == 0 ||
211 ev
->xclient
.data
.l
[3] == fw
->g
.normal
.width
) &&
212 ((value_mask
& CWHeight
) == 0 ||
213 ev
->xclient
.data
.l
[4] == fw
->g
.normal
.height
))
221 do_reconfigure
= !!is_function_allowed(
222 func
, NULL
, fw
, RQORIG_PROGRAM
, False
);
224 if (do_reconfigure
== 1)
226 cre
.value_mask
= value_mask
;
227 cre
.x
= ev
->xclient
.data
.l
[1];
228 cre
.y
= ev
->xclient
.data
.l
[2];
229 cre
.width
= ev
->xclient
.data
.l
[3];
230 cre
.height
= ev
->xclient
.data
.l
[4];
231 cre
.window
= ev
->xclient
.window
;
232 events_handle_configure_request(cre
, fw
, True
, win_gravity
);
238 int ewmh_RestackWindow(EWMH_CMD_ARGS
)
240 XConfigureRequestEvent cre
;
249 /* unmanaged window */
254 do_restack
= !!DO_EWMH_USE_STACKING_HINTS(fw
);
258 cre
.value_mask
= CWSibling
| CWStackMode
;
259 cre
.above
= ev
->xclient
.data
.l
[1];
260 cre
.detail
= ev
->xclient
.data
.l
[2];
261 cre
.window
= ev
->xclient
.window
;
262 events_handle_configure_request(cre
, fw
, True
, ForgetGravity
);
268 int ewmh_WMDesktop(EWMH_CMD_ARGS
)
270 if (ev
!= NULL
&& style
== NULL
)
273 unsigned long d
= (unsigned long)ev
->xclient
.data
.l
[0];
275 /* the spec says that if d = 0xFFFFFFFF then we have to Stick
276 * the window however KDE use 0xFFFFFFFE :o) */
277 if (d
== (unsigned long)-2 || d
== (unsigned long)-1)
279 execute_function_override_window(
280 NULL
, NULL
, "Stick on", 0, fw
);
284 if (IS_STICKY_ACROSS_PAGES(fw
) ||
285 IS_STICKY_ACROSS_DESKS(fw
))
287 execute_function_override_window(
288 NULL
, NULL
, "Stick off", 0, fw
);
292 do_move_window_to_desk(fw
, (int)d
);
298 WARN
, "ewmh_WMDesktop",
299 "The application window (id %#lx)\n"
300 " \"%s\" tried to move to an invalid desk"
302 " using an EWMH client message.\n"
303 " fvwm is ignoring this request.\n",
305 fw
? fw
->name
.name
: "(none)",
306 ev
->xclient
.data
.l
[0]);
307 fvwm_msg_report_app_and_workers();
313 if (style
!= NULL
&& ev
== NULL
)
319 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
321 SET_HAS_EWMH_INIT_WM_DESKTOP(
322 fw
, EWMH_STATE_UNDEFINED_HINT
);
326 if (HAS_EWMH_INIT_WM_DESKTOP(fw
) != EWMH_STATE_UNDEFINED_HINT
)
330 val
= ewmh_AtomGetByName(
331 FW_W(fw
), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN
,
335 SET_HAS_EWMH_INIT_WM_DESKTOP(fw
, EWMH_STATE_NO_HINT
);
339 #if DEBUG_EWMH_INIT_STATE
341 stderr
, "ewmh WM_DESKTOP hint for window 0x%lx "
342 "(%i,%lu,%u)\n", FW_W(fw
),
343 HAS_EWMH_INIT_WM_DESKTOP(fw
),
344 fw
->ewmh_hint_desktop
, val
[0]);
346 if (val
[0] == (CARD32
)-2 || val
[0] == (CARD32
)-1)
348 S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style
), 1);
349 S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style
), 1);
350 S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style
), 1);
351 S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style
), 1);
352 S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style
), 1);
353 S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style
), 1);
355 else if (val
[0] < 256)
357 /* prevent crazy hints ?? */
358 style
->flags
.use_start_on_desk
= 1;
359 style
->flag_mask
.use_start_on_desk
= 1;
360 style
->change_mask
.use_start_on_desk
= 1;
361 SSET_START_DESK(*style
, val
[0]);
363 SET_HAS_EWMH_INIT_WM_DESKTOP(fw
, EWMH_STATE_HAS_HINT
);
364 fw
->ewmh_hint_desktop
= val
[0];
370 int ewmh_MoveResize(EWMH_CMD_ARGS
)
383 dir
= ev
->xclient
.data
.l
[2];
386 case _NET_WM_MOVERESIZE_SIZE_TOPLEFT
:
388 case _NET_WM_MOVERESIZE_SIZE_TOP
:
391 case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
:
394 case _NET_WM_MOVERESIZE_SIZE_RIGHT
:
395 x_warp
= 100; y_warp
= 50;
397 case _NET_WM_MOVERESIZE_SIZE_KEYBOARD
:
398 case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
:
399 x_warp
= 100; y_warp
= 100;
401 case _NET_WM_MOVERESIZE_SIZE_BOTTOM
:
402 x_warp
= 50; y_warp
= 100;
404 case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
:
407 case _NET_WM_MOVERESIZE_SIZE_LEFT
:
410 case _NET_WM_MOVERESIZE_MOVE_KEYBOARD
:
411 case _NET_WM_MOVERESIZE_MOVE
:
421 !is_function_allowed(
422 F_MOVE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
))
430 !is_function_allowed(
431 F_RESIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
))
439 sprintf(cmd
, "WarpToWindow %i %i",x_warp
,y_warp
);
440 execute_function_override_window(NULL
, NULL
, cmd
, 0, fw
);
445 execute_function_override_window(
446 NULL
, NULL
, "Move", 0, fw
);
450 execute_function_override_window(
451 NULL
, NULL
, "Resize", 0, fw
);
460 int ewmh_WMState(EWMH_CMD_ARGS
)
462 unsigned long maximize
= 0;
468 a1
= ewmh_GetEwmhAtomByAtom(
469 ev
->xclient
.data
.l
[1], EWMH_ATOM_LIST_WM_STATE
);
470 a2
= ewmh_GetEwmhAtomByAtom(
471 ev
->xclient
.data
.l
[2], EWMH_ATOM_LIST_WM_STATE
);
475 maximize
|= a1
->action(fw
, ev
, NULL
, 0);
479 maximize
|= a2
->action(fw
, ev
, NULL
, 0);
482 else if (style
!= NULL
)
488 ewmh_atom
*list
= ewmh_atom_wm_state
;
491 val
= ewmh_AtomGetByName(
492 FW_W(fw
), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN
,
500 #if DEBUG_EWMH_INIT_STATE
504 stderr
, "Window 0x%lx has an init"
505 " _NET_WM_STATE hint\n",FW_W(fw
));
508 nitems
= size
/ sizeof(CARD32
);
509 while(list
->name
!= NULL
)
512 for(i
= 0; i
< nitems
; i
++)
514 if (list
->atom
== val
[i
])
519 list
->action(fw
, NULL
, style
, has_hint
);
531 int max_vert
= (maximize
& EWMH_MAXIMIZE_VERT
)? 100:0;
532 int max_horiz
= (maximize
& EWMH_MAXIMIZE_HORIZ
)? 100:0;
535 if (maximize
& EWMH_MAXIMIZE_REMOVE
)
537 sprintf(cmd
,"Maximize off");
541 if (!is_function_allowed(
542 F_MAXIMIZE
, NULL
, fw
, RQORIG_PROGRAM_US
,
547 sprintf(cmd
,"Maximize on %i %i", max_horiz
, max_vert
);
549 execute_function_override_window(NULL
, NULL
, cmd
, 0, fw
);
554 int ewmh_WMStateFullScreen(EWMH_CMD_ARGS
)
556 if (ev
== NULL
&& style
== NULL
)
558 return (IS_EWMH_FULLSCREEN(fw
));
561 if (ev
== NULL
&& style
!= NULL
)
563 /* start full screen */
564 unsigned long has_hint
= any
;
566 #if DEBUG_EWMH_INIT_STATE
569 fprintf(stderr
,"\tFullscreen\n");
572 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
574 SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
575 fw
, EWMH_STATE_UNDEFINED_HINT
);
578 if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw
) !=
579 EWMH_STATE_UNDEFINED_HINT
)
585 SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
586 fw
, EWMH_STATE_NO_HINT
);
589 SET_EWMH_FULLSCREEN(fw
,True
);
590 SET_HAS_EWMH_INIT_FULLSCREEN_STATE(fw
, EWMH_STATE_HAS_HINT
);
597 int bool_arg
= ev
->xclient
.data
.l
[0];
600 is_full_screen
= IS_EWMH_FULLSCREEN(fw
);
601 if ((bool_arg
== NET_WM_STATE_TOGGLE
&& !is_full_screen
) ||
602 bool_arg
== NET_WM_STATE_ADD
)
608 if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw
) ==
611 /* the application started fullscreen */
612 SET_HAS_EWMH_INIT_FULLSCREEN_STATE(
613 fw
, EWMH_STATE_NO_HINT
);
615 /* unmaximize will restore is_ewmh_fullscreen,
616 * layer and apply_decor_change */
617 execute_function_override_window(
618 NULL
, NULL
, "Maximize off", 0, fw
);
620 if ((IS_EWMH_FULLSCREEN(fw
) &&
621 !DO_EWMH_USE_STACKING_HINTS(fw
)) ||
622 (!IS_EWMH_FULLSCREEN(fw
) &&
623 DO_EWMH_USE_STACKING_HINTS(fw
)))
625 /* On: if not raised by a layer cmd raise
626 * Off: if lowered by a layer cmd raise */
627 execute_function_override_window(
628 NULL
, NULL
, "Raise", 0, fw
);
635 int ewmh_WMStateHidden(EWMH_CMD_ARGS
)
637 if (ev
== NULL
&& style
== NULL
)
639 unsigned long do_restore
= any
;
643 if (HAS_EWMH_INIT_HIDDEN_STATE(fw
) ==
650 return IS_ICONIFIED(fw
);
653 if (ev
== NULL
&& style
!= NULL
)
655 /* start iconified */
656 unsigned long has_hint
= any
;
658 #if DEBUG_EWMH_INIT_STATE
660 fprintf(stderr
,"\tHidden\n");
662 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
664 SET_HAS_EWMH_INIT_HIDDEN_STATE(
665 fw
, EWMH_STATE_UNDEFINED_HINT
);
668 if (HAS_EWMH_INIT_HIDDEN_STATE(fw
) !=
669 EWMH_STATE_UNDEFINED_HINT
)
675 SET_HAS_EWMH_INIT_HIDDEN_STATE(fw
, EWMH_STATE_NO_HINT
);
678 style
->flags
.do_start_iconic
= 1;
679 style
->flag_mask
.do_start_iconic
= 1;
680 style
->change_mask
.do_start_iconic
= 1;
681 SET_HAS_EWMH_INIT_HIDDEN_STATE(fw
, EWMH_STATE_HAS_HINT
);
689 int bool_arg
= ev
->xclient
.data
.l
[0];
691 if ((bool_arg
== NET_WM_STATE_TOGGLE
&& !IS_ICONIFIED(fw
)) ||
692 bool_arg
== NET_WM_STATE_ADD
)
696 !is_function_allowed(
697 F_ICONIFY
, NULL
, fw
, RQORIG_PROGRAM_US
,
702 sprintf(cmd
, "Iconify on");
707 sprintf(cmd
, "Iconify off");
709 execute_function_override_window(NULL
, NULL
, cmd
, 0, fw
);
714 int ewmh_WMStateMaxHoriz(EWMH_CMD_ARGS
)
717 if (ev
== NULL
&& style
== NULL
)
720 return (IS_MAXIMIZED(fw
) && !IS_EWMH_FULLSCREEN(fw
));
722 /* DV: the notion of vertical/horizontal maximization does not
723 * make any sense in fvwm, so just claim we're never maximized
729 if (ev
== NULL
&& style
!= NULL
)
731 unsigned long has_hint
= any
;
732 #if DEBUG_EWMH_INIT_STATE
736 stderr
, "\t Maxhoriz %i\n",
737 HAS_EWMH_INIT_MAXHORIZ_STATE(fw
));
740 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
742 SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
743 fw
, EWMH_STATE_UNDEFINED_HINT
);
747 /* If the initial state is STATE_NO_HINT we still want to
748 * override it, since having just one of MAXIMIZED_HORIZ or
749 * MAXIMIZED_HORZ is enough to make the window maximized.
751 if (HAS_EWMH_INIT_MAXHORIZ_STATE(fw
) ==
758 SET_HAS_EWMH_INIT_MAXHORIZ_STATE(
759 fw
, EWMH_STATE_NO_HINT
);
762 SET_HAS_EWMH_INIT_MAXHORIZ_STATE(fw
, EWMH_STATE_HAS_HINT
);
769 int cmd_arg
= ev
->xclient
.data
.l
[0];
772 (cmd_arg
== NET_WM_STATE_TOGGLE
||
773 cmd_arg
== NET_WM_STATE_ADD
))
775 return EWMH_MAXIMIZE_HORIZ
;
779 (cmd_arg
== NET_WM_STATE_TOGGLE
||
780 cmd_arg
== NET_WM_STATE_REMOVE
))
782 return EWMH_MAXIMIZE_REMOVE
;
789 int ewmh_WMStateMaxVert(EWMH_CMD_ARGS
)
792 if (ev
== NULL
&& style
== NULL
)
795 return (IS_MAXIMIZED(fw
) && !IS_EWMH_FULLSCREEN(fw
));
797 /* DV: the notion of vertical/horizontal maximization does not
798 * make any sense in fvwm, so just claim we're never maximized
804 if (ev
== NULL
&& style
!= NULL
)
806 unsigned long has_hint
= any
;
807 #if DEBUG_EWMH_INIT_STATE
811 stderr
, "\t Maxvert %i\n",
812 HAS_EWMH_INIT_MAXVERT_STATE(fw
));
815 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
817 SET_HAS_EWMH_INIT_MAXVERT_STATE(
818 fw
, EWMH_STATE_UNDEFINED_HINT
);
821 if (HAS_EWMH_INIT_MAXVERT_STATE(fw
) !=
822 EWMH_STATE_UNDEFINED_HINT
)
828 SET_HAS_EWMH_INIT_MAXVERT_STATE(
829 fw
, EWMH_STATE_NO_HINT
);
832 SET_HAS_EWMH_INIT_MAXVERT_STATE(fw
, EWMH_STATE_HAS_HINT
);
839 int cmd_arg
= ev
->xclient
.data
.l
[0];
842 (cmd_arg
== NET_WM_STATE_TOGGLE
||
843 cmd_arg
== NET_WM_STATE_ADD
))
845 return EWMH_MAXIMIZE_VERT
;
849 (cmd_arg
== NET_WM_STATE_TOGGLE
||
850 cmd_arg
== NET_WM_STATE_REMOVE
))
852 return EWMH_MAXIMIZE_REMOVE
;
859 int ewmh_WMStateModal(EWMH_CMD_ARGS
)
861 if (ev
== NULL
&& style
== NULL
)
863 unsigned long do_restore
= any
;
867 if (HAS_EWMH_INIT_MODAL_STATE(fw
) ==
874 return IS_EWMH_MODAL(fw
);
877 if (ev
== NULL
&& style
!= NULL
)
879 unsigned long has_hint
= any
;
880 #if DEBUG_EWMH_INIT_STATE
884 stderr
, "\t Modal %i\n",
885 HAS_EWMH_INIT_MODAL_STATE(fw
));
888 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
890 SET_HAS_EWMH_INIT_MODAL_STATE(
891 fw
, EWMH_STATE_UNDEFINED_HINT
);
894 if (HAS_EWMH_INIT_MODAL_STATE(fw
) != EWMH_STATE_UNDEFINED_HINT
)
900 SET_HAS_EWMH_INIT_MODAL_STATE(fw
, EWMH_STATE_NO_HINT
);
904 /* the window map or had mapped with a modal hint */
905 if (IS_TRANSIENT(fw
))
907 SET_EWMH_MODAL(fw
, True
);
908 /* the window is a modal transient window so we grab
909 * the focus it will be good to raise it but ... */
910 FPS_GRAB_FOCUS_TRANSIENT(
911 S_FOCUS_POLICY(SCF(*style
)), 1);
912 FPS_GRAB_FOCUS_TRANSIENT(
913 S_FOCUS_POLICY(SCM(*style
)), 1);
914 FPS_GRAB_FOCUS_TRANSIENT(
915 S_FOCUS_POLICY(SCC(*style
)), 1);
916 SET_HAS_EWMH_INIT_MODAL_STATE(
917 fw
, EWMH_STATE_HAS_HINT
);
921 SET_EWMH_MODAL(fw
, False
);
922 if (!FP_DO_GRAB_FOCUS_TRANSIENT(
923 S_FOCUS_POLICY(SCF(*style
))))
925 FPS_GRAB_FOCUS_TRANSIENT(
926 S_FOCUS_POLICY(SCF(*style
)), 0);
927 FPS_GRAB_FOCUS_TRANSIENT(
928 S_FOCUS_POLICY(SCM(*style
)), 1);
929 FPS_GRAB_FOCUS_TRANSIENT(
930 S_FOCUS_POLICY(SCC(*style
)), 1);
936 if (ev
!= NULL
&& fw
!= NULL
)
938 /* client message: I do not think we can get such message */
939 /* java sends this message */
940 int cmd_arg
= ev
->xclient
.data
.l
[0];
942 !IS_EWMH_MODAL(fw
) &&
943 (cmd_arg
== NET_WM_STATE_TOGGLE
||
944 cmd_arg
== NET_WM_STATE_ADD
))
950 (cmd_arg
== NET_WM_STATE_TOGGLE
||
951 cmd_arg
== NET_WM_STATE_REMOVE
))
957 * STATE_ADD ON do nothing
958 * STATE_TOGGLE ON OFF
959 * STATE_REMOVE do nothing OFF
965 int ewmh_WMStateShaded(EWMH_CMD_ARGS
)
968 if (ev
== NULL
&& style
== NULL
)
970 unsigned long do_restore
= any
;
974 if (HAS_EWMH_INIT_SHADED_STATE(fw
) ==
981 return IS_SHADED(fw
);
984 if (ev
== NULL
&& style
!= NULL
)
987 unsigned long has_hint
= any
;
988 #if DEBUG_EWMH_INIT_STATE
992 stderr
, "\t Shaded %i\n",
993 HAS_EWMH_INIT_SHADED_STATE(fw
));
996 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
998 SET_HAS_EWMH_INIT_SHADED_STATE(
999 fw
, EWMH_STATE_UNDEFINED_HINT
);
1002 if (HAS_EWMH_INIT_SHADED_STATE(fw
) !=
1003 EWMH_STATE_UNDEFINED_HINT
)
1009 SET_HAS_EWMH_INIT_SHADED_STATE(
1010 fw
, EWMH_STATE_NO_HINT
);
1015 SET_SHADED_DIR(fw
, GET_TITLE_DIR(fw
));
1016 SET_HAS_EWMH_INIT_SHADED_STATE(fw
, EWMH_STATE_HAS_HINT
);
1022 /* client message */
1023 int cmd_arg
= ev
->xclient
.data
.l
[0];
1026 (cmd_arg
== NET_WM_STATE_TOGGLE
||
1027 cmd_arg
== NET_WM_STATE_ADD
))
1029 execute_function_override_window(
1030 NULL
, NULL
, "Windowshade on", 0, fw
);
1034 (cmd_arg
== NET_WM_STATE_TOGGLE
||
1035 cmd_arg
== NET_WM_STATE_REMOVE
))
1037 execute_function_override_window(
1038 NULL
, NULL
, "Windowshade off", 0, fw
);
1044 int ewmh_WMStateSkipPager(EWMH_CMD_ARGS
)
1046 if (ev
== NULL
&& style
== NULL
)
1048 unsigned long do_restore
= any
;
1052 if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw
) ==
1053 EWMH_STATE_HAS_HINT
)
1059 return DO_SKIP_WINDOW_LIST(fw
);
1062 if (ev
== NULL
&& style
!= NULL
)
1064 unsigned long has_hint
= any
;
1065 #if DEBUG_EWMH_INIT_STATE
1068 stderr
, "\t Skip_Pager %lu, %i, %i\n", has_hint
,
1069 HAS_EWMH_INIT_SKIP_PAGER_STATE(fw
),
1070 DO_EWMH_IGNORE_STATE_HINTS(style
));
1072 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
1074 SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(
1075 fw
, EWMH_STATE_UNDEFINED_HINT
);
1078 if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw
) !=
1079 EWMH_STATE_UNDEFINED_HINT
)
1085 SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(
1086 fw
, EWMH_STATE_NO_HINT
);
1090 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
1091 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
1092 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
1093 SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(fw
, EWMH_STATE_HAS_HINT
);
1099 /* I do not think we can get such client message */
1100 int bool_arg
= ev
->xclient
.data
.l
[0];
1102 if ((bool_arg
== NET_WM_STATE_TOGGLE
&&
1103 !DO_SKIP_WINDOW_LIST(fw
)) ||
1104 bool_arg
== NET_WM_STATE_ADD
)
1114 int ewmh_WMStateSkipTaskBar(EWMH_CMD_ARGS
)
1116 if (ev
== NULL
&& style
== NULL
)
1118 unsigned long do_restore
= any
;
1122 if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw
) ==
1123 EWMH_STATE_HAS_HINT
)
1129 return DO_SKIP_WINDOW_LIST(fw
);
1132 if (ev
== NULL
&& style
!= NULL
)
1134 unsigned long has_hint
= any
;
1135 #if DEBUG_EWMH_INIT_STATE
1137 fprintf(stderr
,"\t Skip_Taskbar %lu, %i, %i\n",
1139 HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw
),
1140 DO_EWMH_IGNORE_STATE_HINTS(style
));
1142 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
1144 SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
1145 fw
, EWMH_STATE_UNDEFINED_HINT
);
1148 if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw
) !=
1149 EWMH_STATE_UNDEFINED_HINT
)
1155 SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
1156 fw
, EWMH_STATE_NO_HINT
);
1160 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
1161 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
1162 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
1163 SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(
1164 fw
, EWMH_STATE_HAS_HINT
);
1170 /* I do not think we can get such client message */
1171 int bool_arg
= ev
->xclient
.data
.l
[0];
1173 if ((bool_arg
== NET_WM_STATE_TOGGLE
&&
1174 !DO_SKIP_WINDOW_LIST(fw
)) ||
1175 bool_arg
== NET_WM_STATE_ADD
)
1185 int ewmh_WMStateStaysOnTop(EWMH_CMD_ARGS
)
1187 if (ev
== NULL
&& style
== NULL
)
1189 unsigned long do_restore
= any
;
1193 if (fw
->ewmh_hint_layer
== Scr
.TopLayer
)
1199 if (fw
->layer
>= Scr
.TopLayer
)
1206 if (ev
== NULL
&& style
!= NULL
)
1208 unsigned long has_hint
= any
;
1209 #if DEBUG_EWMH_INIT_STATE
1212 fprintf(stderr
,"\tStaysOnTop\n");
1215 if (!DO_EWMH_USE_STACKING_HINTS(style
))
1219 if (!has_hint
&& fw
->ewmh_hint_layer
== 0)
1221 fw
->ewmh_hint_layer
= -1;
1224 if (fw
->ewmh_hint_layer
== -1)
1229 fw
->ewmh_hint_layer
= Scr
.TopLayer
;
1230 SSET_LAYER(*style
, Scr
.TopLayer
);
1231 style
->flags
.use_layer
= 1;
1232 style
->flag_mask
.use_layer
= 1;
1233 style
->change_mask
.use_layer
= 1;
1239 /* client message */
1240 int cmd_arg
= ev
->xclient
.data
.l
[0];
1242 if (!DO_EWMH_USE_STACKING_HINTS(fw
))
1244 /* if we don't pay attention to the hints,
1245 * I don't think we should honor this request also
1249 if (fw
->layer
< Scr
.TopLayer
&&
1250 (cmd_arg
== NET_WM_STATE_TOGGLE
||
1251 cmd_arg
== NET_WM_STATE_ADD
))
1253 new_layer(fw
, Scr
.TopLayer
);
1256 fw
->layer
== Scr
.TopLayer
&&
1257 (cmd_arg
== NET_WM_STATE_TOGGLE
||
1258 cmd_arg
== NET_WM_STATE_REMOVE
))
1260 new_layer(fw
, Scr
.DefaultLayer
);
1262 /* layer < TopLayer layer == TopLayer
1264 * STATE_ADD new_layer(TOP) do nothing
1265 * STATE_TOGGLE new_layer(TOP) new_layer(DEFAULT)
1266 * STATE_REMOVE do nothing new_layer(DEFAULT)
1272 int ewmh_WMStateStaysOnBottom(EWMH_CMD_ARGS
)
1274 if (ev
== NULL
&& style
== NULL
)
1276 unsigned long do_restore
= any
;
1280 if (fw
->ewmh_hint_layer
== Scr
.BottomLayer
)
1286 if (fw
->layer
<= Scr
.BottomLayer
)
1293 if (ev
== NULL
&& style
!= NULL
)
1295 unsigned long has_hint
= any
;
1296 #if DEBUG_EWMH_INIT_STATE
1298 fprintf(stderr
,"\tStaysOnBottom\n");
1300 if (!DO_EWMH_USE_STACKING_HINTS(style
))
1304 if (!has_hint
&& fw
->ewmh_hint_layer
== 0)
1306 fw
->ewmh_hint_layer
= -1;
1309 if (fw
->ewmh_hint_layer
== -1)
1314 fw
->ewmh_hint_layer
= Scr
.BottomLayer
;
1315 SSET_LAYER(*style
, Scr
.BottomLayer
);
1316 style
->flags
.use_layer
= 1;
1317 style
->flag_mask
.use_layer
= 1;
1318 style
->change_mask
.use_layer
= 1;
1324 /* client message */
1325 int cmd_arg
= ev
->xclient
.data
.l
[0];
1327 if (!DO_EWMH_USE_STACKING_HINTS(fw
))
1329 /* if we don't pay attention to the hints,
1330 * I don't think we should honor this request also
1335 fw
->layer
> Scr
.BottomLayer
&&
1336 (cmd_arg
== NET_WM_STATE_TOGGLE
||
1337 cmd_arg
== NET_WM_STATE_ADD
))
1339 new_layer(fw
, Scr
.BottomLayer
);
1342 fw
->layer
== Scr
.BottomLayer
&&
1343 (cmd_arg
== NET_WM_STATE_TOGGLE
||
1344 cmd_arg
== NET_WM_STATE_REMOVE
))
1346 new_layer(fw
, Scr
.DefaultLayer
);
1348 /* layer > BottomLayer layer == BottomLayer
1350 * STATE_ADD new_layer(BOTTOM) do nothing
1351 * STATE_TOGGLE new_layer(BOTTOM) new_layer(DEFAULT)
1352 * STATE_REMOVE do nothing new_layer(DEFAULT)
1358 int ewmh_WMStateSticky(EWMH_CMD_ARGS
)
1361 if (ev
== NULL
&& style
== NULL
)
1363 unsigned long do_restore
= any
;
1367 if (HAS_EWMH_INIT_STICKY_STATE(fw
) ==
1368 EWMH_STATE_HAS_HINT
)
1374 return (IS_STICKY_ACROSS_PAGES(fw
) &&
1375 IS_STICKY_ACROSS_DESKS(fw
));
1378 if (ev
== NULL
&& style
!= NULL
)
1381 unsigned long has_hint
= any
;
1382 #if DEBUG_EWMH_INIT_STATE
1385 fprintf(stderr
,"\t Sticky\n");
1388 if (DO_EWMH_IGNORE_STATE_HINTS(style
))
1390 SET_HAS_EWMH_INIT_STICKY_STATE(
1391 fw
, EWMH_STATE_UNDEFINED_HINT
);
1394 if (HAS_EWMH_INIT_STICKY_STATE(fw
) !=
1395 EWMH_STATE_UNDEFINED_HINT
)
1401 SET_HAS_EWMH_INIT_STICKY_STATE(
1402 fw
, EWMH_STATE_NO_HINT
);
1405 S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style
), 1);
1406 S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style
), 1);
1407 S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style
), 1);
1408 S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style
), 1);
1409 S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style
), 1);
1410 S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style
), 1);
1411 SET_HAS_EWMH_INIT_STICKY_STATE(fw
, EWMH_STATE_HAS_HINT
);
1417 /* client message */
1418 int bool_arg
= ev
->xclient
.data
.l
[0];
1419 if ((bool_arg
== NET_WM_STATE_TOGGLE
&&
1420 (!IS_STICKY_ACROSS_PAGES(fw
) ||
1421 !IS_STICKY_ACROSS_DESKS(fw
))) ||
1422 bool_arg
== NET_WM_STATE_ADD
)
1424 execute_function_override_window(
1425 NULL
, NULL
, "Stick on", 0, fw
);
1429 execute_function_override_window(
1430 NULL
, NULL
, "Stick on", 1, fw
);
1437 * Property Notify (_NET_WM_ICON is in ewmh_icon.c, _NET_WM_*NAME are in
1440 int ewmh_WMIconGeometry(EWMH_CMD_ARGS
)
1445 /* FIXME: After a (un)slide of kicker the geometry are wrong (not
1446 * because we set the geometry just after the property notify). This
1447 * does not happen with kwin */
1448 val
= ewmh_AtomGetByName(
1449 FW_W(fw
), "_NET_WM_ICON_GEOMETRY",
1450 EWMH_ATOM_LIST_PROPERTY_NOTIFY
, &size
);
1452 if (val
!= NULL
&& size
< 4 * sizeof(CARD32
))
1455 WARN
, "ewmh_WMIconGeometry",
1456 "The application window (id %#lx)\n"
1457 " \"%s\" tried to set to an icon geometry via EWMH\n"
1458 " but provided only %d of the 4 values required.\n"
1459 " fvwm is ignoring this request.\n",
1460 fw
? FW_W(fw
) : 0, fw
? fw
->name
.name
: "(none)",
1461 (int)(size
/ sizeof(CARD32
)));
1462 fvwm_msg_report_app_and_workers();
1468 fw
->ewmh_icon_geometry
.x
= 0;
1469 fw
->ewmh_icon_geometry
.y
= 0;
1470 fw
->ewmh_icon_geometry
.width
= 0;
1471 fw
->ewmh_icon_geometry
.height
= 0;
1475 fw
->ewmh_icon_geometry
.x
= val
[0];
1476 fw
->ewmh_icon_geometry
.y
= val
[1];
1477 fw
->ewmh_icon_geometry
.width
= val
[2];
1478 fw
->ewmh_icon_geometry
.height
= val
[3];
1484 /**** for animation ****/
1485 void EWMH_GetIconGeometry(FvwmWindow
*fw
, rectangle
*icon_rect
)
1487 if (!IS_ICON_SUPPRESSED(fw
) ||
1488 (fw
->ewmh_icon_geometry
.x
== 0 &&
1489 fw
->ewmh_icon_geometry
.y
== 0 &&
1490 fw
->ewmh_icon_geometry
.width
== 0 &&
1491 fw
->ewmh_icon_geometry
.height
== 0))
1495 icon_rect
->x
= fw
->ewmh_icon_geometry
.x
;
1496 icon_rect
->y
= fw
->ewmh_icon_geometry
.y
;
1497 icon_rect
->width
= fw
->ewmh_icon_geometry
.width
;
1498 icon_rect
->height
= fw
->ewmh_icon_geometry
.height
;
1503 int ewmh_WMStrut(EWMH_CMD_ARGS
)
1510 fw
->dyn_strut
.left
= fw
->strut
.left
= 0;
1511 fw
->dyn_strut
.right
= fw
->strut
.right
= 0;
1512 fw
->dyn_strut
.top
= fw
->strut
.top
= 0;
1513 fw
->dyn_strut
.bottom
= fw
->strut
.bottom
= 0;
1516 val
= ewmh_AtomGetByName(
1517 FW_W(fw
), "_NET_WM_STRUT",
1518 EWMH_ATOM_LIST_PROPERTY_NOTIFY
, &size
);
1525 if ((val
[0] > 0 || val
[1] > 0 || val
[2] > 0 || val
[3] > 0)
1527 (val
[0] != fw
->strut
.left
|| val
[1] != fw
->strut
.right
||
1528 val
[2] != fw
->strut
.top
|| val
[3] != fw
->strut
.bottom
))
1530 fw
->strut
.left
= val
[0];
1531 fw
->strut
.right
= val
[1];
1532 fw
->strut
.top
= val
[2];
1533 fw
->strut
.bottom
= val
[3];
1534 ewmh_ComputeAndSetWorkArea();
1536 if (val
[0] != fw
->dyn_strut
.left
||
1537 val
[1] != fw
->dyn_strut
.right
||
1538 val
[2] != fw
->dyn_strut
.top
||
1539 val
[3] != fw
->dyn_strut
.bottom
)
1541 fw
->dyn_strut
.left
= val
[0];
1542 fw
->dyn_strut
.right
= val
[1];
1543 fw
->dyn_strut
.top
= val
[2];
1544 fw
->dyn_strut
.bottom
= val
[3];
1545 ewmh_HandleDynamicWorkArea();
1552 Bool
EWMH_ProcessClientMessage(const exec_context_t
*exc
)
1554 ewmh_atom
*ewmh_a
= NULL
;
1555 FvwmWindow
*fw
= exc
->w
.fw
;
1556 XEvent
*ev
= exc
->x
.elast
;
1558 if ((ewmh_a
= (ewmh_atom
*)ewmh_GetEwmhAtomByAtom(
1559 ev
->xclient
.message_type
, EWMH_ATOM_LIST_CLIENT_ROOT
)) !=
1562 if (ewmh_a
->action
!= None
)
1564 ewmh_a
->action(fw
, ev
, NULL
, 0);
1569 if ((ewmh_a
= (ewmh_atom
*)ewmh_GetEwmhAtomByAtom(
1570 ev
->xclient
.message_type
, EWMH_ATOM_LIST_CLIENT_WIN
))
1576 if (ev
->xclient
.window
== None
)
1581 /* these one are special: we can get it on an unamaged window */
1582 if (StrEquals(ewmh_a
->name
, "_NET_MOVERESIZE_WINDOW") ||
1583 StrEquals(ewmh_a
->name
, "_NET_RESTACK_WINDOW"))
1585 ewmh_a
->action(fw
, ev
, NULL
, 0);
1595 if ((ewmh_a
= (ewmh_atom
*)ewmh_GetEwmhAtomByAtom(
1596 ev
->xclient
.message_type
, EWMH_ATOM_LIST_CLIENT_WIN
)) !=
1599 if (ewmh_a
->action
!= None
)
1601 ewmh_a
->action(fw
, ev
, NULL
, 0);
1609 void EWMH_ProcessPropertyNotify(const exec_context_t
*exc
)
1611 ewmh_atom
*ewmh_a
= NULL
;
1612 FvwmWindow
*fw
= exc
->w
.fw
;
1613 XEvent
*ev
= exc
->x
.elast
;
1615 if ((ewmh_a
= (ewmh_atom
*)ewmh_GetEwmhAtomByAtom(
1616 ev
->xproperty
.atom
, EWMH_ATOM_LIST_PROPERTY_NOTIFY
)) !=
1619 if (ewmh_a
->action
!= None
)
1621 flush_property_notify(ewmh_a
->atom
, FW_W(fw
));
1622 ewmh_a
->action(fw
, ev
, NULL
, 0);