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
19 * An implementation of the Extended Window Manager Hints specification
20 * http://freedesktop.org/Standards/wm-spec/
22 * Not Implemented (draft 1.3 - 2004-05-01):
24 * _NET_DESKTOP_LAYOUT (not useful for us)
25 * _NET_VIRTUAL_ROOTS (not useful at all for us)
26 * _NET_SHOWING_DESKTOP should be implemented
27 * _NET_REQUEST_FRAME_EXTENTS may be implemented
29 * Some _NET_WINDOW_TYPE are simply ignored:
30 * _NET_WM_WINDOW_TYPE_SPLASH
31 * _NET_WM_WINDOW_TYPE_UTILITIES
32 * _KDE_NET_WM_WINDOW_TYPE_OVERRIDE (deprecated)
34 * _NET_WM_STATE_DEMANDS_ATTENTION state
36 * _NET_WM_STRUT_PARTIAL should be implemented
38 * _NET_WM_USER_TIME can be used to decide if we give the focus to a newly
41 * The kill huge process protocol: _NET_WM_PID and _NET_WM_PING
43 * _NET_WM_HANDLED_ICONS (what to do? Nothing?)
45 * "Source indication in requests" is not used but can be useful with some
49 * - _NET_WM_WINDOW_TYPE_TOOLBAR is interpreted in a different way
50 * in GNOME (the spec) and in KDE 2/3.0 (~ simple dock?).
57 #include <X11/Xatom.h>
59 #include "libs/fvwmlib.h"
60 #include "libs/FScreen.h"
62 #include "execcontext.h"
63 #include "functions.h"
71 #include "decorations.h"
73 #include "ewmh_intern.h"
75 #include "window_flags.h"
77 typedef struct kst_item
80 struct kst_item
*next
;
84 Atom XA_UTF8_STRING
= None
;
85 KstItem
*ewmh_KstWinList
= NULL
;
92 4, /* NumberOfDesktops */
93 0, /* MaxDesktops limit the number of desktops*/
94 0, /* CurrentNumberOfDesktops */
95 False
, /* NeedsToCheckDesk */
96 {0, 0, 0, 0}, /* BaseStrut */
100 * The ewmh atoms lists
102 #define ENTRY(name, type, func) {name, None, type, func}
104 /* WARNING: lists must be in "name" alphabetic order! */
106 /* EWMH_ATOM_LIST_CLIENT_ROOT
107 * net atoms that can be send (Client Message) by a client and do not
108 * need a window to operate */
109 ewmh_atom ewmh_atom_client_root
[] =
111 ENTRY("_NET_CURRENT_DESKTOP", XA_CARDINAL
, ewmh_CurrentDesktop
),
112 ENTRY("_NET_DESKTOP_GEOMETRY", XA_CARDINAL
, ewmh_DesktopGeometry
),
113 ENTRY("_NET_DESKTOP_NAMES", None
, None
),
114 ENTRY("_NET_DESKTOP_VIEWPORT", XA_CARDINAL
, ewmh_DesktopViewPort
),
115 ENTRY("_NET_NUMBER_OF_DESKTOPS", XA_CARDINAL
, ewmh_NumberOfDesktops
),
119 /* EWMH_ATOM_LIST_CLIENT_WIN
120 * net atoms that can be send (Client Message) by a client and do need
121 * window to operate */
122 ewmh_atom ewmh_atom_client_win
[] =
124 ENTRY("_NET_ACTIVE_WINDOW", XA_WINDOW
, ewmh_ActiveWindow
),
125 ENTRY("_NET_CLOSE_WINDOW", XA_WINDOW
, ewmh_CloseWindow
),
126 ENTRY("_NET_MOVERESIZE_WINDOW", XA_WINDOW
, ewmh_MoveResizeWindow
),
127 ENTRY("_NET_RESTACK_WINDOW", XA_WINDOW
, ewmh_RestackWindow
),
128 ENTRY("_NET_WM_DESKTOP", XA_CARDINAL
, ewmh_WMDesktop
),
129 ENTRY("_NET_WM_MOVERESIZE", XA_WINDOW
, ewmh_MoveResize
),
130 ENTRY("_NET_WM_STATE", XA_ATOM
, ewmh_WMState
),
134 /* EWMH_ATOM_LIST_WM_STATE
135 * the different wm state, a client can ask to add, remove or toggle
136 * via a _NET_WM_STATE Client message. fvwm must maintain these states
138 ewmh_atom ewmh_atom_wm_state
[] =
141 "_NET_WM_STATE_ABOVE", XA_ATOM
,
142 ewmh_WMStateStaysOnTop
),
144 "_NET_WM_STATE_BELOW", XA_ATOM
,
145 ewmh_WMStateStaysOnBottom
),
147 "_NET_WM_STATE_FULLSCREEN", XA_ATOM
,
148 ewmh_WMStateFullScreen
),
149 ENTRY("_NET_WM_STATE_HIDDEN", XA_ATOM
, ewmh_WMStateHidden
),
151 "_NET_WM_STATE_MAXIMIZED_HORIZ", XA_ATOM
,
152 ewmh_WMStateMaxHoriz
),
154 "_NET_WM_STATE_MAXIMIZED_HORZ", XA_ATOM
,
155 ewmh_WMStateMaxHoriz
),
156 ENTRY("_NET_WM_STATE_MAXIMIZED_VERT", XA_ATOM
, ewmh_WMStateMaxVert
),
157 ENTRY("_NET_WM_STATE_MODAL", XA_ATOM
, ewmh_WMStateModal
),
158 ENTRY("_NET_WM_STATE_SHADED", XA_ATOM
, ewmh_WMStateShaded
),
160 "_NET_WM_STATE_SKIP_PAGER", XA_ATOM
,
161 ewmh_WMStateSkipPager
),
163 "_NET_WM_STATE_SKIP_TASKBAR", XA_ATOM
,
164 ewmh_WMStateSkipTaskBar
),
166 "_NET_WM_STATE_STAYS_ON_TOP", XA_ATOM
,
167 ewmh_WMStateStaysOnTop
),
168 ENTRY("_NET_WM_STATE_STICKY", XA_ATOM
, ewmh_WMStateSticky
),
171 #define EWMH_NUMBER_OF_STATE sizeof(ewmh_atom_wm_state)/sizeof(ewmh_atom) - 1
173 /* EWMH ATOM_LIST_ALLOWED_ACTIONS: atom for _NET_WM_ALLOWED_ACTIONS */
174 ewmh_atom ewmh_atom_allowed_actions
[] =
176 ENTRY("_NET_WM_ACTION_CHANGE_DESKTOP", XA_ATOM
, ewmh_AllowsYes
),
177 ENTRY("_NET_WM_ACTION_CLOSE", XA_ATOM
, ewmh_AllowsClose
),
178 ENTRY("_NET_WM_ACTION_FULLSCREEN", XA_ATOM
, ewmh_AllowsFullScreen
),
179 ENTRY("_NET_WM_ACTION_MAXIMIZE_HORZ", XA_ATOM
, ewmh_AllowsMaximize
),
180 ENTRY("_NET_WM_ACTION_MAXIMIZE_VERT", XA_ATOM
, ewmh_AllowsMaximize
),
181 ENTRY("_NET_WM_ACTION_MINIMIZE", XA_ATOM
, ewmh_AllowsMinimize
),
182 ENTRY("_NET_WM_ACTION_MOVE", XA_ATOM
, ewmh_AllowsMove
),
183 ENTRY("_NET_WM_ACTION_RESIZE", XA_ATOM
, ewmh_AllowsResize
),
184 ENTRY("_NET_WM_ACTION_SHADE", XA_ATOM
, ewmh_AllowsYes
),
185 ENTRY("_NET_WM_ACTION_STICK", XA_ATOM
, ewmh_AllowsYes
),
188 #define EWMH_NUMBER_OF_ALLOWED_ACTIONS \
189 sizeof(ewmh_atom_allowed_actions)/sizeof(ewmh_atom) - 1
191 /* EWMH ATOM_LIST_WINDOW_TYPE: the various window type */
192 ewmh_atom ewmh_atom_window_type
[] =
194 ENTRY("_NET_WM_WINDOW_TYPE_DESKTOP", XA_ATOM
, ewmh_HandleDesktop
),
195 ENTRY("_NET_WM_WINDOW_TYPE_DIALOG", XA_ATOM
, ewmh_HandleDialog
),
196 ENTRY("_NET_WM_WINDOW_TYPE_DOCK", XA_ATOM
, ewmh_HandleDock
),
197 ENTRY("_NET_WM_WINDOW_TYPE_MENU", XA_ATOM
, ewmh_HandleMenu
),
198 ENTRY("_NET_WM_WINDOW_TYPE_NORMAL", XA_ATOM
, ewmh_HandleNormal
),
199 ENTRY("_NET_WM_WINDOW_TYPE_TOOLBAR", XA_ATOM
, ewmh_HandleToolBar
),
203 /* EWMH ATOM_LIST_FIXED_PROPERTY
204 * property that have a window at startup and which should not change */
205 ewmh_atom ewmh_atom_fixed_property
[] =
207 ENTRY("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", XA_WINDOW
, None
),
208 ENTRY("_NET_WM_HANDLED_ICON", XA_ATOM
, None
),
209 ENTRY("_NET_WM_PID", XA_ATOM
, None
),
210 ENTRY("_NET_WM_WINDOW_TYPE", XA_ATOM
, None
),
214 /* EWMH ATOM_LIST_PROPERTY_NOTIFY
215 * properties of a window which is updated by the window via a PropertyNotify
217 ewmh_atom ewmh_atom_property_notify
[] =
219 ENTRY("_NET_WM_ICON", XA_CARDINAL
, ewmh_WMIcon
),
220 ENTRY("_NET_WM_ICON_GEOMETRY", XA_CARDINAL
, ewmh_WMIconGeometry
),
221 ENTRY("_NET_WM_ICON_NAME", None
, EWMH_WMIconName
),
222 ENTRY("_NET_WM_NAME", None
, EWMH_WMName
),
223 ENTRY("_NET_WM_STRUT", XA_CARDINAL
, ewmh_WMStrut
),
227 /* EWMH_ATOM_LIST_FVWM_ROOT: root atom that should be maintained by fvwm only
229 ewmh_atom ewmh_atom_fvwm_root
[] =
231 ENTRY("_KDE_NET_SYSTEM_TRAY_WINDOWS", XA_WINDOW
, None
),
232 ENTRY("_NET_CLIENT_LIST", XA_WINDOW
, None
),
233 ENTRY("_NET_CLIENT_LIST_STACKING", XA_WINDOW
, None
),
234 ENTRY("_NET_SUPPORTED", XA_ATOM
, None
),
235 ENTRY("_NET_SUPPORTING_WM_CHECK", XA_WINDOW
, None
),
236 ENTRY("_NET_VIRTUAL_ROOTS", XA_WINDOW
, None
),
237 ENTRY("_NET_WORKAREA", XA_CARDINAL
, None
),
241 /* EWMH_ATOM_LIST_FVWM_WIN: window atom that should be maintained by fvwm
243 ewmh_atom ewmh_atom_fvwm_win
[] =
245 ENTRY("_KDE_NET_WM_FRAME_STRUT", XA_CARDINAL
, None
),
246 ENTRY("_NET_FRAME_EXTENTS", XA_CARDINAL
, None
),
247 ENTRY("_NET_WM_ALLOWED_ACTIONS", XA_ATOM
, None
),
248 ENTRY("_NET_WM_ICON_VISIBLE_NAME", None
, None
),
249 ENTRY("_NET_WM_VISIBLE_NAME", None
, None
),
254 #define NUMBER_OF_ATOM_LISTS 9
255 #define L_ENTRY(x,y) {x,y,sizeof(y)/sizeof(ewmh_atom)}
256 ewmh_atom_list atom_list
[] =
258 L_ENTRY(EWMH_ATOM_LIST_CLIENT_ROOT
, ewmh_atom_client_root
),
259 L_ENTRY(EWMH_ATOM_LIST_CLIENT_WIN
, ewmh_atom_client_win
),
260 L_ENTRY(EWMH_ATOM_LIST_WM_STATE
, ewmh_atom_wm_state
),
261 L_ENTRY(EWMH_ATOM_LIST_ALLOWED_ACTIONS
, ewmh_atom_allowed_actions
),
262 L_ENTRY(EWMH_ATOM_LIST_WINDOW_TYPE
, ewmh_atom_window_type
),
263 L_ENTRY(EWMH_ATOM_LIST_FIXED_PROPERTY
, ewmh_atom_fixed_property
),
264 L_ENTRY(EWMH_ATOM_LIST_PROPERTY_NOTIFY
, ewmh_atom_property_notify
),
265 L_ENTRY(EWMH_ATOM_LIST_FVWM_ROOT
, ewmh_atom_fvwm_root
),
266 L_ENTRY(EWMH_ATOM_LIST_FVWM_WIN
, ewmh_atom_fvwm_win
),
267 L_ENTRY(EWMH_ATOM_LIST_END
, NULL
)
275 int compare(const void *a
, const void *b
)
277 return (strcmp((char *)a
, ((ewmh_atom
*)b
)->name
));
281 ewmh_atom
*get_ewmh_atom_by_name(
282 const char *atom_name
, ewmh_atom_list_name list_name
)
288 while(!done
&& atom_list
[i
].name
!= EWMH_ATOM_LIST_END
)
290 if (atom_list
[i
].name
== list_name
||
291 list_name
== EWMH_ATOM_LIST_ALL
)
293 a
= (ewmh_atom
*)bsearch(
294 atom_name
, atom_list
[i
].list
,
295 atom_list
[i
].size
- 1, sizeof(ewmh_atom
),
297 if (a
!= NULL
|| list_name
!= EWMH_ATOM_LIST_ALL
)
308 ewmh_atom
*ewmh_GetEwmhAtomByAtom(Atom atom
, ewmh_atom_list_name list_name
)
313 while(!done
&& atom_list
[i
].name
!= EWMH_ATOM_LIST_END
)
315 if (atom_list
[i
].name
== list_name
||
316 list_name
== EWMH_ATOM_LIST_ALL
)
318 ewmh_atom
*list
= atom_list
[i
].list
;
319 while(list
->name
!= NULL
)
321 if (atom
== list
->atom
)
327 if (atom_list
[i
].name
== list_name
)
338 static int atom_size(int format
)
346 return (format
>> 3);
350 void ewmh_ChangeProperty(
351 Window w
, const char *atom_name
, ewmh_atom_list_name list
,
352 unsigned char *data
, int length
)
357 if ((a
= get_ewmh_atom_by_name(atom_name
, list
)) != NULL
)
362 if (a
->atom_type
== XA_UTF8_STRING
)
367 asize
= atom_size(format
);
369 format
== 32 && asize
* 8 != format
&&
370 strcmp(atom_name
, "_NET_WM_ICON") == 0)
372 long *datacopy
= (long*)safemalloc(asize
* length
);
375 for (i
= 0; i
< length
; i
++)
377 datacopy
[i
] = ((CARD32
*)data
)[i
];
379 data
= (unsigned char*)datacopy
;
383 dpy
, w
, a
->atom
, a
->atom_type
, format
,
384 PropModeReplace
, data
, length
);
395 void ewmh_DeleteProperty(
396 Window w
, const char *atom_name
, ewmh_atom_list_name list
)
400 if ((a
= get_ewmh_atom_by_name(atom_name
, list
)) != NULL
)
402 XDeleteProperty(dpy
, w
, a
->atom
);
409 void *atom_get(Window win
, Atom to_get
, Atom type
, int *size
)
411 unsigned char *retval
;
413 unsigned long bytes_after
, num_ret
;
421 ok
= XGetWindowProperty(
422 dpy
, win
, to_get
, 0L, length
, False
, type
, &type_ret
,
423 &format_ret
, &num_ret
, &bytes_after
, &retval
);
425 if ((ok
== Success
) && (retval
) && (num_ret
> 0) && (format_ret
> 0))
429 asize
= atom_size(format_ret
);
430 data
= safemalloc(num_ret
* asize
);
431 if (format_ret
== 32 && asize
* 8 != format_ret
)
435 for (i
= 0; i
< num_ret
; i
++)
437 ((CARD32
*)data
)[i
] = ((long *)retval
)[i
];
444 memcpy(data
, retval
, num_ret
* asize
);
448 *size
= num_ret
* (format_ret
>> 3);
460 void *ewmh_AtomGetByName(
461 Window win
, const char *atom_name
, ewmh_atom_list_name list
,
467 if ((a
= get_ewmh_atom_by_name(atom_name
, list
)) != NULL
)
469 data
= atom_get(win
, a
->atom
, a
->atom_type
, size
);
476 * client_root: here the client is fvwm
484 for (fw
= Scr
.FvwmRoot
.next
; fw
!= NULL
; fw
= fw
->next
)
486 if (!IS_STICKY_ACROSS_DESKS(fw
))
488 d
= max(d
, fw
->Desk
);
495 void EWMH_SetCurrentDesktop(void)
499 val
= Scr
.CurrentDesk
;
501 if (val
< 0 || (val
>= ewmhc
.MaxDesktops
&& ewmhc
.MaxDesktops
!= 0))
506 if (val
>= ewmhc
.CurrentNumberOfDesktops
||
507 (ewmhc
.NumberOfDesktops
!= ewmhc
.CurrentNumberOfDesktops
&&
508 val
< ewmhc
.CurrentNumberOfDesktops
))
510 EWMH_SetNumberOfDesktops();
513 ewmh_ChangeProperty(Scr
.Root
,"_NET_CURRENT_DESKTOP",
514 EWMH_ATOM_LIST_CLIENT_ROOT
,
515 (unsigned char *)&val
, 1);
520 void EWMH_SetNumberOfDesktops(void)
524 if (ewmhc
.CurrentNumberOfDesktops
< ewmhc
.NumberOfDesktops
)
526 ewmhc
.CurrentNumberOfDesktops
= ewmhc
.NumberOfDesktops
;
529 if (ewmhc
.CurrentNumberOfDesktops
> ewmhc
.NumberOfDesktops
||
530 ewmhc
.NeedsToCheckDesk
)
532 int d
= check_desk();
534 ewmhc
.NeedsToCheckDesk
= False
;
535 if (d
>= ewmhc
.MaxDesktops
&& ewmhc
.MaxDesktops
!= 0)
537 ewmhc
.CurrentNumberOfDesktops
=
538 max(ewmhc
.NumberOfDesktops
, d
+1);
541 if (Scr
.CurrentDesk
>= ewmhc
.CurrentNumberOfDesktops
&&
542 (Scr
.CurrentDesk
< ewmhc
.MaxDesktops
|| ewmhc
.MaxDesktops
== 0))
544 ewmhc
.CurrentNumberOfDesktops
= Scr
.CurrentDesk
+ 1;
547 val
= (long)ewmhc
.CurrentNumberOfDesktops
;
548 ewmh_ChangeProperty(Scr
.Root
, "_NET_NUMBER_OF_DESKTOPS",
549 EWMH_ATOM_LIST_CLIENT_ROOT
,
550 (unsigned char *)&val
, 1);
556 void EWMH_SetDesktopViewPort(void)
558 long val
[256][2]; /* no more than 256 desktops */
561 while(i
< ewmhc
.NumberOfDesktops
&& i
< 256)
568 Scr
.Root
, "_NET_DESKTOP_VIEWPORT", EWMH_ATOM_LIST_CLIENT_ROOT
,
569 (unsigned char *)&val
, i
*2);
574 void EWMH_SetDesktopGeometry(void)
578 val
[0] = Scr
.VxMax
+ Scr
.MyDisplayWidth
;
579 val
[1] = Scr
.VyMax
+ Scr
.MyDisplayHeight
;
581 Scr
.Root
,"_NET_DESKTOP_GEOMETRY", EWMH_ATOM_LIST_CLIENT_ROOT
,
582 (unsigned char *)&val
, 2);
588 * client_win: here the client is fvwm
590 void EWMH_SetActiveWindow(Window w
)
593 Scr
.Root
, "_NET_ACTIVE_WINDOW", EWMH_ATOM_LIST_CLIENT_WIN
,
594 (unsigned char *)&w
, 1);
599 void EWMH_SetWMDesktop(FvwmWindow
*fw
)
601 long desk
= fw
->Desk
;
603 if (IS_STICKY_ACROSS_DESKS(fw
))
605 desk
= (unsigned long)-1;
607 else if (desk
>= ewmhc
.CurrentNumberOfDesktops
)
609 ewmhc
.NeedsToCheckDesk
= True
;
610 EWMH_SetNumberOfDesktops();
613 FW_W(fw
), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN
,
614 (unsigned char *)&desk
, 1);
620 * fvwm must maintain the _NET_WM_STATE
623 void EWMH_SetWMState(FvwmWindow
*fw
, Bool do_restore
)
625 Atom wm_state
[EWMH_NUMBER_OF_STATE
];
627 ewmh_atom
*list
= ewmh_atom_wm_state
;
629 while(list
->name
!= NULL
)
631 if (list
->action(fw
, NULL
, NULL
, do_restore
))
633 wm_state
[i
++] = list
->atom
;
641 FW_W(fw
), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN
,
642 (unsigned char *)wm_state
, i
);
647 FW_W(fw
), "_NET_WM_STATE",
648 EWMH_ATOM_LIST_CLIENT_WIN
);
658 /*** kde system tray ***/
659 /* #define DEBUG_KST */
661 void add_kst_item(Window w
)
666 prev
= &ewmh_KstWinList
;
673 *prev
= (KstItem
*)safemalloc(sizeof(KstItem
));
675 (*prev
)->next
= NULL
;
681 void delete_kst_item(Window w
)
686 prev
= &ewmh_KstWinList
;
687 while((t
!= NULL
)&&(t
->w
!= w
))
706 void set_kde_sys_tray(void)
721 wins
= (Window
*)safemalloc(sizeof(Window
) * nbr
);
726 fprintf(stderr
,"ADD_TO_KST: ");
731 fprintf(stderr
,"0x%lx ",t
->w
);
737 fprintf(stderr
,"\n");
740 ewmh_ChangeProperty(Scr
.Root
,"_KDE_NET_SYSTEM_TRAY_WINDOWS",
741 EWMH_ATOM_LIST_FVWM_ROOT
,
742 (unsigned char *)wins
,i
);
751 void ewmh_AddToKdeSysTray(FvwmWindow
*fw
)
757 val
= ewmh_AtomGetByName(
758 FW_W(fw
), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
759 EWMH_ATOM_LIST_FIXED_PROPERTY
, &size
);
768 while(t
!= NULL
&& t
->w
!= FW_W(fw
))
773 return; /* already in the list */
776 add_kst_item(FW_W(fw
));
783 /* not used at present time */
784 void ewmh_FreeKdeSysTray(void)
791 XSelectInput(dpy
, t
->w
, NoEventMask
);
792 delete_kst_item(t
->w
);
801 int EWMH_IsKdeSysTrayWindow(Window w
)
806 while(t
!= NULL
&& t
->w
!= w
)
815 fprintf(stderr
,"IsKdeSysTrayWindow: 0x%lx\n", w
);
821 void EWMH_ManageKdeSysTray(Window w
, int type
)
826 while(t
!= NULL
&& t
->w
!= w
)
838 fprintf(stderr
,"KST_UNMAP: 0x%lx\n", w
);
840 XSelectInput(dpy
, w
, StructureNotifyMask
);
845 fprintf(stderr
,"KST_DESTROY: 0x%lx\n", w
);
847 XSelectInput(dpy
, t
->w
, NoEventMask
);
854 fprintf(stderr
,"KST_Reparent: 0x%lx\n", w
);
856 XSelectInput(dpy
, w
, StructureNotifyMask
);
861 fprintf(stderr
,"KST_NO: 0x%lx\n", w
);
869 /**** Client lists ****/
871 void EWMH_SetClientList(void)
878 for (fw
= Scr
.FvwmRoot
.next
; fw
!= NULL
; fw
= fw
->next
)
884 wl
= (Window
*)safemalloc(sizeof(Window
) * nbr
);
885 for (fw
= Scr
.FvwmRoot
.next
; fw
!= NULL
; fw
= fw
->next
)
891 Scr
.Root
,"_NET_CLIENT_LIST", EWMH_ATOM_LIST_FVWM_ROOT
,
892 (unsigned char *)wl
, nbr
);
901 void EWMH_SetClientListStacking(void)
909 fw
= Scr
.FvwmRoot
.stack_next
; fw
!= &Scr
.FvwmRoot
;
917 wl
= (Window
*)safemalloc(sizeof(Window
) * nbr
);
919 fw
= Scr
.FvwmRoot
.stack_next
; fw
!= &Scr
.FvwmRoot
;
926 Scr
.Root
,"_NET_CLIENT_LIST_STACKING", EWMH_ATOM_LIST_FVWM_ROOT
,
927 (unsigned char *)wl
, nbr
);
936 /**** Working Area stuff ****/
937 /**** At present time we support only sticky windows with strut ****/
939 void ewmh_SetWorkArea(void)
941 long val
[256][4]; /* no more than 256 desktops */
944 while(i
< ewmhc
.NumberOfDesktops
&& i
< 256)
946 val
[i
][0] = Scr
.Desktops
->ewmh_working_area
.x
;
947 val
[i
][1] = Scr
.Desktops
->ewmh_working_area
.y
;
948 val
[i
][2] = Scr
.Desktops
->ewmh_working_area
.width
;
949 val
[i
][3] = Scr
.Desktops
->ewmh_working_area
.height
;
953 Scr
.Root
, "_NET_WORKAREA", EWMH_ATOM_LIST_FVWM_ROOT
,
954 (unsigned char *)&val
, i
*4);
959 void ewmh_ComputeAndSetWorkArea(void)
961 int left
= ewmhc
.BaseStrut
.left
;
962 int right
= ewmhc
.BaseStrut
.right
;
963 int top
= ewmhc
.BaseStrut
.top
;
964 int bottom
= ewmhc
.BaseStrut
.bottom
;
965 int x
,y
,width
,height
;
968 for (fw
= Scr
.FvwmRoot
.next
; fw
!= NULL
; fw
= fw
->next
)
971 DO_EWMH_IGNORE_STRUT_HINTS(fw
) ||
972 !IS_STICKY_ACROSS_PAGES(fw
))
976 left
= max(left
, fw
->strut
.left
);
977 right
= max(right
, fw
->strut
.right
);
978 top
= max(top
, fw
->strut
.top
);
979 bottom
= max(bottom
, fw
->strut
.bottom
);
984 width
= Scr
.MyDisplayWidth
- (left
+ right
);
985 height
= Scr
.MyDisplayHeight
- (top
+ bottom
);
988 Scr
.Desktops
->ewmh_working_area
.x
!= x
||
989 Scr
.Desktops
->ewmh_working_area
.y
!= y
||
990 Scr
.Desktops
->ewmh_working_area
.width
!= width
||
991 Scr
.Desktops
->ewmh_working_area
.height
!= height
)
993 Scr
.Desktops
->ewmh_working_area
.x
= x
;
994 Scr
.Desktops
->ewmh_working_area
.y
= y
;
995 Scr
.Desktops
->ewmh_working_area
.width
= width
;
996 Scr
.Desktops
->ewmh_working_area
.height
= height
;
1003 void ewmh_HandleDynamicWorkArea(void)
1005 int dyn_left
= ewmhc
.BaseStrut
.left
;
1006 int dyn_right
= ewmhc
.BaseStrut
.right
;
1007 int dyn_top
= ewmhc
.BaseStrut
.top
;
1008 int dyn_bottom
= ewmhc
.BaseStrut
.bottom
;
1009 int x
,y
,width
,height
;
1012 for (fw
= Scr
.FvwmRoot
.next
; fw
!= NULL
; fw
= fw
->next
)
1015 DO_EWMH_IGNORE_STRUT_HINTS(fw
) ||
1016 !IS_STICKY_ACROSS_PAGES(fw
))
1020 dyn_left
= max(dyn_left
, fw
->dyn_strut
.left
);
1021 dyn_right
= max(dyn_right
, fw
->dyn_strut
.right
);
1022 dyn_top
= max(dyn_top
, fw
->dyn_strut
.top
);
1023 dyn_bottom
= max(dyn_bottom
, fw
->dyn_strut
.bottom
);
1028 width
= Scr
.MyDisplayWidth
- (dyn_left
+ dyn_right
);
1029 height
= Scr
.MyDisplayHeight
- (dyn_top
+ dyn_bottom
);
1032 Scr
.Desktops
->ewmh_dyn_working_area
.x
!= x
||
1033 Scr
.Desktops
->ewmh_dyn_working_area
.y
!= y
||
1034 Scr
.Desktops
->ewmh_dyn_working_area
.width
!= width
||
1035 Scr
.Desktops
->ewmh_dyn_working_area
.height
!= height
)
1037 Scr
.Desktops
->ewmh_dyn_working_area
.x
= x
;
1038 Scr
.Desktops
->ewmh_dyn_working_area
.y
= y
;
1039 Scr
.Desktops
->ewmh_dyn_working_area
.width
= width
;
1040 Scr
.Desktops
->ewmh_dyn_working_area
.height
= height
;
1041 /* here we may update the maximized window ...etc */
1047 void EWMH_UpdateWorkArea(void)
1049 ewmh_ComputeAndSetWorkArea();
1050 ewmh_HandleDynamicWorkArea();
1055 void EWMH_GetWorkAreaIntersection(
1056 FvwmWindow
*fw
, int *x
, int *y
, int *w
, int *h
, int type
)
1059 int area_x
= Scr
.Desktops
->ewmh_working_area
.x
;
1060 int area_y
= Scr
.Desktops
->ewmh_working_area
.y
;
1061 int area_w
= Scr
.Desktops
->ewmh_working_area
.width
;
1062 int area_h
= Scr
.Desktops
->ewmh_working_area
.height
;
1063 Bool is_dynamic
= False
;
1067 case EWMH_IGNORE_WORKING_AREA
:
1069 case EWMH_USE_WORKING_AREA
:
1071 case EWMH_USE_DYNAMIC_WORKING_AREA
:
1079 area_x
= Scr
.Desktops
->ewmh_dyn_working_area
.x
;
1080 area_y
= Scr
.Desktops
->ewmh_dyn_working_area
.y
;
1081 area_w
= Scr
.Desktops
->ewmh_dyn_working_area
.width
;
1082 area_h
= Scr
.Desktops
->ewmh_dyn_working_area
.height
;
1084 nx
= max(*x
, area_x
);
1085 ny
= max(*y
, area_y
);
1086 nw
= min(*x
+ *w
, area_x
+ area_w
) - nx
;
1087 nh
= min(*y
+ *h
, area_y
+ area_h
) - ny
;
1097 float get_intersection(
1098 int x11
, int y11
, int x12
, int y12
, int x21
, int y21
, int x22
, int y22
,
1104 if (x11
< x22
&& x12
> x21
&& y11
< y22
&& y12
> y21
)
1110 ret
= (xr
- xl
) * (yb
- yt
);
1113 (x22
- x21
) * (y22
- y21
) != 0 && (x12
- x11
) * (y12
- y11
) != 0)
1115 ret
= 100 * max(ret
/ ((x22
- x21
) * (y22
- y21
)),
1116 ret
/ ((x12
- x11
) * (y12
- y11
)));
1123 float ewmh_GetStrutIntersection(
1124 int x11
, int y11
, int x12
, int y12
,
1125 int left
, int right
, int top
, int bottom
,
1129 int x21
, y21
, x22
, y22
;
1135 y22
= Scr
.MyDisplayHeight
;
1136 ret
+= get_intersection(
1137 x11
, y11
, x12
, y12
, x21
, y21
, x22
, y22
, use_percent
);
1139 x21
= Scr
.MyDisplayWidth
- right
;
1141 x22
= Scr
.MyDisplayWidth
;
1142 y22
= Scr
.MyDisplayHeight
;
1143 ret
+= get_intersection(
1144 x11
, y11
, x12
, y12
, x21
, y21
, x22
, y22
, use_percent
);
1148 x22
= Scr
.MyDisplayWidth
;
1150 ret
+= get_intersection(
1151 x11
, y11
, x12
, y12
, x21
, y21
, x22
, y22
, use_percent
);
1154 y21
= Scr
.MyDisplayHeight
- bottom
;
1155 x22
= Scr
.MyDisplayWidth
;
1156 y22
= Scr
.MyDisplayHeight
;
1157 ret
+= get_intersection(
1158 x11
, y11
, x12
, y12
, x21
, y21
, x22
, y22
, use_percent
);
1163 float EWMH_GetBaseStrutIntersection(
1164 int x11
, int y11
, int x12
, int y12
, Bool use_percent
)
1166 return ewmh_GetStrutIntersection(
1167 x11
, y11
, x12
, y12
, ewmhc
.BaseStrut
.left
,
1168 ewmhc
.BaseStrut
.right
, ewmhc
.BaseStrut
.top
,
1169 ewmhc
.BaseStrut
.bottom
, use_percent
);
1172 float EWMH_GetStrutIntersection(
1173 int x11
, int y11
, int x12
, int y12
, Bool use_percent
)
1175 int left
, right
, top
, bottom
;
1177 left
= Scr
.Desktops
->ewmh_working_area
.x
;
1178 right
= Scr
.MyDisplayWidth
-
1179 (Scr
.Desktops
->ewmh_working_area
.x
1180 + Scr
.Desktops
->ewmh_working_area
.width
);
1181 top
= Scr
.Desktops
->ewmh_working_area
.y
;
1182 bottom
= Scr
.MyDisplayHeight
-
1183 (Scr
.Desktops
->ewmh_working_area
.y
1184 + Scr
.Desktops
->ewmh_working_area
.height
);
1186 return ewmh_GetStrutIntersection(
1187 x11
, y11
, x12
, y12
, left
, right
, top
, bottom
, use_percent
);
1193 void EWMH_SetFrameStrut(FvwmWindow
*fw
)
1198 if (EWMH_IsKdeSysTrayWindow(FW_W(fw
)))
1200 /* Fixed position of tray window in kicker */
1203 get_window_borders(fw
, &b
);
1206 val
[0] = b
.top_left
.width
;
1208 val
[1] = b
.bottom_right
.width
;
1210 val
[2] = b
.top_left
.height
;
1212 val
[3] = b
.bottom_right
.height
;
1214 ewmh_ChangeProperty(
1215 FW_W(fw
), "_KDE_NET_WM_FRAME_STRUT", EWMH_ATOM_LIST_FVWM_WIN
,
1216 (unsigned char *)&val
, 4);
1217 ewmh_ChangeProperty(
1218 FW_W(fw
), "_NET_FRAME_EXTENTS", EWMH_ATOM_LIST_FVWM_WIN
,
1219 (unsigned char *)&val
, 4);
1227 Bool
ewmh_AllowsYes(EWMH_CMD_ARGS
)
1232 Bool
ewmh_AllowsClose(EWMH_CMD_ARGS
)
1234 return is_function_allowed(
1235 F_CLOSE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
);
1238 Bool
ewmh_AllowsFullScreen(EWMH_CMD_ARGS
)
1241 !is_function_allowed(
1242 F_MAXIMIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
) ||
1243 !is_function_allowed(
1244 F_MOVE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
) ||
1245 !is_function_allowed(
1246 F_RESIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, True
))
1254 Bool
ewmh_AllowsMinimize(EWMH_CMD_ARGS
)
1256 return is_function_allowed(F_ICONIFY
, NULL
, fw
, RQORIG_PROGRAM_US
, False
);
1259 Bool
ewmh_AllowsMaximize(EWMH_CMD_ARGS
)
1261 return is_function_allowed(F_MAXIMIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
);
1264 Bool
ewmh_AllowsMove(EWMH_CMD_ARGS
)
1266 return is_function_allowed(F_MOVE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
);
1269 Bool
ewmh_AllowsResize(EWMH_CMD_ARGS
)
1271 return is_function_allowed(F_RESIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
);
1274 void EWMH_SetAllowedActions(FvwmWindow
*fw
)
1276 Atom wm_actions
[EWMH_NUMBER_OF_ALLOWED_ACTIONS
];
1278 ewmh_atom
*list
= ewmh_atom_allowed_actions
;
1280 while(list
->name
!= NULL
)
1282 if (list
->action(fw
, NULL
, NULL
, 0))
1283 wm_actions
[i
++] = list
->atom
;
1289 ewmh_ChangeProperty(
1290 FW_W(fw
), "_NET_WM_ALLOWED_ACTIONS",
1291 EWMH_ATOM_LIST_FVWM_WIN
, (unsigned char *)wm_actions
,
1296 ewmh_DeleteProperty(
1297 FW_W(fw
), "_NET_WM_ALLOWED_ACTIONS",
1298 EWMH_ATOM_LIST_FVWM_WIN
);
1308 int ewmh_HandleDesktop(EWMH_CMD_ARGS
)
1310 if (Scr
.EwmhDesktop
!= NULL
&& FW_W(Scr
.EwmhDesktop
) != FW_W(fw
))
1313 WARN
,"ewmh_HandleDesktop",
1314 "A Desktop application (0x%lx) already runs! This"
1315 " can cause problems\n", FW_W(Scr
.EwmhDesktop
));
1319 fw
->ewmh_window_type
= EWMH_WINDOW_TYPE_DESKTOP_ID
;
1320 Scr
.EwmhDesktop
= fw
;
1322 SSET_LAYER(*style
, 0);
1323 style
->flags
.use_layer
= 1;
1324 style
->flag_mask
.use_layer
= 1;
1325 style
->change_mask
.use_layer
= 1;
1327 S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style
), 1);
1328 S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style
), 1);
1329 S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style
), 1);
1330 S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style
), 1);
1331 S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style
), 1);
1332 S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style
), 1);
1334 S_SET_IS_FIXED(SCF(*style
), 1);
1335 S_SET_IS_FIXED(SCM(*style
), 1);
1336 S_SET_IS_FIXED(SCC(*style
), 1);
1338 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
1339 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
1340 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
1342 S_SET_DO_CIRCULATE_SKIP(SCF(*style
), 1);
1343 S_SET_DO_CIRCULATE_SKIP(SCM(*style
), 1);
1344 S_SET_DO_CIRCULATE_SKIP(SCC(*style
), 1);
1346 S_SET_IS_UNICONIFIABLE(SCF(*style
), 1);
1347 S_SET_IS_UNICONIFIABLE(SCM(*style
), 1);
1348 S_SET_IS_UNICONIFIABLE(SCC(*style
), 1);
1350 S_SET_IS_UNMAXIMIZABLE(SCF(*style
), 1);
1351 S_SET_IS_UNMAXIMIZABLE(SCM(*style
), 1);
1352 S_SET_IS_UNMAXIMIZABLE(SCC(*style
), 1);
1355 SSET_BORDER_WIDTH(*style
, 0);
1356 style
->flags
.has_border_width
= 1;
1357 style
->flag_mask
.has_border_width
= 1;
1358 style
->change_mask
.has_border_width
= 1;
1360 SSET_HANDLE_WIDTH(*style
, 0);
1361 style
->flags
.has_handle_width
= 1;
1362 style
->flag_mask
.has_handle_width
= 1;
1363 style
->change_mask
.has_handle_width
= 1;
1366 style
->flags
.has_no_title
= 1;
1367 style
->flag_mask
.has_no_title
= 1;
1368 style
->change_mask
.has_no_title
= 1;
1370 /* ClickToFocus, I do not think we should use NeverFocus */
1371 FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*style
)), 1);
1372 FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCM(*style
)), 1);
1373 FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCC(*style
)), 1);
1374 FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCF(*style
)), 1);
1375 FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCM(*style
)), 1);
1376 FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCC(*style
)), 1);
1378 /* ClickToFocusPassesClick */
1379 FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCF(*style
)), 1);
1380 FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCM(*style
)), 1);
1381 FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCC(*style
)), 1);
1382 FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCF(*style
)), 1);
1383 FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCM(*style
)), 1);
1384 FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCC(*style
)), 1);
1387 FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCF(*style
)), 0);
1388 FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCM(*style
)), 1);
1389 FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCC(*style
)), 1);
1390 FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCF(*style
)), 0);
1391 FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCM(*style
)), 1);
1392 FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCC(*style
)), 1);
1393 FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCF(*style
)), 0);
1394 FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCM(*style
)), 1);
1395 FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCC(*style
)), 1);
1396 FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCF(*style
)), 0);
1397 FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCM(*style
)), 1);
1398 FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCC(*style
)), 1);
1403 int ewmh_HandleDialog(EWMH_CMD_ARGS
)
1405 fw
->ewmh_window_type
= EWMH_WINDOW_TYPE_DIALOG_ID
;
1410 int ewmh_HandleDock(EWMH_CMD_ARGS
)
1412 fw
->ewmh_window_type
= EWMH_WINDOW_TYPE_DOCK_ID
;
1414 S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style
), 1);
1415 S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style
), 1);
1416 S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style
), 1);
1417 S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style
), 1);
1418 S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style
), 1);
1419 S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style
), 1);
1421 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
1422 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
1423 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
1425 S_SET_DO_CIRCULATE_SKIP(SCF(*style
), 1);
1426 S_SET_DO_CIRCULATE_SKIP(SCM(*style
), 1);
1427 S_SET_DO_CIRCULATE_SKIP(SCC(*style
), 1);
1429 S_SET_IS_UNICONIFIABLE(SCF(*style
), 1);
1430 S_SET_IS_UNICONIFIABLE(SCM(*style
), 1);
1431 S_SET_IS_UNICONIFIABLE(SCC(*style
), 1);
1433 S_SET_IS_UNMAXIMIZABLE(SCF(*style
), 1);
1434 S_SET_IS_UNMAXIMIZABLE(SCM(*style
), 1);
1435 S_SET_IS_UNMAXIMIZABLE(SCC(*style
), 1);
1437 if (fw
->ewmh_hint_layer
== -1)
1439 fw
->ewmh_hint_layer
= Scr
.TopLayer
;
1440 if (DO_EWMH_USE_STACKING_HINTS(style
))
1442 SSET_LAYER(*style
, Scr
.TopLayer
);
1443 style
->flags
.use_layer
= 1;
1444 style
->flag_mask
.use_layer
= 1;
1445 style
->change_mask
.use_layer
= 1;
1447 else if (!style
->change_mask
.use_layer
)
1449 SSET_LAYER(*style
, Scr
.DefaultLayer
);
1450 style
->flags
.use_layer
= 1;
1451 style
->flag_mask
.use_layer
= 1;
1452 style
->change_mask
.use_layer
= 1;
1455 /* no title ? MWM hints should be used by the app but ... */
1460 int ewmh_HandleMenu(EWMH_CMD_ARGS
)
1462 fw
->ewmh_window_type
= EWMH_WINDOW_TYPE_MENU_ID
;
1466 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
1467 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
1468 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
1470 S_SET_DO_CIRCULATE_SKIP(SCF(*style
), 1);
1471 S_SET_DO_CIRCULATE_SKIP(SCM(*style
), 1);
1472 S_SET_DO_CIRCULATE_SKIP(SCC(*style
), 1);
1475 FPS_LENIENT(S_FOCUS_POLICY(SCF(*style
)), 0);
1476 FPS_LENIENT(S_FOCUS_POLICY(SCM(*style
)), 1);
1477 FPS_LENIENT(S_FOCUS_POLICY(SCC(*style
)), 1);
1479 FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCF(*style
)), 0);
1480 FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCF(*style
)), 0);
1481 FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*style
)), 0);
1482 FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCF(*style
)), 0);
1483 FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCF(*style
)), 0);
1484 FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCF(*style
)), 0);
1486 FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCM(*style
)), 1);
1487 FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCC(*style
)), 1);
1488 FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCM(*style
)), 1);
1489 FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCC(*style
)), 1);
1490 FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCM(*style
)), 1);
1491 FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCC(*style
)), 1);
1492 FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCM(*style
)), 1);
1493 FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCC(*style
)), 1);
1494 FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCM(*style
)), 1);
1495 FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCC(*style
)), 1);
1496 FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCM(*style
)), 1);
1497 FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCC(*style
)), 1);
1502 int ewmh_HandleNormal(EWMH_CMD_ARGS
)
1504 fw
->ewmh_window_type
= EWMH_WINDOW_TYPE_NORMAL_ID
;
1509 int ewmh_HandleToolBar(EWMH_CMD_ARGS
)
1511 fw
->ewmh_window_type
= EWMH_WINDOW_TYPE_TOOLBAR_ID
;
1513 /* this ok for KDE 2 (and 3??) but I do not think that a toolbar
1515 S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style
), 1);
1516 S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style
), 1);
1517 S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style
), 1);
1518 S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style
), 1);
1519 S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style
), 1);
1520 S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style
), 1);
1522 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
1523 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
1524 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
1526 S_SET_DO_CIRCULATE_SKIP(SCF(*style
), 1);
1527 S_SET_DO_CIRCULATE_SKIP(SCM(*style
), 1);
1528 S_SET_DO_CIRCULATE_SKIP(SCC(*style
), 1);
1530 /* no title ? MWM hints should be used by the app but ... */
1535 void ewmh_HandleWindowType(FvwmWindow
*fw
, window_style
*style
)
1538 unsigned int nitems
;
1539 ewmh_atom
*list
= ewmh_atom_window_type
;
1544 fw
->ewmh_window_type
= 0;
1545 if (DO_EWMH_IGNORE_WINDOW_TYPE(style
))
1549 val
= ewmh_AtomGetByName(
1550 FW_W(fw
), "_NET_WM_WINDOW_TYPE",
1551 EWMH_ATOM_LIST_FIXED_PROPERTY
, &size
);
1556 /* we support only one window type: the first that we support */
1557 nitems
= size
/ sizeof(CARD32
);
1558 while(i
< nitems
&& !found
)
1560 list
= ewmh_atom_window_type
;
1561 while(list
->name
!= NULL
&& !found
)
1563 if (list
->atom
== val
[i
])
1565 list
->action(fw
, NULL
, style
, 0);
1578 * a workaround for ksmserver exit windows
1581 int ksmserver_workarround(FvwmWindow
*fw
)
1584 if (fw
->name
.name
!= NULL
&& fw
->class.res_name
!= NULL
&&
1585 fw
->icon_name
.name
!= NULL
&& fw
->class.res_class
!= NULL
&&
1586 strcmp(fw
->name
.name
, "ksmserver") == 0 &&
1587 strcmp(fw
->class.res_class
, "ksmserver") == 0 &&
1588 strcmp(fw
->icon_name
.name
, "ksmserver") == 0 &&
1589 strcmp(fw
->class.res_name
, "unnamed") == 0)
1593 if (IS_TRANSIENT(fw
))
1595 layer
= Scr
.TopLayer
+ 2;
1599 layer
= Scr
.TopLayer
+ 1;
1601 new_layer(fw
, layer
);
1610 * Window Initialisation / Destroy
1613 void EWMH_GetStyle(FvwmWindow
*fw
, window_style
*style
)
1615 if (style
->change_mask
.use_layer
)
1617 fw
->ewmh_normal_layer
= SGET_LAYER(*style
);
1619 else if (fw
->ewmh_normal_layer
== 0)
1621 fw
->ewmh_normal_layer
= Scr
.DefaultLayer
;
1623 ewmh_WMState(fw
, NULL
, style
, 0);
1624 ewmh_WMDesktop(fw
, NULL
, style
, 0);
1625 /* the window type override the state hint */
1626 ewmh_HandleWindowType(fw
, style
);
1631 static void ewmh_check_wm_pid(FvwmWindow
*fw
)
1636 fw
->ewmh_window_type
= 0;
1637 val
= ewmh_AtomGetByName(
1638 FW_W(fw
), "_NET_WM_PID", EWMH_ATOM_LIST_FIXED_PROPERTY
, &size
);
1642 SET_HAS_EWMH_WM_PID(fw
, 1);
1643 if (CR_MOTION_METHOD(fw
) == CR_MOTION_METHOD_AUTO
)
1645 SET_CR_MOTION_METHOD(fw
, CR_MOTION_METHOD_USE_GRAV
);
1646 SET_CR_MOTION_METHOD_DETECTED(fw
, 1);
1653 /* see also EWMH_WMName and EWMH_WMIconName in add_window */
1654 void EWMH_WindowInit(FvwmWindow
*fw
)
1656 /*EWMH_DLOG("Init window 0x%lx",FW_W(fw));*/
1657 EWMH_SetWMState(fw
, False
);
1658 EWMH_SetWMDesktop(fw
);
1659 EWMH_SetAllowedActions(fw
);
1660 ewmh_WMStrut(fw
, NULL
, NULL
, 0);
1661 ewmh_WMIconGeometry(fw
, NULL
, NULL
, 0);
1662 ewmh_AddToKdeSysTray(fw
);
1663 EWMH_SetFrameStrut(fw
);
1664 if (IS_EWMH_DESKTOP(FW_W(fw
)))
1668 if (ksmserver_workarround(fw
))
1672 ewmh_WMIcon(fw
, NULL
, NULL
, 0);
1673 ewmh_check_wm_pid(fw
);
1674 /*EWMH_DLOG("window 0x%lx initialised",FW_W(fw));*/
1679 /* unmap or reparent: restore state */
1680 void EWMH_RestoreInitialStates(FvwmWindow
*fw
, int event_type
)
1682 EWMH_SetWMState(fw
, True
);
1683 if (HAS_EWMH_INIT_WM_DESKTOP(fw
) == EWMH_STATE_HAS_HINT
)
1685 ewmh_ChangeProperty(
1686 FW_W(fw
), "_NET_WM_DESKTOP",
1687 EWMH_ATOM_LIST_CLIENT_WIN
,
1688 (unsigned char *)&(fw
->ewmh_hint_desktop
), 1);
1692 ewmh_DeleteProperty(
1693 FW_W(fw
), "_NET_WM_DESKTOP",
1694 EWMH_ATOM_LIST_CLIENT_WIN
);
1696 if (HAS_EWMH_WM_ICON_HINT(fw
) == EWMH_FVWM_ICON
)
1698 EWMH_DeleteWmIcon(fw
, True
, True
);
1704 /* a window are going to be destroyed (in the add_window.c destroy_window
1706 void EWMH_DestroyWindow(FvwmWindow
*fw
)
1708 if (IS_EWMH_DESKTOP(FW_W(fw
)))
1710 Scr
.EwmhDesktop
= NULL
;
1712 if (fw
->Desk
>= ewmhc
.NumberOfDesktops
)
1714 ewmhc
.NeedsToCheckDesk
= True
;
1720 /* a window has been destroyed (unmap/reparent/destroy) */
1721 void EWMH_WindowDestroyed(void)
1723 EWMH_SetClientList();
1724 EWMH_SetClientListStacking();
1725 if (ewmhc
.NeedsToCheckDesk
)
1727 EWMH_SetNumberOfDesktops();
1729 ewmh_ComputeAndSetWorkArea();
1730 ewmh_HandleDynamicWorkArea();
1739 int set_all_atom_in_list(ewmh_atom
*list
)
1743 while(list
->name
!= NULL
)
1745 list
->atom
= XInternAtom(dpy
,list
->name
,False
);
1746 if (list
->atom_type
== None
)
1748 list
->atom_type
= XA_UTF8_STRING
;
1758 void set_net_supported(int l
)
1763 supported
= (Atom
*)safemalloc(l
*sizeof(Atom
));
1764 for(i
=0; i
< NUMBER_OF_ATOM_LISTS
; i
++)
1766 ewmh_atom
*list
= atom_list
[i
].list
;
1767 while(list
->name
!= NULL
)
1769 supported
[k
++] = list
->atom
;
1774 ewmh_ChangeProperty(
1775 Scr
.Root
, "_NET_SUPPORTED", EWMH_ATOM_LIST_FVWM_ROOT
,
1776 (unsigned char *)supported
, k
);
1785 ewmh_ChangeProperty(
1786 Scr
.Root
,"_KDE_NET_SYSTEM_TRAY_WINDOWS",
1787 EWMH_ATOM_LIST_FVWM_ROOT
, NULL
, 0);
1792 void EWMH_Init(void)
1795 int supported_count
= 0;
1798 unsigned char utf_name
[4];
1800 XClassHint classhints
;
1802 /* initialisation of all the atoms */
1803 XA_UTF8_STRING
= XInternAtom(dpy
,"UTF8_STRING",False
);
1804 for(i
=0; i
< NUMBER_OF_ATOM_LISTS
; i
++)
1806 supported_count
+= set_all_atom_in_list(atom_list
[i
].list
);
1809 /* the laws that we respect */
1810 set_net_supported(supported_count
);
1812 /* use the Scr.NoFocusWin as the WM_CHECK window */
1813 val
= Scr
.NoFocusWin
;
1814 ewmh_ChangeProperty(
1815 Scr
.Root
, "_NET_SUPPORTING_WM_CHECK",
1816 EWMH_ATOM_LIST_FVWM_ROOT
, (unsigned char *)&val
, 1);
1817 ewmh_ChangeProperty(
1818 Scr
.NoFocusWin
, "_NET_SUPPORTING_WM_CHECK",
1819 EWMH_ATOM_LIST_FVWM_ROOT
, (unsigned char *)&val
, 1);
1822 classhints
.res_name
= "fvwm";
1823 classhints
.res_class
= "FVWM";
1825 XSetClassHint(dpy
, Scr
.NoFocusWin
, &classhints
);
1826 if (XStringListToTextProperty(names
, 1, &text
))
1828 XSetWMName(dpy
, Scr
.NoFocusWin
, &text
);
1838 ewmh_ChangeProperty(
1839 Scr
.NoFocusWin
, "_NET_WM_NAME", EWMH_ATOM_LIST_PROPERTY_NOTIFY
,
1840 (unsigned char *)&utf_name
, 4);
1844 EWMH_SetDesktopNames();
1845 EWMH_SetCurrentDesktop();
1846 EWMH_SetNumberOfDesktops();
1847 EWMH_SetDesktopViewPort();
1848 EWMH_SetDesktopGeometry();
1849 EWMH_SetClientList();
1850 EWMH_SetClientListStacking();
1851 ewmh_ComputeAndSetWorkArea();
1859 void EWMH_ExitStuff(void)
1863 for (fw
= Scr
.FvwmRoot
.next
; fw
!= NULL
; fw
= fw
->next
)
1865 EWMH_RestoreInitialStates(fw
, 0);
1872 void EWMH_DLOG(char *msg
, ...)
1875 clock_t time_val
, time_taken
;
1876 static clock_t start_time
= 0;
1877 static clock_t prev_time
= 0;
1878 struct tms not_used_tms
;
1879 char buffer
[200]; /* oversized */
1884 t_ptr
= localtime(&mytime
);
1885 if (start_time
== 0)
1887 /* get clock ticks */
1888 prev_time
= start_time
= (unsigned int)times(¬_used_tms
);
1890 /* get clock ticks */
1891 time_val
= (unsigned int)times(¬_used_tms
);
1892 time_taken
= time_val
- prev_time
;
1893 prev_time
= time_val
;
1895 buffer
, "%.2d:%.2d:%.2d %6ld",
1896 t_ptr
->tm_hour
, t_ptr
->tm_min
, t_ptr
->tm_sec
, time_taken
);
1898 fprintf(stderr
, "EWMH DEBUG: ");
1900 vfprintf(stderr
, msg
, args
);
1902 fprintf(stderr
, "\n");
1903 fprintf(stderr
, " [time]: %s\n",buffer
);
1909 void EWMH_fullscreen(FvwmWindow
*fw
)
1911 fscreen_scr_arg fscr
;
1916 char cmd
[128] = "\0";
1918 /* maximize with ResizeMoveMaximize */
1920 !is_function_allowed(
1921 F_MAXIMIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
) ||
1922 !is_function_allowed(
1923 F_MOVE
, NULL
, fw
, RQORIG_PROGRAM_US
, False
) ||
1924 !is_function_allowed(
1925 F_RESIZE
, NULL
, fw
, RQORIG_PROGRAM_US
, True
))
1929 if (IS_ICONIFIED(fw
))
1931 execute_function_override_window(
1932 NULL
, NULL
, "Iconify off", 0, fw
);
1936 int sas
= fw
->shade_anim_steps
;
1938 fw
->shade_anim_steps
= 0;
1939 execute_function_override_window(
1940 NULL
, NULL
, "WindowShade off", 0, fw
);
1941 fw
->shade_anim_steps
= sas
;
1943 SET_EWMH_FULLSCREEN(fw
,True
);
1944 apply_decor_change(fw
);
1945 fscr
.xypos
.x
= fw
->g
.frame
.x
+ fw
->g
.frame
.width
/ 2;
1946 fscr
.xypos
.y
= fw
->g
.frame
.y
+ fw
->g
.frame
.height
/ 2;
1948 &fscr
, FSCREEN_XYPOS
, &scr_g
.x
, &scr_g
.y
,
1949 &scr_g
.width
, &scr_g
.height
);
1950 get_window_borders(fw
, &b
);
1951 get_page_offset_check_visible(&page_x
, &page_y
, fw
);
1953 cmd
, "ResizeMoveMaximize %dp %dp +%dp +%dp",
1954 scr_g
.width
, scr_g
.height
,
1955 scr_g
.x
- b
.top_left
.width
+ page_x
,
1956 scr_g
.y
- b
.top_left
.height
+ page_y
);
1957 if (DO_EWMH_USE_STACKING_HINTS(fw
))
1959 int sl
= fw
->ewmh_normal_layer
;
1961 new_layer(fw
, Scr
.TopLayer
);
1964 fw
->ewmh_normal_layer
= Scr
.DefaultLayer
;
1968 fw
->ewmh_normal_layer
= sl
;
1973 SET_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw
, 1);
1974 execute_function_override_window(NULL
, NULL
, cmd
, 0, fw
);
1975 SET_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw
, 0);