From 615aff336980901bb6e697626227437aa35d5129 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 29 Jul 2012 16:39:03 +0200 Subject: [PATCH] gears.wallpaper: Import This is a lua module for managing the wallpaper. Signed-off-by: Uli Schlachter --- lib/gears/init.lua.in | 1 + lib/gears/wallpaper.lua.in | 160 +++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 lib/gears/wallpaper.lua.in diff --git a/lib/gears/init.lua.in b/lib/gears/init.lua.in index a4101569..94c31f66 100644 --- a/lib/gears/init.lua.in +++ b/lib/gears/init.lua.in @@ -13,6 +13,7 @@ return object = require("gears.object"); sort = require("gears.sort"); surface = require("gears.surface"); + wallpaper = require("gears.wallpaper"); } -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/gears/wallpaper.lua.in b/lib/gears/wallpaper.lua.in new file mode 100644 index 00000000..a2841d96 --- /dev/null +++ b/lib/gears/wallpaper.lua.in @@ -0,0 +1,160 @@ +--------------------------------------------------------------------------- +-- @author Uli Schlachter +-- @copyright 2012 Uli Schlachter +-- @release @AWESOME_VERSION@ +--------------------------------------------------------------------------- + +local cairo = require("lgi").cairo +local color = require("gears.color") +local surface = require("gears.surface") + +-- gears.wallpaper +local wallpaper = { mt = {} } + +-- The size of the root window +local root_geom +do + local geom = screen[1].geometry + root_geom = { + x = 0, y = 0, + width = geom.x + geom.width, + height = geom.y + geom.height + } + for s = 1, screen.count() do + local g = screen[s].geometry + root_geom.width = math.max(root_geom.width, g.x + g.width) + root_geom.height = math.max(root_geom.height, g.y + g.height) + end +end + +--- Prepare the needed state for setting a wallpaper +-- @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) + local geom = s and screen[s].geometry or root_geom + local img = surface(root.wallpaper()) + + if not img then + -- No wallpaper yet + img = cairo.ImageSurface(cairo.Format.RGB24, root_geom.width, root_geom.height) + 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 +end + +--- Get the size of a cairo surface +-- @param surf The surface you are interested in +-- @returns The surface's width and height +local function surface_size(surf) + local cr = cairo.Context(surf) + local x, y, w, h = cr:clip_extents() + return w, h +end + +--- Set the current wallpaper. +-- @param pattern The wallpaper that should be set. This can be a cairo surface, +-- a description for gears.color or a cairo pattern. +function wallpaper.set(pattern) + if cairo.Surface:is_type_of(pattern) then + pattern = cairo.Pattern.create_for_surface(pattern) + end + if type(pattern) == "string" or type(pattern) == "table" then + pattern = color(pattern) + end + if not cairo.Pattern:is_type_of(pattern) then + error("wallpaper.set() called with an invalid argument") + end + root.wallpaper(pattern._native) +end + +--- Set a centered wallpaper. +-- @param surf The wallpaper to center. Either a cairo surface or a file name. +-- @param s The screen whose wallpaper should be set. Can be nil, in which case +-- all screens are set. +-- @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 surf = surface(surf) + local background = color(background) + + -- Fill the area with the background + cr.operator = cairo.Operator.SOURCE + cr.source = background + cr:paint() + + -- Now center the surface + local w, h = surface_size(surf) + cr:translate((geom.width - w) / 2, (geom.height - h) / 2) + cr:rectangle(0, 0, w, h) + cr:clip() + cr:set_source_surface(surf, 0, 0) + cr:paint() + + wallpaper.set(img) +end + +--- Set a tiled wallpaper. +-- @param surf The wallpaper to tile. Either a cairo surface or a file name. +-- @param s The screen whose wallpaper should be set. Can be nil, in which case +-- 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) + + if offset then + cr:translate(offset.x, offset.y) + end + + local pattern = cairo.Pattern.create_for_surface(surface(surf)) + pattern.extend = cairo.Extend.REPEAT + cr.source = pattern + cr.operator = cairo.Operator.SOURCE + cr:paint() + + wallpaper.set(img) +end + +--- Set a maximized wallpaper. +-- @param surf The wallpaper to set. Either a cairo surface or a file name. +-- @param s The screen whose wallpaper should be set. Can be nil, in which case +-- all screens are set. +-- @param ignore_aspect If this is true, the image's aspect ratio is ignored. +-- 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 surf = surface(surf) + local w, h = surface_size(surf) + local aspect_w = geom.width / w + local aspect_h = geom.height / h + + if not ignore_aspect then + aspect_h = math.max(aspect_w, aspect_h) + aspect_w = math.max(aspect_w, aspect_h) + end + cr:scale(aspect_w, aspect_h) + + if offset then + cr:translate(offset.x, offset.y) + end + + cr:set_source_surface(surf, 0, 0) + cr.operator = cairo.Operator.SOURCE + cr:paint() + + wallpaper.set(img) +end + +return wallpaper + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80