Redraw titlebars more intelligently

Whenever a titlebar of a client needed to be refreshed, all (possibly) four
titlebars would get completely refreshed. So if someone actually added more than
one titlebar to a client, awesome would copy each titlebar's content to the
window four times. Fix this by introducing more fine-grined functions for
uploads.

This also makes awesome only update the affected area when it gets an expose
event for a titlebar instead of all four titlebars completely.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2014-03-16 15:29:11 +01:00
parent 1924ee9e6e
commit 6b8bd49c0b
3 changed files with 52 additions and 11 deletions

View File

@ -547,7 +547,7 @@ event_handle_expose(xcb_expose_event_t *ev)
ev->x, ev->y,
ev->width, ev->height);
if ((client = client_getbyframewin(ev->window)))
client_refresh(client);
client_refresh_partial(client, ev->x, ev->y, ev->width, ev->height);
}
/** The key press event handler.

View File

@ -1551,17 +1551,43 @@ client_get_drawable(client_t *c, int x, int y)
return client_get_drawable_offset(c, &x, &y);
}
void
client_refresh(client_t *c)
static void
client_refresh_titlebar_partial(client_t *c, client_titlebar_t bar, int16_t x, int16_t y, uint16_t width, uint16_t height)
{
for (client_titlebar_t bar = CLIENT_TITLEBAR_TOP; bar < CLIENT_TITLEBAR_COUNT; bar++) {
if (c->titlebar[bar].drawable == NULL || c->titlebar[bar].drawable->surface == NULL)
continue;
if(c->titlebar[bar].drawable == NULL || c->titlebar[bar].drawable->surface == NULL)
return;
area_t area = titlebar_get_area(c, bar);
/* Is the titlebar part of the area that should get redrawn? */
if (AREA_LEFT(area) >= x + width || AREA_RIGHT(area) <= x)
return;
if (AREA_TOP(area) >= y + height || AREA_BOTTOM(area) <= y)
return;
/* Redraw the affected parts */
cairo_surface_flush(c->titlebar[bar].drawable->surface);
xcb_copy_area(globalconf.connection, c->titlebar[bar].pixmap, c->frame_window,
globalconf.gc, 0, 0, area.x, area.y, area.width, area.height);
globalconf.gc, x - area.x, y - area.y, x, y, width, height);
}
#define HANDLE_TITLEBAR_REFRESH(name, index) \
static void \
client_refresh_titlebar_ ## name(client_t *c) \
{ \
area_t area = titlebar_get_area(c, index); \
client_refresh_titlebar_partial(c, index, area.x, area.y, area.width, area.height); \
}
HANDLE_TITLEBAR_REFRESH(top, CLIENT_TITLEBAR_TOP)
HANDLE_TITLEBAR_REFRESH(right, CLIENT_TITLEBAR_RIGHT)
HANDLE_TITLEBAR_REFRESH(bottom, CLIENT_TITLEBAR_BOTTOM)
HANDLE_TITLEBAR_REFRESH(left, CLIENT_TITLEBAR_LEFT)
/**
* Refresh all titlebars that are in the specified rectangle
*/
void
client_refresh_partial(client_t *c, int16_t x, int16_t y, uint16_t width, uint16_t height)
{
for (client_titlebar_t bar = CLIENT_TITLEBAR_TOP; bar < CLIENT_TITLEBAR_COUNT; bar++) {
client_refresh_titlebar_partial(c, bar, x, y, width, height);
}
}
@ -1571,7 +1597,22 @@ titlebar_get_drawable(lua_State *L, client_t *c, int cl_idx, client_titlebar_t b
if (c->titlebar[bar].drawable == NULL)
{
cl_idx = luaA_absindex(L, cl_idx);
drawable_allocator(L, (drawable_refresh_callback *) client_refresh, c);
switch (bar) {
case CLIENT_TITLEBAR_TOP:
drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_top, c);
break;
case CLIENT_TITLEBAR_BOTTOM:
drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_bottom, c);
break;
case CLIENT_TITLEBAR_RIGHT:
drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_right, c);
break;
case CLIENT_TITLEBAR_LEFT:
drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_left, c);
break;
default:
fatal("Unknown titlebar kind %d\n", (int) bar);
}
c->titlebar[bar].drawable = luaA_object_ref_item(L, cl_idx, -1);
}

View File

@ -179,7 +179,7 @@ void client_focus_refresh(void);
bool client_hasproto(client_t *, xcb_atom_t);
void client_ignore_enterleave_events(void);
void client_restore_enterleave_events(void);
void client_refresh(client_t *);
void client_refresh_partial(client_t *, int16_t, int16_t, uint16_t, uint16_t);
void client_class_setup(lua_State *);
void client_send_configure(client_t *);
drawable_t *client_get_drawable(client_t *, int, int);