From 2be620618b43dbf77b6fe45bb2e0a580c65a73fe Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 16 Sep 2008 14:09:56 +0200 Subject: [PATCH] property: use xcb property handler system Signed-off-by: Julien Danjou --- CMakeLists.txt | 1 + awesome.c | 2 + client.c | 143 ++----------------- client.h | 3 - common/xembed.c | 44 +++--- common/xembed.h | 2 +- event.c | 59 -------- ewmh.c | 42 +++--- ewmh.h | 3 +- property.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++ property.h | 34 +++++ structs.h | 3 + 12 files changed, 452 insertions(+), 239 deletions(-) create mode 100644 property.c create mode 100644 property.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d4e6785..0e2da26b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ set(AWE_SRCS ${SOURCE_DIR}/cnode.c ${SOURCE_DIR}/dbus.c ${SOURCE_DIR}/event.c + ${SOURCE_DIR}/property.c ${SOURCE_DIR}/ewmh.c ${SOURCE_DIR}/keybinding.c ${SOURCE_DIR}/keygrabber.c diff --git a/awesome.c b/awesome.c index 8b645bb7..73962bfe 100644 --- a/awesome.c +++ b/awesome.c @@ -38,6 +38,7 @@ #include "dbus.h" #include "systray.h" #include "event.h" +#include "property.h" #include "screen.h" #include "common/version.h" #include "common/atoms.h" @@ -474,6 +475,7 @@ main(int argc, char **argv) /* process all errors in the queue if any */ xcb_event_poll_for_event_loop(&globalconf.evenths); a_xcb_set_event_handlers(); + a_xcb_set_property_handlers(); /* do this only for real screen */ for(screen_nbr = 0; diff --git a/client.c b/client.c index 0d21f4f1..0b44a60f 100644 --- a/client.c +++ b/client.c @@ -36,6 +36,7 @@ #include "mouse.h" #include "systray.h" #include "statusbar.h" +#include "property.h" #include "layouts/floating.h" #include "common/markup.h" #include "common/atoms.h" @@ -172,36 +173,6 @@ client_getbywin(xcb_window_t w) return c; } -/** Update client name attribute with its new title. - * \param c The client. - * \param Return true if it has been updated. - */ -bool -client_updatetitle(client_t *c) -{ - char *name, *utf8; - ssize_t len; - - if(!xutil_text_prop_get(globalconf.connection, c->win, _NET_WM_NAME, &name, &len)) - if(!xutil_text_prop_get(globalconf.connection, c->win, WM_NAME, &name, &len)) - return false; - - p_delete(&c->name); - - if((utf8 = draw_iso2utf8(name, len))) - c->name = utf8; - else - c->name = name; - - /* call hook */ - luaA_client_userdata_new(globalconf.L, c); - luaA_dofunction(globalconf.L, globalconf.hooks.titleupdate, 1, 0); - - widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); - - return true; -} - /** Unfocus a client. * \param c The client. */ @@ -431,8 +402,8 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, c->honorsizehints = true; /* update hints */ - client_updatesizehints(c); - client_updatewmhints(c); + property_update_wm_normal_hints(c, NULL); + property_update_wm_hints(c, NULL); /* Try to load props if any */ client_loadprops(c, &globalconf.screens[screen]); @@ -462,6 +433,10 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, tag_client(c, tags->tab[i]); } + /* Check if it's a transient window, and manually set it floating. */ + if(!client_isfloating(c)) + property_update_wm_transient_for(c, NULL); + /* Push client in client list */ client_list_push(&globalconf.clients, c); client_ref(&c); @@ -469,10 +444,10 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, client_raise(c); /* update window title */ - client_updatetitle(c); + property_update_wm_name(c); /* update strut */ - ewmh_client_strut_update(c); + ewmh_client_strut_update(c, NULL); ewmh_update_net_client_list(c->phys_screen); widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); @@ -853,106 +828,6 @@ client_unmanage(client_t *c) client_unref(&c); } -/** Update the WM hints of a client. - * \param c The client. - */ -void -client_updatewmhints(client_t *c) -{ - xcb_wm_hints_t wmh; - - if(xcb_get_wm_hints_reply(globalconf.connection, - xcb_get_wm_hints_unchecked(globalconf.connection, c->win), - &wmh, NULL)) - { - bool isurgent = xcb_wm_hints_get_urgency(&wmh); - if(isurgent != c->isurgent) - { - c->isurgent = isurgent; - - /* execute hook */ - luaA_client_userdata_new(globalconf.L, c); - luaA_dofunction(globalconf.L, globalconf.hooks.urgent, 1, 0); - - widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); - } - if((wmh.flags & XCB_WM_HINT_STATE) && - wmh.initial_state == XCB_WM_STATE_WITHDRAWN) - client_setborder(c, 0); - - c->nofocus = !wmh.input; - } -} - -/** Update the size hints of a client. - * \param c The client. - */ -void -client_updatesizehints(client_t *c) -{ - if(!xcb_get_wm_normal_hints_reply(globalconf.connection, - xcb_get_wm_normal_hints_unchecked(globalconf.connection, - c->win), - &c->size_hints, NULL)) - return; - - if((c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)) - { - c->basew = c->size_hints.base_width; - c->baseh = c->size_hints.base_height; - } - else if((c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) - { - c->basew = c->size_hints.min_width; - c->baseh = c->size_hints.min_height; - } - else - c->basew = c->baseh = 0; - - if((c->size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)) - { - c->incw = c->size_hints.width_inc; - c->inch = c->size_hints.height_inc; - } - else - c->incw = c->inch = 0; - - if((c->size_hints.flags & XCB_SIZE_HINT_P_MAX_SIZE)) - { - c->maxw = c->size_hints.max_width; - c->maxh = c->size_hints.max_height; - } - else - c->maxw = c->maxh = 0; - - if((c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) - { - c->minw = c->size_hints.min_width; - c->minh = c->size_hints.min_height; - } - else if((c->size_hints.flags & XCB_SIZE_HINT_BASE_SIZE)) - { - c->minw = c->size_hints.base_width; - c->minh = c->size_hints.base_height; - } - else - c->minw = c->minh = 0; - - if((c->size_hints.flags & XCB_SIZE_HINT_P_ASPECT)) - { - c->minax = c->size_hints.min_aspect_num; - c->minay = c->size_hints.min_aspect_den; - c->maxax = c->size_hints.max_aspect_num; - c->maxay = c->size_hints.max_aspect_den; - } - else - c->minax = c->maxax = c->minay = c->maxay = 0; - - c->hassizehints = !(!c->basew && !c->baseh && !c->incw && !c->inch - && !c->maxw && !c->maxh && !c->minw && !c->minh - && !c->minax && !c->maxax && !c->minax && !c->minay); -} - /** Kill a client via a WM_DELETE_WINDOW request or XKillClient if not * supported. * \param c The client to kill. diff --git a/client.h b/client.h index 2936fa38..6139e42c 100644 --- a/client.h +++ b/client.h @@ -43,9 +43,6 @@ void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, int, int); area_t client_geometry_hints(client_t *, area_t); bool client_resize(client_t *, area_t, bool); void client_unmanage(client_t *); -void client_updatewmhints(client_t *); -void client_updatesizehints(client_t *); -bool client_updatetitle(client_t *); void client_saveprops_tags(client_t *); void client_kill(client_t *); void client_setfloating(client_t *, bool); diff --git a/common/xembed.c b/common/xembed.c index 1fec16ac..be7c061f 100644 --- a/common/xembed.c +++ b/common/xembed.c @@ -64,6 +64,23 @@ xembed_info_get_unchecked(xcb_connection_t *connection, xcb_window_t win) XCB_GET_PROPERTY_TYPE_ANY, 0L, 2); } +static bool +xembed_info_from_reply(xembed_info_t *info, xcb_get_property_reply_t *prop_r) +{ + uint32_t *data; + + if(!prop_r || !prop_r->value_len) + return false; + + if(!(data = (uint32_t *) xcb_get_property_value(prop_r))) + return false; + + info->version = data[0]; + info->flags = data[1] & XEMBED_INFO_FLAGS_ALL; + + return true; +} + /** Get the XEMBED info for a window. * \param connection The X connection. * \param cookie The cookie of the request. @@ -74,23 +91,8 @@ xembed_info_get_reply(xcb_connection_t *connection, xcb_get_property_cookie_t cookie, xembed_info_t *info) { - xcb_get_property_reply_t *prop_r; - uint32_t *data; - bool ret = false; - - prop_r = xcb_get_property_reply(connection, cookie, NULL); - - if(!prop_r || !prop_r->value_len) - goto bailout; - - if(!(data = (uint32_t *) xcb_get_property_value(prop_r))) - goto bailout; - - info->version = data[0]; - info->flags = data[1] & XEMBED_INFO_FLAGS_ALL; - ret = true; - -bailout: + xcb_get_property_reply_t *prop_r = xcb_get_property_reply(connection, cookie, NULL); + bool ret = xembed_info_from_reply(info, prop_r); p_delete(&prop_r); return ret; } @@ -114,15 +116,13 @@ xembed_getbywin(xembed_window_t *list, xcb_window_t win) * \param emwin The embedded window. */ void -xembed_property_update(xcb_connection_t *connection, xembed_window_t *emwin) +xembed_property_update(xcb_connection_t *connection, xembed_window_t *emwin, + xcb_get_property_reply_t *reply) { int flags_changed; xembed_info_t info = { 0, 0 }; - xembed_info_get_reply(connection, - xembed_info_get_unchecked(connection, - emwin->win), - &info); + xembed_info_from_reply(&info, reply); /* test if it changed */ if(!(flags_changed = info.flags ^ emwin->info.flags)) diff --git a/common/xembed.h b/common/xembed.h index 4bbac7b9..7f0eb45b 100644 --- a/common/xembed.h +++ b/common/xembed.h @@ -92,7 +92,7 @@ DO_SLIST(xembed_window_t, xembed_window, p_delete) void xembed_message_send(xcb_connection_t *, xcb_window_t, long, long, long, long); xembed_window_t * xembed_getbywin(xembed_window_t *, xcb_window_t); -void xembed_property_update(xcb_connection_t *, xembed_window_t *); +void xembed_property_update(xcb_connection_t *, xembed_window_t *, xcb_get_property_reply_t *); xcb_get_property_cookie_t xembed_info_get_unchecked(xcb_connection_t *, xcb_window_t); bool xembed_info_get_reply(xcb_connection_t *connection, diff --git a/event.c b/event.c index 5a79e883..c8428757 100644 --- a/event.c +++ b/event.c @@ -626,64 +626,6 @@ bailout: return ret; } -/** The property notify event handler. - * \param data currently unused. - * \param connection The connection to the X server. - * \param ev The event. - */ -static int -event_handle_propertynotify(void *data __attribute__ ((unused)), - xcb_connection_t *connection, xcb_property_notify_event_t *ev) -{ - client_t *c; - xembed_window_t *emwin; - - if(ev->state == XCB_PROPERTY_DELETE) - return 0; /* ignore */ - else if((emwin = xembed_getbywin(globalconf.embedded, ev->window))) - xembed_property_update(connection, emwin); - else if((c = client_getbywin(ev->window))) - { - if(ev->atom == WM_TRANSIENT_FOR) - { - if(!client_isfloating(c)) - { - xcb_window_t trans; - xcb_get_wm_transient_for_reply(connection, - xcb_get_wm_transient_for_unchecked(connection, - c->win), - &trans, NULL); - if(client_getbywin(trans)) - client_setfloating(c, true); - } - } - else if (ev->atom == WM_NORMAL_HINTS) - client_updatesizehints(c); - else if (ev->atom == WM_HINTS) - client_updatewmhints(c); - else if(ev->atom == WM_NAME || ev->atom == _NET_WM_NAME) - client_updatetitle(c); - else if(ev->atom == _NET_WM_STRUT_PARTIAL) - ewmh_client_strut_update(c); - else if(ev->atom == _NET_WM_ICON) - { - xcb_get_property_cookie_t icon_q = ewmh_window_icon_get_unchecked(c->win); - draw_image_t *icon; - image_unref(&c->icon); - widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); - if((icon = ewmh_window_icon_get_reply(icon_q))) - { - c->icon = image_new(icon); - image_ref(&c->icon); - } - else - c->icon = NULL; - } - } - - return 0; -} - /** The unmap notify event handler. * \param data currently unused. * \param connection The connection to the X server. @@ -838,7 +780,6 @@ void a_xcb_set_event_handlers(void) xcb_event_set_expose_handler(&globalconf.evenths, event_handle_expose, NULL); xcb_event_set_key_press_handler(&globalconf.evenths, event_handle_keypress, NULL); xcb_event_set_map_request_handler(&globalconf.evenths, event_handle_maprequest, NULL); - xcb_event_set_property_notify_handler(&globalconf.evenths, event_handle_propertynotify, NULL); xcb_event_set_unmap_notify_handler(&globalconf.evenths, event_handle_unmapnotify, NULL); xcb_event_set_client_message_handler(&globalconf.evenths, event_handle_clientmessage, NULL); xcb_event_set_mapping_notify_handler(&globalconf.evenths, event_handle_mappingnotify, NULL); diff --git a/ewmh.c b/ewmh.c index 2088a620..ae8f5fac 100644 --- a/ewmh.c +++ b/ewmh.c @@ -440,16 +440,17 @@ ewmh_check_client_hints(client_t *c) * \param c The client. */ void -ewmh_client_strut_update(client_t *c) +ewmh_client_strut_update(client_t *c, xcb_get_property_reply_t *strut_r) { void *data; - xcb_get_property_cookie_t strut_q; - xcb_get_property_reply_t *strut_r; + xcb_get_property_reply_t *mstrut_r = NULL; - strut_q = xcb_get_property_unchecked(globalconf.connection, false, c->win, - _NET_WM_STRUT_PARTIAL, CARDINAL, 0, 12); - - strut_r = xcb_get_property_reply(globalconf.connection, strut_q, NULL); + if(!strut_r) + { + xcb_get_property_cookie_t strut_q = xcb_get_property_unchecked(globalconf.connection, false, c->win, + _NET_WM_STRUT_PARTIAL, CARDINAL, 0, 12); + strut_r = mstrut_r = xcb_get_property_reply(globalconf.connection, strut_q, NULL); + } if(strut_r && strut_r->value_len @@ -490,7 +491,8 @@ ewmh_client_strut_update(client_t *c) statusbar_position_update(s); } } - p_delete(&strut_r); + + p_delete(&mstrut_r); } @@ -505,27 +507,18 @@ ewmh_window_icon_get_unchecked(xcb_window_t w) _NET_WM_ICON, CARDINAL, 0, UINT32_MAX); } -/** Get NET_WM_ICON. - * \param cookie The cookie. - * \return A draw_image_t structure which must be deleted after usage. - */ draw_image_t * -ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie) +ewmh_window_icon_from_reply(xcb_get_property_reply_t *r) { double alpha; draw_image_t *icon; int size, i; uint32_t *data; unsigned char *imgdata; - xcb_get_property_reply_t *r; - r = xcb_get_property_reply(globalconf.connection, cookie, NULL); if(!r || r->type != CARDINAL || r->format != 32 || r->length < 2 || !(data = (uint32_t *) xcb_get_property_value(r))) - { - p_delete(&r); return NULL; - } icon = p_new(draw_image_t, 1); @@ -550,8 +543,19 @@ ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie) imgdata[0] = (data[i] & 0xff) * alpha; /* B */ } - p_delete(&r); + return icon; +} +/** Get NET_WM_ICON. + * \param cookie The cookie. + * \return A draw_image_t structure which must be deleted after usage. + */ +draw_image_t * +ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie) +{ + xcb_get_property_reply_t *r = xcb_get_property_reply(globalconf.connection, cookie, NULL); + draw_image_t *icon = ewmh_window_icon_from_reply(r); + p_delete(&r); return icon; } diff --git a/ewmh.h b/ewmh.h index 63aea45b..481d0883 100644 --- a/ewmh.h +++ b/ewmh.h @@ -34,8 +34,9 @@ int ewmh_process_client_message(xcb_client_message_event_t *); void ewmh_update_net_client_list_stacking(int); void ewmh_check_client_hints(client_t *); void ewmh_update_workarea(int); -void ewmh_client_strut_update(client_t *); +void ewmh_client_strut_update(client_t *, xcb_get_property_reply_t *); xcb_get_property_cookie_t ewmh_window_icon_get_unchecked(xcb_window_t); +draw_image_t *ewmh_window_icon_from_reply(xcb_get_property_reply_t *); draw_image_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t); #endif diff --git a/property.c b/property.c new file mode 100644 index 00000000..a83a846e --- /dev/null +++ b/property.c @@ -0,0 +1,355 @@ +/* + * property.c - property handlers + * + * Copyright © 2008 Julien Danjou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include + +#include "property.h" +#include "client.h" +#include "widget.h" +#include "ewmh.h" +#include "common/atoms.h" + +extern awesome_t globalconf; + + +void +property_update_wm_transient_for(client_t *c, xcb_get_property_reply_t *reply) +{ + xcb_window_t trans; + + if(reply) + { + if(!xcb_get_wm_transient_for_from_reply(&trans, reply)) + return; + } + else + { + if(!xcb_get_wm_transient_for_reply(globalconf.connection, + xcb_get_wm_transient_for_unchecked(globalconf.connection, + c->win), + &trans, NULL)) + return; + } + + client_setfloating(c, true); +} + +static int +property_handle_wm_transient_for(void *data, + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + client_t *c = client_getbywin(window); + + if(c && !client_isfloating(c)) + property_update_wm_transient_for(c, reply); + + return 0; +} + +/** Update the size hints of a client. + * \param c The client. + */ +void +property_update_wm_normal_hints(client_t *c, xcb_get_property_reply_t *reply) +{ + if(reply) + { + if(!xcb_get_wm_size_hints_from_reply(&c->size_hints, reply)) + return; + } + else + { + if(!xcb_get_wm_normal_hints_reply(globalconf.connection, + xcb_get_wm_normal_hints_unchecked(globalconf.connection, + c->win), + &c->size_hints, NULL)) + return; + } + + if((c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)) + { + c->basew = c->size_hints.base_width; + c->baseh = c->size_hints.base_height; + } + else if((c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) + { + c->basew = c->size_hints.min_width; + c->baseh = c->size_hints.min_height; + } + else + c->basew = c->baseh = 0; + + if((c->size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)) + { + c->incw = c->size_hints.width_inc; + c->inch = c->size_hints.height_inc; + } + else + c->incw = c->inch = 0; + + if((c->size_hints.flags & XCB_SIZE_HINT_P_MAX_SIZE)) + { + c->maxw = c->size_hints.max_width; + c->maxh = c->size_hints.max_height; + } + else + c->maxw = c->maxh = 0; + + if((c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) + { + c->minw = c->size_hints.min_width; + c->minh = c->size_hints.min_height; + } + else if((c->size_hints.flags & XCB_SIZE_HINT_BASE_SIZE)) + { + c->minw = c->size_hints.base_width; + c->minh = c->size_hints.base_height; + } + else + c->minw = c->minh = 0; + + if((c->size_hints.flags & XCB_SIZE_HINT_P_ASPECT)) + { + c->minax = c->size_hints.min_aspect_num; + c->minay = c->size_hints.min_aspect_den; + c->maxax = c->size_hints.max_aspect_num; + c->maxay = c->size_hints.max_aspect_den; + } + else + c->minax = c->maxax = c->minay = c->maxay = 0; + + c->hassizehints = !(!c->basew && !c->baseh && !c->incw && !c->inch + && !c->maxw && !c->maxh && !c->minw && !c->minh + && !c->minax && !c->maxax && !c->minax && !c->minay); +} + +static int +property_handle_wm_normal_hints(void *data, + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + client_t *c = client_getbywin(window); + + if(c) + property_update_wm_normal_hints(c, reply); + + return 0; +} + +/** Update the WM hints of a client. + * \param c The client. + */ +void +property_update_wm_hints(client_t *c, xcb_get_property_reply_t *reply) +{ + xcb_wm_hints_t wmh; + + if(reply) + { + if(!xcb_get_wm_hints_from_reply(&wmh, reply)) + return; + } + else + { + if(!xcb_get_wm_hints_reply(globalconf.connection, + xcb_get_wm_hints_unchecked(globalconf.connection, c->win), + &wmh, NULL)) + return; + } + + bool isurgent = xcb_wm_hints_get_urgency(&wmh); + if(isurgent != c->isurgent) + { + c->isurgent = isurgent; + + /* execute hook */ + luaA_client_userdata_new(globalconf.L, c); + luaA_dofunction(globalconf.L, globalconf.hooks.urgent, 1, 0); + + widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); + } + if((wmh.flags & XCB_WM_HINT_STATE) && + wmh.initial_state == XCB_WM_STATE_WITHDRAWN) + client_setborder(c, 0); + + c->nofocus = !wmh.input; +} + +static int +property_handle_wm_hints(void *data, + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + client_t *c = client_getbywin(window); + + if(c) + property_update_wm_hints(c, reply); + + return 0; +} + +/** Update client name attribute with its new title. + * \param c The client. + * \param Return true if it has been updated. + */ +void +property_update_wm_name(client_t *c) +{ + char *name, *utf8; + ssize_t len; + + if(!xutil_text_prop_get(globalconf.connection, c->win, _NET_WM_NAME, &name, &len)) + if(!xutil_text_prop_get(globalconf.connection, c->win, WM_NAME, &name, &len)) + return; + + p_delete(&c->name); + + if((utf8 = draw_iso2utf8(name, len))) + c->name = utf8; + else + c->name = name; + + /* call hook */ + luaA_client_userdata_new(globalconf.L, c); + luaA_dofunction(globalconf.L, globalconf.hooks.titleupdate, 1, 0); + + widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); +} + +static int +property_handle_wm_name(void *data, + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + client_t *c = client_getbywin(window); + + if(c) + property_update_wm_name(c); + + return 0; +} + +static int +property_handle_net_wm_strut_partial(void *data, + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + client_t *c = client_getbywin(window); + + if(c) + ewmh_client_strut_update(c, reply); + + return 0; +} + +static int +property_handle_net_wm_icon(void *data, + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + client_t *c = client_getbywin(window); + + if(c) + { + draw_image_t *icon; + image_unref(&c->icon); + widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS); + if((icon = ewmh_window_icon_from_reply(reply))) + { + c->icon = image_new(icon); + image_ref(&c->icon); + } + else + c->icon = NULL; + } + + return 0; +} + +/** The property notify event handler. + * \param data currently unused. + * \param connection The connection to the X server. + * \param ev The event. + */ +static int +property_handle_xembed_info(void *data __attribute__ ((unused)), + xcb_connection_t *connection, + uint8_t state, + xcb_window_t window, + xcb_atom_t name, + xcb_get_property_reply_t *reply) +{ + xembed_window_t *emwin = xembed_getbywin(globalconf.embedded, window); + + if(emwin) + xembed_property_update(connection, emwin, reply); + + return 0; +} + +void a_xcb_set_property_handlers(void) +{ + /* init */ + xcb_property_handlers_init(&globalconf.prophs, &globalconf.evenths); + + /* Xembed stuff */ + xcb_property_set_handler(&globalconf.prophs, _XEMBED_INFO, UINT_MAX, + property_handle_xembed_info, NULL); + + /* ICCCM stuff */ + xcb_property_set_handler(&globalconf.prophs, WM_TRANSIENT_FOR, UINT_MAX, + property_handle_wm_transient_for, NULL); + xcb_property_set_handler(&globalconf.prophs, WM_NORMAL_HINTS, UINT_MAX, + property_handle_wm_normal_hints, NULL); + xcb_property_set_handler(&globalconf.prophs, WM_HINTS, UINT_MAX, + property_handle_wm_hints, NULL); + xcb_property_set_handler(&globalconf.prophs, WM_NAME, UINT_MAX, + property_handle_wm_name, NULL); + + /* EWMH stuff */ + xcb_property_set_handler(&globalconf.prophs, _NET_WM_NAME, UINT_MAX, + property_handle_wm_name, NULL); + xcb_property_set_handler(&globalconf.prophs, _NET_WM_STRUT_PARTIAL, UINT_MAX, + property_handle_net_wm_strut_partial, NULL); + xcb_property_set_handler(&globalconf.prophs, _NET_WM_ICON, UINT_MAX, + property_handle_net_wm_icon, NULL); +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/property.h b/property.h new file mode 100644 index 00000000..56cfba4d --- /dev/null +++ b/property.h @@ -0,0 +1,34 @@ +/* + * property.h - property handlers header + * + * Copyright © 2008 Julien Danjou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef AWESOME_PROPERTY_H +#define AWESOME_PROPERTY_H + +#include "structs.h" + +void property_update_wm_transient_for(client_t *, xcb_get_property_reply_t *); +void property_update_wm_normal_hints(client_t *, xcb_get_property_reply_t *); +void property_update_wm_hints(client_t *, xcb_get_property_reply_t *); +void property_update_wm_name(client_t *); +void a_xcb_set_property_handlers(void); + +#endif +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/structs.h b/structs.h index 38dd4e01..92040c33 100644 --- a/structs.h +++ b/structs.h @@ -24,6 +24,7 @@ #include #include +#include #include #include "lua.h" @@ -425,6 +426,8 @@ struct awesome_t xcb_connection_t *connection; /** Event and error handlers */ xcb_event_handlers_t evenths; + /** Property change handler */ + xcb_property_handlers_t prophs; /** Default screen number */ int default_screen; /** Keys symbol table */