Rewrite tests/_client.lua
The new client is hopefully faster. Why, you ask? Instead of spawning a new Lua process each time a test asks for a new window, there is a "daemon process" which gets commands to open new windows from its standard input. That way, Lua doesn't have to load LGI all the time and lots of pointless work is skipped. The daemon process exits when its stdin is closed and thus should automatically exit when awesome exits. Fixes: https://github.com/awesomeWM/awesome/issues/1089 Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
7f74c783cd
commit
8dc6c5f502
|
@ -3,27 +3,101 @@ local spawn = require("awful.spawn")
|
|||
-- This file provide a simple, yet flexible, test client.
|
||||
-- It is used to test the `awful.rules`
|
||||
|
||||
return function(class, title, use_sn)
|
||||
class = class or 'test_app'
|
||||
title = title or 'Awesome test client'
|
||||
local test_client_source = [[
|
||||
local lgi = require 'lgi'
|
||||
local Gtk = lgi.require('Gtk')
|
||||
local Gio = lgi.require('Gio')
|
||||
Gtk.init()
|
||||
|
||||
local cmd = {"lua" , "-e", table.concat {
|
||||
"local lgi = require 'lgi';",
|
||||
"local Gtk = lgi.require('Gtk');",
|
||||
"Gtk.init();",
|
||||
"local class = '",class,"';",
|
||||
"local window = Gtk.Window {",
|
||||
" default_width = 100,",
|
||||
" default_height = 100,",
|
||||
" on_destroy = Gtk.main_quit,",
|
||||
" title = '",title,
|
||||
"'};",
|
||||
"window:set_wmclass(class, class);",
|
||||
"window:show_all();",
|
||||
"Gtk:main{...}"
|
||||
}}
|
||||
local function open_window(class, title, snid)
|
||||
local window = Gtk.Window {
|
||||
default_width = 100,
|
||||
default_height = 100,
|
||||
title = title
|
||||
}
|
||||
if snid ~= "" then
|
||||
window:set_startup_id(snid)
|
||||
end
|
||||
window:set_wmclass(class, class)
|
||||
window:show_all()
|
||||
end
|
||||
|
||||
return spawn(cmd, use_sn)
|
||||
-- Start a coroutine for nicer input handling
|
||||
local coro = coroutine.wrap(function()
|
||||
while true do
|
||||
local class = coroutine.yield()
|
||||
local title = coroutine.yield()
|
||||
local snid = coroutine.yield()
|
||||
open_window(class, title, snid)
|
||||
end
|
||||
end)
|
||||
coro()
|
||||
|
||||
-- Read lines from stdin and feed them to the coroutine
|
||||
local stdin = Gio.UnixInputStream.new(0, false)
|
||||
stdin = Gio.DataInputStream.new(stdin)
|
||||
|
||||
local read_start, read_finish
|
||||
read_start = function()
|
||||
stdin:read_line_async(0, nil, read_finish)
|
||||
end
|
||||
read_finish = function(...)
|
||||
local line, length = stdin.read_line_finish(...)
|
||||
if type(length) ~= "number" then
|
||||
error("Error reading line: " .. tostring(length))
|
||||
end
|
||||
|
||||
local eof = not line -- Behaviour of up-to-date LGI
|
||||
or (tostring(line) == "" and #line ~= length) -- (Ab)use uninitialized variable
|
||||
if eof then
|
||||
Gtk.main_quit()
|
||||
else
|
||||
coro(tostring(line)) -- tostring() needed for older LGI versions
|
||||
read_start()
|
||||
end
|
||||
end
|
||||
|
||||
read_start()
|
||||
Gtk:main{...}
|
||||
]]
|
||||
|
||||
local lgi = require("lgi")
|
||||
local Gio = lgi.require("Gio")
|
||||
|
||||
local initialized = false
|
||||
local pipe
|
||||
local function init()
|
||||
if initialized then return end
|
||||
initialized = true
|
||||
local cmd = { "lua", "-e", test_client_source }
|
||||
local _, _, stdin, stdout, stderr = awesome.spawn(cmd, false, true, true, true)
|
||||
pipe = Gio.UnixOutputStream.new(stdin, true)
|
||||
stdout = Gio.UnixInputStream.new(stdout, true)
|
||||
stderr = Gio.UnixInputStream.new(stderr, true)
|
||||
spawn.read_lines(stdout, function(...) print("_client", ...) end)
|
||||
spawn.read_lines(stderr, function(...) print("_client", ...) end)
|
||||
end
|
||||
|
||||
-- Hack needed for awesome's Startup Notification machinery
|
||||
local function get_snid(sn_rules)
|
||||
local success, snid = spawn({ "/bin/true" }, sn_rules)
|
||||
assert(success)
|
||||
assert(snid)
|
||||
return snid
|
||||
end
|
||||
|
||||
return function(class, title, sn_rules)
|
||||
class = class or "test_app"
|
||||
title = title or "Awesome test client"
|
||||
|
||||
init()
|
||||
local snid = sn_rules and get_snid(sn_rules) or ""
|
||||
local data = class .. "\n" .. title .. "\n" .. snid .. "\n"
|
||||
local success, msg = pipe:write_all(data)
|
||||
assert(success, msg)
|
||||
|
||||
-- TODO: Fix the API of this function
|
||||
return true, sn_rules and snid or nil
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
Loading…
Reference in New Issue