add an option to set the preferred client icon size

_NET_WM_ICON contains a list of icons and until now, the first one was
picked without regard to it's size. This adds a global option to set
the preferred icon size. When getting the client icon, the best size
match is picked. The size can be set via
awesome.set_preferred_icon_size() and the default is 0, which will pick
the smallest non-zero size icon available.

Signed-off-by: Lukáš Hrázký <lukkash@email.cz>
This commit is contained in:
Lukáš Hrázký 2015-11-30 20:26:26 +01:00
parent 0516203610
commit ea94f7f7e6
6 changed files with 55 additions and 16 deletions

View file

@ -543,6 +543,9 @@ main(int argc, char **argv)
/* We have no clue where the input focus is right now */
globalconf.focus.need_update = true;
/* set the default preferred icon size */
globalconf.preferred_icon_size = 0;
/* XLib sucks */
XkbIgnoreExtension(True);

46
ewmh.c
View file

@ -662,27 +662,45 @@ ewmh_window_icon_get_unchecked(xcb_window_t w)
}
static cairo_surface_t *
ewmh_window_icon_from_reply(xcb_get_property_reply_t *r)
ewmh_window_icon_from_reply(xcb_get_property_reply_t *r, uint32_t preferred_size)
{
uint32_t *data;
uint64_t len;
uint32_t *data, *end, *found_data = 0;
uint32_t found_size = 0;
if(!r || r->type != XCB_ATOM_CARDINAL || r->format != 32 || r->length < 2)
return 0;
data = (uint32_t *) xcb_get_property_value(r);
if (!data)
return 0;
if (!data) return 0;
/* Check that the property is as long as it should be, handling integer
* overflow. <uint32_t> times <another uint32_t casted to uint64_t> always
* fits into an uint64_t and thus this multiplication cannot overflow.
end = data + r->length;
/* Goes over the icon data and picks the icon that best matches the size preference.
* In case the size match is not exact, picks the closest bigger size if present,
* closest smaller size otherwise.
*/
len = data[0] * (uint64_t) data[1];
if (!data[0] || !data[1] || len > r->length - 2)
return 0;
while (data + 1 < end) {
/* check whether the data size specified by width and height fits into the array we got */
uint64_t data_size = (uint64_t) data[0] * data[1];
if (data_size > (uint64_t) (end - data - 2)) break;
return draw_surface_from_data(data[0], data[1], data + 2);
/* use the greater of the two dimensions to match against the preferred size */
uint32_t size = MAX(data[0], data[1]);
/* pick the icon if it's a better match than the one we already have */
if (data[0] && data[1] && (
(found_size < preferred_size && size > found_size) ||
(found_size > preferred_size && size >= preferred_size && size < found_size)))
{
found_data = data;
found_size = size;
}
data += data_size + 2;
}
if (!found_data) return 0;
return draw_surface_from_data(found_data[0], found_data[1], found_data + 2);
}
/** Get NET_WM_ICON.
@ -690,10 +708,10 @@ ewmh_window_icon_from_reply(xcb_get_property_reply_t *r)
* \return The number of elements on stack.
*/
cairo_surface_t *
ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie)
ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie, uint32_t preferred_size)
{
xcb_get_property_reply_t *r = xcb_get_property_reply(globalconf.connection, cookie, NULL);
cairo_surface_t *surface = ewmh_window_icon_from_reply(r);
cairo_surface_t *surface = ewmh_window_icon_from_reply(r, preferred_size);
p_delete(&r);
return surface;
}

2
ewmh.h
View file

@ -41,7 +41,7 @@ void ewmh_process_client_strut(client_t *);
void ewmh_update_strut(xcb_window_t, strut_t *);
void ewmh_update_window_type(xcb_window_t window, uint32_t type);
xcb_get_property_cookie_t ewmh_window_icon_get_unchecked(xcb_window_t);
cairo_surface_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t);
cairo_surface_t *ewmh_window_icon_get_reply(xcb_get_property_cookie_t, uint32_t preferred_size);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View file

@ -167,6 +167,8 @@ typedef struct
struct xkb_context *xkb_ctx;
/* xkb state of dead keys on keyboard */
struct xkb_state *xkb_state;
/** The preferred size of client icons for this screen */
uint32_t preferred_icon_size;
} awesome_t;
extern awesome_t globalconf;

16
luaa.c
View file

@ -162,6 +162,21 @@ luaA_load_image(lua_State *L)
return 1;
}
/** Set the preferred size for client icons.
*
* The closest equal or bigger size is picked if present, otherwise the closest
* smaller size is picked. The default is 0 pixels, ie. the smallest icon.
*
* @param size The size of the icons in pixels.
* @function set_preferred_icon_size
*/
static int
luaA_set_preferred_icon_size(lua_State *L)
{
globalconf.preferred_icon_size = luaL_checknumber(L, 1);
return 0;
}
/** UTF-8 aware string length computing.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
@ -407,6 +422,7 @@ luaA_init(xdgHandle* xdg)
{ "emit_signal", luaA_awesome_emit_signal },
{ "systray", luaA_systray },
{ "load_image", luaA_load_image },
{ "set_preferred_icon_size", luaA_set_preferred_icon_size },
{ "register_xproperty", luaA_register_xproperty },
{ "set_xproperty", luaA_set_xproperty },
{ "get_xproperty", luaA_get_xproperty },

View file

@ -273,7 +273,7 @@ property_get_net_wm_icon(client_t *c)
void
property_update_net_wm_icon(client_t *c, xcb_get_property_cookie_t cookie)
{
cairo_surface_t *surface = ewmh_window_icon_get_reply(cookie);
cairo_surface_t *surface = ewmh_window_icon_get_reply(cookie, globalconf.preferred_icon_size);
if(!surface)
return;