[progressbar] check_settings should be static
[awesome.git] / ewmh.c
blobc186100d1bbf60e2627b4599e201c153a01d7744
1 /*
2 * ewmh.c - EWMH support functions
4 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <X11/Xatom.h>
23 #include <X11/Xmd.h>
25 #include "ewmh.h"
26 #include "tag.h"
27 #include "focus.h"
28 #include "screen.h"
29 #include "client.h"
30 #include "widget.h"
32 extern AwesomeConf globalconf;
34 static Atom net_supported;
35 static Atom net_client_list;
36 static Atom net_number_of_desktops;
37 static Atom net_current_desktop;
38 static Atom net_desktop_names;
39 static Atom net_active_window;
41 static Atom net_close_window;
43 static Atom net_wm_name;
44 static Atom net_wm_icon_name;
45 static Atom net_wm_window_type;
46 static Atom net_wm_window_type_normal;
47 static Atom net_wm_window_type_dock;
48 static Atom net_wm_window_type_splash;
49 static Atom net_wm_window_type_dialog;
50 static Atom net_wm_icon;
51 static Atom net_wm_state;
52 static Atom net_wm_state_sticky;
53 static Atom net_wm_state_skip_taskbar;
54 static Atom net_wm_state_fullscreen;
56 static Atom utf8_string;
58 typedef struct
60 const char *name;
61 Atom *atom;
62 } AtomItem;
64 static AtomItem AtomNames[] =
66 { "_NET_SUPPORTED", &net_supported },
67 { "_NET_CLIENT_LIST", &net_client_list },
68 { "_NET_NUMBER_OF_DESKTOPS", &net_number_of_desktops },
69 { "_NET_CURRENT_DESKTOP", &net_current_desktop },
70 { "_NET_DESKTOP_NAMES", &net_desktop_names },
71 { "_NET_ACTIVE_WINDOW", &net_active_window },
73 { "_NET_CLOSE_WINDOW", &net_close_window },
75 { "_NET_WM_NAME", &net_wm_name },
76 { "_NET_WM_ICON_NAME", &net_wm_icon_name },
77 { "_NET_WM_WINDOW_TYPE", &net_wm_window_type },
78 { "_NET_WM_WINDOW_TYPE_NORMAL", &net_wm_window_type_normal },
79 { "_NET_WM_WINDOW_TYPE_DOCK", &net_wm_window_type_dock },
80 { "_NET_WM_WINDOW_TYPE_SPLASH", &net_wm_window_type_splash },
81 { "_NET_WM_WINDOW_TYPE_DIALOG", &net_wm_window_type_dialog },
82 { "_NET_WM_ICON", &net_wm_icon },
83 { "_NET_WM_STATE", &net_wm_state },
84 { "_NET_WM_STATE_STICKY", &net_wm_state_sticky },
85 { "_NET_WM_STATE_SKIP_TASKBAR", &net_wm_state_skip_taskbar },
86 { "_NET_WM_STATE_FULLSCREEN", &net_wm_state_fullscreen },
88 { "UTF8_STRING", &utf8_string },
91 #define ATOM_NUMBER (sizeof(AtomNames)/sizeof(AtomItem))
93 #define _NET_WM_STATE_REMOVE 0
94 #define _NET_WM_STATE_ADD 1
95 #define _NET_WM_STATE_TOGGLE 2
97 void
98 ewmh_init_atoms(void)
100 unsigned int i;
101 char *names[ATOM_NUMBER];
102 Atom atoms[ATOM_NUMBER];
104 for(i = 0; i < ATOM_NUMBER; i++)
105 names[i] = (char *) AtomNames[i].name;
106 XInternAtoms(globalconf.display, names, ATOM_NUMBER, False, atoms);
107 for(i = 0; i < ATOM_NUMBER; i++)
108 *AtomNames[i].atom = atoms[i];
111 void
112 ewmh_set_supported_hints(int phys_screen)
114 Atom atom[ATOM_NUMBER];
115 int i = 0;
117 atom[i++] = net_supported;
118 atom[i++] = net_client_list;
119 atom[i++] = net_number_of_desktops;
120 atom[i++] = net_current_desktop;
121 atom[i++] = net_desktop_names;
122 atom[i++] = net_active_window;
124 atom[i++] = net_close_window;
126 atom[i++] = net_wm_name;
127 atom[i++] = net_wm_icon_name;
128 atom[i++] = net_wm_window_type;
129 atom[i++] = net_wm_window_type_normal;
130 atom[i++] = net_wm_window_type_dock;
131 atom[i++] = net_wm_window_type_splash;
132 atom[i++] = net_wm_window_type_dialog;
133 atom[i++] = net_wm_icon;
134 atom[i++] = net_wm_state;
135 atom[i++] = net_wm_state_sticky;
136 atom[i++] = net_wm_state_skip_taskbar;
137 atom[i++] = net_wm_state_fullscreen;
139 XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen),
140 net_supported, XA_ATOM, 32,
141 PropModeReplace, (unsigned char *) atom, i);
144 void
145 ewmh_update_net_client_list(int phys_screen)
147 Window *wins;
148 Client *c;
149 int n = 0;
151 for(c = globalconf.clients; c; c = c->next)
152 n++;
154 wins = p_new(Window, n);
156 for(n = 0, c = globalconf.clients; c; c = c->next, n++)
157 if(c->phys_screen == phys_screen)
158 wins[n] = c->win;
160 XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen),
161 net_client_list, XA_WINDOW, 32, PropModeReplace, (unsigned char *) wins, n);
163 p_delete(&wins);
166 void
167 ewmh_update_net_numbers_of_desktop(int phys_screen)
169 CARD32 count = 0;
170 Tag *tag;
172 for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next)
173 count++;
175 XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen),
176 net_number_of_desktops, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &count, 1);
179 void
180 ewmh_update_net_current_desktop(int phys_screen)
182 CARD32 count = 0;
183 Tag *tag, **curtags = tags_get_current(phys_screen);
185 for(tag = globalconf.screens[phys_screen].tags; tag != curtags[0]; tag = tag->next)
186 count++;
188 XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen),
189 net_current_desktop, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &count, 1);
191 p_delete(&curtags);
194 void
195 ewmh_update_net_desktop_names(int phys_screen)
197 char buf[1024], *pos;
198 ssize_t len, curr_size;
199 Tag *tag;
201 pos = buf;
202 len = 0;
203 for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next)
205 curr_size = a_strlen(tag->name);
206 a_strcpy(pos, sizeof(buf), tag->name);
207 pos += curr_size + 1;
208 len += curr_size + 1;
211 XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen),
212 net_desktop_names, utf8_string, 8, PropModeReplace, (unsigned char *) buf, len);
215 void
216 ewmh_update_net_active_window(int phys_screen)
218 Window win;
219 Client *sel = focus_get_current_client(phys_screen);
221 win = sel ? sel->win : None;
223 XChangeProperty(globalconf.display, RootWindow(globalconf.display, phys_screen),
224 net_active_window, XA_WINDOW, 32, PropModeReplace, (unsigned char *) &win, 1);
227 static void
228 ewmh_process_state_atom(Client *c, Atom state, int set)
230 if(state == net_wm_state_sticky)
232 Tag *tag;
233 for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
234 tag_client(c, tag);
236 else if(state == net_wm_state_skip_taskbar)
238 if(set == _NET_WM_STATE_REMOVE)
240 c->skiptb = False;
241 c->skip = False;
243 else if(set == _NET_WM_STATE_ADD)
245 c->skiptb = True;
246 c->skip = True;
249 else if(state == net_wm_state_fullscreen)
251 area_t geometry = c->geometry;
252 if(set == _NET_WM_STATE_REMOVE)
254 /* restore geometry */
255 geometry = c->m_geometry;
256 /* restore borders and titlebar */
257 c->titlebar.position = c->titlebar.dposition;
258 c->border = c->oldborder;
259 c->ismax = False;
260 client_setfloating(c, c->wasfloating);
262 else if(set == _NET_WM_STATE_ADD)
264 geometry = screen_get_area(c->screen, NULL, &globalconf.screens[c->screen].padding);
265 /* save geometry */
266 c->m_geometry = c->geometry;
267 c->wasfloating = c->isfloating;
268 /* disable titlebar and borders */
269 c->titlebar.position = Off;
270 c->oldborder = c->border;
271 c->border = 0;
272 c->ismax = True;
273 client_setfloating(c, True);
275 widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
276 client_resize(c, geometry, False);
277 XRaiseWindow(globalconf.display, c->win);
281 static void
282 ewmh_process_window_type_atom(Client *c, Atom state)
284 if(state == net_wm_window_type_normal)
286 /* do nothing. this is REALLY IMPORTANT */
288 else if(state == net_wm_window_type_dock
289 || state == net_wm_window_type_splash)
291 c->border = 0;
292 c->skip = True;
293 c->isfixed = True;
294 c->titlebar.position = Off;
295 client_setfloating(c, True);
297 else if (state == net_wm_window_type_dialog)
298 client_setfloating(c, True);
300 void
301 ewmh_process_client_message(XClientMessageEvent *ev)
303 Client *c;
304 int screen;
306 if(ev->message_type == net_current_desktop)
307 for(screen = 0; screen < ScreenCount(globalconf.display); screen++)
308 if(ev->window == RootWindow(globalconf.display, screen))
309 tag_view_only_byindex(screen, ev->data.l[0]);
311 if(ev->message_type == net_close_window)
313 if((c = client_get_bywin(globalconf.clients, ev->window)))
314 client_kill(c);
316 else if(ev->message_type == net_wm_state)
318 if((c = client_get_bywin(globalconf.clients, ev->window)))
320 ewmh_process_state_atom(c, (Atom) ev->data.l[1], ev->data.l[0]);
321 if(ev->data.l[2])
322 ewmh_process_state_atom(c, (Atom) ev->data.l[2], ev->data.l[0]);
327 void
328 ewmh_check_client_hints(Client *c)
330 int format;
331 Atom real, *state;
332 unsigned char *data = NULL;
333 unsigned long i, n, extra;
335 if(XGetWindowProperty(globalconf.display, c->win, net_wm_state, 0L, LONG_MAX, False,
336 XA_ATOM, &real, &format, &n, &extra,
337 (unsigned char **) &data) == Success && data)
339 state = (Atom *) data;
340 for(i = 0; i < n; i++)
341 ewmh_process_state_atom(c, state[i], _NET_WM_STATE_ADD);
343 XFree(data);
346 if(XGetWindowProperty(globalconf.display, c->win, net_wm_window_type, 0L, LONG_MAX, False,
347 XA_ATOM, &real, &format, &n, &extra,
348 (unsigned char **) &data) == Success && data)
350 state = (Atom *) data;
351 for(i = 0; i < n; i++)
352 ewmh_process_window_type_atom(c, state[i]);
354 XFree(data);
358 NetWMIcon *
359 ewmh_get_window_icon(Window w)
361 double alpha;
362 NetWMIcon *icon;
363 Atom type;
364 int format, size, i;
365 unsigned long items, rest, *data;
366 unsigned char *imgdata, *wdata;
368 if(XGetWindowProperty(globalconf.display, w,
369 net_wm_icon, 0L, LONG_MAX, False, XA_CARDINAL, &type, &format,
370 &items, &rest, &wdata) != Success
371 || !wdata)
372 return NULL;
374 if(type != XA_CARDINAL || format != 32 || items < 2)
376 XFree(wdata);
377 return NULL;
380 icon = p_new(NetWMIcon, 1);
382 data = (unsigned long *) wdata;
384 icon->width = data[0];
385 icon->height = data[1];
386 size = icon->width * icon->height;
388 if(!size)
390 p_delete(&icon);
391 XFree(wdata);
392 return NULL;
395 icon->image = p_new(unsigned char, size * 4);
396 for(imgdata = icon->image, i = 2; i < size + 2; i++, imgdata += 4)
398 imgdata[3] = (data[i] >> 24) & 0xff; /* A */
399 alpha = imgdata[3] / 255.0;
400 imgdata[2] = ((data[i] >> 16) & 0xff) * alpha; /* R */
401 imgdata[1] = ((data[i] >> 8) & 0xff) * alpha; /* G */
402 imgdata[0] = (data[i] & 0xff) * alpha; /* B */
405 XFree(wdata);
407 return icon;
410 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80