awesome/tests/test-screenshot.lua

171 lines
4.7 KiB
Lua

-- This test suite tests the various screenshot related APIs.
--
-- Credit: https://www.reddit.com/r/awesomewm/comments/i6nf7z/need_help_writing_a_color_picker_widget_using_lgi/
local wibox = require("wibox")
local spawn = require("awful.spawn")
local gsurface = require("gears.surface")
local lgi = require('lgi')
local cairo = lgi.cairo
local gdk = lgi.require('Gdk', '3.0')
local capi = {
root = _G.root
}
-- Dummy blue client for the client.content test
-- the lua_executable portion may need to get ironed out. I need to specify 5.3
local lua_executable = os.getenv("LUA")
if lua_executable == nil or lua_executable == "" then
lua_executable = "lua5.3"
end
local client_dim = 250
local tiny_client_code_template = [[
local lgi = require('lgi')
local Gdk = lgi.require('Gdk', '3.0')
local Gtk = lgi.require('Gtk', '3.0')
local class = 'client'
window = Gtk.Window {default_width=%d, default_height=%d, title='title'}
window:set_wmclass(class, class)
window:override_background_color(0,
Gdk.RGBA({red = 0, green = 0, blue = 1, alpha = 1}))
window:show_all()
Gtk:main{...}
]]
local tiny_client = { lua_executable, "-e", string.format(
tiny_client_code_template, client_dim, client_dim)}
-- Split in the screen into 2 distict screens.
screen[1]:split()
-- Add a green wibox on screen 1 at (100, 100)
wibox {
bg = "#00ff00",
visible = true,
width = 100,
height = 100,
x = 100,
y = 100,
}
local corners = {}
-- Add red squares at 1 pixel away from each screen corners.
for s in screen do
-- Top left
table.insert(corners, {
x = s.geometry.x + 1,
y = s.geometry.y + 1,
})
-- Top right
table.insert(corners, {
x = s.geometry.x + s.geometry.width - 11,
y = s.geometry.y + 1,
})
-- Bottom left
table.insert(corners, {
x = s.geometry.x + 1,
y = s.geometry.y + s.geometry.height - 11,
})
-- Bottom right
table.insert(corners, {
x = s.geometry.x + s.geometry.width - 11,
y = s.geometry.y + s.geometry.height - 11,
})
end
-- Make 10x10 wibox in each corner to eliminate any geometry errors
for _, corner in ipairs(corners) do
corner.bg = "#ff0000"
corner.visible = true
corner.width = 10
corner.height = 10
wibox(corner)
end
local function copy_to_image_surface(content, w, h)
local sur = gsurface(content)
local img = cairo.ImageSurface(cairo.Format.RGB24, w, h)
local cr = cairo.Context(img)
cr:set_source_surface(sur)
cr:paint()
img:flush()
return img
end
local function get_pixel(img, x, y)
local bytes = gdk.pixbuf_get_from_surface(img, x, y, 1, 1):get_pixels()
return "#" .. bytes:gsub('.', function(c) return ('%02x'):format(c:byte()) end)
end
local steps = {}
-- Check the whole root window.
table.insert(steps, function()
local root_width, root_height = root.size()
local img = copy_to_image_surface(capi.root.content(), root_width,
root_height)
if get_pixel(img, 100, 100) ~= "#00ff00" then return end
if get_pixel(img, 2, 2) ~= "#ff0000" then return end
assert(get_pixel(img, 100, 100) == "#00ff00")
assert(get_pixel(img, 199, 199) == "#00ff00")
assert(get_pixel(img, 201, 201) ~= "#00ff00")
assert(get_pixel(img, 2, 2) == "#ff0000")
assert(get_pixel(img, root_width - 2, 2) == "#ff0000")
assert(get_pixel(img, 2, root_height - 2) == "#ff0000")
assert(get_pixel(img, root_width - 2, root_height - 2) == "#ff0000")
return true
end)
-- Check the screen.content
table.insert(steps, function()
for s in screen do
local geo = s.geometry
local img = copy_to_image_surface(s.content, geo.width, geo.height)
assert(get_pixel(img, geo.x + 4, geo.y + 4) == "#ff0000")
assert(get_pixel(img, geo.x + geo.width - 4, geo.y + 4) == "#ff0000")
assert(get_pixel(img, geo.x + 4, geo.y + geo.height - 4) == "#ff0000")
assert(get_pixel(img, geo.x + geo.width - 4, geo.y + geo.height - 4) == "#ff0000")
end
-- Spawn for the client.content test
assert(#client.get() == 0)
spawn(tiny_client)
return true
end)
-- Check the client.content
table.insert(steps, function()
if #client.get() ~= 1 then return end
local c = client.get()[1]
local geo = c:geometry()
local img = copy_to_image_surface(c.content, geo.width, geo.height)
if get_pixel(img, math.floor(geo.width / 2), math.floor(geo.height / 2)) ~= "#0000ff" then
return
end
-- Make sure the process finishes. Just `c:kill()` only
-- closes the window. Adding some handlers to the GTK "app"
-- created some unwanted side effects in the CI.
awesome.kill(c.pid, 9)
return true
end)
require("_runner").run_steps(steps)