drawin: lazily configure drawin windows

Ref: https://github.com/awesomeWM/awesome/issues/411.
Source: https://github.com/awesomeWM/awesome/pull/174#commitcomment-12708326.
(With some minor changes)
This commit is contained in:
Uli Schlachter 2015-08-14 14:39:43 +02:00
parent 462055cb36
commit 9408b61a97
3 changed files with 60 additions and 38 deletions

View File

@ -31,6 +31,9 @@
/* luaa.c */ /* luaa.c */
void luaA_emit_refresh(void); void luaA_emit_refresh(void);
/* objects/drawin.c */
void drawin_refresh(void);
/* objects/client.c */ /* objects/client.c */
void client_focus_refresh(void); void client_focus_refresh(void);
@ -40,6 +43,7 @@ awesome_refresh(void)
luaA_emit_refresh(); luaA_emit_refresh();
banning_refresh(); banning_refresh();
stack_refresh(); stack_refresh();
drawin_refresh();
client_focus_refresh(); client_focus_refresh();
return xcb_flush(globalconf.connection); return xcb_flush(globalconf.connection);
} }

View File

@ -34,6 +34,7 @@
#include "drawin.h" #include "drawin.h"
#include "common/atoms.h" #include "common/atoms.h"
#include "common/xcursor.h" #include "common/xcursor.h"
#include "event.h"
#include "ewmh.h" #include "ewmh.h"
#include "objects/client.h" #include "objects/client.h"
#include "objects/screen.h" #include "objects/screen.h"
@ -139,6 +140,34 @@ drawin_refresh_pixmap(drawin_t *w)
drawin_refresh_pixmap_partial(w, 0, 0, w->geometry.width, w->geometry.height); drawin_refresh_pixmap_partial(w, 0, 0, w->geometry.width, w->geometry.height);
} }
static void
drawin_apply_moveresize(drawin_t *w)
{
if (!w->geometry_dirty)
return;
w->geometry_dirty = false;
client_ignore_enterleave_events();
xcb_configure_window(globalconf.connection, w->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
| XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
(const uint32_t [])
{
w->geometry.x,
w->geometry.y,
w->geometry.width,
w->geometry.height
});
client_restore_enterleave_events();
}
void
drawin_refresh(void)
{
foreach(item, globalconf.drawins)
drawin_apply_moveresize(*item);
}
/** Move and/or resize a drawin /** Move and/or resize a drawin
* \param L The Lua VM state. * \param L The Lua VM state.
* \param udx The index of the drawin. * \param udx The index of the drawin.
@ -148,51 +177,24 @@ static void
drawin_moveresize(lua_State *L, int udx, area_t geometry) drawin_moveresize(lua_State *L, int udx, area_t geometry)
{ {
drawin_t *w = luaA_checkudata(L, udx, &drawin_class); drawin_t *w = luaA_checkudata(L, udx, &drawin_class);
int number_of_vals = 0; area_t old_geometry = w->geometry;
uint32_t moveresize_win_vals[4], mask_vals = 0;
if(w->geometry.x != geometry.x) w->geometry = geometry;
{ if(w->geometry.width <= 0)
w->geometry.x = moveresize_win_vals[number_of_vals++] = geometry.x; w->geometry.width = old_geometry.width;
mask_vals |= XCB_CONFIG_WINDOW_X; if(w->geometry.height <= 0)
} w->geometry.height = old_geometry.height;
if(w->geometry.y != geometry.y)
{
w->geometry.y = moveresize_win_vals[number_of_vals++] = geometry.y;
mask_vals |= XCB_CONFIG_WINDOW_Y;
}
if(geometry.width > 0 && w->geometry.width != geometry.width)
{
w->geometry.width = moveresize_win_vals[number_of_vals++] = geometry.width;
mask_vals |= XCB_CONFIG_WINDOW_WIDTH;
}
if(geometry.height > 0 && w->geometry.height != geometry.height)
{
w->geometry.height = moveresize_win_vals[number_of_vals++] = geometry.height;
mask_vals |= XCB_CONFIG_WINDOW_HEIGHT;
}
w->geometry_dirty = true;
drawin_update_drawing(L, udx); drawin_update_drawing(L, udx);
/* Activate BMA */ if (old_geometry.x != w->geometry.x)
client_ignore_enterleave_events();
if(mask_vals)
xcb_configure_window(globalconf.connection, w->window, mask_vals, moveresize_win_vals);
/* Deactivate BMA */
client_restore_enterleave_events();
if(mask_vals & XCB_CONFIG_WINDOW_X)
luaA_object_emit_signal(L, udx, "property::x", 0); luaA_object_emit_signal(L, udx, "property::x", 0);
if(mask_vals & XCB_CONFIG_WINDOW_Y) if (old_geometry.y != w->geometry.y)
luaA_object_emit_signal(L, udx, "property::y", 0); luaA_object_emit_signal(L, udx, "property::y", 0);
if(mask_vals & XCB_CONFIG_WINDOW_WIDTH) if (old_geometry.width != w->geometry.width)
luaA_object_emit_signal(L, udx, "property::width", 0); luaA_object_emit_signal(L, udx, "property::width", 0);
if(mask_vals & XCB_CONFIG_WINDOW_HEIGHT) if (old_geometry.height != w->geometry.height)
luaA_object_emit_signal(L, udx, "property::height", 0); luaA_object_emit_signal(L, udx, "property::height", 0);
} }
@ -211,6 +213,9 @@ drawin_refresh_pixmap_partial(drawin_t *drawin,
if (!drawin->drawable || !drawin->drawable->pixmap || !drawin->drawable->refreshed) if (!drawin->drawable || !drawin->drawable->pixmap || !drawin->drawable->refreshed)
return; return;
/* Make sure it really has the size it should have */
drawin_apply_moveresize(drawin);
/* Make cairo do all pending drawing */ /* Make cairo do all pending drawing */
cairo_surface_flush(drawin->drawable->surface); cairo_surface_flush(drawin->drawable->surface);
xcb_copy_area(globalconf.connection, drawin->drawable->pixmap, xcb_copy_area(globalconf.connection, drawin->drawable->pixmap,
@ -224,6 +229,8 @@ drawin_map(lua_State *L, int widx)
drawin_t *drawin = luaA_checkudata(L, widx, &drawin_class); drawin_t *drawin = luaA_checkudata(L, widx, &drawin_class);
/* Activate BMA */ /* Activate BMA */
client_ignore_enterleave_events(); client_ignore_enterleave_events();
/* Apply any pending changes */
drawin_apply_moveresize(drawin);
/* Map the drawin */ /* Map the drawin */
xcb_map_window(globalconf.connection, drawin->window); xcb_map_window(globalconf.connection, drawin->window);
/* Deactivate BMA */ /* Deactivate BMA */
@ -317,6 +324,7 @@ drawin_allocator(lua_State *L)
w->cursor = a_strdup("left_ptr"); w->cursor = a_strdup("left_ptr");
w->geometry.width = 1; w->geometry.width = 1;
w->geometry.height = 1; w->geometry.height = 1;
w->geometry_dirty = false;
w->type = _NET_WM_WINDOW_TYPE_NORMAL; w->type = _NET_WM_WINDOW_TYPE_NORMAL;
drawable_allocator(L, (drawable_refresh_callback *) drawin_refresh_pixmap, w); drawable_allocator(L, (drawable_refresh_callback *) drawin_refresh_pixmap, w);
@ -564,6 +572,10 @@ luaA_drawin_set_shape_bounding(lua_State *L, drawin_t *drawin)
cairo_surface_t *surf = NULL; cairo_surface_t *surf = NULL;
if(!lua_isnil(L, -1)) if(!lua_isnil(L, -1))
surf = (cairo_surface_t *)lua_touserdata(L, -1); surf = (cairo_surface_t *)lua_touserdata(L, -1);
/* The drawin might have been resized to a larger size. Apply that. */
drawin_apply_moveresize(drawin);
xwindow_set_shape(drawin->window, xwindow_set_shape(drawin->window,
drawin->geometry.width + 2*drawin->border_width, drawin->geometry.width + 2*drawin->border_width,
drawin->geometry.height + 2*drawin->border_width, drawin->geometry.height + 2*drawin->border_width,
@ -599,6 +611,10 @@ luaA_drawin_set_shape_clip(lua_State *L, drawin_t *drawin)
cairo_surface_t *surf = NULL; cairo_surface_t *surf = NULL;
if(!lua_isnil(L, -1)) if(!lua_isnil(L, -1))
surf = (cairo_surface_t *)lua_touserdata(L, -1); surf = (cairo_surface_t *)lua_touserdata(L, -1);
/* The drawin might have been resized to a larger size. Apply that. */
drawin_apply_moveresize(drawin);
xwindow_set_shape(drawin->window, drawin->geometry.width, drawin->geometry.height, xwindow_set_shape(drawin->window, drawin->geometry.width, drawin->geometry.height,
XCB_SHAPE_SK_CLIP, surf, 0); XCB_SHAPE_SK_CLIP, surf, 0);
luaA_object_emit_signal(L, -3, "property::shape_clip", 0); luaA_object_emit_signal(L, -3, "property::shape_clip", 0);

View File

@ -40,6 +40,8 @@ struct drawin_t
drawable_t *drawable; drawable_t *drawable;
/** The window geometry. */ /** The window geometry. */
area_t geometry; area_t geometry;
/** Do we have a pending geometry change that still needs to be applied? */
bool geometry_dirty;
}; };
ARRAY_FUNCS(drawin_t *, drawin, DO_NOTHING) ARRAY_FUNCS(drawin_t *, drawin, DO_NOTHING)