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>
29 #include "common/atoms.h"
30 #include "common/xutil.h"
34 property_update_wm_transient_for(client_t
*c
, xcb_get_property_reply_t
*reply
)
40 if(!xcb_get_wm_transient_for_from_reply(&trans
, reply
))
45 if(!xcb_get_wm_transient_for_reply(globalconf
.connection
,
46 xcb_get_wm_transient_for_unchecked(globalconf
.connection
,
52 c
->type
= WINDOW_TYPE_DIALOG
;
53 c
->transient_for
= client_getbywin(trans
);
54 client_setabove(c
, false);
58 property_handle_wm_transient_for(void *data
,
59 xcb_connection_t
*connection
,
63 xcb_get_property_reply_t
*reply
)
65 client_t
*c
= client_getbywin(window
);
68 property_update_wm_transient_for(c
, reply
);
74 /** Update leader hint of a client.
75 * \param c The client.
76 * \param reply (Optional) An existing reply.
79 property_update_wm_client_leader(client_t
*c
, xcb_get_property_reply_t
*reply
)
81 xcb_get_property_cookie_t client_leader_q
;
83 bool no_reply
= !reply
;
87 client_leader_q
= xcb_get_property_unchecked(globalconf
.connection
, false, c
->win
,
88 WM_CLIENT_LEADER
, WINDOW
, 0, 32);
90 reply
= xcb_get_property_reply(globalconf
.connection
, client_leader_q
, NULL
);
93 if(reply
&& reply
->value_len
&& (data
= xcb_get_property_value(reply
)))
94 c
->leader_win
= *(xcb_window_t
*) data
;
96 /* Only free when we created a reply ourselves. */
102 property_handle_wm_client_leader(void *data
,
103 xcb_connection_t
*connection
,
107 xcb_get_property_reply_t
*reply
)
109 client_t
*c
= client_getbywin(window
);
112 property_update_wm_client_leader(c
, reply
);
117 /** Update the size hints of a client.
118 * \param c The client.
119 * \param reply (Optional) An existing reply.
122 property_update_wm_normal_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
126 if(!xcb_get_wm_size_hints_from_reply(&c
->size_hints
, reply
))
131 if(!xcb_get_wm_normal_hints_reply(globalconf
.connection
,
132 xcb_get_wm_normal_hints_unchecked(globalconf
.connection
,
134 &c
->size_hints
, NULL
))
140 property_handle_wm_normal_hints(void *data
,
141 xcb_connection_t
*connection
,
145 xcb_get_property_reply_t
*reply
)
147 client_t
*c
= client_getbywin(window
);
150 property_update_wm_normal_hints(c
, reply
);
155 /** Update the WM hints of a client.
156 * \param c The client.
157 * \param reply (Optional) An existing reply.
160 property_update_wm_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
166 if(!xcb_get_wm_hints_from_reply(&wmh
, reply
))
171 if(!xcb_get_wm_hints_reply(globalconf
.connection
,
172 xcb_get_wm_hints_unchecked(globalconf
.connection
, c
->win
),
177 bool isurgent
= xcb_wm_hints_get_urgency(&wmh
);
178 client_seturgent(c
, isurgent
);
179 if(wmh
.flags
& XCB_WM_HINT_STATE
&&
180 wmh
.initial_state
== XCB_WM_STATE_WITHDRAWN
)
181 client_setborder(c
, 0);
183 if(wmh
.flags
& XCB_WM_HINT_INPUT
)
184 c
->nofocus
= !wmh
.input
;
186 if(wmh
.flags
& XCB_WM_HINT_WINDOW_GROUP
)
187 c
->group_win
= wmh
.window_group
;
191 property_handle_wm_hints(void *data
,
192 xcb_connection_t
*connection
,
196 xcb_get_property_reply_t
*reply
)
198 client_t
*c
= client_getbywin(window
);
201 property_update_wm_hints(c
, reply
);
206 /** Update client name attribute with its new title.
207 * \param c The client.
210 property_update_wm_name(client_t
*c
)
215 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, _NET_WM_NAME
, &name
, &len
))
216 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, WM_NAME
, &name
, &len
))
224 hook_property(client
, c
, "name");
227 /** Update WM_CLASS of a client.
228 * \param c The client.
229 * \param reply The reply to get property request, or NULL if none.
232 property_update_wm_class(client_t
*c
, xcb_get_property_reply_t
*reply
)
234 xcb_get_wm_class_reply_t hint
;
238 if(!xcb_get_wm_class_from_reply(&hint
, reply
))
243 if(!xcb_get_wm_class_reply(globalconf
.connection
,
244 xcb_get_wm_class_unchecked(globalconf
.connection
, c
->win
),
249 p_delete(&c
->instance
);
252 c
->instance
= a_strdup(hint
.instance_name
);
253 c
->class = a_strdup(hint
.class_name
);
254 /* only delete reply if we get it ourselves */
256 xcb_get_wm_class_reply_wipe(&hint
);
259 /** Update client icon name attribute with its new title.
260 * \param c The client.
263 property_update_wm_icon_name(client_t
*c
)
268 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, _NET_WM_ICON_NAME
, &name
, &len
))
269 if(!xutil_text_prop_get(globalconf
.connection
, c
->win
, WM_ICON_NAME
, &name
, &len
))
272 p_delete(&c
->icon_name
);
277 hook_property(client
, c
, "icon_name");
281 property_handle_wm_name(void *data
,
282 xcb_connection_t
*connection
,
286 xcb_get_property_reply_t
*reply
)
288 client_t
*c
= client_getbywin(window
);
291 property_update_wm_name(c
);
297 property_handle_wm_icon_name(void *data
,
298 xcb_connection_t
*connection
,
302 xcb_get_property_reply_t
*reply
)
304 client_t
*c
= client_getbywin(window
);
307 property_update_wm_icon_name(c
);
313 property_handle_wm_class(void *data
,
314 xcb_connection_t
*connection
,
318 xcb_get_property_reply_t
*reply
)
320 client_t
*c
= client_getbywin(window
);
323 property_update_wm_class(c
, reply
);
329 property_handle_net_wm_strut_partial(void *data
,
330 xcb_connection_t
*connection
,
334 xcb_get_property_reply_t
*reply
)
336 client_t
*c
= client_getbywin(window
);
339 ewmh_process_client_strut(c
, reply
);
345 property_handle_net_wm_icon(void *data
,
346 xcb_connection_t
*connection
,
350 xcb_get_property_reply_t
*reply
)
352 client_t
*c
= client_getbywin(window
);
356 client_push(globalconf
.L
, c
);
357 luaA_object_unref_item(globalconf
.L
, -1, c
->icon
);
358 if(ewmh_window_icon_from_reply(reply
))
359 c
->icon
= luaA_object_ref_item(globalconf
.L
, -2, -1);
363 lua_pop(globalconf
.L
, 1);
365 hook_property(client
, c
, "icon");
371 /** Update the list of supported protocols for a client.
372 * \param c The client.
375 property_update_wm_protocols(client_t
*c
)
377 xcb_get_wm_protocols_reply_t protocols
;
379 /* If this fails for any reason, we still got the old value */
380 if(xcb_get_wm_protocols_reply(globalconf
.connection
,
381 xcb_get_wm_protocols_unchecked(globalconf
.connection
,
382 c
->win
, WM_PROTOCOLS
),
385 xcb_get_wm_protocols_reply_wipe(&c
->protocols
);
386 memcpy(&c
->protocols
, &protocols
, sizeof(protocols
));
390 /** The property notify event handler.
391 * \param data currently unused.
392 * \param connection currently unusued.
393 * \param state currently unused.
394 * \param window The window to obtain update protocols from.
395 * \param name currently unused.
396 * \param reply currently unused.
399 property_handle_wm_protocols(void *data
,
400 xcb_connection_t
*connection
,
404 xcb_get_property_reply_t
*reply
)
406 client_t
*c
= client_getbywin(window
);
409 property_update_wm_protocols(c
);
414 /** The property notify event handler.
415 * \param data currently unused.
416 * \param connection The connection to the X server.
417 * \param state currently unused
418 * \param window The window to obtain update the property with.
419 * \param name The protocol atom, currently unused.
420 * \param reply (Optional) An existing reply.
423 property_handle_xembed_info(void *data
__attribute__ ((unused
)),
424 xcb_connection_t
*connection
,
428 xcb_get_property_reply_t
*reply
)
430 xembed_window_t
*emwin
= xembed_getbywin(&globalconf
.embedded
, window
);
433 xembed_property_update(connection
, emwin
, reply
);
439 property_handle_xrootpmap_id(void *data
__attribute__ ((unused
)),
440 xcb_connection_t
*connection
,
444 xcb_get_property_reply_t
*reply
)
446 if(globalconf
.xinerama_is_active
)
447 foreach(w
, globalconf
.wiboxes
)
448 (*w
)->need_update
= true;
451 int screen
= xutil_root2screen(connection
, window
);
452 foreach(w
, globalconf
.wiboxes
)
453 if(screen
== screen_array_indexof(&globalconf
.screens
, (*w
)->screen
))
454 (*w
)->need_update
= true;
461 property_handle_opacity(void *data
__attribute__ ((unused
)),
462 xcb_connection_t
*connection
,
466 xcb_get_property_reply_t
*reply
)
468 wibox_t
*wibox
= wibox_getbywin(window
);
471 wibox
->opacity
= window_opacity_get_from_reply(reply
);
475 void a_xcb_set_property_handlers(void)
478 xcb_property_handlers_init(&globalconf
.prophs
, &globalconf
.evenths
);
481 xcb_property_set_handler(&globalconf
.prophs
, _XEMBED_INFO
, UINT_MAX
,
482 property_handle_xembed_info
, NULL
);
485 xcb_property_set_handler(&globalconf
.prophs
, WM_TRANSIENT_FOR
, UINT_MAX
,
486 property_handle_wm_transient_for
, NULL
);
487 xcb_property_set_handler(&globalconf
.prophs
, WM_CLIENT_LEADER
, UINT_MAX
,
488 property_handle_wm_client_leader
, NULL
);
489 xcb_property_set_handler(&globalconf
.prophs
, WM_NORMAL_HINTS
, UINT_MAX
,
490 property_handle_wm_normal_hints
, NULL
);
491 xcb_property_set_handler(&globalconf
.prophs
, WM_HINTS
, UINT_MAX
,
492 property_handle_wm_hints
, NULL
);
493 xcb_property_set_handler(&globalconf
.prophs
, WM_NAME
, UINT_MAX
,
494 property_handle_wm_name
, NULL
);
495 xcb_property_set_handler(&globalconf
.prophs
, WM_ICON_NAME
, UINT_MAX
,
496 property_handle_wm_icon_name
, NULL
);
497 xcb_property_set_handler(&globalconf
.prophs
, WM_CLASS
, UINT_MAX
,
498 property_handle_wm_class
, NULL
);
499 xcb_property_set_handler(&globalconf
.prophs
, WM_PROTOCOLS
, UINT_MAX
,
500 property_handle_wm_protocols
, NULL
);
503 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_NAME
, UINT_MAX
,
504 property_handle_wm_name
, NULL
);
505 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_ICON_NAME
, UINT_MAX
,
506 property_handle_wm_icon_name
, NULL
);
507 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_STRUT_PARTIAL
, UINT_MAX
,
508 property_handle_net_wm_strut_partial
, NULL
);
509 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_ICON
, UINT_MAX
,
510 property_handle_net_wm_icon
, NULL
);
512 /* background change */
513 xcb_property_set_handler(&globalconf
.prophs
, _XROOTPMAP_ID
, 1,
514 property_handle_xrootpmap_id
, NULL
);
517 xcb_property_set_handler(&globalconf
.prophs
, _NET_WM_WINDOW_OPACITY
, 1,
518 property_handle_opacity
, NULL
);
521 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80