From 6b8bd49c0b8493829252e860be8488b3ca4d0cbf Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 16 Mar 2014 15:29:11 +0100 Subject: [PATCH] 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 --- event.c | 2 +- objects/client.c | 59 ++++++++++++++++++++++++++++++++++++++++-------- objects/client.h | 2 +- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/event.c b/event.c index 7eb16acd..7915d423 100644 --- a/event.c +++ b/event.c @@ -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. diff --git a/objects/client.c b/objects/client.c index 2feed76f..76f0128e 100644 --- a/objects/client.c +++ b/objects/client.c @@ -1551,17 +1551,43 @@ client_get_drawable(client_t *c, int x, int y) return client_get_drawable_offset(c, &x, &y); } +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) +{ + 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, 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(client_t *c) +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++) { - if (c->titlebar[bar].drawable == NULL || c->titlebar[bar].drawable->surface == NULL) - continue; - - area_t area = titlebar_get_area(c, bar); - 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); + 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); } diff --git a/objects/client.h b/objects/client.h index de2e5954..712cbd3e 100644 --- a/objects/client.h +++ b/objects/client.h @@ -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);