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>
28 #include "common/atoms.h"
29 #include "common/xutil.h"
32 property_update_wm_transient_for(client_t
*c
, xcb_get_property_reply_t
*reply
)
38 if(!xcb_get_wm_transient_for_from_reply(&trans
, reply
))
43 if(!xcb_get_wm_transient_for_reply(globalconf
.connection
,
44 xcb_get_wm_transient_for_unchecked(globalconf
.connection
,
50 c
->type
= WINDOW_TYPE_DIALOG
;
51 c
->transient_for
= client_getbywin(trans
);
52 client_setabove(c
, false);
56 property_handle_wm_transient_for(void *data
,
57 xcb_connection_t
*connection
,
61 xcb_get_property_reply_t
*reply
)
63 client_t
*c
= client_getbywin(window
);
66 property_update_wm_transient_for(c
, reply
);
72 /** Update leader hint of a client.
73 * \param c The client.
74 * \param reply (Optional) An existing reply.
77 property_update_wm_client_leader(client_t
*c
, xcb_get_property_reply_t
*reply
)
79 xcb_get_property_cookie_t client_leader_q
;
81 bool no_reply
= !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. */
100 property_handle_wm_client_leader(void *data
,
101 xcb_connection_t
*connection
,
105 xcb_get_property_reply_t
*reply
)
107 client_t
*c
= client_getbywin(window
);
110 property_update_wm_client_leader(c
, reply
);
115 /** Update the size hints of a client.
116 * \param c The client.
119 property_update_wm_normal_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
123 if(!xcb_get_wm_size_hints_from_reply(&c
->size_hints
, reply
))
128 if(!xcb_get_wm_normal_hints_reply(globalconf
.connection
,
129 xcb_get_wm_normal_hints_unchecked(globalconf
.connection
,
131 &c
->size_hints
, NULL
))
137 property_handle_wm_normal_hints(void *data
,
138 xcb_connection_t
*connection
,
142 xcb_get_property_reply_t
*reply
)
144 client_t
*c
= client_getbywin(window
);
147 property_update_wm_normal_hints(c
, reply
);
152 /** Update the WM hints of a client.
153 * \param c The client.
156 property_update_wm_hints(client_t
*c
, xcb_get_property_reply_t
*reply
)
162 if(!xcb_get_wm_hints_from_reply(&wmh
, reply
))
167 if(!xcb_get_wm_hints_reply(globalconf
.connection
,
168 xcb_get_wm_hints_unchecked(globalconf
.connection
, c
->win
),
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
;
187 property_handle_wm_hints(void *data
,
188 xcb_connection_t
*connection
,
192 xcb_get_property_reply_t
*reply
)
194 client_t
*c
= client_getbywin(window
);
197 property_update_wm_hints(c
, reply
);
202 /** Update client name attribute with its new title.
203 * \param c The client.
204 * \param Return true if it has been updated.
207 property_update_wm_name(client_t
*c
)
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
))
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.
229 property_update_wm_class(client_t
*c
, xcb_get_property_reply_t
*reply
)
231 xcb_get_wm_class_reply_t hint
;
235 if(!xcb_get_wm_class_from_reply(&hint
, reply
))
240 if(!xcb_get_wm_class_reply(globalconf
.connection
,
241 xcb_get_wm_class_unchecked(globalconf
.connection
, c
->win
),
246 p_delete(&c
->instance
);
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 */
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.
261 property_update_wm_icon_name(client_t
*c
)
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
))
270 p_delete(&c
->icon_name
);
275 hooks_property(c
, "icon_name");
279 property_handle_wm_name(void *data
,
280 xcb_connection_t
*connection
,
284 xcb_get_property_reply_t
*reply
)
286 client_t
*c
= client_getbywin(window
);
289 property_update_wm_name(c
);
295 property_handle_wm_icon_name(void *data
,
296 xcb_connection_t
*connection
,
300 xcb_get_property_reply_t
*reply
)
302 client_t
*c
= client_getbywin(window
);
305 property_update_wm_icon_name(c
);
311 property_handle_wm_class(void *data
,
312 xcb_connection_t
*connection
,
316 xcb_get_property_reply_t
*reply
)
318 client_t
*c
= client_getbywin(window
);
321 property_update_wm_class(c
, reply
);
327 property_handle_net_wm_strut_partial(void *data
,
328 xcb_connection_t
*connection
,
332 xcb_get_property_reply_t
*reply
)
334 client_t
*c
= client_getbywin(window
);
337 ewmh_process_client_strut(c
, reply
);
343 property_handle_net_wm_icon(void *data
,
344 xcb_connection_t
*connection
,
348 xcb_get_property_reply_t
*reply
)
350 client_t
*c
= client_getbywin(window
);
354 image_unref(globalconf
.L
, c
->icon
);
355 if(ewmh_window_icon_from_reply(reply
))
356 c
->icon
= image_ref(globalconf
.L
);
358 hooks_property(c
, "icon");
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.
370 property_handle_xembed_info(void *data
__attribute__ ((unused
)),
371 xcb_connection_t
*connection
,
375 xcb_get_property_reply_t
*reply
)
377 xembed_window_t
*emwin
= xembed_getbywin(&globalconf
.embedded
, window
);
380 xembed_property_update(connection
, emwin
, reply
);
386 property_handle_xrootpmap_id(void *data
__attribute__ ((unused
)),
387 xcb_connection_t
*connection
,
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;
399 int screen
= xutil_root2screen(connection
, window
);
400 foreach(w
, globalconf
.screens
.tab
[screen
].wiboxes
)
401 (*w
)->need_update
= true;
407 void a_xcb_set_property_handlers(void)
410 xcb_property_handlers_init(&globalconf
.prophs
, &globalconf
.evenths
);
413 xcb_property_set_handler(&globalconf
.prophs
, _XEMBED_INFO
, UINT_MAX
,
414 property_handle_xembed_info
, NULL
);
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
);
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