Add better error handling to gears.surface
Previously, a Lua error was thrown when loading a file failed. Most callers are not prepared for this and the result is less than optimal. This commit makes the functions print the errors and return nil instead. For callers that want to handle errors themselves, "_silent" variants of the functions are introduced which just return errors to the caller. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
2e58a9c6eb
commit
58ecd92b8e
|
@ -9,6 +9,7 @@ local setmetatable = setmetatable
|
|||
local type = type
|
||||
local capi = { awesome = awesome }
|
||||
local cairo = require("lgi").cairo
|
||||
local gdebug = require("gears.debug")
|
||||
|
||||
-- Keep this in sync with build-utils/lgi-check.sh!
|
||||
local ver_major, ver_minor, ver_patch = string.match(require('lgi.version'), '(%d)%.(%d)%.(%d)')
|
||||
|
@ -19,13 +20,22 @@ end
|
|||
local surface = { mt = {} }
|
||||
local surface_cache = setmetatable({}, { __mode = 'v' })
|
||||
|
||||
local function get_empty_surface()
|
||||
return cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
|
||||
end
|
||||
|
||||
--- Try to convert the argument into an lgi cairo surface.
|
||||
-- This is usually needed for loading images by file name.
|
||||
function surface.load_uncached(_surface)
|
||||
-- @param _surface The surface to load or nil
|
||||
-- @param default The default value to return on error; when nil, then a surface
|
||||
-- in an error state is returned.
|
||||
-- @return The loaded surface, or the replacement default
|
||||
-- @return An error message, or nil on success
|
||||
function surface.load_uncached_silently(_surface, default)
|
||||
local file
|
||||
-- Nil is not changed
|
||||
-- On nil, return an empty surface
|
||||
if not _surface then
|
||||
return nil
|
||||
return get_empty_surface()
|
||||
end
|
||||
-- Remove from cache if it was cached
|
||||
surface_cache[_surface] = nil
|
||||
|
@ -35,8 +45,15 @@ function surface.load_uncached(_surface)
|
|||
end
|
||||
-- Strings are assumed to be file names and get loaded
|
||||
if type(_surface) == "string" then
|
||||
local err
|
||||
file = _surface
|
||||
_surface = capi.awesome.load_image(file)
|
||||
_surface, err = capi.awesome.load_image(file)
|
||||
if not _surface then
|
||||
if type(default) == 'nil' then
|
||||
default = get_empty_surface()
|
||||
end
|
||||
return default, err
|
||||
end
|
||||
end
|
||||
-- Everything else gets forced into a surface
|
||||
_surface = cairo.Surface(_surface, true)
|
||||
|
@ -47,14 +64,53 @@ function surface.load_uncached(_surface)
|
|||
return _surface
|
||||
end
|
||||
|
||||
function surface.load(_surface)
|
||||
--- Try to convert the argument into an lgi cairo surface.
|
||||
-- This is usually needed for loading images by file name and uses a cache.
|
||||
-- In contrast to `load()`, errors are returned to the caller.
|
||||
-- @param _surface The surface to load or nil
|
||||
-- @param default The default value to return on error; when nil, then a surface
|
||||
-- in an error state is returned.
|
||||
-- @return The loaded surface, or the replacement default, or nil if called with
|
||||
-- nil.
|
||||
-- @return An error message, or nil on success
|
||||
function surface.load_silently(_surface, default)
|
||||
if type(_surface) == "string" then
|
||||
local cache = surface_cache[_surface]
|
||||
if cache then
|
||||
return cache
|
||||
end
|
||||
end
|
||||
return surface.load_uncached(_surface)
|
||||
return surface.load_uncached_silently(_surface, default)
|
||||
end
|
||||
|
||||
local function do_load_and_handle_errors(_surface, func)
|
||||
if type(_surface) == 'nil' then
|
||||
return get_empty_surface()
|
||||
end
|
||||
local result, err = func(_surface, false)
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
gdebug.print_error("Failed to load '" .. tostring(_surface) .. "': " .. tostring(err))
|
||||
return get_empty_surface()
|
||||
end
|
||||
|
||||
--- Try to convert the argument into an lgi cairo surface.
|
||||
-- This is usually needed for loading images by file name. Errors are handled
|
||||
-- via `gears.debug.print_error`.
|
||||
-- @param _surface The surface to load or nil
|
||||
-- @return The loaded surface, or nil
|
||||
function surface.load_uncached(_surface)
|
||||
return do_load_and_handle_errors(_surface, surface.load_uncached_silently)
|
||||
end
|
||||
|
||||
--- Try to convert the argument into an lgi cairo surface.
|
||||
-- This is usually needed for loading images by file name. Errors are handled
|
||||
-- via `gears.debug.print_error`.
|
||||
-- @param _surface The surface to load or nil
|
||||
-- @return The loaded surface, or nil
|
||||
function surface.load(_surface)
|
||||
return do_load_and_handle_errors(_surface, surface.load_silently)
|
||||
end
|
||||
|
||||
function surface.mt:__call(...)
|
||||
|
@ -70,7 +126,6 @@ function surface.get_size(surf)
|
|||
return w - x, h - y
|
||||
end
|
||||
|
||||
|
||||
--- Create a copy of a cairo surface.
|
||||
-- The surfaces returned by `surface.load` are cached and must not be
|
||||
-- modified to avoid unintended side-effects. This function allows to create
|
||||
|
|
Loading…
Reference in New Issue