[all] Implement an atom cache in xutil as an ordered linked-list
This commit is contained in:
parent
6a06e44461
commit
162b8a690c
|
@ -386,7 +386,8 @@ main(int argc, char **argv)
|
|||
xutil_getlockmask(globalconf.connection, globalconf.keysyms, &globalconf.numlockmask,
|
||||
&globalconf.shiftlockmask, &globalconf.capslockmask);
|
||||
|
||||
/* init EWMH atoms */
|
||||
/* init Atoms cache and then EWMH atoms */
|
||||
atom_cache_list_init(&globalconf.atoms);
|
||||
ewmh_init_atoms();
|
||||
|
||||
/* init screens struct */
|
||||
|
|
51
client.c
51
client.c
|
@ -60,8 +60,11 @@ client_loadprops(client_t * c, int screen)
|
|||
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
|
||||
ntags++;
|
||||
|
||||
if(xutil_gettextprop(globalconf.connection, c->win,
|
||||
xutil_intern_atom(globalconf.connection, "_AWESOME_PROPERTIES"),
|
||||
if(xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
|
||||
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"_AWESOME_PROPERTIES")),
|
||||
&prop))
|
||||
{
|
||||
for(i = 0, tag = globalconf.screens[screen].tags; tag && i < ntags && prop[i]; i++, tag = tag->next)
|
||||
|
@ -90,13 +93,19 @@ static bool
|
|||
client_isprotodel(xcb_window_t win)
|
||||
{
|
||||
uint32_t i, n;
|
||||
xcb_atom_t wm_delete_win_atom;
|
||||
xcb_atom_t *protocols;
|
||||
bool ret = false;
|
||||
|
||||
if(xcb_get_wm_protocols(globalconf.connection, win, &n, &protocols))
|
||||
{
|
||||
wm_delete_win_atom = xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"WM_DELETE_WINDOW"));
|
||||
|
||||
for(i = 0; !ret && i < n; i++)
|
||||
if(protocols[i] == xutil_intern_atom(globalconf.connection, "WM_DELETE_WINDOW"))
|
||||
if(protocols[i] == wm_delete_win_atom)
|
||||
ret = true;
|
||||
p_delete(&protocols);
|
||||
}
|
||||
|
@ -188,11 +197,18 @@ client_updatetitle(client_t *c)
|
|||
{
|
||||
char *name;
|
||||
|
||||
if(!xutil_gettextprop(globalconf.connection, c->win,
|
||||
xutil_intern_atom(globalconf.connection, "_NET_WM_NAME"),
|
||||
if(!xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
|
||||
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"_NET_WM_NAME")),
|
||||
&name))
|
||||
if(!xutil_gettextprop(globalconf.connection, c->win,
|
||||
xutil_intern_atom(globalconf.connection, "WM_NAME"),
|
||||
if(!xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
|
||||
xutil_intern_atom_reply(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"WM_NAME")),
|
||||
&name))
|
||||
return;
|
||||
|
||||
|
@ -687,7 +703,10 @@ client_saveprops(client_t *c)
|
|||
prop[++i] = '\0';
|
||||
|
||||
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, c->win,
|
||||
xutil_intern_atom(globalconf.connection, "_AWESOME_PROPERTIES"),
|
||||
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"_AWESOME_PROPERTIES")),
|
||||
STRING, 8, i, (unsigned char *) prop);
|
||||
|
||||
p_delete(&prop);
|
||||
|
@ -871,7 +890,11 @@ uicb_client_settrans(int screen __attribute__ ((unused)), char *arg)
|
|||
prop_r = xcb_get_property_reply(globalconf.connection,
|
||||
xcb_get_property_unchecked(globalconf.connection,
|
||||
false, sel->win,
|
||||
xutil_intern_atom(globalconf.connection, "_NET_WM_WINDOW_OPACITY"),
|
||||
xutil_intern_atom_reply(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"_NET_WM_WINDOW_OPACITY")),
|
||||
CARDINAL,
|
||||
0, 1),
|
||||
NULL);
|
||||
|
@ -1048,10 +1071,16 @@ client_kill(client_t *c)
|
|||
|
||||
ev.response_type = XCB_CLIENT_MESSAGE;
|
||||
ev.window = c->win;
|
||||
ev.type = xutil_intern_atom(globalconf.connection, "WM_PROTOCOLS");
|
||||
ev.type = xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"WM_PROTOCOLS"));
|
||||
ev.format = 32;
|
||||
|
||||
ev.data.data32[0] = xutil_intern_atom(globalconf.connection, "WM_DELETE_WINDOW");
|
||||
ev.data.data32[0] = xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"WM_DELETE_WINDOW"));
|
||||
ev.data.data32[1] = XCB_CURRENT_TIME;
|
||||
|
||||
xcb_send_event(globalconf.connection, false, c->win,
|
||||
|
|
114
common/xutil.c
114
common/xutil.c
|
@ -33,13 +33,14 @@
|
|||
/** Get the string value of an atom.
|
||||
* \param conn X connection
|
||||
* \param w window
|
||||
* \param atoms atoms cache
|
||||
* \param atom the atom
|
||||
* \param text buffer to fill
|
||||
* \return true on sucess, falsse on failure
|
||||
*/
|
||||
bool
|
||||
xutil_gettextprop(xcb_connection_t *conn, xcb_window_t w, xcb_atom_t atom,
|
||||
char **text)
|
||||
xutil_gettextprop(xcb_connection_t *conn, xcb_window_t w, xutil_atom_cache_t **atoms,
|
||||
xcb_atom_t atom, char **text)
|
||||
{
|
||||
xcb_get_property_cookie_t prop_c;
|
||||
xcb_get_property_reply_t *prop_r;
|
||||
|
@ -67,7 +68,9 @@ xutil_gettextprop(xcb_connection_t *conn, xcb_window_t w, xcb_atom_t atom,
|
|||
* string or utf8 string. At the moment it doesn't handle
|
||||
* COMPOUND_TEXT and multibyte but it's not needed... */
|
||||
if(prop_r->type == STRING ||
|
||||
prop_r->type == xutil_intern_atom(conn, "UTF8_STRING"))
|
||||
prop_r->type == xutil_intern_atom_reply(conn, atoms,
|
||||
xutil_intern_atom(conn, atoms,
|
||||
"UTF8_STRING")))
|
||||
{
|
||||
*text = p_new(char, prop_r->value_len + 1);
|
||||
/* use memcpy() because prop_val may not be \0 terminated */
|
||||
|
@ -152,29 +155,106 @@ xutil_get_transient_for_hint(xcb_connection_t *c, xcb_window_t win,
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Get an internal atom.
|
||||
/** Send an unchecked InternAtom request if it is not already in the
|
||||
* cache, in the second case it stores the cache entry (an ordered
|
||||
* linked-list)
|
||||
* \param c X connection
|
||||
* \param atoms atoms cache
|
||||
* \param property atom name
|
||||
* \return an brand new xcb_atom_t
|
||||
* \return a request structure
|
||||
*/
|
||||
xutil_intern_atom_request_t
|
||||
xutil_intern_atom(xcb_connection_t *c, xutil_atom_cache_t **atoms,
|
||||
const char *name)
|
||||
{
|
||||
xutil_intern_atom_request_t atom_req;
|
||||
xutil_atom_cache_t *atom_next;
|
||||
int cmp_cache;
|
||||
|
||||
atom_req.name = strdup(name);
|
||||
|
||||
/* Check if this atom is present in the cache ordered
|
||||
* linked-list */
|
||||
for(atom_next = *atoms;
|
||||
atom_next && (cmp_cache = a_strcmp(name, atom_next->name)) >= 0;
|
||||
atom_next = atom_cache_list_next(NULL, atom_next))
|
||||
if(cmp_cache == 0)
|
||||
{
|
||||
atom_req.cache_hit = true;
|
||||
atom_req.cache = atom_next;
|
||||
return atom_req;
|
||||
}
|
||||
|
||||
/* Otherwise send an InternAtom request to the server */
|
||||
atom_req.cache_hit = false;
|
||||
atom_req.cookie = xcb_intern_atom_unchecked(c, false, a_strlen(name),
|
||||
name);
|
||||
|
||||
return atom_req;
|
||||
}
|
||||
|
||||
/** Treat the reply which may be a cache entry or a reply from
|
||||
* InternAtom request (cookie), in the second case, add the atom to
|
||||
* the cache
|
||||
* \param c X connection
|
||||
* \param atoms atoms cache
|
||||
* \param atom_req atom request
|
||||
* \return a brand new xcb_atom_t
|
||||
*/
|
||||
xcb_atom_t
|
||||
xutil_intern_atom(xcb_connection_t *c, const char *property)
|
||||
xutil_intern_atom_reply(xcb_connection_t *c, xutil_atom_cache_t **atoms,
|
||||
xutil_intern_atom_request_t atom_req)
|
||||
{
|
||||
xcb_atom_t atom = 0;
|
||||
xcb_intern_atom_reply_t *r_atom;
|
||||
xcb_intern_atom_reply_t *atom_rep;
|
||||
xutil_atom_cache_t *atom_cache, *atom_next;
|
||||
|
||||
if((r_atom = xcb_intern_atom_reply(c,
|
||||
xcb_intern_atom_unchecked(c,
|
||||
false,
|
||||
a_strlen(property),
|
||||
property),
|
||||
NULL)))
|
||||
/* If the atom is present in the cache, just returns the
|
||||
* atom... */
|
||||
if(atom_req.cache_hit)
|
||||
return atom_req.cache->atom;
|
||||
|
||||
/* Get the reply from InternAtom request */
|
||||
if((atom_rep = xcb_intern_atom_reply(c, atom_req.cookie, NULL)) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Create a new atom cache entry */
|
||||
atom_cache = p_new(xutil_atom_cache_t, 1);
|
||||
atom_cache->atom = atom_rep->atom;
|
||||
atom_cache->name = atom_req.name;
|
||||
|
||||
/* Add the entry in the list at the beginning of the cache list */
|
||||
if(*atoms == NULL || a_strcmp(atom_req.name, (*atoms)->name) < 0)
|
||||
atom_cache_list_push(atoms, atom_cache);
|
||||
/* Otherwise insert it at the proper position in the cache list
|
||||
* according to its name */
|
||||
else
|
||||
{
|
||||
atom = r_atom->atom;
|
||||
p_delete(&r_atom);
|
||||
for(atom_next = *atoms;
|
||||
atom_next && atom_next->next && a_strcmp(atom_req.name, atom_next->next->name) > 0;
|
||||
atom_next = atom_cache_list_next(NULL, atom_next));
|
||||
|
||||
atom_cache->prev = atom_next;
|
||||
atom_cache->next = atom_next->next;
|
||||
|
||||
if(atom_next->next)
|
||||
atom_next->next->prev = atom_cache;
|
||||
|
||||
atom_next->next = atom_cache;
|
||||
}
|
||||
|
||||
return atom;
|
||||
p_delete(&atom_rep);
|
||||
|
||||
return atom_cache->atom;
|
||||
}
|
||||
|
||||
/* Delete a cache entry
|
||||
* \param entry cache entry
|
||||
*/
|
||||
void
|
||||
xutil_atom_cache_delete(xutil_atom_cache_t **entry)
|
||||
{
|
||||
p_delete(&(*entry)->name);
|
||||
p_delete(entry);
|
||||
}
|
||||
|
||||
class_hint_t *
|
||||
|
|
|
@ -31,9 +31,7 @@
|
|||
/* XCB doesn't provide keysyms definition */
|
||||
#include <X11/keysym.h>
|
||||
|
||||
bool xutil_gettextprop(xcb_connection_t *, xcb_window_t, xcb_atom_t, char **);
|
||||
void xutil_getlockmask(xcb_connection_t *, xcb_key_symbols_t *,
|
||||
unsigned int *, unsigned int *, unsigned int *);
|
||||
#include "common/list.h"
|
||||
|
||||
/* See http://tronche.com/gui/x/xlib/appendix/b/ for values */
|
||||
#define CURSOR_FLEUR 52
|
||||
|
@ -81,7 +79,7 @@ void xutil_getlockmask(xcb_connection_t *, xcb_key_symbols_t *,
|
|||
/* Common function defined in Xlib but not in XCB */
|
||||
bool xutil_get_transient_for_hint(xcb_connection_t *, xcb_window_t, xcb_window_t *);
|
||||
|
||||
typedef struct _class_hint_t
|
||||
typedef struct
|
||||
{
|
||||
char *res_name;
|
||||
char *res_class;
|
||||
|
@ -97,18 +95,61 @@ typedef struct
|
|||
|
||||
class_hint_t *xutil_get_class_hint(xcb_connection_t *, xcb_window_t);
|
||||
|
||||
/* Equivalent call to XInternAtom
|
||||
*
|
||||
* WARNING: should not be used in loop, in this case, it should send
|
||||
* the queries first and then treat the answer as late as possible)
|
||||
*/
|
||||
xcb_atom_t xutil_intern_atom(xcb_connection_t *, const char *);
|
||||
/** Cache entry */
|
||||
typedef struct xutil_atom_cache_t xutil_atom_cache_t;
|
||||
struct xutil_atom_cache_t
|
||||
{
|
||||
/** Atom X identifier */
|
||||
xcb_atom_t atom;
|
||||
/** Atom name */
|
||||
char *name;
|
||||
/** Next and previous atom cache entries */
|
||||
xutil_atom_cache_t *prev, *next;
|
||||
};
|
||||
|
||||
/** InternAtom request data structure which may hold the cookie if the
|
||||
* atom is not already present in the cache */
|
||||
typedef struct
|
||||
{
|
||||
/* Cache hit */
|
||||
bool cache_hit;
|
||||
/* Atom string name */
|
||||
char *name;
|
||||
union
|
||||
{
|
||||
/* Cookie of the InternAtom request */
|
||||
xcb_intern_atom_cookie_t cookie;
|
||||
/* Cache entry */
|
||||
xutil_atom_cache_t *cache;
|
||||
};
|
||||
} xutil_intern_atom_request_t;
|
||||
|
||||
/* InternATom request which relies on a cache stored as a ordered
|
||||
* linked-list */
|
||||
xutil_intern_atom_request_t xutil_intern_atom(xcb_connection_t *, xutil_atom_cache_t **,
|
||||
const char *);
|
||||
|
||||
/** Treat reply from InternAtom request */
|
||||
xcb_atom_t xutil_intern_atom_reply(xcb_connection_t *, xutil_atom_cache_t **,
|
||||
xutil_intern_atom_request_t);
|
||||
|
||||
/** Delete a entry in the cache */
|
||||
void xutil_atom_cache_delete(xutil_atom_cache_t **);
|
||||
|
||||
/** Cache list utils functions */
|
||||
DO_SLIST(xutil_atom_cache_t, atom_cache, xutil_atom_cache_delete)
|
||||
|
||||
bool xutil_gettextprop(xcb_connection_t *, xcb_window_t, xutil_atom_cache_t **,
|
||||
xcb_atom_t, char **);
|
||||
|
||||
void xutil_getlockmask(xcb_connection_t *, xcb_key_symbols_t *,
|
||||
unsigned int *, unsigned int *, unsigned int *);
|
||||
|
||||
/** Set the same handler for all errors */
|
||||
void xutil_set_error_handler_catch_all(xcb_event_handlers_t *,
|
||||
xcb_generic_error_handler_t, void *);
|
||||
|
||||
typedef struct xutil_error_t
|
||||
typedef struct
|
||||
{
|
||||
uint8_t request_code;
|
||||
char *request_label;
|
||||
|
|
5
event.c
5
event.c
|
@ -520,7 +520,10 @@ event_handle_propertynotify(void *data __attribute__ ((unused)),
|
|||
client_updatewmhints(c);
|
||||
|
||||
if(ev->atom == WM_NAME
|
||||
|| ev->atom == xutil_intern_atom(globalconf.connection, "_NET_WM_NAME"))
|
||||
|| ev->atom == xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"_NET_WM_NAME")))
|
||||
client_updatetitle(c);
|
||||
}
|
||||
|
||||
|
|
8
rules.c
8
rules.c
|
@ -83,8 +83,12 @@ rule_matching_client(client_t *c)
|
|||
if(!ret
|
||||
&& r->xprop
|
||||
&& r->xpropval_r
|
||||
&& xutil_gettextprop(globalconf.connection, c->win,
|
||||
xutil_intern_atom(globalconf.connection, r->xprop),
|
||||
&& xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
|
||||
xutil_intern_atom_reply(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
r->xprop)),
|
||||
&buf))
|
||||
ret = !regexec(r->xpropval_r, buf, 1, &tmp, 0);
|
||||
|
||||
|
|
|
@ -380,6 +380,8 @@ struct AwesomeConf
|
|||
char *argv;
|
||||
/** Last XMotionEvent coords */
|
||||
int pointer_x, pointer_y;
|
||||
/** Atoms cache */
|
||||
xutil_atom_cache_t *atoms;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
23
window.c
23
window.c
|
@ -41,11 +41,13 @@ void
|
|||
window_setstate(xcb_window_t win, long state)
|
||||
{
|
||||
long data[] = { state, XCB_NONE };
|
||||
const xcb_atom_t wm_state_atom = xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"WM_STATE"));
|
||||
|
||||
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, win,
|
||||
xutil_intern_atom(globalconf.connection, "WM_STATE"),
|
||||
xutil_intern_atom(globalconf.connection, "WM_STATE"), 32,
|
||||
2, data);
|
||||
wm_state_atom, wm_state_atom, 32, 2, data);
|
||||
}
|
||||
|
||||
/** Get a window state (WM_STATE).
|
||||
|
@ -58,7 +60,10 @@ window_getstate(xcb_window_t w)
|
|||
long result = -1;
|
||||
unsigned char *p = NULL;
|
||||
xcb_get_property_cookie_t prop_c;
|
||||
xcb_atom_t wm_state_atom = xutil_intern_atom(globalconf.connection, "WM_STATE");
|
||||
xcb_atom_t wm_state_atom = xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"WM_STATE"));
|
||||
xcb_get_property_reply_t *prop_r;
|
||||
|
||||
prop_c = xcb_get_property_unchecked(globalconf.connection, false, w,
|
||||
|
@ -224,17 +229,21 @@ void
|
|||
window_settrans(xcb_window_t win, double opacity)
|
||||
{
|
||||
unsigned int real_opacity = 0xffffffff;
|
||||
const xcb_atom_t wopacity_atom = xutil_intern_atom_reply(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
xutil_intern_atom(globalconf.connection,
|
||||
&globalconf.atoms,
|
||||
"_NET_WM_WINDOW_OPACITY"));
|
||||
|
||||
if(opacity >= 0 && opacity <= 1)
|
||||
{
|
||||
real_opacity = opacity * 0xffffffff;
|
||||
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, win,
|
||||
xutil_intern_atom(globalconf.connection, "_NET_WM_WINDOW_OPACITY"),
|
||||
CARDINAL, 32, 1L, &real_opacity);
|
||||
wopacity_atom, CARDINAL, 32, 1L, &real_opacity);
|
||||
}
|
||||
else
|
||||
xcb_delete_property(globalconf.connection, win,
|
||||
xutil_intern_atom(globalconf.connection, "_NET_WM_WINDOW_OPACITY"));
|
||||
wopacity_atom);
|
||||
}
|
||||
|
||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
||||
|
|
Loading…
Reference in New Issue