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_ungrab_server(globalconf.connection);
|
||||||
xcb_flush(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 */
|
/* Parse and run configuration file */
|
||||||
if (!luaA_parserc(&xdg, confpath, true))
|
if (!luaA_parserc(&xdg, confpath, true))
|
||||||
fatal("couldn't find any rc file");
|
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) {
|
if(ev->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) {
|
||||||
xcb_randr_output_t output = ev->u.oc.output;
|
xcb_randr_output_t output = ev->u.oc.output;
|
||||||
uint8_t connection = ev->u.oc.connection;
|
uint8_t connection = ev->u.oc.connection;
|
||||||
char *output_name = NULL;
|
|
||||||
const char *connection_str = NULL;
|
const char *connection_str = NULL;
|
||||||
xcb_randr_get_output_info_reply_t *info = NULL;
|
xcb_randr_get_output_info_reply_t *info = NULL;
|
||||||
lua_State *L = globalconf_get_lua_State();
|
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)
|
if(!info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
output_name = p_dup((char *)xcb_randr_get_output_info_name(info),
|
|
||||||
xcb_randr_get_output_info_name_length(info));
|
|
||||||
|
|
||||||
switch(connection) {
|
switch(connection) {
|
||||||
case XCB_RANDR_CONNECTION_CONNECTED:
|
case XCB_RANDR_CONNECTION_CONNECTED:
|
||||||
connection_str = "Connected";
|
connection_str = "Connected";
|
||||||
|
@ -821,11 +817,10 @@ event_handle_randr_output_change_notify(xcb_randr_notify_event_t *ev)
|
||||||
break;
|
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);
|
lua_pushstring(L, connection_str);
|
||||||
signal_object_emit(L, &global_signals, "screen::change", 2);
|
signal_object_emit(L, &global_signals, "screen::change", 2);
|
||||||
|
|
||||||
p_delete(&output_name);
|
|
||||||
p_delete(&info);
|
p_delete(&info);
|
||||||
|
|
||||||
/* The docs for RRSetOutputPrimary say we get this signal */
|
/* The docs for RRSetOutputPrimary say we get this signal */
|
||||||
|
|
|
@ -171,6 +171,8 @@ typedef struct
|
||||||
struct xkb_state *xkb_state;
|
struct xkb_state *xkb_state;
|
||||||
/** The preferred size of client icons for this screen */
|
/** The preferred size of client icons for this screen */
|
||||||
uint32_t preferred_icon_size;
|
uint32_t preferred_icon_size;
|
||||||
|
/** Cached wallpaper information */
|
||||||
|
cairo_surface_t *wallpaper;
|
||||||
} awesome_t;
|
} awesome_t;
|
||||||
|
|
||||||
extern awesome_t globalconf;
|
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;
|
return globalconf.L.real_L_dont_use_directly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Defined in root.c */
|
||||||
|
void root_update_wallpaper(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
// 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 unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||||
|
|
||||||
local drawables = setmetatable({}, { __mode = 'k' })
|
local drawables = setmetatable({}, { __mode = 'k' })
|
||||||
local wallpaper = nil
|
|
||||||
|
|
||||||
-- This is awful.screen.getbycoord() which we sadly cannot use from here (cyclic
|
-- This is awful.screen.getbycoord() which we sadly cannot use from here (cyclic
|
||||||
-- dependencies are bad!)
|
-- dependencies are bad!)
|
||||||
|
@ -113,9 +112,7 @@ local function do_redraw(self)
|
||||||
|
|
||||||
if not capi.awesome.composite_manager_running then
|
if not capi.awesome.composite_manager_running then
|
||||||
-- This is pseudo-transparency: We draw the wallpaper in the background
|
-- This is pseudo-transparency: We draw the wallpaper in the background
|
||||||
if not wallpaper then
|
local wallpaper = surface.load_silently(capi.root.wallpaper(), false)
|
||||||
wallpaper = surface.load_silently(capi.root.wallpaper(), false)
|
|
||||||
end
|
|
||||||
if wallpaper then
|
if wallpaper then
|
||||||
cr.operator = cairo.Operator.SOURCE
|
cr.operator = cairo.Operator.SOURCE
|
||||||
cr:set_source_surface(wallpaper, -x, -y)
|
cr:set_source_surface(wallpaper, -x, -y)
|
||||||
|
@ -426,7 +423,6 @@ end
|
||||||
|
|
||||||
-- Redraw all drawables when the wallpaper changes
|
-- Redraw all drawables when the wallpaper changes
|
||||||
capi.awesome.connect_signal("wallpaper_changed", function()
|
capi.awesome.connect_signal("wallpaper_changed", function()
|
||||||
wallpaper = nil
|
|
||||||
for k in pairs(drawables) do
|
for k in pairs(drawables) do
|
||||||
k()
|
k()
|
||||||
end
|
end
|
||||||
|
|
|
@ -381,6 +381,7 @@ property_handle_xrootpmap_id(uint8_t state,
|
||||||
xcb_window_t window)
|
xcb_window_t window)
|
||||||
{
|
{
|
||||||
lua_State *L = globalconf_get_lua_State();
|
lua_State *L = globalconf_get_lua_State();
|
||||||
|
root_update_wallpaper();
|
||||||
signal_object_emit(L, &global_signals, "wallpaper_changed", 0);
|
signal_object_emit(L, &global_signals, "wallpaper_changed", 0);
|
||||||
return 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
|
static bool
|
||||||
root_set_wallpaper(cairo_pattern_t *pattern)
|
root_set_wallpaper(cairo_pattern_t *pattern)
|
||||||
{
|
{
|
||||||
|
lua_State *L = globalconf_get_lua_State();
|
||||||
xcb_connection_t *c = xcb_connect(NULL, NULL);
|
xcb_connection_t *c = xcb_connect(NULL, NULL);
|
||||||
xcb_pixmap_t p = xcb_generate_id(c);
|
xcb_pixmap_t p = xcb_generate_id(c);
|
||||||
/* globalconf.connection should be connected to the same X11 server, so we
|
/* 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_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
cairo_destroy(cr);
|
cairo_destroy(cr);
|
||||||
cairo_surface_finish(surface);
|
cairo_surface_flush(surface);
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
xcb_aux_sync(globalconf.connection);
|
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);
|
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. */
|
/* Make sure our pixmap is not destroyed when we disconnect. */
|
||||||
xcb_set_close_down_mode(c, XCB_CLOSE_DOWN_RETAIN_PERMANENT);
|
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;
|
result = true;
|
||||||
disconnect:
|
disconnect:
|
||||||
xcb_flush(c);
|
xcb_flush(c);
|
||||||
|
@ -123,6 +139,58 @@ disconnect:
|
||||||
return result;
|
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
|
static xcb_keycode_t
|
||||||
_string_to_key_code(const char *s)
|
_string_to_key_code(const char *s)
|
||||||
{
|
{
|
||||||
|
@ -344,13 +412,6 @@ luaA_root_drawins(lua_State *L)
|
||||||
static int
|
static int
|
||||||
luaA_root_wallpaper(lua_State *L)
|
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)
|
if(lua_gettop(L) == 1)
|
||||||
{
|
{
|
||||||
cairo_pattern_t *pattern = (cairo_pattern_t *)lua_touserdata(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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop_c = xcb_get_property_unchecked(globalconf.connection, false,
|
if(globalconf.wallpaper == NULL)
|
||||||
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 0;
|
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 has to make sure this surface gets destroyed */
|
||||||
lua_pushlightuserdata(L, surface);
|
lua_pushlightuserdata(L, cairo_surface_reference(globalconf.wallpaper));
|
||||||
p_delete(&prop_r);
|
|
||||||
p_delete(&geom_r);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue