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 c
->type
= WINDOW_TYPE_DIALOG
;
54 c
->transient_for
= client_getbywin(trans
);
55 client_setabove(c
, false);
59 property_handle_wm_transient_for(void *data
,
60 xcb_connection_t
*connection
,
64 xcb_get_property_reply_t
*reply
)
66 client_t
*c
= client_getbywin(window
);
69 property_update_wm_transient_for(c
, reply
);
75 property_update_wm_client_machine(client_t
*c
)
80 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
,
81 WM_CLIENT_MACHINE
, &value
, &slen
))
84 p_delete(&c
->machine
);
85 c
->machine
= a_strdup(value
);
89 property_handle_wm_client_machine(void *data
,
90 xcb_connection_t
*connection
,
94 xcb_get_property_reply_t
*reply
)
96 client_t
*c
= client_getbywin(window
);
99 property_update_wm_client_machine(c
);
105 property_update_wm_window_role(client_t
*c
)
110 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
,
111 WM_WINDOW_ROLE
, &value
, &slen
))
115 c
->role
= a_strdup(value
);
119 property_handle_wm_window_role(void *data
,
120 xcb_connection_t
*connection
,
124 xcb_get_property_reply_t
*reply
)
126 client_t
*c
= client_getbywin(window
);
129 property_update_wm_window_role(c
);
134 /** Update leader hint of a client.
135 * \param c The client.
136 * \param reply (Optional) An existing reply.
139 property_update_wm_client_leader(client_t
*c
, xcb_get_property_reply_t
*reply
)
141 xcb_get_property_cookie_t client_leader_q
;
143 bool no_reply
= !reply
;
147 client_leader_q
= xcb_get_property_unchecked(globalconf
.connection
, false, c
->win
,
148 WM_CLIENT_LEADER
, WINDOW
, 0, 32);
150 reply
= xcb_get_property_reply(globalconf
.connection
, client_leader_q
, NULL
);
153 if(reply
&& reply
->value_len
&& (data
= xcb_get_property_value(reply
)))
154 c
->leader_win
= *(xcb_window_t
*) data
;
156 /* Only free when we created a reply ourselves. */
162 property_handle_wm_client_leader(void *data
,
163 xcb_connection_t
*connection
,
167 xcb_get_property_reply_t
*reply
)
169 client_t
*c
= client_getbywin(window
);
172 property_update_wm_client_leader(c
, reply
);
177 /** Update the size hints of a client.
178 * \param c The client.
179 * \param reply (Optional) An existing reply.
182 property_update_wm_normal_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
186 if(!xcb_get_wm_size_hints_from_reply(&c
->size_hints
, reply
))
191 if(!xcb_get_wm_normal_hints_reply(globalconf
.connection
,
192 xcb_get_wm_normal_hints_unchecked(globalconf
.connection
,
194 &c
->size_hints
, NULL
))
200 property_handle_wm_normal_hints(void *data
,
201 xcb_connection_t
*connection
,
205 xcb_get_property_reply_t
*reply
)
207 client_t
*c
= client_getbywin(window
);
210 property_update_wm_normal_hints(c
, reply
);
215 /** Update the WM hints of a client.
216 * \param c The client.
217 * \param reply (Optional) An existing reply.
220 property_update_wm_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
226 if(!xcb_get_wm_hints_from_reply(&wmh
, reply
))
231 if(!xcb_get_wm_hints_reply(globalconf
.connection
,
232 xcb_get_wm_hints_unchecked(globalconf
.connection
, c
->win
),
237 bool isurgent
= xcb_wm_hints_get_urgency(&wmh
);
238 client_seturgent(c
, isurgent
);
239 if(wmh
.flags
& XCB_WM_HINT_STATE
&&
240 wmh
.initial_state
== XCB_WM_STATE_WITHDRAWN
)
241 client_setborder(c
, 0);
243 if(wmh
.flags
& XCB_WM_HINT_INPUT
)
244 c
->nofocus
= !wmh
.input
;
246 if(wmh
.flags
& XCB_WM_HINT_WINDOW_GROUP
)
247 c
->group_win
= wmh
.window_group
;
251 property_handle_wm_hints(void *data
,
252 xcb_connection_t
*connection
,
256 xcb_get_property_reply_t
*reply
)
258 client_t
*c
= client_getbywin(window
);
261 property_update_wm_hints(c
, reply
);
266 /** Update client name attribute with its new title.
267 * \param c The client.
270 property_update_wm_name(client_t
*c
)
275 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, _NET_WM_NAME
, &name
, &len
))
276 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, WM_NAME
, &name
, &len
))
284 hook_property(c
, "name");
287 /** Update WM_CLASS of a client.
288 * \param c The client.
289 * \param reply The reply to get property request, or NULL if none.
292 property_update_wm_class(client_t
*c
, xcb_get_property_reply_t
*reply
)
294 xcb_get_wm_class_reply_t hint
;
298 if(!xcb_get_wm_class_from_reply(&hint
, reply
))
303 if(!xcb_get_wm_class_reply(globalconf
.connection
,
304 xcb_get_wm_class_unchecked(globalconf
.connection
, c
->win
),
309 p_delete(&c
->instance
);
312 c
->instance
= a_strdup(hint
.instance_name
);
313 c
->class = a_strdup(hint
.class_name
);
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
->win
, _NET_WM_ICON_NAME
, &name
, &len
))
329 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, WM_ICON_NAME
, &name
, &len
))
332 p_delete(&c
->icon_name
);
337 hook_property(c
, "icon_name");
341 property_handle_wm_name(void *data
,
342 xcb_connection_t
*connection
,
346 xcb_get_property_reply_t
*reply
)
348 client_t
*c
= client_getbywin(window
);
351 property_update_wm_name(c
);
357 property_handle_wm_icon_name(void *data
,
358 xcb_connection_t
*connection
,
362 xcb_get_property_reply_t
*reply
)
364 client_t
*c
= client_getbywin(window
);
367 property_update_wm_icon_name(c
);
373 property_handle_wm_class(void *data
,
374 xcb_connection_t
*connection
,
378 xcb_get_property_reply_t
*reply
)
380 client_t
*c
= client_getbywin(window
);
383 property_update_wm_class(c
, reply
);
389 property_handle_net_wm_strut_partial(void *data
,
390 xcb_connection_t
*connection
,
394 xcb_get_property_reply_t
*reply
)
396 client_t
*c
= client_getbywin(window
);
399 ewmh_process_client_strut(c
, reply
);
405 property_handle_net_wm_icon(void *data
,
406 xcb_connection_t
*connection
,
410 xcb_get_property_reply_t
*reply
)
412 client_t
*c
= client_getbywin(window
);
416 luaA_object_push(globalconf
.L
, c
);
417 luaA_object_unref_item(globalconf
.L
, -1, c
->icon
);
418 if(ewmh_window_icon_from_reply(reply
))
419 c
->icon
= luaA_object_ref_item(globalconf
.L
, -2, -1);
423 lua_pop(globalconf
.L
, 1);
425 hook_property(c
, "icon");
432 property_update_net_wm_pid(client_t
*c
,
433 xcb_get_property_reply_t
*reply
)
435 bool no_reply
= !reply
;
439 xcb_get_property_cookie_t prop_c
=
440 xcb_get_property_unchecked(globalconf
.connection
, false, c
->win
, _NET_WM_PID
, CARDINAL
, 0L, 1L);
441 reply
= xcb_get_property_reply(globalconf
.connection
, prop_c
, NULL
);
444 if(reply
&& reply
->value_len
)
446 uint32_t *rdata
= xcb_get_property_value(reply
);
456 property_handle_net_wm_pid(void *data
,
457 xcb_connection_t
*connection
,
461 xcb_get_property_reply_t
*reply
)
463 client_t
*c
= client_getbywin(window
);
466 property_update_net_wm_pid(c
, reply
);
471 /** Update the list of supported protocols for a client.
472 * \param c The client.
475 property_update_wm_protocols(client_t
*c
)
477 xcb_get_wm_protocols_reply_t protocols
;
479 /* If this fails for any reason, we still got the old value */
480 if(xcb_get_wm_protocols_reply(globalconf
.connection
,
481 xcb_get_wm_protocols_unchecked(globalconf
.connection
,
482 c
->win
, WM_PROTOCOLS
),
485 xcb_get_wm_protocols_reply_wipe(&c
->protocols
);
486 memcpy(&c
->protocols
, &protocols
, sizeof(protocols
));
490 /** The property notify event handler.
491 * \param data currently unused.
492 * \param connection currently unusued.
493 * \param state currently unused.
494 * \param window The window to obtain update protocols from.
495 * \param name currently unused.
496 * \param reply currently unused.
499 property_handle_wm_protocols(void *data
,
500 xcb_connection_t
*connection
,
504 xcb_get_property_reply_t
*reply
)
506 client_t
*c
= client_getbywin(window
);
509 property_update_wm_protocols(c
);
514 /** The property notify event handler.
515 * \param data currently unused.
516 * \param connection The connection to the X server.
517 * \param state currently unused
518 * \param window The window to obtain update the property with.
519 * \param name The protocol atom, currently unused.
520 * \param reply (Optional) An existing reply.
523 property_handle_xembed_info(void *data
__attribute__ ((unused
)),
524 xcb_connection_t
*connection
,
528 xcb_get_property_reply_t
*reply
)
530 xembed_window_t
*emwin
= xembed_getbywin(&globalconf
.embedded
, window
);
533 xembed_property_update(connection
, emwin
, reply
);
539 property_handle_xrootpmap_id(void *data
__attribute__ ((unused
)),
540 xcb_connection_t
*connection
,
544 xcb_get_property_reply_t
*reply
)
546 if(globalconf
.xinerama_is_active
)
547 foreach(w
, globalconf
.wiboxes
)
548 (*w
)->need_update
= true;
551 int screen
= xutil_root2screen(connection
, window
);
552 foreach(w
, globalconf
.wiboxes
)
553 if(screen
== screen_array_indexof(&globalconf
.screens
, (*w
)->screen
))
554 (*w
)->need_update
= true;
561 property_handle_net_wm_opacity(void *data
__attribute__ ((unused
)),
562 xcb_connection_t
*connection
,
566 xcb_get_property_reply_t
*reply
)
568 wibox_t
*wibox
= wibox_getbywin(window
);
571 wibox
->opacity
= window_opacity_get_from_reply(reply
);
574 client_t
*c
= client_getbywin(window
);
576 c
->opacity
= window_opacity_get_from_reply(reply
);
582 void a_xcb_set_property_handlers(void)
585 xcb_property_handlers_init(&globalconf
.prophs
, &globalconf
.evenths
);
588 xcb_property_set_handler(&globalconf
.prophs
, _XEMBED_INFO
, UINT_MAX
,
589 property_handle_xembed_info
, NULL
);
592 xcb_property_set_handler(&globalconf
.prophs
, WM_TRANSIENT_FOR
, UINT_MAX
,
593 property_handle_wm_transient_for
, NULL
);
594 xcb_property_set_handler(&globalconf
.prophs
, WM_CLIENT_LEADER
, UINT_MAX
,
595 property_handle_wm_client_leader
, NULL
);
596 xcb_property_set_handler(&globalconf
.prophs
, WM_NORMAL_HINTS
, UINT_MAX
,
597 property_handle_wm_normal_hints
, NULL
);
598 xcb_property_set_handler(&globalconf
.prophs
, WM_HINTS
, UINT_MAX
,
599 property_handle_wm_hints
, NULL
);
600 xcb_property_set_handler(&globalconf
.prophs
, WM_NAME
, UINT_MAX
,
601 property_handle_wm_name
, NULL
);
602 xcb_property_set_handler(&globalconf
.prophs
, WM_ICON_NAME
, UINT_MAX
,
603 property_handle_wm_icon_name
, NULL
);
604 xcb_property_set_handler(&globalconf
.prophs
, WM_CLASS
, UINT_MAX
,
605 property_handle_wm_class
, NULL
);
606 xcb_property_set_handler(&globalconf
.prophs
, WM_PROTOCOLS
, UINT_MAX
,
607 property_handle_wm_protocols
, NULL
);
608 xcb_property_set_handler(&globalconf
.prophs
, WM_CLIENT_MACHINE
, UINT_MAX
,
609 property_handle_wm_client_machine
, NULL
);
610 xcb_property_set_handler(&globalconf
.prophs
, WM_WINDOW_ROLE
, UINT_MAX
,
611 property_handle_wm_window_role
, NULL
);
614 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_NAME
, UINT_MAX
,
615 property_handle_wm_name
, NULL
);
616 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_ICON_NAME
, UINT_MAX
,
617 property_handle_wm_icon_name
, NULL
);
618 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_STRUT_PARTIAL
, UINT_MAX
,
619 property_handle_net_wm_strut_partial
, NULL
);
620 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_ICON
, UINT_MAX
,
621 property_handle_net_wm_icon
, NULL
);
622 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_PID
, UINT_MAX
,
623 property_handle_net_wm_pid
, NULL
);
624 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_WINDOW_OPACITY
, 1,
625 property_handle_net_wm_opacity
, NULL
);
627 /* background change */
628 xcb_property_set_handler(&globalconf
.prophs
, _XROOTPMAP_ID
, 1,
629 property_handle_xrootpmap_id
, NULL
);
632 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80