Set the wallpaper more intelligently
Usually users want a wallpaper on all their screens. With the current code, this resulted in a loop of upload-wallpaper, {download-wallpaper, add-new-part, upload-wallpaper}*. Fix this by being more intelligent: Instead of setting the wallpaper immediately, this now uses gears.timer.delayed_call() to set the wallpaper. All following modifications which come in before the delayed call runs will still be part of the current update. This should mean that during startup, there is just a single upload of a wallpaper. (The above is what happens if there is no wallpaper yet. If there is already one, we use :create_similar() and thus should only upload the part of the wallpaper that changed, but this doesn't really make a difference.) As a side-effect, the new code no longer draws to the old wallpaper to modify it, but always creates a copy of it. This means that: Fixes https://github.com/awesomeWM/awesome/issues/288. Closes https://github.com/awesomeWM/awesome/pull/530. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
57e3927cbd
commit
112ce3b419
|
@ -8,6 +8,7 @@
|
|||
local cairo = require("lgi").cairo
|
||||
local color = require("gears.color")
|
||||
local surface = require("gears.surface")
|
||||
local timer = require("gears.timer")
|
||||
|
||||
local wallpaper = { mt = {} }
|
||||
|
||||
|
@ -27,29 +28,56 @@ do
|
|||
end
|
||||
end
|
||||
|
||||
--- Prepare the needed state for setting a wallpaper
|
||||
-- A cairo surface that we still want to set as the wallpaper
|
||||
local pending_wallpaper = nil
|
||||
|
||||
--- Prepare the needed state for setting a wallpaper.
|
||||
-- This function returns a cairo context through which a wallpaper can be drawn.
|
||||
-- The context is only valid for a short time and should not be saved in a
|
||||
-- global variable.
|
||||
-- @param s The screen to set the wallpaper on or nil for all screens
|
||||
-- @return The available geometry (table with entries width and height), a
|
||||
-- that should be used for setting the wallpaper and a cairo context for
|
||||
-- drawing to this surface
|
||||
local function prepare_wallpaper(s)
|
||||
-- @return[1] The available geometry (table with entries width and height)
|
||||
-- @return[1] A cairo context that the wallpaper should be drawn to
|
||||
function wallpaper.prepare_context(s)
|
||||
local geom = s and screen[s].geometry or root_geom
|
||||
local img = surface(root.wallpaper())
|
||||
local cr
|
||||
|
||||
if not img then
|
||||
-- No wallpaper yet, create an image surface for just the part we need
|
||||
img = cairo.ImageSurface(cairo.Format.RGB24, geom.width, geom.height)
|
||||
img:set_device_offset(-geom.x, -geom.y)
|
||||
if not pending_wallpaper then
|
||||
-- Prepare a pending wallpaper
|
||||
local wp = surface(root.wallpaper())
|
||||
|
||||
if not wp then
|
||||
-- No wallpaper yet
|
||||
wp = cairo.ImageSurface(cairo.Format.RGB24, 0, 0)
|
||||
end
|
||||
|
||||
pending_wallpaper = wp:create_similar(cairo.Content.COLOR, root_geom.width, root_geom.height)
|
||||
|
||||
-- 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)
|
||||
timer.delayed_call(function()
|
||||
local wp = pending_wallpaper
|
||||
pending_wallpaper = nil
|
||||
wallpaper.set(wp)
|
||||
end)
|
||||
else
|
||||
-- Draw to the already-pending wallpaper
|
||||
cr = cairo.Context(pending_wallpaper)
|
||||
end
|
||||
|
||||
local cr = cairo.Context(img)
|
||||
|
||||
-- Only draw to the selected area
|
||||
cr:translate(geom.x, geom.y)
|
||||
cr:rectangle(0, 0, geom.width, geom.height)
|
||||
cr:clip()
|
||||
|
||||
return geom, img, cr
|
||||
return geom, cr
|
||||
end
|
||||
|
||||
--- Set the current wallpaper.
|
||||
|
@ -75,7 +103,7 @@ end
|
|||
-- @param background The background color that should be used. Gets handled via
|
||||
-- gears.color. The default is black.
|
||||
function wallpaper.centered(surf, s, background)
|
||||
local geom, img, cr = prepare_wallpaper(s)
|
||||
local geom, cr = wallpaper.prepare_context(s)
|
||||
local surf = surface(surf)
|
||||
local background = color(background)
|
||||
|
||||
|
@ -91,8 +119,6 @@ function wallpaper.centered(surf, s, background)
|
|||
cr:clip()
|
||||
cr:set_source_surface(surf, 0, 0)
|
||||
cr:paint()
|
||||
|
||||
wallpaper.set(img)
|
||||
end
|
||||
|
||||
--- Set a tiled wallpaper.
|
||||
|
@ -101,7 +127,7 @@ end
|
|||
-- all screens are set.
|
||||
-- @param offset This can be set to a table with entries x and y.
|
||||
function wallpaper.tiled(surf, s, offset)
|
||||
local geom, img, cr = prepare_wallpaper(s)
|
||||
local geom, cr = wallpaper.prepare_context(s)
|
||||
|
||||
if offset then
|
||||
cr:translate(offset.x, offset.y)
|
||||
|
@ -112,8 +138,6 @@ function wallpaper.tiled(surf, s, offset)
|
|||
cr.source = pattern
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
|
||||
wallpaper.set(img)
|
||||
end
|
||||
|
||||
--- Set a maximized wallpaper.
|
||||
|
@ -124,7 +148,7 @@ end
|
|||
-- The default is to honor the aspect ratio.
|
||||
-- @param offset This can be set to a table with entries x and y.
|
||||
function wallpaper.maximized(surf, s, ignore_aspect, offset)
|
||||
local geom, img, cr = prepare_wallpaper(s)
|
||||
local geom, cr = wallpaper.prepare_context(s)
|
||||
local surf = surface(surf)
|
||||
local w, h = surface.get_size(surf)
|
||||
local aspect_w = geom.width / w
|
||||
|
@ -147,8 +171,6 @@ function wallpaper.maximized(surf, s, ignore_aspect, offset)
|
|||
cr:set_source_surface(surf, 0, 0)
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
|
||||
wallpaper.set(img)
|
||||
end
|
||||
|
||||
--- Set a fitting wallpaper.
|
||||
|
@ -158,7 +180,7 @@ end
|
|||
-- @param background The background color that should be used. Gets handled via
|
||||
-- gears.color. The default is black.
|
||||
function wallpaper.fit(surf, s, background)
|
||||
local geom, img, cr = prepare_wallpaper(s)
|
||||
local geom, cr = wallpaper.prepare_context(s)
|
||||
local surf = surface(surf)
|
||||
local background = color(background)
|
||||
|
||||
|
@ -179,8 +201,6 @@ function wallpaper.fit(surf, s, background)
|
|||
cr:scale(scale, scale)
|
||||
cr:set_source_surface(surf, 0, 0)
|
||||
cr:paint()
|
||||
|
||||
wallpaper.set(img)
|
||||
end
|
||||
|
||||
return wallpaper
|
||||
|
|
Loading…
Reference in New Issue