client: disallow client border change when fullscreen
[awesome.git] / property.c
blob4203704762af6664c26318a70d7ec9c7ad0ae5c6
1 /*
2 * property.c - property handlers
4 * Copyright © 2008-2009 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 "wibox.h"
29 #include "window.h"
30 #include "luaa.h"
31 #include "common/atoms.h"
32 #include "common/xutil.h"
34 void
35 property_update_wm_transient_for(client_t *c, xcb_get_property_reply_t *reply)
37 xcb_window_t trans;
39 if(reply)
41 if(!xcb_get_wm_transient_for_from_reply(&trans, reply))
42 return;
44 else
46 if(!xcb_get_wm_transient_for_reply(globalconf.connection,
47 xcb_get_wm_transient_for_unchecked(globalconf.connection,
48 c->window),
49 &trans, NULL))
50 return;
53 luaA_object_push(globalconf.L, c);
54 client_set_type(globalconf.L, -1, WINDOW_TYPE_DIALOG);
55 client_set_above(globalconf.L, -1, false);
56 client_set_transient_for(globalconf.L, -1, client_getbywin(trans));
57 lua_pop(globalconf.L, 1);
60 static int
61 property_handle_wm_transient_for(void *data,
62 xcb_connection_t *connection,
63 uint8_t state,
64 xcb_window_t window,
65 xcb_atom_t name,
66 xcb_get_property_reply_t *reply)
68 client_t *c = client_getbywin(window);
70 if(c)
71 property_update_wm_transient_for(c, reply);
73 return 0;
76 void
77 property_update_wm_client_machine(client_t *c)
79 ssize_t slen;
80 char *value;
82 if(!xutil_text_prop_get(globalconf.connection, c->window,
83 WM_CLIENT_MACHINE, &value, &slen))
84 return;
86 luaA_object_push(globalconf.L, c);
87 client_set_machine(globalconf.L, -1, value);
88 lua_pop(globalconf.L, 1);
91 static int
92 property_handle_wm_client_machine(void *data,
93 xcb_connection_t *connection,
94 uint8_t state,
95 xcb_window_t window,
96 xcb_atom_t name,
97 xcb_get_property_reply_t *reply)
99 client_t *c = client_getbywin(window);
101 if(c)
102 property_update_wm_client_machine(c);
104 return 0;
107 void
108 property_update_wm_window_role(client_t *c)
110 ssize_t slen;
111 char *value;
113 if(!xutil_text_prop_get(globalconf.connection, c->window,
114 WM_WINDOW_ROLE, &value, &slen))
115 return;
117 luaA_object_push(globalconf.L, c);
118 client_set_role(globalconf.L, -1, value);
119 lua_pop(globalconf.L, 1);
122 static int
123 property_handle_wm_window_role(void *data,
124 xcb_connection_t *connection,
125 uint8_t state,
126 xcb_window_t window,
127 xcb_atom_t name,
128 xcb_get_property_reply_t *reply)
130 client_t *c = client_getbywin(window);
132 if(c)
133 property_update_wm_window_role(c);
135 return 0;
138 /** Update leader hint of a client.
139 * \param c The client.
140 * \param reply (Optional) An existing reply.
142 void
143 property_update_wm_client_leader(client_t *c, xcb_get_property_reply_t *reply)
145 xcb_get_property_cookie_t client_leader_q;
146 void *data;
147 bool no_reply = !reply;
149 if(no_reply)
151 client_leader_q = xcb_get_property_unchecked(globalconf.connection, false, c->window,
152 WM_CLIENT_LEADER, WINDOW, 0, 32);
154 reply = xcb_get_property_reply(globalconf.connection, client_leader_q, NULL);
157 if(reply && reply->value_len && (data = xcb_get_property_value(reply)))
158 c->leader_window = *(xcb_window_t *) data;
160 /* Only free when we created a reply ourselves. */
161 if(no_reply)
162 p_delete(&reply);
165 static int
166 property_handle_wm_client_leader(void *data,
167 xcb_connection_t *connection,
168 uint8_t state,
169 xcb_window_t window,
170 xcb_atom_t name,
171 xcb_get_property_reply_t *reply)
173 client_t *c = client_getbywin(window);
175 if(c)
176 property_update_wm_client_leader(c, reply);
178 return 0;
181 /** Update the size hints of a client.
182 * \param c The client.
183 * \param reply (Optional) An existing reply.
185 void
186 property_update_wm_normal_hints(client_t *c, xcb_get_property_reply_t *reply)
188 if(reply)
190 if(!xcb_get_wm_size_hints_from_reply(&c->size_hints, reply))
191 return;
193 else
195 if(!xcb_get_wm_normal_hints_reply(globalconf.connection,
196 xcb_get_wm_normal_hints_unchecked(globalconf.connection,
197 c->window),
198 &c->size_hints, NULL))
199 return;
203 static int
204 property_handle_wm_normal_hints(void *data,
205 xcb_connection_t *connection,
206 uint8_t state,
207 xcb_window_t window,
208 xcb_atom_t name,
209 xcb_get_property_reply_t *reply)
211 client_t *c = client_getbywin(window);
213 if(c)
214 property_update_wm_normal_hints(c, reply);
216 return 0;
219 /** Update the WM hints of a client.
220 * \param c The client.
221 * \param reply (Optional) An existing reply.
223 void
224 property_update_wm_hints(client_t *c, xcb_get_property_reply_t *reply)
226 xcb_wm_hints_t wmh;
228 if(reply)
230 if(!xcb_get_wm_hints_from_reply(&wmh, reply))
231 return;
233 else
235 if(!xcb_get_wm_hints_reply(globalconf.connection,
236 xcb_get_wm_hints_unchecked(globalconf.connection, c->window),
237 &wmh, NULL))
238 return;
241 luaA_object_push(globalconf.L, c);
242 client_set_urgent(globalconf.L, -1, xcb_wm_hints_get_urgency(&wmh));
243 if(wmh.flags & XCB_WM_HINT_STATE &&
244 wmh.initial_state == XCB_WM_STATE_WITHDRAWN)
245 client_set_border_width(globalconf.L, -1, 0);
247 if(wmh.flags & XCB_WM_HINT_INPUT)
248 c->nofocus = !wmh.input;
250 if(wmh.flags & XCB_WM_HINT_WINDOW_GROUP)
251 client_set_group_window(globalconf.L, -1, wmh.window_group);
254 static int
255 property_handle_wm_hints(void *data,
256 xcb_connection_t *connection,
257 uint8_t state,
258 xcb_window_t window,
259 xcb_atom_t name,
260 xcb_get_property_reply_t *reply)
262 client_t *c = client_getbywin(window);
264 if(c)
265 property_update_wm_hints(c, reply);
267 return 0;
270 /** Update client name attribute with its new title.
271 * \param c The client.
273 void
274 property_update_wm_name(client_t *c)
276 char *name;
277 ssize_t len;
279 if(!xutil_text_prop_get(globalconf.connection, c->window, _NET_WM_NAME, &name, &len))
280 if(!xutil_text_prop_get(globalconf.connection, c->window, WM_NAME, &name, &len))
281 return;
283 luaA_object_push(globalconf.L, c);
284 client_set_name(globalconf.L, -1, name);
285 lua_pop(globalconf.L, 1);
288 /** Update WM_CLASS of a client.
289 * \param c The client.
290 * \param reply The reply to get property request, or NULL if none.
292 void
293 property_update_wm_class(client_t *c, xcb_get_property_reply_t *reply)
295 xcb_get_wm_class_reply_t hint;
297 if(reply)
299 if(!xcb_get_wm_class_from_reply(&hint, reply))
300 return;
302 else
304 if(!xcb_get_wm_class_reply(globalconf.connection,
305 xcb_get_wm_class_unchecked(globalconf.connection, c->window),
306 &hint, NULL))
307 return;
310 luaA_object_push(globalconf.L, c);
311 client_set_class_instance(globalconf.L, -1, hint.instance_name, hint.class_name);
312 lua_pop(globalconf.L, 1);
314 /* only delete reply if we get it ourselves */
315 if(!reply)
316 xcb_get_wm_class_reply_wipe(&hint);
319 /** Update client icon name attribute with its new title.
320 * \param c The client.
322 void
323 property_update_wm_icon_name(client_t *c)
325 char *name;
326 ssize_t len;
328 if(!xutil_text_prop_get(globalconf.connection, c->window, _NET_WM_ICON_NAME, &name, &len))
329 if(!xutil_text_prop_get(globalconf.connection, c->window, WM_ICON_NAME, &name, &len))
330 return;
332 luaA_object_push(globalconf.L, c);
333 client_set_icon_name(globalconf.L, -1, name);
334 lua_pop(globalconf.L, 1);
337 static int
338 property_handle_wm_name(void *data,
339 xcb_connection_t *connection,
340 uint8_t state,
341 xcb_window_t window,
342 xcb_atom_t name,
343 xcb_get_property_reply_t *reply)
345 client_t *c = client_getbywin(window);
347 if(c)
348 property_update_wm_name(c);
350 return 0;
353 static int
354 property_handle_wm_icon_name(void *data,
355 xcb_connection_t *connection,
356 uint8_t state,
357 xcb_window_t window,
358 xcb_atom_t name,
359 xcb_get_property_reply_t *reply)
361 client_t *c = client_getbywin(window);
363 if(c)
364 property_update_wm_icon_name(c);
366 return 0;
369 static int
370 property_handle_wm_class(void *data,
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 client_t *c = client_getbywin(window);
379 if(c)
380 property_update_wm_class(c, reply);
382 return 0;
385 static int
386 property_handle_net_wm_strut_partial(void *data,
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 client_t *c = client_getbywin(window);
395 if(c)
396 ewmh_process_client_strut(c, reply);
398 return 0;
401 void
402 property_update_net_wm_icon(client_t *c,
403 xcb_get_property_reply_t *reply)
405 luaA_object_push(globalconf.L, c);
407 if(reply)
409 if(ewmh_window_icon_from_reply(reply))
411 client_set_icon(globalconf.L, -2, -1);
412 /* remove icon */
413 lua_pop(globalconf.L, 1);
416 else if(ewmh_window_icon_get_reply(ewmh_window_icon_get_unchecked(c->window)))
418 client_set_icon(globalconf.L, -2, -1);
419 /* remove icon */
420 lua_pop(globalconf.L, 1);
423 lua_pop(globalconf.L, 1);
426 static int
427 property_handle_net_wm_icon(void *data,
428 xcb_connection_t *connection,
429 uint8_t state,
430 xcb_window_t window,
431 xcb_atom_t name,
432 xcb_get_property_reply_t *reply)
434 client_t *c = client_getbywin(window);
436 if(c)
437 property_update_net_wm_icon(c, reply);
439 return 0;
442 void
443 property_update_net_wm_pid(client_t *c,
444 xcb_get_property_reply_t *reply)
446 bool no_reply = !reply;
448 if(no_reply)
450 xcb_get_property_cookie_t prop_c =
451 xcb_get_property_unchecked(globalconf.connection, false, c->window, _NET_WM_PID, CARDINAL, 0L, 1L);
452 reply = xcb_get_property_reply(globalconf.connection, prop_c, NULL);
455 if(reply && reply->value_len)
457 uint32_t *rdata = xcb_get_property_value(reply);
458 if(rdata)
460 luaA_object_push(globalconf.L, c);
461 client_set_pid(globalconf.L, -1, *rdata);
462 lua_pop(globalconf.L, 1);
466 if(no_reply)
467 p_delete(&reply);
470 static int
471 property_handle_net_wm_pid(void *data,
472 xcb_connection_t *connection,
473 uint8_t state,
474 xcb_window_t window,
475 xcb_atom_t name,
476 xcb_get_property_reply_t *reply)
478 client_t *c = client_getbywin(window);
480 if(c)
481 property_update_net_wm_pid(c, reply);
483 return 0;
486 /** Update the list of supported protocols for a client.
487 * \param c The client.
489 void
490 property_update_wm_protocols(client_t *c)
492 xcb_get_wm_protocols_reply_t protocols;
494 /* If this fails for any reason, we still got the old value */
495 if(xcb_get_wm_protocols_reply(globalconf.connection,
496 xcb_get_wm_protocols_unchecked(globalconf.connection,
497 c->window, WM_PROTOCOLS),
498 &protocols, NULL))
500 xcb_get_wm_protocols_reply_wipe(&c->protocols);
501 memcpy(&c->protocols, &protocols, sizeof(protocols));
505 /** The property notify event handler.
506 * \param data currently unused.
507 * \param connection currently unusued.
508 * \param state currently unused.
509 * \param window The window to obtain update protocols from.
510 * \param name currently unused.
511 * \param reply currently unused.
513 static int
514 property_handle_wm_protocols(void *data,
515 xcb_connection_t *connection,
516 uint8_t state,
517 xcb_window_t window,
518 xcb_atom_t name,
519 xcb_get_property_reply_t *reply)
521 client_t *c = client_getbywin(window);
523 if(c)
524 property_update_wm_protocols(c);
526 return 0;
529 /** The property notify event handler.
530 * \param data currently unused.
531 * \param connection The connection to the X server.
532 * \param state currently unused
533 * \param window The window to obtain update the property with.
534 * \param name The protocol atom, currently unused.
535 * \param reply (Optional) An existing reply.
537 static int
538 property_handle_xembed_info(void *data __attribute__ ((unused)),
539 xcb_connection_t *connection,
540 uint8_t state,
541 xcb_window_t window,
542 xcb_atom_t name,
543 xcb_get_property_reply_t *reply)
545 xembed_window_t *emwin = xembed_getbywin(&globalconf.embedded, window);
547 if(emwin)
548 xembed_property_update(connection, emwin, reply);
550 return 0;
553 static int
554 property_handle_xrootpmap_id(void *data __attribute__ ((unused)),
555 xcb_connection_t *connection,
556 uint8_t state,
557 xcb_window_t window,
558 xcb_atom_t name,
559 xcb_get_property_reply_t *reply)
561 if(globalconf.xinerama_is_active)
562 foreach(w, globalconf.wiboxes)
563 (*w)->need_update = true;
564 else
566 int screen = xutil_root2screen(connection, window);
567 foreach(w, globalconf.wiboxes)
568 if(screen == screen_array_indexof(&globalconf.screens, (*w)->screen))
569 (*w)->need_update = true;
572 return 0;
575 static int
576 property_handle_net_wm_opacity(void *data __attribute__ ((unused)),
577 xcb_connection_t *connection,
578 uint8_t state,
579 xcb_window_t window,
580 xcb_atom_t name,
581 xcb_get_property_reply_t *reply)
583 wibox_t *wibox = wibox_getbywin(window);
585 if(wibox)
587 luaA_object_push(globalconf.L, wibox);
588 wibox_set_opacity(globalconf.L, -1, window_opacity_get_from_reply(reply));
589 lua_pop(globalconf.L, -1);
591 else
593 client_t *c = client_getbywin(window);
594 if(c)
596 luaA_object_push(globalconf.L, c);
597 client_set_opacity(globalconf.L, -1, window_opacity_get_from_reply(reply));
598 lua_pop(globalconf.L, 1);
602 return 0;
605 void a_xcb_set_property_handlers(void)
607 /* init */
608 xcb_property_handlers_init(&globalconf.prophs, &globalconf.evenths);
610 /* Xembed stuff */
611 xcb_property_set_handler(&globalconf.prophs, _XEMBED_INFO, UINT_MAX,
612 property_handle_xembed_info, NULL);
614 /* ICCCM stuff */
615 xcb_property_set_handler(&globalconf.prophs, WM_TRANSIENT_FOR, UINT_MAX,
616 property_handle_wm_transient_for, NULL);
617 xcb_property_set_handler(&globalconf.prophs, WM_CLIENT_LEADER, UINT_MAX,
618 property_handle_wm_client_leader, NULL);
619 xcb_property_set_handler(&globalconf.prophs, WM_NORMAL_HINTS, UINT_MAX,
620 property_handle_wm_normal_hints, NULL);
621 xcb_property_set_handler(&globalconf.prophs, WM_HINTS, UINT_MAX,
622 property_handle_wm_hints, NULL);
623 xcb_property_set_handler(&globalconf.prophs, WM_NAME, UINT_MAX,
624 property_handle_wm_name, NULL);
625 xcb_property_set_handler(&globalconf.prophs, WM_ICON_NAME, UINT_MAX,
626 property_handle_wm_icon_name, NULL);
627 xcb_property_set_handler(&globalconf.prophs, WM_CLASS, UINT_MAX,
628 property_handle_wm_class, NULL);
629 xcb_property_set_handler(&globalconf.prophs, WM_PROTOCOLS, UINT_MAX,
630 property_handle_wm_protocols, NULL);
631 xcb_property_set_handler(&globalconf.prophs, WM_CLIENT_MACHINE, UINT_MAX,
632 property_handle_wm_client_machine, NULL);
633 xcb_property_set_handler(&globalconf.prophs, WM_WINDOW_ROLE, UINT_MAX,
634 property_handle_wm_window_role, NULL);
636 /* EWMH stuff */
637 xcb_property_set_handler(&globalconf.prophs, _NET_WM_NAME, UINT_MAX,
638 property_handle_wm_name, NULL);
639 xcb_property_set_handler(&globalconf.prophs, _NET_WM_ICON_NAME, UINT_MAX,
640 property_handle_wm_icon_name, NULL);
641 xcb_property_set_handler(&globalconf.prophs, _NET_WM_STRUT_PARTIAL, UINT_MAX,
642 property_handle_net_wm_strut_partial, NULL);
643 xcb_property_set_handler(&globalconf.prophs, _NET_WM_ICON, UINT_MAX,
644 property_handle_net_wm_icon, NULL);
645 xcb_property_set_handler(&globalconf.prophs, _NET_WM_PID, UINT_MAX,
646 property_handle_net_wm_pid, NULL);
647 xcb_property_set_handler(&globalconf.prophs, _NET_WM_WINDOW_OPACITY, 1,
648 property_handle_net_wm_opacity, NULL);
650 /* background change */
651 xcb_property_set_handler(&globalconf.prophs, _XROOTPMAP_ID, 1,
652 property_handle_xrootpmap_id, NULL);
655 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80