property: use xcb property handler system
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
71ac6710e5
commit
2be620618b
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
143
client.c
143
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.
|
||||
|
|
3
client.h
3
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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
59
event.c
59
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);
|
||||
|
|
42
ewmh.c
42
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;
|
||||
}
|
||||
|
||||
|
|
3
ewmh.h
3
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
|
||||
|
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* property.c - property handlers
|
||||
*
|
||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
||||
*
|
||||
* 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 <xcb/xcb_atom.h>
|
||||
|
||||
#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
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* property.h - property handlers header
|
||||
*
|
||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
||||
*
|
||||
* 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
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <xcb/xcb_event.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xcb_property.h>
|
||||
#include <ev.h>
|
||||
|
||||
#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 */
|
||||
|
|
Loading…
Reference in New Issue