Merge branch 'surface-errors' of https://github.com/psychon/awesome
This commit is contained in:
commit
3793c339ce
15
draw.c
15
draw.c
|
@ -229,23 +229,18 @@ draw_dup_image_surface(cairo_surface_t *surface)
|
|||
/** Load the specified path into a cairo surface
|
||||
* \param L Lua state
|
||||
* \param path file to load
|
||||
* \param error A place to store an error message, if needed
|
||||
* \return A cairo image surface or NULL on error.
|
||||
*/
|
||||
cairo_surface_t *
|
||||
draw_load_image(lua_State *L, const char *path)
|
||||
draw_load_image(lua_State *L, const char *path, GError **error)
|
||||
{
|
||||
GError *error = NULL;
|
||||
cairo_surface_t *ret;
|
||||
GdkPixbuf *buf = gdk_pixbuf_new_from_file(path, &error);
|
||||
GdkPixbuf *buf = gdk_pixbuf_new_from_file(path, error);
|
||||
|
||||
if (!buf) {
|
||||
luaL_where(L, 1);
|
||||
lua_pushstring(L, error->message);
|
||||
lua_concat(L, 2);
|
||||
g_error_free(error);
|
||||
lua_error(L);
|
||||
if (!buf)
|
||||
/* error was set above */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = draw_surface_from_pixbuf(buf);
|
||||
g_object_unref(buf);
|
||||
|
|
3
draw.h
3
draw.h
|
@ -25,6 +25,7 @@
|
|||
#include <xcb/xcb.h>
|
||||
#include <cairo.h>
|
||||
#include <lua.h>
|
||||
#include <glib.h> /* for GError */
|
||||
|
||||
#include "common/util.h"
|
||||
|
||||
|
@ -70,7 +71,7 @@ a_iso2utf8(const char *str, ssize_t len, char **dest, ssize_t *dlen)
|
|||
|
||||
cairo_surface_t *draw_surface_from_data(int width, int height, uint32_t *data);
|
||||
cairo_surface_t *draw_dup_image_surface(cairo_surface_t *surface);
|
||||
cairo_surface_t *draw_load_image(lua_State *L, const char *path);
|
||||
cairo_surface_t *draw_load_image(lua_State *L, const char *path, GError **error);
|
||||
|
||||
xcb_visualtype_t *draw_find_visual(const xcb_screen_t *s, xcb_visualid_t visual);
|
||||
xcb_visualtype_t *draw_default_visual(const xcb_screen_t *s);
|
||||
|
|
|
@ -558,7 +558,7 @@ function menu.entry(parent, args)
|
|||
if type(args.cmd) == "table" then
|
||||
if args.theme.submenu_icon then
|
||||
submenu = wibox.widget.imagebox()
|
||||
submenu:set_image(surface.load(args.theme.submenu_icon))
|
||||
submenu:set_image(args.theme.submenu_icon)
|
||||
else
|
||||
submenu = wibox.widget.textbox()
|
||||
submenu:set_font(args.theme.font)
|
||||
|
|
|
@ -107,9 +107,7 @@ function taglist.taglist_label(t, args)
|
|||
text = text .. "</span>"
|
||||
end
|
||||
if not taglist_disable_icon then
|
||||
if tag.geticon(t) and type(tag.geticon(t)) == "image" then
|
||||
icon = tag.geticon(t)
|
||||
elseif tag.geticon(t) then
|
||||
if tag.geticon(t) then
|
||||
icon = surface.load(tag.geticon(t))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -562,13 +562,7 @@ function naughty.notify(args)
|
|||
end
|
||||
|
||||
-- is the icon file readable?
|
||||
local success, res = pcall(function() return surface.load_uncached(icon) end)
|
||||
if success then
|
||||
icon = res
|
||||
else
|
||||
io.stderr:write(string.format("naughty: Couldn't load image '%s': %s\n", tostring(icon), res))
|
||||
icon = nil
|
||||
end
|
||||
local icon = surface.load_uncached(icon)
|
||||
|
||||
-- if we have an icon, use it
|
||||
if icon then
|
||||
|
|
|
@ -72,17 +72,16 @@ end
|
|||
--- Set an imagebox' image
|
||||
-- @param image Either a string or a cairo image surface. A string is
|
||||
-- interpreted as the path to a png image file.
|
||||
-- @return true on success, false if the image cannot be used
|
||||
function imagebox:set_image(image)
|
||||
local image = image
|
||||
|
||||
if type(image) == "string" then
|
||||
local success, result = pcall(surface.load, image)
|
||||
if not success then
|
||||
print("Error while reading '" .. image .. "': " .. result)
|
||||
image = surface.load(image)
|
||||
if not image then
|
||||
print(debug.traceback())
|
||||
return false
|
||||
end
|
||||
image = result
|
||||
end
|
||||
|
||||
image = surface.load(image)
|
||||
|
|
16
luaa.c
16
luaa.c
|
@ -147,16 +147,24 @@ luaA_restart(lua_State *L)
|
|||
/** Load an image from a given path.
|
||||
*
|
||||
* @param name The file name.
|
||||
* @return A cairo surface as light user datum.
|
||||
* @return[1] A cairo surface as light user datum.
|
||||
* @return[2] nil
|
||||
* @treturn[2] string Error message
|
||||
* @function load_image
|
||||
*/
|
||||
static int
|
||||
luaA_load_image(lua_State *L)
|
||||
{
|
||||
GError *error = NULL;
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
cairo_surface_t *surface = draw_load_image(L, filename);
|
||||
if (!surface)
|
||||
return 0;
|
||||
cairo_surface_t *surface = draw_load_image(L, filename, &error);
|
||||
if (!surface) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, error->message);
|
||||
g_error_free(error);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* lua has to make sure to free the ref or we have a leak */
|
||||
lua_pushlightuserdata(L, surface);
|
||||
return 1;
|
||||
|
|
|
@ -124,8 +124,11 @@ drawable_set_geometry(lua_State *L, int didx, area_t geom)
|
|||
static int
|
||||
luaA_drawable_get_surface(lua_State *L, drawable_t *drawable)
|
||||
{
|
||||
/* Lua gets its own reference which it will have to destroy */
|
||||
lua_pushlightuserdata(L, cairo_surface_reference(drawable->surface));
|
||||
if (drawable->surface)
|
||||
/* Lua gets its own reference which it will have to destroy */
|
||||
lua_pushlightuserdata(L, cairo_surface_reference(drawable->surface));
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue