This code snippet allows you to force a wibox.widget.imagebox
to be re-draw itself without pointing it to a new file path.
Important: the solution given here only works with PNG files. If your file is either not a PNG or you are not sure
about its type, you can convert it using ffmpeg
, shown at the end.
Let's assume you have a bit of code where you want to update your imagebox whenever the global signal imagebox_update_signal
is emitted.
The signal passes a string to a file path that's always the same.
Note that this would be the same if image
would be a constant.
-- This code is broken. It does not work.
local wibox = require("wibox")
local my_imagebox = wibox.widget {
resize = true,
widget = wibox.widget.imagebox,
}
awesome.connect_signal("imagebox_update_signal", function(image)
my_imagebox:set_image(image)
end)
This will not work, because you are giving the same path to the :set_image
-method.
So what can you do?
Instead of sending the same path string every time, what you have to do is to create a new "cairo surface" every time you want to redraw the imagebox (cairo is the graphics library used by awesome under the hood to paint custom widgets and graphics to the screen).
-- This is the code you want to copy without reading what I wrote ;)
local cairo = require("lgi").cairo
local wibox = require("wibox")
local gears = require("gears")
local image_path =
local my_imagebox = wibox.widget {
resize = true,
widget = wibox.widget.imagebox,
}
awesome.connect_signal("imagebox_update_signal", function(image)
my_imagebox:set_image(image)
end)
local function redraw_imagebox(image_path)
local surface = cairo.ImageSurface.create('ARGB32', 50, 50)
local cr = cairo.Context(surface)
local img = cairo.ImageSurface.create_from_png(image_path)
cr:paint()
awesome.emit_signal("imagebox_update_signal", img)
end
The redraw_imagebox
-function needs to be triggered every time you want to redraw the imagebox. This can, for example,
be done using a gears.timer
:
local timer = gears.timer {
timeout = 1, -- call once per second
autostart = true, -- start without `calling timer:start()` first
callback = function() { -- the function called by the timer
redraw_imagebox(image_path) -- assumes `image_path` was previously defined in-scope, like in the example above
}
}
As mentioned at the beginning, this only works with PNG files. If you need to convert the image to a PNG beforehand, you can do so using this function calling ffmpeg:
local function convert_image_file_to_png(input_image_path, output_image_path)
-- The `-y`-flag causes ffmpeg to automatically overwrite files, so be aware of that
awful.spawn({"ffmpeg", "-y", "-i", input_image_path, output_image_path})
end
Important: The -y
-flag causes ffmpeg
to automatically overwrite files, so be aware of that.
However, you probably want that to have an asynchronous callback, so you can redraw your imagebox once ffmpeg
is done:
local function convert_image_file_to_png(input_image_path, output_image_path)
awful.spawn.easy_async({"ffmpeg", "-y", "-i", input_image_path, output_image_path}, function()
redraw_imagebox(output_image_path)
end)
end
- Awesome wm cairo guide: https://awesomewm.org/apidoc/documentation/16-using-cairo.md.html
- LGI cairo documentation: https://github.com/pavouk/lgi/blob/master/docs/cairo.md
- LGI cairo examples: https://github.com/pavouk/lgi/blob/master/samples/cairo.lua
- u/SirAiedail on Reddit, who pointed me in the right direction here.
This document is released into the public domain under the Creative Commons Zero (CC0 license) license, while the code snippets within it are licensed under the unlicense. Both licenses can be considered public domain, as-is licenses (this is not legal advice; read the licenses).
Just leave a comment, I'll try to help!