4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
12 #include <X11/Xatom.h>
15 #include <libtu/util.h>
18 #include "fullscreen.h"
19 #include "clientwin.h"
30 static Atom atom_net_wm_name=0;
31 static Atom atom_net_wm_state=0;
32 static Atom atom_net_wm_state_fullscreen=0;
33 static Atom atom_net_supporting_wm_check=0;
34 static Atom atom_net_virtual_roots=0;
35 static Atom atom_net_active_window=0;
39 static Atom atom_net_supported=0;
44 /*{{{ Initialisation */
49 atom_net_wm_name=XInternAtom(ioncore_g.dpy, "_NET_WM_NAME", False);
50 atom_net_wm_state=XInternAtom(ioncore_g.dpy, "_NET_WM_STATE", False);
51 atom_net_wm_state_fullscreen=XInternAtom(ioncore_g.dpy, "_NET_WM_STATE_FULLSCREEN", False);
52 atom_net_supported=XInternAtom(ioncore_g.dpy, "_NET_SUPPORTED", False);
53 atom_net_supporting_wm_check=XInternAtom(ioncore_g.dpy, "_NET_SUPPORTING_WM_CHECK", False);
54 atom_net_virtual_roots=XInternAtom(ioncore_g.dpy, "_NET_VIRTUAL_ROOTS", False);
55 atom_net_active_window=XInternAtom(ioncore_g.dpy, "_NET_ACTIVE_WINDOW", False);
59 void netwm_init_rootwin(WRootWin *rw)
64 atoms[0]=atom_net_wm_name;
65 atoms[1]=atom_net_wm_state;
66 atoms[2]=atom_net_wm_state_fullscreen;
67 atoms[3]=atom_net_supporting_wm_check;
68 atoms[4]=atom_net_virtual_roots;
69 atoms[5]=atom_net_active_window;
71 XChangeProperty(ioncore_g.dpy, WROOTWIN_ROOT(rw),
72 atom_net_supporting_wm_check, XA_WINDOW,
73 32, PropModeReplace, (uchar*)&(rw->dummy_win), 1);
74 XChangeProperty(ioncore_g.dpy, WROOTWIN_ROOT(rw),
75 atom_net_supported, XA_ATOM,
76 32, PropModeReplace, (uchar*)atoms, N_NETWM);
78 p[0]=libtu_progbasename();
79 xwindow_set_text_property(rw->dummy_win, atom_net_wm_name, p, 1);
86 /*{{{ _NET_WM_STATE */
89 WScreen *netwm_check_initial_fullscreen(WClientWin *cwin)
96 n=xwindow_get_property(cwin->win, atom_net_wm_state, XA_ATOM,
97 1, TRUE, (uchar**)&data);
103 if(data[i]==(long)atom_net_wm_state_fullscreen)
104 return region_screen_of((WRegion*)cwin);
113 void netwm_update_state(WClientWin *cwin)
118 if(REGION_IS_FULLSCREEN(cwin))
119 data[n++]=atom_net_wm_state_fullscreen;
121 XChangeProperty(ioncore_g.dpy, cwin->win, atom_net_wm_state,
122 XA_ATOM, 32, PropModeReplace, (uchar*)data, n);
126 void netwm_delete_state(WClientWin *cwin)
128 XDeleteProperty(ioncore_g.dpy, cwin->win, atom_net_wm_state);
133 static void netwm_state_change_rq(WClientWin *cwin,
134 const XClientMessageEvent *ev)
136 if((ev->data.l[1]==0 ||
137 ev->data.l[1]!=(long)atom_net_wm_state_fullscreen) &&
139 ev->data.l[2]!=(long)atom_net_wm_state_fullscreen)){
143 /* Ok, full screen add/remove/toggle */
144 if(!REGION_IS_FULLSCREEN(cwin)){
145 if(ev->data.l[0]==_NET_WM_STATE_ADD ||
146 ev->data.l[0]==_NET_WM_STATE_TOGGLE){
147 WRegion *grp=region_groupleader_of((WRegion*)cwin);
148 bool sw=clientwin_fullscreen_may_switchto(cwin);
149 cwin->flags|=CLIENTWIN_FS_RQ;
150 if(!region_enter_fullscreen(grp, sw))
151 cwin->flags&=~CLIENTWIN_FS_RQ;
153 /* Should not be set.. */
154 cwin->flags&=~CLIENTWIN_FS_RQ;
157 if(ev->data.l[0]==_NET_WM_STATE_REMOVE ||
158 ev->data.l[0]==_NET_WM_STATE_TOGGLE){
159 WRegion *grp=region_groupleader_of((WRegion*)cwin);
160 bool sw=clientwin_fullscreen_may_switchto(cwin);
161 cwin->flags&=~CLIENTWIN_FS_RQ;
162 region_leave_fullscreen(grp, sw);
165 cwin->flags|=CLIENTWIN_FS_RQ;
174 /*{{{ _NET_ACTIVE_WINDOW */
177 void netwm_set_active(WRegion *reg)
179 CARD32 data[1]={None};
181 if(OBJ_IS(reg, WClientWin))
182 data[0]=region_xwindow(reg);
184 /* The spec doesn't say how multihead should be handled, so
185 * we just update the root window the window is on.
187 XChangeProperty(ioncore_g.dpy, region_root_of(reg),
188 atom_net_active_window, XA_WINDOW,
189 32, PropModeReplace, (uchar*)data, 1);
193 static void netwm_active_window_rq(WClientWin *cwin,
194 const XClientMessageEvent *ev)
198 extl_table_gets_b(cwin->proptab, "ignore_net_active_window", &ignore);
201 region_goto((WRegion*)cwin);
208 /*{{{ _NET_WM_NAME */
211 char **netwm_get_name(WClientWin *cwin)
213 return xwindow_get_text_property(cwin->win, atom_net_wm_name, NULL);
220 /*{{{ netwm_handle_client_message */
223 void netwm_handle_client_message(const XClientMessageEvent *ev)
225 /* Check _NET_WM_STATE fullscreen request */
226 if(ev->message_type==atom_net_wm_state && ev->format==32){
227 WClientWin *cwin=XWINDOW_REGION_OF_T(ev->window, WClientWin);
229 netwm_state_change_rq(cwin, ev);
231 /* Check _NET_ACTIVE_WINDOW request */
232 else if(ev->message_type==atom_net_active_window && ev->format==32){
233 WClientWin *cwin=XWINDOW_REGION_OF_T(ev->window, WClientWin);
235 netwm_active_window_rq(cwin, ev);
243 /*{{{ netwm_handle_property */
246 bool netwm_handle_property(WClientWin *cwin, const XPropertyEvent *ev)
248 if(ev->atom!=atom_net_wm_name)
251 clientwin_get_set_name(cwin);