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:
Uli Schlachter 2016-09-16 18:16:28 +02:00
parent 7f74c783cd
commit 8dc6c5f502
1 changed files with 93 additions and 19 deletions

View File

@ -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