git: initial import (.gitignore)
[evilwm.git] / ewmh.c
blob4ea6d745bf2c3c18a72ccbd7b566a7e3664de644
1 /* evilwm - Minimalist Window Manager for X
2 * Copyright (C) 1999-2009 Ciaran Anscomb <evilwm@6809.org.uk>
3 * see README for license and other details. */
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include "evilwm.h"
8 #include "log.h"
10 /* Root Window Properties (and Related Messages) */
11 static Atom xa_net_supported;
12 static Atom xa_net_client_list;
13 static Atom xa_net_client_list_stacking;
14 #ifdef VWM
15 static Atom xa_net_number_of_desktops;
16 #endif
17 static Atom xa_net_desktop_geometry;
18 static Atom xa_net_desktop_viewport;
19 #ifdef VWM
20 Atom xa_net_current_desktop;
21 #endif
22 Atom xa_net_active_window;
23 static Atom xa_net_workarea;
24 static Atom xa_net_supporting_wm_check;
26 /* Other Root Window Messages */
27 Atom xa_net_close_window;
28 Atom xa_net_moveresize_window;
29 Atom xa_net_restack_window;
30 Atom xa_net_request_frame_extents;
32 /* Application Window Properties */
33 static Atom xa_net_wm_name;
34 #ifdef VWM
35 Atom xa_net_wm_desktop;
36 #endif
37 Atom xa_net_wm_window_type;
38 Atom xa_net_wm_window_type_dock;
39 Atom xa_net_wm_state;
40 Atom xa_net_wm_state_maximized_vert;
41 Atom xa_net_wm_state_maximized_horz;
42 Atom xa_net_wm_state_fullscreen;
43 static Atom xa_net_wm_allowed_actions;
44 static Atom xa_net_wm_action_move;
45 static Atom xa_net_wm_action_resize;
46 static Atom xa_net_wm_action_maximize_horz;
47 static Atom xa_net_wm_action_maximize_vert;
48 static Atom xa_net_wm_action_fullscreen;
49 static Atom xa_net_wm_action_change_desktop;
50 static Atom xa_net_wm_action_close;
51 static Atom xa_net_wm_pid;
52 Atom xa_net_frame_extents;
54 /* Maintain a reasonably sized allocated block of memory for lists
55 * of windows (for feeding to XChangeProperty in one hit). */
56 static Window *window_array = NULL;
57 static Window *alloc_window_array(void);
59 void ewmh_init(void) {
60 /* Root Window Properties (and Related Messages) */
61 xa_net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False);
62 xa_net_client_list = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
63 xa_net_client_list_stacking = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
64 #ifdef VWM
65 xa_net_number_of_desktops = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
66 #endif
67 xa_net_desktop_geometry = XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", False);
68 xa_net_desktop_viewport = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
69 #ifdef VWM
70 xa_net_current_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
71 #endif
72 xa_net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
73 xa_net_workarea = XInternAtom(dpy, "_NET_WORKAREA", False);
74 xa_net_supporting_wm_check = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
76 /* Other Root Window Messages */
77 xa_net_close_window = XInternAtom(dpy, "_NET_CLOSE_WINDOW", False);
78 xa_net_moveresize_window = XInternAtom(dpy, "_NET_MOVERESIZE_WINDOW", False);
79 xa_net_restack_window = XInternAtom(dpy, "_NET_RESTACK_WINDOW", False);
80 xa_net_request_frame_extents = XInternAtom(dpy, "_NET_REQUEST_FRAME_EXTENTS", False);
82 /* Application Window Properties */
83 xa_net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", False);
84 #ifdef VWM
85 xa_net_wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
86 #endif
87 xa_net_wm_window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
88 xa_net_wm_window_type_dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
89 xa_net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
90 xa_net_wm_state_maximized_vert = XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False);
91 xa_net_wm_state_maximized_horz = XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
92 xa_net_wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
93 xa_net_wm_allowed_actions = XInternAtom(dpy, "_NET_WM_ALLOWED_ACTIONS", False);
94 xa_net_wm_action_move = XInternAtom(dpy, "_NET_WM_ACTION_MOVE", False);
95 xa_net_wm_action_resize = XInternAtom(dpy, "_NET_WM_ACTION_RESIZE", False);
96 xa_net_wm_action_maximize_horz = XInternAtom(dpy, "_NET_WM_ACTION_MAXIMIZE_HORZ", False);
97 xa_net_wm_action_maximize_vert = XInternAtom(dpy, "_NET_WM_ACTION_MAXIMIZE_VERT", False);
98 xa_net_wm_action_fullscreen = XInternAtom(dpy, "_NET_WM_ACTION_FULLSCREEN", False);
99 xa_net_wm_action_change_desktop = XInternAtom(dpy, "_NET_WM_ACTION_CHANGE_DESKTOP", False);
100 xa_net_wm_action_close = XInternAtom(dpy, "_NET_WM_ACTION_CLOSE", False);
101 xa_net_wm_pid = XInternAtom(dpy, "_NET_WM_PID", False);
102 xa_net_frame_extents = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False);
105 void ewmh_init_screen(ScreenInfo *s) {
106 unsigned long pid = getpid();
107 Atom supported[] = {
108 xa_net_client_list,
109 xa_net_client_list_stacking,
110 #ifdef VWM
111 xa_net_number_of_desktops,
112 #endif
113 xa_net_desktop_geometry,
114 xa_net_desktop_viewport,
115 #ifdef VWM
116 xa_net_current_desktop,
117 #endif
118 xa_net_active_window,
119 xa_net_workarea,
120 xa_net_supporting_wm_check,
122 xa_net_close_window,
123 xa_net_moveresize_window,
124 xa_net_restack_window,
125 xa_net_request_frame_extents,
127 #ifdef VWM
128 xa_net_wm_desktop,
129 #endif
130 xa_net_wm_window_type,
131 xa_net_wm_window_type_dock,
132 xa_net_wm_state,
133 xa_net_wm_state_maximized_vert,
134 xa_net_wm_state_maximized_horz,
135 xa_net_wm_state_fullscreen,
136 xa_net_wm_allowed_actions,
137 /* Not sure if it makes any sense including every action here
138 * as they'll already be listed per-client in the
139 * _NET_WM_ALOWED_ACTIONS property, but EWMH spec is unclear.
140 * */
141 xa_net_wm_action_move,
142 xa_net_wm_action_resize,
143 xa_net_wm_action_maximize_horz,
144 xa_net_wm_action_maximize_vert,
145 xa_net_wm_action_fullscreen,
146 xa_net_wm_action_change_desktop,
147 xa_net_wm_action_close,
148 xa_net_frame_extents,
150 #ifdef VWM
151 unsigned long num_desktops = 8;
152 unsigned long vdesk = s->vdesk;
153 #endif
154 unsigned long workarea[4] = {
155 0, 0,
156 DisplayWidth(dpy, s->screen), DisplayHeight(dpy, s->screen)
158 s->supporting = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 0, 0, 0);
159 XChangeProperty(dpy, s->root, xa_net_supported,
160 XA_ATOM, 32, PropModeReplace,
161 (unsigned char *)&supported,
162 sizeof(supported) / sizeof(Atom));
163 #ifdef VWM
164 XChangeProperty(dpy, s->root, xa_net_number_of_desktops,
165 XA_CARDINAL, 32, PropModeReplace,
166 (unsigned char *)&num_desktops, 1);
167 #endif
168 XChangeProperty(dpy, s->root, xa_net_desktop_geometry,
169 XA_CARDINAL, 32, PropModeReplace,
170 (unsigned char *)&workarea[2], 2);
171 XChangeProperty(dpy, s->root, xa_net_desktop_viewport,
172 XA_CARDINAL, 32, PropModeReplace,
173 (unsigned char *)&workarea[0], 2);
174 #ifdef VWM
175 XChangeProperty(dpy, s->root, xa_net_current_desktop,
176 XA_CARDINAL, 32, PropModeReplace,
177 (unsigned char *)&vdesk, 1);
178 #endif
179 XChangeProperty(dpy, s->root, xa_net_workarea,
180 XA_CARDINAL, 32, PropModeReplace,
181 (unsigned char *)&workarea, 4);
182 XChangeProperty(dpy, s->root, xa_net_supporting_wm_check,
183 XA_WINDOW, 32, PropModeReplace,
184 (unsigned char *)&s->supporting, 1);
185 XChangeProperty(dpy, s->supporting, xa_net_supporting_wm_check,
186 XA_WINDOW, 32, PropModeReplace,
187 (unsigned char *)&s->supporting, 1);
188 XChangeProperty(dpy, s->supporting, xa_net_wm_name,
189 XA_STRING, 8, PropModeReplace,
190 (const unsigned char *)"evilwm", 6);
191 XChangeProperty(dpy, s->supporting, xa_net_wm_pid,
192 XA_CARDINAL, 32, PropModeReplace,
193 (unsigned char *)&pid, 1);
196 void ewmh_deinit_screen(ScreenInfo *s) {
197 XDeleteProperty(dpy, s->root, xa_net_supported);
198 XDeleteProperty(dpy, s->root, xa_net_client_list);
199 XDeleteProperty(dpy, s->root, xa_net_client_list_stacking);
200 #ifdef VWM
201 XDeleteProperty(dpy, s->root, xa_net_number_of_desktops);
202 #endif
203 XDeleteProperty(dpy, s->root, xa_net_desktop_geometry);
204 XDeleteProperty(dpy, s->root, xa_net_desktop_viewport);
205 #ifdef VWM
206 XDeleteProperty(dpy, s->root, xa_net_current_desktop);
207 #endif
208 XDeleteProperty(dpy, s->root, xa_net_active_window);
209 XDeleteProperty(dpy, s->root, xa_net_workarea);
210 XDeleteProperty(dpy, s->root, xa_net_supporting_wm_check);
211 XDestroyWindow(dpy, s->supporting);
214 void ewmh_init_client(Client *c) {
215 Atom allowed_actions[] = {
216 xa_net_wm_action_move,
217 xa_net_wm_action_maximize_horz,
218 xa_net_wm_action_maximize_vert,
219 xa_net_wm_action_fullscreen,
220 xa_net_wm_action_change_desktop,
221 xa_net_wm_action_close,
222 /* nelements reduced to omit this if not possible: */
223 xa_net_wm_action_resize,
225 int nelements = sizeof(allowed_actions) / sizeof(Atom);
226 /* Omit resize element if resizing not possible: */
227 if (c->max_width && c->max_width == c->min_width
228 && c->max_height && c->max_height == c->min_height)
229 nelements--;
230 XChangeProperty(dpy, c->window, xa_net_wm_allowed_actions,
231 XA_ATOM, 32, PropModeReplace,
232 (unsigned char *)&allowed_actions,
233 nelements);
236 void ewmh_deinit_client(Client *c) {
237 XDeleteProperty(dpy, c->window, xa_net_wm_allowed_actions);
240 void ewmh_withdraw_client(Client *c) {
241 #ifdef VWM
242 XDeleteProperty(dpy, c->window, xa_net_wm_desktop);
243 #endif
244 XDeleteProperty(dpy, c->window, xa_net_wm_state);
247 void ewmh_select_client(Client *c) {
248 clients_tab_order = list_to_head(clients_tab_order, c);
251 void ewmh_set_net_client_list(ScreenInfo *s) {
252 Window *windows = alloc_window_array();
253 struct list *iter;
254 int i = 0;
255 for (iter = clients_mapping_order; iter; iter = iter->next) {
256 Client *c = iter->data;
257 if (c->screen == s) {
258 windows[i++] = c->window;
261 XChangeProperty(dpy, s->root, xa_net_client_list,
262 XA_WINDOW, 32, PropModeReplace,
263 (unsigned char *)windows, i);
266 void ewmh_set_net_client_list_stacking(ScreenInfo *s) {
267 Window *windows = alloc_window_array();
268 struct list *iter;
269 int i = 0;
270 for (iter = clients_stacking_order; iter; iter = iter->next) {
271 Client *c = iter->data;
272 if (c->screen == s) {
273 windows[i++] = c->window;
276 XChangeProperty(dpy, s->root, xa_net_client_list_stacking,
277 XA_WINDOW, 32, PropModeReplace,
278 (unsigned char *)windows, i);
281 #ifdef VWM
282 void ewmh_set_net_current_desktop(ScreenInfo *s) {
283 unsigned long vdesk = s->vdesk;
284 XChangeProperty(dpy, s->root, xa_net_current_desktop,
285 XA_CARDINAL, 32, PropModeReplace,
286 (unsigned char *)&vdesk, 1);
288 #endif
290 void ewmh_set_net_active_window(Client *c) {
291 int i;
292 for (i = 0; i < num_screens; i++) {
293 Window w;
294 if (c && i == c->screen->screen) {
295 w = c->window;
296 } else {
297 w = None;
299 XChangeProperty(dpy, screens[i].root, xa_net_active_window,
300 XA_WINDOW, 32, PropModeReplace,
301 (unsigned char *)&w, 1);
305 #ifdef VWM
306 void ewmh_set_net_wm_desktop(Client *c) {
307 XChangeProperty(dpy, c->window, xa_net_wm_desktop,
308 XA_CARDINAL, 32, PropModeReplace,
309 (unsigned char *)&c->vdesk, 1);
311 #endif
313 void ewmh_set_net_wm_state(Client *c) {
314 Atom state[3];
315 int i = 0;
316 if (c->oldh)
317 state[i++] = xa_net_wm_state_maximized_vert;
318 if (c->oldw)
319 state[i++] = xa_net_wm_state_maximized_horz;
320 if (c->oldh && c->oldw)
321 state[i++] = xa_net_wm_state_fullscreen;
322 XChangeProperty(dpy, c->window, xa_net_wm_state,
323 XA_ATOM, 32, PropModeReplace,
324 (unsigned char *)&state, i);
327 void ewmh_set_net_frame_extents(Window w) {
328 unsigned long extents[4];
329 extents[0] = extents[1] = extents[2] = extents[3] = opt_bw;
330 XChangeProperty(dpy, w, xa_net_frame_extents,
331 XA_CARDINAL, 32, PropModeReplace,
332 (unsigned char *)&extents, 4);
335 static Window *alloc_window_array(void) {
336 struct list *iter;
337 unsigned int count = 0;
338 for (iter = clients_mapping_order; iter; iter = iter->next) {
339 count++;
341 if (count == 0) count++;
342 /* Round up to next block of 128 */
343 count = (count + 127) & ~127;
344 window_array = realloc(window_array, count * sizeof(Window));
345 return window_array;