Merge pull request #782 from psychon/wallpaper-change
Changes to wallpaper change
This commit is contained in:
commit
3e5b1b3ba9
|
@ -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");
|
||||
|
|
7
event.c
7
event.c
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
115
root.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue