Merge pull request #782 from psychon/wallpaper-change

Changes to wallpaper change
This commit is contained in:
Daniel Hahler 2016-04-03 18:35:27 +02:00
commit 3e5b1b3ba9
6 changed files with 83 additions and 54 deletions

View File

@ -691,6 +691,9 @@ main(int argc, char **argv)
xcb_ungrab_server(globalconf.connection);
xcb_flush(globalconf.connection);
/* get the current wallpaper, from now on we are informed when it changes */
root_update_wallpaper();
/* Parse and run configuration file */
if (!luaA_parserc(&xdg, confpath, true))
fatal("couldn't find any rc file");

View File

@ -793,7 +793,6 @@ event_handle_randr_output_change_notify(xcb_randr_notify_event_t *ev)
if(ev->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) {
xcb_randr_output_t output = ev->u.oc.output;
uint8_t connection = ev->u.oc.connection;
char *output_name = NULL;
const char *connection_str = NULL;
xcb_randr_get_output_info_reply_t *info = NULL;
lua_State *L = globalconf_get_lua_State();
@ -806,9 +805,6 @@ event_handle_randr_output_change_notify(xcb_randr_notify_event_t *ev)
if(!info)
return;
output_name = p_dup((char *)xcb_randr_get_output_info_name(info),
xcb_randr_get_output_info_name_length(info));
switch(connection) {
case XCB_RANDR_CONNECTION_CONNECTED:
connection_str = "Connected";
@ -821,11 +817,10 @@ event_handle_randr_output_change_notify(xcb_randr_notify_event_t *ev)
break;
}
lua_pushstring(L, output_name);
lua_pushlstring(L, (char *)xcb_randr_get_output_info_name(info), xcb_randr_get_output_info_name_length(info));
lua_pushstring(L, connection_str);
signal_object_emit(L, &global_signals, "screen::change", 2);
p_delete(&output_name);
p_delete(&info);
/* The docs for RRSetOutputPrimary say we get this signal */

View File

@ -171,6 +171,8 @@ typedef struct
struct xkb_state *xkb_state;
/** The preferred size of client icons for this screen */
uint32_t preferred_icon_size;
/** Cached wallpaper information */
cairo_surface_t *wallpaper;
} awesome_t;
extern awesome_t globalconf;
@ -182,5 +184,8 @@ static inline lua_State *globalconf_get_lua_State(void) {
return globalconf.L.real_L_dont_use_directly;
}
/* Defined in root.c */
void root_update_wallpaper(void);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -24,7 +24,6 @@ local hierarchy = require("wibox.hierarchy")
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
local drawables = setmetatable({}, { __mode = 'k' })
local wallpaper = nil
-- This is awful.screen.getbycoord() which we sadly cannot use from here (cyclic
-- dependencies are bad!)
@ -113,9 +112,7 @@ local function do_redraw(self)
if not capi.awesome.composite_manager_running then
-- This is pseudo-transparency: We draw the wallpaper in the background
if not wallpaper then
wallpaper = surface.load_silently(capi.root.wallpaper(), false)
end
local wallpaper = surface.load_silently(capi.root.wallpaper(), false)
if wallpaper then
cr.operator = cairo.Operator.SOURCE
cr:set_source_surface(wallpaper, -x, -y)
@ -426,7 +423,6 @@ end
-- Redraw all drawables when the wallpaper changes
capi.awesome.connect_signal("wallpaper_changed", function()
wallpaper = nil
for k in pairs(drawables) do
k()
end

View File

@ -381,6 +381,7 @@ property_handle_xrootpmap_id(uint8_t state,
xcb_window_t window)
{
lua_State *L = globalconf_get_lua_State();
root_update_wallpaper();
signal_object_emit(L, &global_signals, "wallpaper_changed", 0);
return 0;
}

115
root.c
View File

@ -74,6 +74,7 @@ root_set_wallpaper_pixmap(xcb_connection_t *c, xcb_pixmap_t p)
static bool
root_set_wallpaper(cairo_pattern_t *pattern)
{
lua_State *L = globalconf_get_lua_State();
xcb_connection_t *c = xcb_connect(NULL, NULL);
xcb_pixmap_t p = xcb_generate_id(c);
/* globalconf.connection should be connected to the same X11 server, so we
@ -107,15 +108,30 @@ root_set_wallpaper(cairo_pattern_t *pattern)
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr);
cairo_destroy(cr);
cairo_surface_finish(surface);
cairo_surface_destroy(surface);
cairo_surface_flush(surface);
xcb_aux_sync(globalconf.connection);
/* Change the wallpaper, without sending us a PropertyNotify event */
xcb_grab_server(globalconf.connection);
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
(uint32_t[]) { 0 });
root_set_wallpaper_pixmap(c, p);
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
ROOT_WINDOW_EVENT_MASK);
xcb_ungrab_server(globalconf.connection);
/* Make sure our pixmap is not destroyed when we disconnect. */
xcb_set_close_down_mode(c, XCB_CLOSE_DOWN_RETAIN_PERMANENT);
/* Tell Lua that the wallpaper changed */
cairo_surface_destroy(globalconf.wallpaper);
globalconf.wallpaper = surface;
signal_object_emit(L, &global_signals, "wallpaper_changed", 0);
result = true;
disconnect:
xcb_flush(c);
@ -123,6 +139,58 @@ disconnect:
return result;
}
void
root_update_wallpaper(void)
{
xcb_get_property_cookie_t prop_c;
xcb_get_property_reply_t *prop_r;
xcb_get_geometry_cookie_t geom_c;
xcb_get_geometry_reply_t *geom_r;
xcb_pixmap_t *rootpix;
cairo_surface_destroy(globalconf.wallpaper);
globalconf.wallpaper = NULL;
prop_c = xcb_get_property_unchecked(globalconf.connection, false,
globalconf.screen->root, _XROOTPMAP_ID, XCB_ATOM_PIXMAP, 0, 1);
prop_r = xcb_get_property_reply(globalconf.connection, prop_c, NULL);
if (!prop_r || !prop_r->value_len)
{
p_delete(&prop_r);
return;
}
rootpix = xcb_get_property_value(prop_r);
if (!rootpix)
{
p_delete(&prop_r);
return;
}
geom_c = xcb_get_geometry_unchecked(globalconf.connection, *rootpix);
geom_r = xcb_get_geometry_reply(globalconf.connection, geom_c, NULL);
if (!geom_r)
{
p_delete(&prop_r);
return;
}
/* Only the default visual makes sense, so just the default depth */
if (geom_r->depth != draw_visual_depth(globalconf.screen, globalconf.default_visual->visual_id))
warn("Got a pixmap with depth %d, but the default depth is %d, continuing anyway",
geom_r->depth, draw_visual_depth(globalconf.screen, globalconf.default_visual->visual_id));
globalconf.wallpaper = cairo_xcb_surface_create(globalconf.connection,
*rootpix,
globalconf.default_visual,
geom_r->width,
geom_r->height);
p_delete(&prop_r);
p_delete(&geom_r);
}
static xcb_keycode_t
_string_to_key_code(const char *s)
{
@ -344,13 +412,6 @@ luaA_root_drawins(lua_State *L)
static int
luaA_root_wallpaper(lua_State *L)
{
xcb_get_property_cookie_t prop_c;
xcb_get_property_reply_t *prop_r;
xcb_get_geometry_cookie_t geom_c;
xcb_get_geometry_reply_t *geom_r;
xcb_pixmap_t *rootpix;
cairo_surface_t *surface;
if(lua_gettop(L) == 1)
{
cairo_pattern_t *pattern = (cairo_pattern_t *)lua_touserdata(L, -1);
@ -359,43 +420,11 @@ luaA_root_wallpaper(lua_State *L)
return 1;
}
prop_c = xcb_get_property_unchecked(globalconf.connection, false,
globalconf.screen->root, _XROOTPMAP_ID, XCB_ATOM_PIXMAP, 0, 1);
prop_r = xcb_get_property_reply(globalconf.connection, prop_c, NULL);
if (!prop_r || !prop_r->value_len)
{
p_delete(&prop_r);
if(globalconf.wallpaper == NULL)
return 0;
}
rootpix = xcb_get_property_value(prop_r);
if (!rootpix)
{
p_delete(&prop_r);
return 0;
}
geom_c = xcb_get_geometry_unchecked(globalconf.connection, *rootpix);
geom_r = xcb_get_geometry_reply(globalconf.connection, geom_c, NULL);
if (!geom_r)
{
p_delete(&prop_r);
return 0;
}
/* Only the default visual makes sense, so just the default depth */
if (geom_r->depth != draw_visual_depth(globalconf.screen, globalconf.default_visual->visual_id))
warn("Got a pixmap with depth %d, but the default depth is %d, continuing anyway",
geom_r->depth, draw_visual_depth(globalconf.screen, globalconf.default_visual->visual_id));
surface = cairo_xcb_surface_create(globalconf.connection, *rootpix, globalconf.default_visual,
geom_r->width, geom_r->height);
/* lua has to make sure this surface gets destroyed */
lua_pushlightuserdata(L, surface);
p_delete(&prop_r);
p_delete(&geom_r);
lua_pushlightuserdata(L, cairo_surface_reference(globalconf.wallpaper));
return 1;
}