naughty: add vertical margin
[awesome.git] / property.c
blob7b0812f4714fb0110f834d2f19935092dfecdaf3
1 /*
2 * property.c - property handlers
4 * Copyright © 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 <xcb/xcb_atom.h>
24 #include "screen.h"
25 #include "property.h"
26 #include "client.h"
27 #include "ewmh.h"
28 #include "common/atoms.h"
29 #include "common/xutil.h"
31 void
32 property_update_wm_transient_for(client_t *c, xcb_get_property_reply_t *reply)
34 xcb_window_t trans;
36 if(reply)
38 if(!xcb_get_wm_transient_for_from_reply(&trans, reply))
39 return;
41 else
43 if(!xcb_get_wm_transient_for_reply(globalconf.connection,
44 xcb_get_wm_transient_for_unchecked(globalconf.connection,
45 c->win),
46 &trans, NULL))
47 return;
50 c->type = WINDOW_TYPE_DIALOG;
51 c->transient_for = client_getbywin(trans);
52 client_setabove(c, false);
55 static int
56 property_handle_wm_transient_for(void *data,
57 xcb_connection_t *connection,
58 uint8_t state,
59 xcb_window_t window,
60 xcb_atom_t name,
61 xcb_get_property_reply_t *reply)
63 client_t *c = client_getbywin(window);
65 if(c)
66 property_update_wm_transient_for(c, reply);
68 return 0;
72 /** Update leader hint of a client.
73 * \param c The client.
74 * \param reply (Optional) An existing reply.
76 void
77 property_update_wm_client_leader(client_t *c, xcb_get_property_reply_t *reply)
79 xcb_get_property_cookie_t client_leader_q;
80 void *data;
81 bool no_reply = !reply;
83 if(no_reply)
85 client_leader_q = xcb_get_property_unchecked(globalconf.connection, false, c->win,
86 WM_CLIENT_LEADER, WINDOW, 0, 32);
88 reply = xcb_get_property_reply(globalconf.connection, client_leader_q, NULL);
91 if(reply && reply->value_len && (data = xcb_get_property_value(reply)))
92 c->leader_win = *(xcb_window_t *) data;
94 /* Only free when we created a reply ourselves. */
95 if(no_reply)
96 p_delete(&reply);
99 static int
100 property_handle_wm_client_leader(void *data,
101 xcb_connection_t *connection,
102 uint8_t state,
103 xcb_window_t window,
104 xcb_atom_t name,
105 xcb_get_property_reply_t *reply)
107 client_t *c = client_getbywin(window);
109 if(c)
110 property_update_wm_client_leader(c, reply);
112 return 0;
115 /** Update the size hints of a client.
116 * \param c The client.
118 void
119 property_update_wm_normal_hints(client_t *c, xcb_get_property_reply_t *reply)
121 if(reply)
123 if(!xcb_get_wm_size_hints_from_reply(&c->size_hints, reply))
124 return;
126 else
128 if(!xcb_get_wm_normal_hints_reply(globalconf.connection,
129 xcb_get_wm_normal_hints_unchecked(globalconf.connection,
130 c->win),
131 &c->size_hints, NULL))
132 return;
136 static int
137 property_handle_wm_normal_hints(void *data,
138 xcb_connection_t *connection,
139 uint8_t state,
140 xcb_window_t window,
141 xcb_atom_t name,
142 xcb_get_property_reply_t *reply)
144 client_t *c = client_getbywin(window);
146 if(c)
147 property_update_wm_normal_hints(c, reply);
149 return 0;
152 /** Update the WM hints of a client.
153 * \param c The client.
155 void
156 property_update_wm_hints(client_t *c, xcb_get_property_reply_t *reply)
158 xcb_wm_hints_t wmh;
160 if(reply)
162 if(!xcb_get_wm_hints_from_reply(&wmh, reply))
163 return;
165 else
167 if(!xcb_get_wm_hints_reply(globalconf.connection,
168 xcb_get_wm_hints_unchecked(globalconf.connection, c->win),
169 &wmh, NULL))
170 return;
173 bool isurgent = xcb_wm_hints_get_urgency(&wmh);
174 client_seturgent(c, isurgent);
175 if(wmh.flags & XCB_WM_HINT_STATE &&
176 wmh.initial_state == XCB_WM_STATE_WITHDRAWN)
177 client_setborder(c, 0);
179 if(wmh.flags & XCB_WM_HINT_INPUT)
180 c->nofocus = !wmh.input;
182 if(wmh.flags & XCB_WM_HINT_WINDOW_GROUP)
183 c->group_win = wmh.window_group;
186 static int
187 property_handle_wm_hints(void *data,
188 xcb_connection_t *connection,
189 uint8_t state,
190 xcb_window_t window,
191 xcb_atom_t name,
192 xcb_get_property_reply_t *reply)
194 client_t *c = client_getbywin(window);
196 if(c)
197 property_update_wm_hints(c, reply);
199 return 0;
202 /** Update client name attribute with its new title.
203 * \param c The client.
204 * \param Return true if it has been updated.
206 void
207 property_update_wm_name(client_t *c)
209 char *name;
210 ssize_t len;
212 if(!xutil_text_prop_get(globalconf.connection, c->win, _NET_WM_NAME, &name, &len))
213 if(!xutil_text_prop_get(globalconf.connection, c->win, WM_NAME, &name, &len))
214 return;
216 p_delete(&c->name);
218 c->name = name;
220 /* call hook */
221 hooks_property(c, "name");
224 /** Update WM_CLASS of a client.
225 * \param c The client.
226 * \param reply The reply to get property request, or NULL if none.
228 void
229 property_update_wm_class(client_t *c, xcb_get_property_reply_t *reply)
231 xcb_get_wm_class_reply_t hint;
233 if(reply)
235 if(!xcb_get_wm_class_from_reply(&hint, reply))
236 return;
238 else
240 if(!xcb_get_wm_class_reply(globalconf.connection,
241 xcb_get_wm_class_unchecked(globalconf.connection, c->win),
242 &hint, NULL))
243 return;
246 p_delete(&c->instance);
247 p_delete(&c->class);
249 c->instance = a_strdup(hint.instance_name);
250 c->class = a_strdup(hint.class_name);
251 /* only delete reply if we get it ourselves */
252 if(!reply)
253 xcb_get_wm_class_reply_wipe(&hint);
256 /** Update client icon name attribute with its new title.
257 * \param c The client.
258 * \param Return true if it has been updated.
260 void
261 property_update_wm_icon_name(client_t *c)
263 char *name;
264 ssize_t len;
266 if(!xutil_text_prop_get(globalconf.connection, c->win, _NET_WM_ICON_NAME, &name, &len))
267 if(!xutil_text_prop_get(globalconf.connection, c->win, WM_ICON_NAME, &name, &len))
268 return;
270 p_delete(&c->icon_name);
272 c->icon_name = name;
274 /* call hook */
275 hooks_property(c, "icon_name");
278 static int
279 property_handle_wm_name(void *data,
280 xcb_connection_t *connection,
281 uint8_t state,
282 xcb_window_t window,
283 xcb_atom_t name,
284 xcb_get_property_reply_t *reply)
286 client_t *c = client_getbywin(window);
288 if(c)
289 property_update_wm_name(c);
291 return 0;
294 static int
295 property_handle_wm_icon_name(void *data,
296 xcb_connection_t *connection,
297 uint8_t state,
298 xcb_window_t window,
299 xcb_atom_t name,
300 xcb_get_property_reply_t *reply)
302 client_t *c = client_getbywin(window);
304 if(c)
305 property_update_wm_icon_name(c);
307 return 0;
310 static int
311 property_handle_wm_class(void *data,
312 xcb_connection_t *connection,
313 uint8_t state,
314 xcb_window_t window,
315 xcb_atom_t name,
316 xcb_get_property_reply_t *reply)
318 client_t *c = client_getbywin(window);
320 if(c)
321 property_update_wm_class(c, reply);
323 return 0;
326 static int
327 property_handle_net_wm_strut_partial(void *data,
328 xcb_connection_t *connection,
329 uint8_t state,
330 xcb_window_t window,
331 xcb_atom_t name,
332 xcb_get_property_reply_t *reply)
334 client_t *c = client_getbywin(window);
336 if(c)
337 ewmh_process_client_strut(c, reply);
339 return 0;
342 static int
343 property_handle_net_wm_icon(void *data,
344 xcb_connection_t *connection,
345 uint8_t state,
346 xcb_window_t window,
347 xcb_atom_t name,
348 xcb_get_property_reply_t *reply)
350 client_t *c = client_getbywin(window);
352 if(c)
354 image_unref(globalconf.L, c->icon);
355 if(ewmh_window_icon_from_reply(reply))
356 c->icon = image_ref(globalconf.L);
357 /* execute hook */
358 hooks_property(c, "icon");
361 return 0;
364 /** The property notify event handler.
365 * \param data currently unused.
366 * \param connection The connection to the X server.
367 * \param ev The event.
369 static int
370 property_handle_xembed_info(void *data __attribute__ ((unused)),
371 xcb_connection_t *connection,
372 uint8_t state,
373 xcb_window_t window,
374 xcb_atom_t name,
375 xcb_get_property_reply_t *reply)
377 xembed_window_t *emwin = xembed_getbywin(&globalconf.embedded, window);
379 if(emwin)
380 xembed_property_update(connection, emwin, reply);
382 return 0;
385 static int
386 property_handle_xrootpmap_id(void *data __attribute__ ((unused)),
387 xcb_connection_t *connection,
388 uint8_t state,
389 xcb_window_t window,
390 xcb_atom_t name,
391 xcb_get_property_reply_t *reply)
393 if(globalconf.xinerama_is_active)
394 foreach(screen, globalconf.screens)
395 foreach(w, screen->wiboxes)
396 (*w)->need_update = true;
397 else
399 int screen = xutil_root2screen(connection, window);
400 foreach(w, globalconf.screens.tab[screen].wiboxes)
401 (*w)->need_update = true;
404 return 0;
407 void a_xcb_set_property_handlers(void)
409 /* init */
410 xcb_property_handlers_init(&globalconf.prophs, &globalconf.evenths);
412 /* Xembed stuff */
413 xcb_property_set_handler(&globalconf.prophs, _XEMBED_INFO, UINT_MAX,
414 property_handle_xembed_info, NULL);
416 /* ICCCM stuff */
417 xcb_property_set_handler(&globalconf.prophs, WM_TRANSIENT_FOR, UINT_MAX,
418 property_handle_wm_transient_for, NULL);
419 xcb_property_set_handler(&globalconf.prophs, WM_CLIENT_LEADER, UINT_MAX,
420 property_handle_wm_client_leader, NULL);
421 xcb_property_set_handler(&globalconf.prophs, WM_NORMAL_HINTS, UINT_MAX,
422 property_handle_wm_normal_hints, NULL);
423 xcb_property_set_handler(&globalconf.prophs, WM_HINTS, UINT_MAX,
424 property_handle_wm_hints, NULL);
425 xcb_property_set_handler(&globalconf.prophs, WM_NAME, UINT_MAX,
426 property_handle_wm_name, NULL);
427 xcb_property_set_handler(&globalconf.prophs, WM_ICON_NAME, UINT_MAX,
428 property_handle_wm_icon_name, NULL);
429 xcb_property_set_handler(&globalconf.prophs, WM_CLASS, UINT_MAX,
430 property_handle_wm_class, NULL);
432 /* EWMH stuff */
433 xcb_property_set_handler(&globalconf.prophs, _NET_WM_NAME, UINT_MAX,
434 property_handle_wm_name, NULL);
435 xcb_property_set_handler(&globalconf.prophs, _NET_WM_ICON_NAME, UINT_MAX,
436 property_handle_wm_icon_name, NULL);
437 xcb_property_set_handler(&globalconf.prophs, _NET_WM_STRUT_PARTIAL, UINT_MAX,
438 property_handle_net_wm_strut_partial, NULL);
439 xcb_property_set_handler(&globalconf.prophs, _NET_WM_ICON, UINT_MAX,
440 property_handle_net_wm_icon, NULL);
442 /* background change */
443 xcb_property_set_handler(&globalconf.prophs, _XROOTPMAP_ID, 1,
444 property_handle_xrootpmap_id, NULL);
447 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80