Implement icon_pixmap and icon_mask from WM_HINTS (FS#1297)
Fun fact: ICCCM specifies that icon_pixmap must have depth 1. Xterm uses a pixmap with depth 24. Yay... As such, I don't have any test for the depth == 1 case and will just assume that it does the right thing. If it doesn't, I bet no one will notice anyway. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
b9ea9255e9
commit
30b313f77a
25
draw.c
25
draw.c
|
@ -188,6 +188,18 @@ draw_surface_from_pixbuf(GdkPixbuf *buf)
|
|||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
get_surface_size(cairo_surface_t *surface, int *width, int *height)
|
||||
{
|
||||
double x1, y1, x2, y2;
|
||||
cairo_t *cr = cairo_create(surface);
|
||||
|
||||
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
|
||||
cairo_destroy(cr);
|
||||
*width = x2 - x1;
|
||||
*height = y2 - y1;
|
||||
}
|
||||
|
||||
/** Duplicate the specified image surface.
|
||||
* \param surface The surface to copy
|
||||
* \return A pointer to a new cairo image surface.
|
||||
|
@ -195,10 +207,15 @@ draw_surface_from_pixbuf(GdkPixbuf *buf)
|
|||
cairo_surface_t *
|
||||
draw_dup_image_surface(cairo_surface_t *surface)
|
||||
{
|
||||
cairo_surface_t *res = cairo_image_surface_create(
|
||||
cairo_image_surface_get_format(surface),
|
||||
cairo_image_surface_get_width(surface),
|
||||
cairo_image_surface_get_height(surface));
|
||||
cairo_surface_t *res;
|
||||
int width, height;
|
||||
|
||||
get_surface_size(surface, &width, &height);
|
||||
#if CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR > 12
|
||||
res = cairo_surface_create_similar_image(surface, CAIRO_FORMAT_ARGB32, width, height);
|
||||
#else
|
||||
res = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
#endif
|
||||
|
||||
cairo_t *cr = cairo_create(res);
|
||||
cairo_set_source_surface(cr, surface, 0, 0);
|
||||
|
|
|
@ -1308,6 +1308,71 @@ client_set_icon(client_t *c, cairo_surface_t *s)
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/** Set a client icon.
|
||||
* \param c The client to change.
|
||||
* \param icon A bitmap containing the icon.
|
||||
* \param mask A mask for the bitmap (optional)
|
||||
*/
|
||||
void
|
||||
client_set_icon_from_pixmaps(client_t *c, xcb_pixmap_t icon, xcb_pixmap_t mask)
|
||||
{
|
||||
xcb_get_geometry_cookie_t geom_icon_c, geom_mask_c;
|
||||
xcb_get_geometry_reply_t *geom_icon_r, *geom_mask_r = NULL;
|
||||
cairo_surface_t *s_icon, *result;
|
||||
|
||||
geom_icon_c = xcb_get_geometry_unchecked(globalconf.connection, icon);
|
||||
if (mask)
|
||||
geom_mask_c = xcb_get_geometry_unchecked(globalconf.connection, mask);
|
||||
geom_icon_r = xcb_get_geometry_reply(globalconf.connection, geom_icon_c, NULL);
|
||||
if (mask)
|
||||
geom_mask_r = xcb_get_geometry_reply(globalconf.connection, geom_mask_c, NULL);
|
||||
|
||||
if (!geom_icon_r || (mask && !geom_mask_r))
|
||||
goto out;
|
||||
if ((geom_icon_r->depth != 1 && geom_icon_r->depth != globalconf.screen->root_depth)
|
||||
|| (geom_mask_r && geom_mask_r->depth != 1))
|
||||
{
|
||||
warn("Got pixmaps with depth (%d, %d) while processing icon, but only depth 1 and %d are allowed",
|
||||
geom_icon_r->depth, geom_mask_r ? geom_mask_r->depth : 0, globalconf.screen->root_depth);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (geom_icon_r->depth == 1)
|
||||
s_icon = cairo_xcb_surface_create_for_bitmap(globalconf.connection,
|
||||
globalconf.screen, icon, geom_icon_r->width, geom_icon_r->height);
|
||||
else
|
||||
s_icon = cairo_xcb_surface_create(globalconf.connection, icon, globalconf.default_visual,
|
||||
geom_icon_r->width, geom_icon_r->height);
|
||||
result = s_icon;
|
||||
|
||||
if (mask)
|
||||
{
|
||||
cairo_surface_t *s_mask;
|
||||
cairo_t *cr;
|
||||
|
||||
result = cairo_surface_create_similar(s_icon, CAIRO_CONTENT_COLOR_ALPHA, geom_icon_r->width, geom_icon_r->height);
|
||||
s_mask = cairo_xcb_surface_create_for_bitmap(globalconf.connection,
|
||||
globalconf.screen, mask, geom_icon_r->width, geom_icon_r->height);
|
||||
cr = cairo_create(result);
|
||||
|
||||
cairo_set_source_surface(cr, s_icon, 0, 0);
|
||||
cairo_mask_surface(cr, s_mask, 0, 0);
|
||||
cairo_surface_destroy(s_mask);
|
||||
cairo_destroy(cr);
|
||||
}
|
||||
|
||||
client_set_icon(c, result);
|
||||
|
||||
cairo_surface_destroy(result);
|
||||
if (result != s_icon)
|
||||
cairo_surface_destroy(s_icon);
|
||||
|
||||
out:
|
||||
p_delete(&geom_icon_r);
|
||||
p_delete(&geom_mask_r);
|
||||
}
|
||||
|
||||
|
||||
/** Kill a client.
|
||||
* \param L The Lua VM state.
|
||||
*
|
||||
|
|
|
@ -101,6 +101,8 @@ struct client_t
|
|||
key_array_t keys;
|
||||
/** Icon */
|
||||
cairo_surface_t *icon;
|
||||
/** True if we ever got an icon from _NET_WM_ICON */
|
||||
bool have_ewmh_icon;
|
||||
/** Size hints */
|
||||
xcb_size_hints_t size_hints;
|
||||
/** The visualtype that c->window uses */
|
||||
|
@ -164,7 +166,8 @@ void client_set_transient_for(lua_State *L, int, client_t *);
|
|||
void client_set_name(lua_State *L, int, char *);
|
||||
void client_set_alt_name(lua_State *L, int, char *);
|
||||
void client_set_group_window(lua_State *, int, xcb_window_t);
|
||||
void client_set_icon(client_t *c, cairo_surface_t *s);
|
||||
void client_set_icon(client_t *, cairo_surface_t *);
|
||||
void client_set_icon_from_pixmaps(client_t *, xcb_pixmap_t, xcb_pixmap_t);
|
||||
void client_set_skip_taskbar(lua_State *, int, bool);
|
||||
void client_focus(client_t *);
|
||||
void client_focus_update(client_t *);
|
||||
|
|
14
property.c
14
property.c
|
@ -206,6 +206,19 @@ property_update_wm_hints(client_t *c, xcb_get_property_cookie_t cookie)
|
|||
if(wmh.flags & XCB_ICCCM_WM_HINT_WINDOW_GROUP)
|
||||
client_set_group_window(L, -1, wmh.window_group);
|
||||
|
||||
if(!c->have_ewmh_icon)
|
||||
{
|
||||
if(wmh.flags & XCB_ICCCM_WM_HINT_ICON_PIXMAP)
|
||||
{
|
||||
if(wmh.flags & XCB_ICCCM_WM_HINT_ICON_MASK)
|
||||
client_set_icon_from_pixmaps(c, wmh.icon_pixmap, wmh.icon_mask);
|
||||
else
|
||||
client_set_icon_from_pixmaps(c, wmh.icon_pixmap, XCB_NONE);
|
||||
}
|
||||
else
|
||||
client_set_icon(c, NULL);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
@ -263,6 +276,7 @@ property_update_net_wm_icon(client_t *c, xcb_get_property_cookie_t cookie)
|
|||
if(!surface)
|
||||
return;
|
||||
|
||||
c->have_ewmh_icon = true;
|
||||
client_set_icon(c, surface);
|
||||
cairo_surface_destroy(surface);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue