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>
31 #include "common/atoms.h"
32 #include "common/xutil.h"
35 property_update_wm_transient_for(client_t
*c
, xcb_get_property_reply_t
*reply
)
41 if(!xcb_get_wm_transient_for_from_reply(&trans
, reply
))
46 if(!xcb_get_wm_transient_for_reply(globalconf
.connection
,
47 xcb_get_wm_transient_for_unchecked(globalconf
.connection
,
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);
61 property_handle_wm_transient_for(void *data
,
62 xcb_connection_t
*connection
,
66 xcb_get_property_reply_t
*reply
)
68 client_t
*c
= client_getbywin(window
);
71 property_update_wm_transient_for(c
, reply
);
77 property_update_wm_client_machine(client_t
*c
)
82 if(!xutil_text_prop_get(globalconf
.connection
, c
->window
,
83 WM_CLIENT_MACHINE
, &value
, &slen
))
86 luaA_object_push(globalconf
.L
, c
);
87 client_set_machine(globalconf
.L
, -1, value
);
88 lua_pop(globalconf
.L
, 1);
92 property_handle_wm_client_machine(void *data
,
93 xcb_connection_t
*connection
,
97 xcb_get_property_reply_t
*reply
)
99 client_t
*c
= client_getbywin(window
);
102 property_update_wm_client_machine(c
);
108 property_update_wm_window_role(client_t
*c
)
113 if(!xutil_text_prop_get(globalconf
.connection
, c
->window
,
114 WM_WINDOW_ROLE
, &value
, &slen
))
117 luaA_object_push(globalconf
.L
, c
);
118 client_set_role(globalconf
.L
, -1, value
);
119 lua_pop(globalconf
.L
, 1);
123 property_handle_wm_window_role(void *data
,
124 xcb_connection_t
*connection
,
128 xcb_get_property_reply_t
*reply
)
130 client_t
*c
= client_getbywin(window
);
133 property_update_wm_window_role(c
);
138 /** Update leader hint of a client.
139 * \param c The client.
140 * \param reply (Optional) An existing reply.
143 property_update_wm_client_leader(client_t
*c
, xcb_get_property_reply_t
*reply
)
145 xcb_get_property_cookie_t client_leader_q
;
147 bool no_reply
= !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. */
166 property_handle_wm_client_leader(void *data
,
167 xcb_connection_t
*connection
,
171 xcb_get_property_reply_t
*reply
)
173 client_t
*c
= client_getbywin(window
);
176 property_update_wm_client_leader(c
, reply
);
181 /** Update the size hints of a client.
182 * \param c The client.
183 * \param reply (Optional) An existing reply.
186 property_update_wm_normal_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
190 if(!xcb_get_wm_size_hints_from_reply(&c
->size_hints
, reply
))
195 if(!xcb_get_wm_normal_hints_reply(globalconf
.connection
,
196 xcb_get_wm_normal_hints_unchecked(globalconf
.connection
,
198 &c
->size_hints
, NULL
))
204 property_handle_wm_normal_hints(void *data
,
205 xcb_connection_t
*connection
,
209 xcb_get_property_reply_t
*reply
)
211 client_t
*c
= client_getbywin(window
);
214 property_update_wm_normal_hints(c
, reply
);
219 /** Update the WM hints of a client.
220 * \param c The client.
221 * \param reply (Optional) An existing reply.
224 property_update_wm_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
230 if(!xcb_get_wm_hints_from_reply(&wmh
, reply
))
235 if(!xcb_get_wm_hints_reply(globalconf
.connection
,
236 xcb_get_wm_hints_unchecked(globalconf
.connection
, c
->window
),
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
);
255 property_handle_wm_hints(void *data
,
256 xcb_connection_t
*connection
,
260 xcb_get_property_reply_t
*reply
)
262 client_t
*c
= client_getbywin(window
);
265 property_update_wm_hints(c
, reply
);
270 /** Update client name attribute with its new title.
271 * \param c The client.
274 property_update_wm_name(client_t
*c
)
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
))
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.
293 property_update_wm_class(client_t
*c
, xcb_get_property_reply_t
*reply
)
295 xcb_get_wm_class_reply_t hint
;
299 if(!xcb_get_wm_class_from_reply(&hint
, reply
))
304 if(!xcb_get_wm_class_reply(globalconf
.connection
,
305 xcb_get_wm_class_unchecked(globalconf
.connection
, c
->window
),
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 */
316 xcb_get_wm_class_reply_wipe(&hint
);
319 /** Update client icon name attribute with its new title.
320 * \param c The client.
323 property_update_wm_icon_name(client_t
*c
)
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
))
332 luaA_object_push(globalconf
.L
, c
);
333 client_set_icon_name(globalconf
.L
, -1, name
);
334 lua_pop(globalconf
.L
, 1);
338 property_handle_wm_name(void *data
,
339 xcb_connection_t
*connection
,
343 xcb_get_property_reply_t
*reply
)
345 client_t
*c
= client_getbywin(window
);
348 property_update_wm_name(c
);
354 property_handle_wm_icon_name(void *data
,
355 xcb_connection_t
*connection
,
359 xcb_get_property_reply_t
*reply
)
361 client_t
*c
= client_getbywin(window
);
364 property_update_wm_icon_name(c
);
370 property_handle_wm_class(void *data
,
371 xcb_connection_t
*connection
,
375 xcb_get_property_reply_t
*reply
)
377 client_t
*c
= client_getbywin(window
);
380 property_update_wm_class(c
, reply
);
386 property_handle_net_wm_strut_partial(void *data
,
387 xcb_connection_t
*connection
,
391 xcb_get_property_reply_t
*reply
)
393 client_t
*c
= client_getbywin(window
);
396 ewmh_process_client_strut(c
, reply
);
402 property_update_net_wm_icon(client_t
*c
,
403 xcb_get_property_reply_t
*reply
)
405 luaA_object_push(globalconf
.L
, c
);
409 if(ewmh_window_icon_from_reply(reply
))
411 client_set_icon(globalconf
.L
, -2, -1);
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);
420 lua_pop(globalconf
.L
, 1);
423 lua_pop(globalconf
.L
, 1);
427 property_handle_net_wm_icon(void *data
,
428 xcb_connection_t
*connection
,
432 xcb_get_property_reply_t
*reply
)
434 client_t
*c
= client_getbywin(window
);
437 property_update_net_wm_icon(c
, reply
);
443 property_update_net_wm_pid(client_t
*c
,
444 xcb_get_property_reply_t
*reply
)
446 bool no_reply
= !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
);
460 luaA_object_push(globalconf
.L
, c
);
461 client_set_pid(globalconf
.L
, -1, *rdata
);
462 lua_pop(globalconf
.L
, 1);
471 property_handle_net_wm_pid(void *data
,
472 xcb_connection_t
*connection
,
476 xcb_get_property_reply_t
*reply
)
478 client_t
*c
= client_getbywin(window
);
481 property_update_net_wm_pid(c
, reply
);
486 /** Update the list of supported protocols for a client.
487 * \param c The client.
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
),
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.
514 property_handle_wm_protocols(void *data
,
515 xcb_connection_t
*connection
,
519 xcb_get_property_reply_t
*reply
)
521 client_t
*c
= client_getbywin(window
);
524 property_update_wm_protocols(c
);
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.
538 property_handle_xembed_info(void *data
__attribute__ ((unused
)),
539 xcb_connection_t
*connection
,
543 xcb_get_property_reply_t
*reply
)
545 xembed_window_t
*emwin
= xembed_getbywin(&globalconf
.embedded
, window
);
548 xembed_property_update(connection
, emwin
, reply
);
554 property_handle_xrootpmap_id(void *data
__attribute__ ((unused
)),
555 xcb_connection_t
*connection
,
559 xcb_get_property_reply_t
*reply
)
561 if(globalconf
.xinerama_is_active
)
562 foreach(w
, globalconf
.wiboxes
)
563 (*w
)->need_update
= true;
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;
576 property_handle_net_wm_opacity(void *data
__attribute__ ((unused
)),
577 xcb_connection_t
*connection
,
581 xcb_get_property_reply_t
*reply
)
583 wibox_t
*wibox
= wibox_getbywin(window
);
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);
593 client_t
*c
= client_getbywin(window
);
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);
605 void a_xcb_set_property_handlers(void)
608 xcb_property_handlers_init(&globalconf
.prophs
, &globalconf
.evenths
);
611 xcb_property_set_handler(&globalconf
.prophs
, _XEMBED_INFO
, UINT_MAX
,
612 property_handle_xembed_info
, NULL
);
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
);
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