3 * GNOME WM Compliance adapted for fvwm
4 * Properties set on the root window (or desktop window)
6 * Even though the rest of fvwm is GPL consider this file
7 * Public Domain - use it however you see fit to make
8 * your WM GNOME compiant
11 * adapted for fvwm by Jay Painter <jpaint@gnu.org>
22 #include <X11/Xatom.h>
24 #include "libs/fvwmlib.h"
25 #include "libs/Parse.h"
29 #include "functions.h"
34 #include "move_resize.h"
39 #include "window_flags.h"
41 #include "decorations.h"
45 * Properties set on the root window (or desktop window)
48 /* WIN_AREA CARD32[2] contains the current desktop area X,Y */
49 #define XA_WIN_AREA "_WIN_AREA"
51 /* WIN_AREA CARD32[2] contains the current desktop area size WxH */
52 #define XA_WIN_AREA_COUNT "_WIN_AREA_COUNT"
54 /* array of atoms - atom being one of the following atoms */
55 #define XA_WIN_PROTOCOLS "_WIN_PROTOCOLS"
57 /* array of iocn in various sizes */
58 /* Type: array of CARD32 */
59 /* first item is icon count (n) */
60 /* second item is icon record length (in CARD32s) */
61 /* this is followed by (n) icon records as follows */
66 /* depth (of pixmap, mask is assumed to be of depth 1) (CARD32) */
67 /* drawable (screen root drawable of pixmap) (XID) */
68 /* ... additional fields can be added at the end of this list */
69 #define XA_WIN_ICONS "_WIN_ICONS"
71 /* WIN_WORKSPACE CARD32 contains the current desktop number */
72 #define XA_WIN_WORKSPACE "_WIN_WORKSPACE"
73 /* WIN_WORKSPACE_COUNT CARD32 contains the number of desktops */
74 #define XA_WIN_WORKSPACE_COUNT "_WIN_WORKSPACE_COUNT"
76 /* WIN_WORKSPACE_NAMES StringList (Text Property) of workspace names */
77 /* unused by enlightenment */
78 #define XA_WIN_WORKSPACE_NAMES "_WIN_WORKSPACE_NAMES"
80 /* *** Don't use this.. iffy at best. ** */
81 /* The available work area for client windows. The WM can set this and the WM */
82 /* and/or clients may change it at any time. If it is changed the WM and/or */
83 /* clients should honor the changes. If this property does not exist a client */
84 /* or WM can create it. */
91 #define XA_WIN_WORKAREA "_WIN_WORKAREA"
92 /* array of 4 CARD32's */
94 /* This is a list of window id's the WM is currently managing - primarily */
95 /* for being able to have external "tasklist" apps */
96 #define XA_WIN_CLIENT_LIST "_WIN_CLIENT_LIST"
97 /* array of N XID's */
100 * Properties on client windows
103 /* The layer the window exists in */
106 /* 2 = Normal (default app layer) */
108 /* 6 = Dock (always on top - for panel) */
109 /* The app sets this alone, not the WM. If this property changes the WM */
110 /* should comply and change the appearance/behavior of the Client window */
111 /* if this hint does not exist the WM Will create it on the Client window */
112 #define WIN_LAYER_DESKTOP 0
113 #define WIN_LAYER_BELOW 2
114 #define WIN_LAYER_NORMAL 4
115 #define WIN_LAYER_ONTOP 6
116 #define WIN_LAYER_DOCK 8
117 #define WIN_LAYER_ABOVE_DOCK 10
118 #define WIN_LAYER_MENU 12
119 #define XA_WIN_LAYER "_WIN_LAYER"
120 /* WIN_LAYER = CARD32 */
122 /* flags for the window's state. The WM will change these as needed when */
123 /* state changes. If the property contains info on client map, E will modify */
124 /* the windows state accordingly. if the Hint does not exist the WM will */
125 /* create it on the client window. 0 for the bit means off, 1 means on. */
126 /* unused (default) values are 0 */
128 /* removed Minimized - no explanation of what it really means - ambiguity */
129 /* should not be here if not clear */
130 #define WIN_STATE_STICKY (1<<0) /* everyone knows sticky */
131 #define WIN_STATE_RESERVED_BIT1 (1<<1) /* removed minimize here */
132 #define WIN_STATE_MAXIMIZED_VERT (1<<2) /* window in maximized V state */
133 #define WIN_STATE_MAXIMIZED_HORIZ (1<<3) /* window in maximized H state */
134 #define WIN_STATE_HIDDEN (1<<4) /* not on taskbar but window visible */
135 #define WIN_STATE_SHADED (1<<5) /* shaded (NeXT style) */
136 #define WIN_STATE_HID_WORKSPACE (1<<6) /* not on current desktop */
137 #define WIN_STATE_HID_TRANSIENT (1<<7) /* Owner of transient is hidden */
138 #define WIN_STATE_FIXED_POSITION (1<<8) /* window is fixed in position even */
139 #define WIN_STATE_ARRANGE_IGNORE (1<<9) /* ignore for auto arranging */
140 /* when scrolling about large */
141 /* virtual desktops ala fvwm */
142 #define XA_WIN_STATE "_WIN_STATE"
143 /* WIN_STATE = CARD32 */
145 /* Preferences for behavior for app */
146 /* ONLY the client sets this */
147 #define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
148 #define WIN_HINTS_SKIP_WINLIST (1<<1) /* not in win list */
149 #define WIN_HINTS_SKIP_TASKBAR (1<<2) /* not on taskbar */
150 #define WIN_HINTS_GROUP_TRANSIENT (1<<3) /* ??????? */
151 #define WIN_HINTS_FOCUS_ON_CLICK (1<<4) /* app only accepts focus when clicked
153 #define XA_WIN_HINTS "_WIN_HINTS"
154 /* WIN_HINTS = CARD32 */
156 /* Application state - also "color reactiveness" - the app can keep changing */
157 /* this property when it changes its state and the WM or monitoring program */
158 /* will pick this up and dpylay somehting accordingly. ONLY the client sets */
160 #define WIN_APP_STATE_NONE 0
161 #define WIN_APP_STATE_ACTIVE1 1
162 #define WIN_APP_STATE_ACTIVE2 2
163 #define WIN_APP_STATE_ERROR1 3
164 #define WIN_APP_STATE_ERROR2 4
165 #define WIN_APP_STATE_FATAL_ERROR1 5
166 #define WIN_APP_STATE_FATAL_ERROR2 6
167 #define WIN_APP_STATE_IDLE1 7
168 #define WIN_APP_STATE_IDLE2 8
169 #define WIN_APP_STATE_WAITING1 9
170 #define WIN_APP_STATE_WAITING2 10
171 #define WIN_APP_STATE_WORKING1 11
172 #define WIN_APP_STATE_WORKING2 12
173 #define WIN_APP_STATE_NEED_USER_INPUT1 13
174 #define WIN_APP_STATE_NEED_USER_INPUT2 14
175 #define WIN_APP_STATE_STRUGGLING1 15
176 #define WIN_APP_STATE_STRUGGLING2 16
177 #define WIN_APP_STATE_DISK_TRAFFIC1 17
178 #define WIN_APP_STATE_DISK_TRAFFIC2 18
179 #define WIN_APP_STATE_NETWORK_TRAFFIC1 19
180 #define WIN_APP_STATE_NETWORK_TRAFFIC2 20
181 #define WIN_APP_STATE_OVERLOADED1 21
182 #define WIN_APP_STATE_OVERLOADED2 22
183 #define WIN_APP_STATE_PERCENT000_1 23
184 #define WIN_APP_STATE_PERCENT000_2 24
185 #define WIN_APP_STATE_PERCENT010_1 25
186 #define WIN_APP_STATE_PERCENT010_2 26
187 #define WIN_APP_STATE_PERCENT020_1 27
188 #define WIN_APP_STATE_PERCENT020_2 28
189 #define WIN_APP_STATE_PERCENT030_1 29
190 #define WIN_APP_STATE_PERCENT030_2 30
191 #define WIN_APP_STATE_PERCENT040_1 31
192 #define WIN_APP_STATE_PERCENT040_2 32
193 #define WIN_APP_STATE_PERCENT050_1 33
194 #define WIN_APP_STATE_PERCENT050_2 34
195 #define WIN_APP_STATE_PERCENT060_1 35
196 #define WIN_APP_STATE_PERCENT060_2 36
197 #define WIN_APP_STATE_PERCENT070_1 37
198 #define WIN_APP_STATE_PERCENT070_2 38
199 #define WIN_APP_STATE_PERCENT080_1 39
200 #define WIN_APP_STATE_PERCENT080_2 40
201 #define WIN_APP_STATE_PERCENT090_1 41
202 #define WIN_APP_STATE_PERCENT090_2 42
203 #define WIN_APP_STATE_PERCENT100_1 43
204 #define WIN_APP_STATE_PERCENT100_2 44
205 #define XA_WIN_APP_STATE "_WIN_APP_STATE"
206 /* WIN_APP_STATE = CARD32 */
208 /* Expanded space occupied - this is the area on screen the app's window */
209 /* will occupy when "expanded" - ie if you have a button on an app that */
210 /* "hides" it by reducing its size, this is the geometry of the expanded */
211 /* window - so the window manager can allow for this when doign auto */
212 /* positioing of client windows assuming the app can at any point use this */
213 /* this area and thus try and keep it clear. ONLY the client sets this */
220 #define XA_WIN_EXPANDED_SIZE "_WIN_EXPANDED_SIZE"
221 /* array of 4 CARD32's */
223 /* CARD32 that contians the desktop number the application is on If the */
224 /* application's state is "sticky" it is irrelevant. Only the WM should */
226 #define XA_WIN_WORKSPACE "_WIN_WORKSPACE"
228 /* This atom is a 32-bit integer that is either 0 or 1 (currently). */
229 /* 0 denotes everything is as per usual but 1 denotes that ALL configure */
230 /* requests by the client on the client window with this property are */
231 /* not just a simple "moving" of the window, but the result of a user */
232 /* moving the window BUT the client handling that interaction by moving */
233 /* its own window. The window manager should respond accordingly by assuming */
234 /* any configure requests for this window whilst this atom is "active" in */
235 /* the "1" state are a client move and should handle flipping desktops if */
236 /* the window is being dragged "off screem" or across desktop boundaries */
237 /* etc. This atom is ONLY ever set by the client */
238 #define XA_WIN_CLIENT_MOVING "_WIN_CLIENT_MOVING"
239 /* WIN_CLIENT_MOVING = CARD32 */
241 /* Designed for checking if the WIN_ supporting WM is still there */
242 /* and kicking about - basically check this property - check the window */
243 /* ID it points to - then check that window Id has this property too */
244 /* if that is the case the WIN_ supporting WM is there and alive and the */
245 /* list of WIN_PROTOCOLS is valid */
246 #define XA_WIN_SUPPORTING_WM_CHECK "_WIN_SUPPORTING_WM_CHECK"
249 /* for root window button clicks */
250 #define XA_WIN_DESKTOP_BUTTON_PROXY "_WIN_DESKTOP_BUTTON_PROXY"
254 /* for the root window clicks */
255 static Window __button_proxy
= 0;
258 /* how many desks does gnome know about */
259 static int gnome_max_desk
= 1;
261 static int atom_size(int format
)
269 return (format
>> 3);
274 AtomGet(Window win
, Atom to_get
, Atom type
, int *size
)
276 unsigned char *retval
;
278 unsigned long bytes_after
, num_ret
;
286 dpy
, win
, to_get
, 0L, length
, False
, type
, &type_ret
,
287 &format_ret
, &num_ret
, &bytes_after
, &retval
);
289 if ((retval
) && (num_ret
> 0) && (format_ret
> 0))
293 asize
= atom_size(format_ret
);
294 data
= safemalloc(num_ret
* asize
);
297 memcpy(data
, retval
, num_ret
* asize
);
300 *size
= num_ret
* (format_ret
>> 3);
308 /*** GET WINDOW PROPERTIES ***/
312 GNOME_GetHintIcons(FvwmWindow
*fwin
)
321 atom_get
= XInternAtom(dpy
, XA_WIN_ICONS
, False
);
322 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_PIXMAP
, &size
);
327 n
= size
/ atom_size(32);
328 for (i
= 0; i
< n
; i
+= 2)
331 mask
= retval
[i
+ 1];
340 GNOME_GetHintLayer(FvwmWindow
*fwin
)
346 atom_get
= XInternAtom(dpy
, XA_WIN_LAYER
, False
);
347 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
350 set_layer(fwin
, *retval
);
358 GNOME_GetHintState(FvwmWindow
*fwin
)
364 atom_get
= XInternAtom(dpy
, XA_WIN_STATE
, False
);
365 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
368 if (*retval
& WIN_STATE_STICKY
)
373 if (*retval
& WIN_STATE_SHADED
)
375 /* Fixme: how do we find out the correct shade
378 SET_SHADED_DIR(fwin
, DIR_N
);
381 if (*retval
& WIN_STATE_FIXED_POSITION
)
393 GNOME_GetHintAppState(FvwmWindow
*fwin
)
396 unsigned char *retval
;
399 /* have nothing interesting to do with an app state (lamp) right now */
400 atom_get
= XInternAtom(dpy
, XA_WIN_APP_STATE
, False
);
401 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
411 GNOME_GetHintDesktop(FvwmWindow
*fwin
)
414 unsigned char *retval
;
418 atom_get
= XInternAtom(dpy
, XA_WIN_WORKSPACE
, False
);
419 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
422 desk
= (int *)retval
;
425 /* XXX: hide window if it's not on the current desktop! */
433 GNOME_GetHint(FvwmWindow
*fwin
)
439 atom_get
= XInternAtom(dpy
, XA_WIN_HINTS
, False
);
440 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
443 if (*retval
& WIN_HINTS_SKIP_WINLIST
)
445 SET_DO_SKIP_WINDOW_LIST(fwin
, 1);
447 /* XXX: unimplimented */
448 if (*retval
& WIN_HINTS_SKIP_TASKBAR
)
452 if (*retval
& WIN_HINTS_SKIP_FOCUS
)
456 if (*retval
& WIN_HINTS_FOCUS_ON_CLICK
)
460 /* if (*retval & WIN_HINTS_DO_NOT_COVER);*/
469 GNOME_GetExpandedSize(FvwmWindow
*fwin
)
476 int expanded_x
, expanded_y
, expanded_width
, expanded_height
;
478 atom_get
= XInternAtom(dpy
, XA_WIN_EXPANDED_SIZE
, False
);
479 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
482 expanded_x
= retval
[0];
483 expanded_y
= retval
[1];
484 expanded_width
= retval
[2];
485 expanded_height
= retval
[3];
493 GNOME_GetHints(FvwmWindow
*fwin
)
495 if (DO_IGNORE_GNOME_HINTS(fwin
))
499 GNOME_GetHintDesktop(fwin
);
500 GNOME_GetHintIcons(fwin
);
501 GNOME_GetHintLayer(fwin
);
502 GNOME_GetHintState(fwin
);
503 GNOME_GetHintAppState(fwin
);
505 GNOME_GetExpandedSize(fwin
);
512 GNOME_SetHints(FvwmWindow
*fwin
)
517 atom_set
= XInternAtom(dpy
, XA_WIN_STATE
, False
);
520 if (IS_STICKY_ACROSS_PAGES(fwin
) && IS_STICKY_ACROSS_DESKS(fwin
))
522 val
|= WIN_STATE_STICKY
;
526 val
|= WIN_STATE_SHADED
;
528 if (!is_function_allowed(F_MOVE
, NULL
, fwin
, RQORIG_PROGRAM_US
, False
))
530 val
|= WIN_STATE_FIXED_POSITION
;
533 dpy
, FW_W(fwin
), atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
534 (unsigned char *)&val
, 1);
540 /* this duplicates most of the above... and it assumes
541 that style is inizialized to zero.
544 GNOME_GetStyle (FvwmWindow
*fwin
, window_style
*style
)
547 unsigned char *retval
;
550 if (S_DO_IGNORE_GNOME_HINTS(SCF(*style
)))
555 atom_get
= XInternAtom(dpy
, XA_WIN_WORKSPACE
, False
);
556 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
559 SSET_START_DESK(*style
, *(int*)retval
);
560 /* Allow special case of -1 to work. */
561 if (SGET_START_DESK(*style
) > -1)
563 SSET_START_DESK(*style
, SGET_START_DESK(*style
) + 1);
565 style
->flags
.use_start_on_desk
= 1;
566 style
->flag_mask
.use_start_on_desk
= 1;
570 /* Icons - not implemented */
573 atom_get
= XInternAtom(dpy
, XA_WIN_LAYER
, False
);
574 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
577 SSET_LAYER(*style
, *(int*)retval
);
578 style
->flags
.use_layer
= (SGET_LAYER(*style
) >= 0) ? 1 : 0;
579 style
->flag_mask
.use_layer
= 1;
584 atom_get
= XInternAtom(dpy
, XA_WIN_STATE
, False
);
585 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
588 if (*(int*)retval
& WIN_STATE_STICKY
)
590 S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style
), 1);
591 S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style
), 1);
592 S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style
), 1);
593 S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style
), 1);
594 S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style
), 1);
595 S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style
), 1);
598 if (*(int*)retval
& WIN_STATE_SHADED
)
600 /* unimplemented, since we don't have a
601 start_shaded flag. SM code relies on a
602 separate do_shade flag, but that is ugly.
606 if ((*(int*)retval
& WIN_STATE_FIXED_POSITION
))
608 S_SET_IS_FIXED(SCF(*style
), 1);
609 S_SET_IS_FIXED(SCM(*style
), 1);
610 S_SET_IS_FIXED(SCC(*style
), 1);
616 /* App state - not implemented */
619 atom_get
= XInternAtom(dpy
, XA_WIN_HINTS
, False
);
620 retval
= AtomGet(FW_W(fwin
), atom_get
, XA_CARDINAL
, &size
);
623 if (*retval
& WIN_HINTS_SKIP_WINLIST
)
625 S_SET_DO_WINDOW_LIST_SKIP(SCF(*style
), 1);
626 S_SET_DO_WINDOW_LIST_SKIP(SCM(*style
), 1);
627 S_SET_DO_WINDOW_LIST_SKIP(SCC(*style
), 1);
633 /* Expanded size - not implemented */
639 /*** SET WINDOW PROPERTIES ***/
641 GNOME_SetDesk(FvwmWindow
*fwin
)
646 atom_set
= XInternAtom(dpy
, XA_WIN_WORKSPACE
, False
);
648 if (val
>= gnome_max_desk
)
650 GNOME_SetDeskCount();
653 dpy
, FW_W(fwin
), atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
654 (unsigned char *)&val
, 1);
661 GNOME_SetLayer(FvwmWindow
*fwin
)
666 atom_set
= XInternAtom(dpy
, XA_WIN_LAYER
, False
);
667 val
= get_layer(fwin
);
669 dpy
, FW_W(fwin
), atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
670 (unsigned char *)&val
, 1);
676 /*** INITIALIZE GNOME WM SUPPORT ***/
678 /* sets the virtual desktop grid properties */
680 GNOME_SetAreaCount(void)
685 atom_set
= XInternAtom(dpy
, XA_WIN_AREA_COUNT
, False
);
686 val
[0] = (Scr
.VxMax
+ Scr
.MyDisplayWidth
) / Scr
.MyDisplayWidth
;
687 val
[1] = (Scr
.VyMax
+ Scr
.MyDisplayHeight
) / Scr
.MyDisplayHeight
;
689 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
690 (unsigned char *)val
, 2);
696 /* sets the property indicating the current virtual desktop
700 GNOME_SetCurrentArea(void)
705 atom_set
= XInternAtom(dpy
, XA_WIN_AREA
, False
);
706 val
[0] = Scr
.Vx
/ Scr
.MyDisplayWidth
;
707 val
[1] = Scr
.Vy
/ Scr
.MyDisplayHeight
;
709 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
710 (unsigned char *)val
, 2);
715 /* FIXME: what to do about negative desks ? */
718 GNOME_SetDeskCount(void)
724 atom_set
= XInternAtom(dpy
, XA_WIN_WORKSPACE_COUNT
, False
);
726 if (Scr
.CurrentDesk
> 0)
728 val
= Scr
.CurrentDesk
;
730 for (t
= get_next_window_in_stack_ring(&Scr
.FvwmRoot
);
731 t
!= &Scr
.FvwmRoot
; t
= get_next_window_in_stack_ring(t
))
739 if (gnome_max_desk
> val
)
741 val
= gnome_max_desk
;
744 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
745 (unsigned char *)&val
, 1);
751 /* XXX: this function is hard-coded to one! -JMP */
753 GNOME_SetCurrentDesk(void)
758 atom_set
= XInternAtom(dpy
, XA_WIN_WORKSPACE
, False
);
759 val
= (long) Scr
.CurrentDesk
;
760 if (val
>= gnome_max_desk
)
762 GNOME_SetDeskCount();
765 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
766 (unsigned char *)&val
, 1);
767 GNOME_SetCurrentArea();
773 /* sets the names assigned to the desktops */
775 GNOME_SetDeskNames(void)
781 atom_set
= XInternAtom(dpy
, XA_WIN_WORKSPACE_NAMES
, False
);
782 names
[0] = "GNOME Desktop";
783 if (XStringListToTextProperty(names
, 1, &text
))
785 XSetTextProperty(dpy
, Scr
.Root
, &text
, atom_set
);
794 GNOME_SetClientList(void)
802 /* Find out how many window pointers we need to store, allocate
803 * the space and go through the list again to actually store them.
805 for (t
= Scr
.FvwmRoot
.next
; t
; t
= t
->next
)
807 if (!DO_SKIP_WINDOW_LIST(t
))
814 wl
=(Window
*)safemalloc(sizeof(Window
*)*displayed
);
815 for (t
= Scr
.FvwmRoot
.next
; t
; t
= t
->next
)
817 if (!DO_SKIP_WINDOW_LIST(t
))
824 atom_set
= XInternAtom(dpy
, XA_WIN_CLIENT_LIST
, False
);
826 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32,
827 PropModeReplace
, (unsigned char *)wl
, i
);
835 GNOME_SetWinArea(FvwmWindow
*w
)
840 atom_set
= XInternAtom(dpy
, XA_WIN_AREA
, False
);
842 if (!DO_SKIP_WINDOW_LIST(w
))
844 if (IsRectangleOnThisPage(&(w
->g
.frame
), w
->Desk
))
846 val
[0] = Scr
.Vx
/ Scr
.MyDisplayWidth
;
847 val
[1] = Scr
.Vy
/ Scr
.MyDisplayHeight
;
851 val
[0] = (w
->g
.frame
.x
+ Scr
.Vx
) / Scr
.MyDisplayWidth
;
853 w
->g
.frame
.x
+ Scr
.Vx
+ w
->g
.frame
.width
> 0)
857 val
[1] = (w
->g
.frame
.y
+ Scr
.Vy
) / Scr
.MyDisplayHeight
;
859 w
->g
.frame
.y
+ Scr
.Vy
+ w
->g
.frame
.height
> 0)
865 dpy
, FW_W(w
), atom_set
, XA_CARDINAL
, 32,
866 PropModeReplace
, (unsigned char *)val
, 2);
876 Atom atom_set
, list
[11];
879 atom_set
= XInternAtom(dpy
, XA_WIN_PROTOCOLS
, False
);
880 /* these indicate what GNOME compliance properties have been
883 list
[i
++] = XInternAtom(dpy
, XA_WIN_LAYER
, False
);
884 list
[i
++] = XInternAtom(dpy
, XA_WIN_STATE
, False
);
885 list
[i
++] = XInternAtom(dpy
, XA_WIN_HINTS
, False
);
886 /* list[i++] = XInternAtom(dpy, XA_WIN_APP_STATE, False); */
887 /* list[i++] = XInternAtom(dpy, XA_WIN_EXPANDED_SIZE, False); */
888 /* list[i++] = XInternAtom(dpy, XA_WIN_ICONS, False); */
889 list
[i
++] = XInternAtom(dpy
, XA_WIN_WORKSPACE
, False
);
890 list
[i
++] = XInternAtom(dpy
, XA_WIN_WORKSPACE_COUNT
, False
);
891 list
[i
++] = XInternAtom(dpy
, XA_WIN_WORKSPACE_NAMES
, False
);
892 list
[i
++] = XInternAtom(dpy
, XA_WIN_CLIENT_LIST
, False
);
893 list
[i
++] = XInternAtom(dpy
, XA_WIN_DESKTOP_BUTTON_PROXY
, False
);
895 dpy
, Scr
.Root
, atom_set
, XA_ATOM
, 32, PropModeReplace
,
896 (unsigned char *)list
, i
);
898 /*--------------------------------------------------------------------
899 why use two windows when one does just fine ?
900 --------------------------------------------------------------------*/
901 /* create a window which is a child of the root window and set the
902 * XA_WIN_SUPPORTING_WM_CHECK property on it, and also set the
903 * same property on the root window with the window ID of of the
904 * window we just created
906 __button_proxy
= XCreateWindow(dpy
, Scr
.Root
, -10, -10, 10, 10, 0, 0,
907 InputOnly
, CopyFromParent
, 0, NULL
);
908 atom_set
= XInternAtom(dpy
, XA_WIN_SUPPORTING_WM_CHECK
, False
);
909 val
= __button_proxy
;
911 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
912 (unsigned char *)&val
, 1);
914 dpy
, __button_proxy
, atom_set
, XA_CARDINAL
, 32,
915 PropModeReplace
, (unsigned char *)&val
, 1);
917 /* create a window which is the child of the root window for proxying
920 atom_set
= XInternAtom(dpy
, XA_WIN_DESKTOP_BUTTON_PROXY
, False
);
922 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32,
923 PropModeReplace
, (unsigned char *)&val
, 1);
925 dpy
, __button_proxy
, atom_set
, XA_CARDINAL
, 32,
926 PropModeReplace
, (unsigned char *)&val
, 1);
928 /* some initial settings */
929 GNOME_SetDeskCount();
930 GNOME_SetCurrentDesk();
931 GNOME_SetDeskNames();
932 GNOME_SetAreaCount();
933 GNOME_SetCurrentArea();
934 GNOME_SetClientList();
940 /*-----------------------------------------------------------------------
941 tell gnome how many desks to show
942 -----------------------------------------------------------------------*/
944 CMD_GnomeShowDesks(F_CMD_ARGS
)
950 atom_set
= XInternAtom(dpy
, XA_WIN_WORKSPACE_COUNT
, False
);
951 DBUG("GNOME_ShowDesks","Routine Entered");
952 n
= GetIntegerArguments(action
, NULL
, (int *)val
, 1);
955 fvwm_msg(ERR
, "GnomeShowDesks", "requires one argument");
958 gnome_max_desk
= val
[0];
960 dpy
, Scr
.Root
, atom_set
, XA_CARDINAL
, 32, PropModeReplace
,
961 (unsigned char *)(&val
[0]), 1);
967 /*** RECIVING MESSAGES ***/
969 GNOME_ProcessClientMessage(const exec_context_t
*exc
)
972 FvwmWindow
*fw
= exc
->w
.fw
;
973 XEvent
*ev
= exc
->x
.etrigger
;
976 const char* invalid_req
= "---";
977 const char* invalid_prop
= "---";
979 if (fw
!= NULL
&& DO_IGNORE_GNOME_HINTS(fw
))
983 a
= XInternAtom(dpy
, XA_WIN_AREA
, False
);
984 if (ev
->xclient
.message_type
== a
)
986 /* convert to integer grid */
987 p0
= ev
->xclient
.data
.l
[0] * Scr
.MyDisplayWidth
;
988 p1
= ev
->xclient
.data
.l
[1] * Scr
.MyDisplayHeight
;
989 if (p0
< 0 || p0
> 0x7fffffff || p1
< 0 || p1
> 0x7fffffff)
991 invalid_prop
= "page";
992 invalid_req
= "_WIN_AREA";
995 MoveViewport(p0
, p1
, 1);
999 a
= XInternAtom(dpy
, XA_WIN_WORKSPACE
, False
);
1000 if (ev
->xclient
.message_type
== a
)
1002 p0
= ev
->xclient
.data
.l
[0];
1003 if (p0
< 0 || p0
> 0x7fffffff)
1005 invalid_prop
= "desk";
1006 invalid_req
= "_WIN_WORKSPACE";
1013 a
= XInternAtom(dpy
, XA_WIN_LAYER
, False
);
1014 if (ev
->xclient
.message_type
== a
&& fw
)
1016 p0
= ev
->xclient
.data
.l
[0];
1017 if (p0
< 0 || p0
> 0x7fffffff)
1019 invalid_prop
= "layer";
1020 invalid_req
= "_WIN_LAYER";
1027 a
= XInternAtom(dpy
, XA_WIN_STATE
, False
);
1028 if (ev
->xclient
.message_type
== a
&& fw
)
1030 GNOME_HandlePropRequest(
1031 exc
, ev
->xclient
.data
.l
[0], ev
->xclient
.data
.l
[1]);
1040 WARN
, "GNOME_ProcessClientMessage",
1041 "The application window (id %#lx)\n"
1042 " \"%s\" has requested an invalid %s (%ld, %ld)\n"
1043 " using a %s client message.\n"
1044 " fvwm is ignoring this request.\n",
1045 fw
? FW_W(fw
) : 0, fw
? fw
->name
.name
: "(none)", invalid_prop
,
1046 p0
, p1
, invalid_req
);
1047 fvwm_msg_report_app_and_workers();
1053 void GNOME_HandlePropRequest(
1054 const exec_context_t
*exc
, unsigned int propm
, unsigned int prop
)
1060 unsigned char *indi
;
1061 unsigned long nitems
, bytes_remain
, oldprop
;
1062 indi
= (unsigned char *)&oldprop
;
1063 DBUG("HandleGnomePropRequest","Routine Entered");
1065 a
= XInternAtom(dpy
, XA_WIN_STATE
, False
);
1067 for (fwin
= Scr
.FvwmRoot
.next
; fwin
; fwin
= fwin
->next
)
1069 if (FW_W(fwin
) == exc
->w
.w
)
1074 /*--------------------------------------------------------------------
1075 First change the props on the window so the gnome app knows we did
1077 --------------------------------------------------------------------*/
1078 #ifdef FVWM_DEBUG_MSGS
1080 DBG
, "HandleGnomePropRequest", "window is %d", (int)FW_W(fwin
));
1086 if (DO_IGNORE_GNOME_HINTS(fwin
))
1091 #ifdef FVWM_DEBUG_MSGS
1092 fvwm_msg(DBG
, "HandleGnomePropRequest", "prop req is %d", prop
);
1093 fvwm_msg(DBG
, "HandleGnomePropRequest", "propm req is %d", propm
);
1095 XGetWindowProperty(dpy
, FW_W(fwin
), a
, 0L, 3L, False
, a
,
1096 &atype
, &aformat
, &nitems
, &bytes_remain
, &indi
);
1097 oldprop
&= ~(propm
);
1098 oldprop
|= (propm
& prop
);
1099 #ifdef FVWM_DEBUG_MSGS
1101 DBG
, "HandleGnomePropRequest", "oldprop req is %d",
1105 dpy
, FW_W(fwin
), a
, XA_CARDINAL
, 32, PropModeReplace
,
1106 (unsigned char *)&oldprop
, 1);
1108 /*--------------------------------------------------------------------
1109 Then apply the requests
1110 --------------------------------------------------------------------*/
1112 /*--------------------------------------------------------------------
1114 --------------------------------------------------------------------*/
1115 if (propm
& WIN_STATE_STICKY
)
1117 if (prop
& WIN_STATE_STICKY
)
1119 SET_STICKY_ACROSS_PAGES(fwin
, 1);
1120 SET_STICKY_ACROSS_DESKS(fwin
, 1);
1124 SET_STICKY_ACROSS_PAGES(fwin
, 0);
1125 SET_STICKY_ACROSS_DESKS(fwin
, 0);
1127 border_draw_decorations(
1128 fwin
, PART_TITLE
, (Scr
.Hilite
==fwin
), True
, CLEAR_ALL
,
1131 /*--------------------------------------------------------------------
1133 -------------------------------------------------------------------*/
1134 if (propm
& WIN_STATE_SHADED
)
1136 if (prop
& WIN_STATE_SHADED
)
1139 execute_function_override_window(
1140 NULL
, exc
, "WindowShade True", 0, fwin
);
1145 execute_function_override_window(
1146 NULL
, exc
, "WindowShade False", 0, fwin
);
1154 GNOME_ProxyButtonEvent(const XEvent
*ev
)
1159 XUngrabPointer(dpy
, CurrentTime
);
1161 dpy
, __button_proxy
, False
, SubstructureNotifyMask
,
1167 dpy
, __button_proxy
, False
, SubstructureNotifyMask
,
1176 /* this is the function entered into fvwm's functions table */
1178 CMD_GnomeButton(F_CMD_ARGS
)
1180 /* send off the button press event */
1181 GNOME_ProxyButtonEvent(exc
->x
.etrigger
);