4 * Copyright (c) Tuomo Valkonen 1999-2006.
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"
29 static Atom atom_net_wm_name=0;
30 static Atom atom_net_wm_state=0;
31 static Atom atom_net_wm_state_fullscreen=0;
32 static Atom atom_net_supporting_wm_check=0;
33 static Atom atom_net_virtual_roots=0;
34 static Atom atom_net_active_window=0;
38 static Atom atom_net_supported=0;
43 /*{{{ Initialisation */
48 atom_net_wm_name=XInternAtom(ioncore_g.dpy, "_NET_WM_NAME", False);
49 atom_net_wm_state=XInternAtom(ioncore_g.dpy, "_NET_WM_STATE", False);
50 atom_net_wm_state_fullscreen=XInternAtom(ioncore_g.dpy, "_NET_WM_STATE_FULLSCREEN", False);
51 atom_net_supported=XInternAtom(ioncore_g.dpy, "_NET_SUPPORTED", False);
52 atom_net_supporting_wm_check=XInternAtom(ioncore_g.dpy, "_NET_SUPPORTING_WM_CHECK", False);
53 atom_net_virtual_roots=XInternAtom(ioncore_g.dpy, "_NET_VIRTUAL_ROOTS", False);
54 atom_net_active_window=XInternAtom(ioncore_g.dpy, "_NET_ACTIVE_WINDOW", False);
58 void netwm_init_rootwin(WRootWin *rw)
63 atoms[0]=atom_net_wm_name;
64 atoms[1]=atom_net_wm_state;
65 atoms[2]=atom_net_wm_state_fullscreen;
66 atoms[3]=atom_net_supporting_wm_check;
67 atoms[4]=atom_net_virtual_roots;
68 atoms[5]=atom_net_active_window;
70 XChangeProperty(ioncore_g.dpy, WROOTWIN_ROOT(rw),
71 atom_net_supporting_wm_check, XA_WINDOW,
72 32, PropModeReplace, (uchar*)&(rw->dummy_win), 1);
73 XChangeProperty(ioncore_g.dpy, WROOTWIN_ROOT(rw),
74 atom_net_supported, XA_ATOM,
75 32, PropModeReplace, (uchar*)atoms, N_NETWM);
76 /* Something else should probably be used as WM name here. */
78 xwindow_set_text_property(rw->dummy_win, atom_net_wm_name, p, 1);
85 /*{{{ _NET_WM_STATE */
88 int netwm_check_initial_fullscreen(WClientWin *cwin, bool sw)
95 n=xwindow_get_property(cwin->win, atom_net_wm_state, XA_ATOM,
96 1, TRUE, (uchar**)&data);
102 if(data[i]==(long)atom_net_wm_state_fullscreen){
103 ret=clientwin_enter_fullscreen(cwin, sw);
114 void netwm_update_state(WClientWin *cwin)
119 if(REGION_IS_FULLSCREEN(cwin))
120 data[n++]=atom_net_wm_state_fullscreen;
122 XChangeProperty(ioncore_g.dpy, cwin->win, atom_net_wm_state,
123 XA_ATOM, 32, PropModeReplace, (uchar*)data, n);
127 void netwm_delete_state(WClientWin *cwin)
129 XDeleteProperty(ioncore_g.dpy, cwin->win, atom_net_wm_state);
134 static void netwm_state_change_rq(WClientWin *cwin,
135 const XClientMessageEvent *ev)
137 if((ev->data.l[1]==0 ||
138 ev->data.l[1]!=(long)atom_net_wm_state_fullscreen) &&
140 ev->data.l[2]!=(long)atom_net_wm_state_fullscreen)){
144 /* Ok, full screen add/remove/toggle */
145 if(!REGION_IS_FULLSCREEN(cwin)){
146 if(ev->data.l[0]==_NET_WM_STATE_ADD ||
147 ev->data.l[0]==_NET_WM_STATE_TOGGLE){
148 bool sw=clientwin_fullscreen_may_switchto(cwin);
149 cwin->flags|=CLIENTWIN_FS_RQ;
150 if(!clientwin_enter_fullscreen(cwin, 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 bool sw=clientwin_fullscreen_may_switchto(cwin);
160 cwin->flags&=~CLIENTWIN_FS_RQ;
161 clientwin_leave_fullscreen(cwin, sw);
164 cwin->flags|=CLIENTWIN_FS_RQ;
173 /*{{{ _NET_ACTIVE_WINDOW */
176 void netwm_set_active(WRegion *reg)
178 CARD32 data[1]={None};
180 if(OBJ_IS(reg, WClientWin))
181 data[0]=region_xwindow(reg);
183 /* The spec doesn't say how multihead should be handled, so
184 * we just update the root window the window is on.
186 XChangeProperty(ioncore_g.dpy, region_root_of(reg),
187 atom_net_active_window, XA_WINDOW,
188 32, PropModeReplace, (uchar*)data, 1);
192 static void netwm_active_window_rq(WClientWin *cwin,
193 const XClientMessageEvent *ev)
197 extl_table_gets_b(cwin->proptab, "ignore_net_active_window", &ignore);
200 region_goto((WRegion*)cwin);
207 /*{{{ _NET_WM_NAME */
210 char **netwm_get_name(WClientWin *cwin)
212 return xwindow_get_text_property(cwin->win, atom_net_wm_name, NULL);
219 /*{{{ netwm_handle_client_message */
222 void netwm_handle_client_message(const XClientMessageEvent *ev)
224 /* Check _NET_WM_STATE fullscreen request */
225 if(ev->message_type==atom_net_wm_state && ev->format==32){
226 WClientWin *cwin=XWINDOW_REGION_OF_T(ev->window, WClientWin);
228 netwm_state_change_rq(cwin, ev);
230 /* Check _NET_ACTIVE_WINDOW request */
231 else if(ev->message_type==atom_net_active_window && ev->format==32){
232 WClientWin *cwin=XWINDOW_REGION_OF_T(ev->window, WClientWin);
234 netwm_active_window_rq(cwin, ev);
242 /*{{{ netwm_handle_property */
245 bool netwm_handle_property(WClientWin *cwin, const XPropertyEvent *ev)
247 if(ev->atom!=atom_net_wm_name)
250 clientwin_get_set_name(cwin);