gears.wallpaper: Handle concurrent screen changes
The code in gears.wallpaper currently sets a wallpaper in a deferred fashion. Only a while after it is told to do something does it actually do the wallpaper change. This is to incorporate many wallpaper changes right after another. These changes happens during startup where the wallpaper for each screen is set one after another. However, since we no longer restart on RandR changes, the screen configuration could change while we have a pending wallpaper. In this case, part of the wallpaper could be "chopped off", because the surface that we draw the wallpaper to is too small. This commit makes gears.wallpaper track the size of the pending wallpaper and create a new surface if the already-pending one is too small. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
d497cdf081
commit
aed571eb48
|
@ -18,7 +18,7 @@ local function root_geometry()
|
||||||
return { x = 0, y = 0, width = width, height = height }
|
return { x = 0, y = 0, width = width, height = height }
|
||||||
end
|
end
|
||||||
|
|
||||||
-- A cairo surface that we still want to set as the wallpaper
|
-- Information about a pending wallpaper change, see prepare_context()
|
||||||
local pending_wallpaper = nil
|
local pending_wallpaper = nil
|
||||||
|
|
||||||
--- Prepare the needed state for setting a wallpaper.
|
--- Prepare the needed state for setting a wallpaper.
|
||||||
|
@ -29,35 +29,49 @@ local pending_wallpaper = nil
|
||||||
-- @return[1] The available geometry (table with entries width and height)
|
-- @return[1] The available geometry (table with entries width and height)
|
||||||
-- @return[1] A cairo context that the wallpaper should be drawn to
|
-- @return[1] A cairo context that the wallpaper should be drawn to
|
||||||
function wallpaper.prepare_context(s)
|
function wallpaper.prepare_context(s)
|
||||||
|
local root_width, root_height = root.size()
|
||||||
local geom = s and screen[s].geometry or root_geometry()
|
local geom = s and screen[s].geometry or root_geometry()
|
||||||
local cr
|
local source, target, cr
|
||||||
|
|
||||||
if not pending_wallpaper then
|
if not pending_wallpaper then
|
||||||
-- Prepare a pending wallpaper
|
-- Prepare a pending wallpaper
|
||||||
local wp = surface(root.wallpaper())
|
source = surface(root.wallpaper())
|
||||||
|
target = source:create_similar(cairo.Content.COLOR, root_width, root_height)
|
||||||
pending_wallpaper = wp:create_similar(cairo.Content.COLOR, root.size())
|
|
||||||
|
|
||||||
-- Copy the old wallpaper to the new one
|
|
||||||
cr = cairo.Context(pending_wallpaper)
|
|
||||||
cr:save()
|
|
||||||
cr.operator = cairo.Operator.SOURCE
|
|
||||||
cr:set_source_surface(wp, 0, 0)
|
|
||||||
cr:paint()
|
|
||||||
cr:restore()
|
|
||||||
|
|
||||||
-- Set the wallpaper (delayed)
|
-- Set the wallpaper (delayed)
|
||||||
timer.delayed_call(function()
|
timer.delayed_call(function()
|
||||||
local paper = pending_wallpaper
|
local paper = pending_wallpaper
|
||||||
pending_wallpaper = nil
|
pending_wallpaper = nil
|
||||||
wallpaper.set(paper)
|
wallpaper.set(paper.surface)
|
||||||
paper:finish()
|
paper.surface:finish()
|
||||||
end)
|
end)
|
||||||
|
elseif root_width > pending_wallpaper.width or root_height > pending_wallpaper.height then
|
||||||
|
-- The root window was resized while a wallpaper is pending
|
||||||
|
source = pending_wallpaper.surface
|
||||||
|
target = source:create_similar(cairo.Content.COLOR, root_width, root_height)
|
||||||
else
|
else
|
||||||
-- Draw to the already-pending wallpaper
|
-- Draw to the already-pending wallpaper
|
||||||
cr = cairo.Context(pending_wallpaper)
|
source = nil
|
||||||
|
target = pending_wallpaper.surface
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cr = cairo.Context(target)
|
||||||
|
|
||||||
|
if source then
|
||||||
|
-- Copy the old wallpaper to the new one
|
||||||
|
cr:save()
|
||||||
|
cr.operator = cairo.Operator.SOURCE
|
||||||
|
cr:set_source_surface(source, 0, 0)
|
||||||
|
cr:paint()
|
||||||
|
cr:restore()
|
||||||
|
end
|
||||||
|
|
||||||
|
pending_wallpaper = {
|
||||||
|
surface = target,
|
||||||
|
width = root_width,
|
||||||
|
height = root_height
|
||||||
|
}
|
||||||
|
|
||||||
-- Only draw to the selected area
|
-- Only draw to the selected area
|
||||||
cr:translate(geom.x, geom.y)
|
cr:translate(geom.x, geom.y)
|
||||||
cr:rectangle(0, 0, geom.width, geom.height)
|
cr:rectangle(0, 0, geom.width, geom.height)
|
||||||
|
|
Loading…
Reference in New Issue