Merge pull request #3490 from Elv13/less_flacky_tests
Less flacky tests
This commit is contained in:
commit
062ecfb6f0
|
@ -257,7 +257,7 @@ jobs:
|
||||||
grep -q 'May not access' lib/beautiful/init.lua
|
grep -q 'May not access' lib/beautiful/init.lua
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cd "${{ github.workspace }}/build" && make
|
run: cd "${{ github.workspace }}/build" && make -j3
|
||||||
|
|
||||||
# Executable needs to be run once to provide coverage results
|
# Executable needs to be run once to provide coverage results
|
||||||
- name: Install and run
|
- name: Install and run
|
||||||
|
|
|
@ -402,6 +402,11 @@ add_custom_target(check DEPENDS check-integration)
|
||||||
add_executable(test-gravity tests/test-gravity.c)
|
add_executable(test-gravity tests/test-gravity.c)
|
||||||
target_link_libraries(test-gravity
|
target_link_libraries(test-gravity
|
||||||
${AWESOME_COMMON_REQUIRED_LDFLAGS} ${AWESOME_REQUIRED_LDFLAGS})
|
${AWESOME_COMMON_REQUIRED_LDFLAGS} ${AWESOME_REQUIRED_LDFLAGS})
|
||||||
|
|
||||||
|
add_executable(test-systray tests/test-systray.c)
|
||||||
|
target_link_libraries(test-systray
|
||||||
|
${AWESOME_COMMON_REQUIRED_LDFLAGS} ${AWESOME_REQUIRED_LDFLAGS})
|
||||||
|
|
||||||
if(DO_COVERAGE)
|
if(DO_COVERAGE)
|
||||||
set(TESTS_RUN_ENV DO_COVERAGE=1)
|
set(TESTS_RUN_ENV DO_COVERAGE=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -46,22 +46,24 @@ end
|
||||||
-- @propemits true false
|
-- @propemits true false
|
||||||
|
|
||||||
function background:set_notification(notif)
|
function background:set_notification(notif)
|
||||||
if self._private.notification == notif then return end
|
local old = self._private.notification[1]
|
||||||
|
|
||||||
if self._private.notification then
|
if old == notif then return end
|
||||||
self._private.notification:disconnect_signal("property::bg",
|
|
||||||
|
if old then
|
||||||
|
old:disconnect_signal("property::bg",
|
||||||
self._private.background_changed_callback)
|
self._private.background_changed_callback)
|
||||||
self._private.notification:disconnect_signal("property::border_width",
|
old:disconnect_signal("property::border_width",
|
||||||
self._private.background_changed_callback)
|
self._private.background_changed_callback)
|
||||||
self._private.notification:disconnect_signal("property::border_color",
|
old:disconnect_signal("property::border_color",
|
||||||
self._private.background_changed_callback)
|
self._private.background_changed_callback)
|
||||||
self._private.notification:disconnect_signal("property::shape",
|
old:disconnect_signal("property::shape",
|
||||||
self._private.background_changed_callback)
|
self._private.background_changed_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
update_background(notif, self)
|
update_background(notif, self)
|
||||||
|
|
||||||
self._private.notification = notif
|
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||||
|
|
||||||
notif:connect_signal("property::bg" , self._private.background_changed_callback)
|
notif:connect_signal("property::bg" , self._private.background_changed_callback)
|
||||||
notif:connect_signal("property::border_width", self._private.background_changed_callback)
|
notif:connect_signal("property::border_width", self._private.background_changed_callback)
|
||||||
|
@ -82,12 +84,13 @@ local function new(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
local bg = wbg()
|
local bg = wbg()
|
||||||
|
bg._private.notification = {}
|
||||||
bg:set_border_strategy("inner")
|
bg:set_border_strategy("inner")
|
||||||
|
|
||||||
gtable.crush(bg, background, true)
|
gtable.crush(bg, background, true)
|
||||||
|
|
||||||
function bg._private.background_changed_callback()
|
function bg._private.background_changed_callback()
|
||||||
update_background(bg._private.notification, bg)
|
update_background(bg._private.notification[1], bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.notification then
|
if args.notification then
|
||||||
|
|
|
@ -47,14 +47,16 @@ local function init_screen(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function disconnect(self)
|
local function disconnect(self)
|
||||||
if self._private.notification then
|
local n = self._private.notification[1]
|
||||||
self._private.notification:disconnect_signal("destroyed",
|
|
||||||
|
if n then
|
||||||
|
n:disconnect_signal("destroyed",
|
||||||
self._private.destroy_callback)
|
self._private.destroy_callback)
|
||||||
|
|
||||||
self._private.notification:disconnect_signal("property::margin",
|
n:disconnect_signal("property::margin",
|
||||||
self._private.update)
|
self._private.update)
|
||||||
|
|
||||||
self._private.notification:disconnect_signal("property::suspended",
|
n:disconnect_signal("property::suspended",
|
||||||
self._private.hide)
|
self._private.hide)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -123,14 +125,13 @@ local function finish(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local preset
|
local preset = (self._private.notification[1] or {}).preset
|
||||||
if self.private and self.private.args and self.private.args.notification then
|
|
||||||
preset = self.private.args.notification.preset
|
|
||||||
end
|
|
||||||
|
|
||||||
update_position(self.position, preset)
|
update_position(self.position, preset)
|
||||||
|
|
||||||
disconnect(self)
|
disconnect(self)
|
||||||
|
|
||||||
|
self._private.notification = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- It isn't a good idea to use the `attach` `awful.placement` property. If the
|
-- It isn't a good idea to use the `attach` `awful.placement` property. If the
|
||||||
|
@ -236,21 +237,19 @@ local function generate_widget(args, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Call `:set_notification` on all children
|
-- Call `:set_notification` on all children
|
||||||
awcommon._set_common_property(w, "notification", n or args.notification)
|
awcommon._set_common_property(w, "notification", n)
|
||||||
|
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
||||||
local function init(self, notification)
|
local function init(self, notification)
|
||||||
local args = self._private.args
|
|
||||||
|
|
||||||
local preset = notification.preset or {}
|
local preset = notification.preset or {}
|
||||||
|
|
||||||
local position = args.position or notification.position or
|
local position = self._private.position or notification.position or
|
||||||
preset.position or beautiful.notification_position or "top_right"
|
preset.position or beautiful.notification_position or "top_right"
|
||||||
|
|
||||||
if not self.widget then
|
if not self.widget then
|
||||||
self.widget = generate_widget(self._private.args, notification)
|
self.widget = generate_widget(self._private, notification)
|
||||||
end
|
end
|
||||||
|
|
||||||
local bg = self._private.widget:get_children_by_id( "background_role" )[1]
|
local bg = self._private.widget:get_children_by_id( "background_role" )[1]
|
||||||
|
@ -295,20 +294,26 @@ local function init(self, notification)
|
||||||
end
|
end
|
||||||
|
|
||||||
function box:set_notification(notif)
|
function box:set_notification(notif)
|
||||||
if self._private.notification == notif then return end
|
if self._private.notification[1] == notif then return end
|
||||||
|
|
||||||
disconnect(self)
|
disconnect(self)
|
||||||
|
|
||||||
init(self, notif)
|
init(self, notif)
|
||||||
|
|
||||||
self._private.notification = notif
|
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||||
|
|
||||||
self:emit_signal("property::notification", notif)
|
self:emit_signal("property::notification", notif)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function box:get_notification()
|
||||||
|
return self._private.notification[1]
|
||||||
|
end
|
||||||
|
|
||||||
function box:get_position()
|
function box:get_position()
|
||||||
if self._private.notification then
|
local n = self._private.notification[1]
|
||||||
return self._private.notification:get_position()
|
|
||||||
|
if n then
|
||||||
|
return n:get_position()
|
||||||
end
|
end
|
||||||
|
|
||||||
return "top_right"
|
return "top_right"
|
||||||
|
@ -357,7 +362,9 @@ local function new(args)
|
||||||
if not new_args.widget then return nil end
|
if not new_args.widget then return nil end
|
||||||
|
|
||||||
local ret = popup(new_args)
|
local ret = popup(new_args)
|
||||||
ret._private.args = new_args
|
ret._private.notification = {}
|
||||||
|
ret._private.widget_template = args.widget_template
|
||||||
|
ret._private.position = args.position
|
||||||
|
|
||||||
gtable.crush(ret, box, true)
|
gtable.crush(ret, box, true)
|
||||||
|
|
||||||
|
@ -371,8 +378,10 @@ local function new(args)
|
||||||
|
|
||||||
--TODO remove
|
--TODO remove
|
||||||
local function hide()
|
local function hide()
|
||||||
if ret._private.notification then
|
local n = ret._private.notification[1]
|
||||||
ret._private.notification:destroy()
|
|
||||||
|
if n then
|
||||||
|
n:destroy()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -168,14 +168,16 @@ local function wb_label(action, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update(self)
|
local function update(self)
|
||||||
if not self._private.layout or not self._private.notification then return end
|
local n = self._private.notification[1]
|
||||||
|
|
||||||
|
if not self._private.layout or not n then return end
|
||||||
|
|
||||||
awcommon.list_update(
|
awcommon.list_update(
|
||||||
self._private.layout,
|
self._private.layout,
|
||||||
self._private.default_buttons,
|
self._private.default_buttons,
|
||||||
function(o) return wb_label(o, self) end,
|
function(o) return wb_label(o, self) end,
|
||||||
self._private.data,
|
self._private.data,
|
||||||
self._private.notification.actions,
|
n.actions,
|
||||||
{
|
{
|
||||||
widget_template = self._private.widget_template
|
widget_template = self._private.widget_template
|
||||||
}
|
}
|
||||||
|
@ -229,7 +231,7 @@ local actionlist = {}
|
||||||
|
|
||||||
|
|
||||||
function actionlist:set_notification(notif)
|
function actionlist:set_notification(notif)
|
||||||
self._private.notification = notif
|
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||||
|
|
||||||
if not self._private.layout then
|
if not self._private.layout then
|
||||||
self._private.layout = wibox.layout.fixed.horizontal()
|
self._private.layout = wibox.layout.fixed.horizontal()
|
||||||
|
@ -329,8 +331,9 @@ local function new(_, args)
|
||||||
gtable.crush(wdg, actionlist, true)
|
gtable.crush(wdg, actionlist, true)
|
||||||
|
|
||||||
wdg._private.data = {}
|
wdg._private.data = {}
|
||||||
|
wdg._private.notification = {}
|
||||||
|
|
||||||
gtable.crush(wdg, args)
|
gtable.crush(wdg, args, false)
|
||||||
|
|
||||||
wdg._private.style = wdg._private.style or {}
|
wdg._private.style = wdg._private.style or {}
|
||||||
|
|
||||||
|
@ -338,7 +341,7 @@ local function new(_, args)
|
||||||
|
|
||||||
wdg._private.default_buttons = gtable.join(
|
wdg._private.default_buttons = gtable.join(
|
||||||
abutton({ }, 1, function(a)
|
abutton({ }, 1, function(a)
|
||||||
local notif = wdg._private.notification or args.notification
|
local notif = wdg._private.notification[1]
|
||||||
a:invoke(notif)
|
a:invoke(notif)
|
||||||
end)
|
end)
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,7 +22,7 @@ local function notif_size()
|
||||||
constraint:set_width(beautiful.notification_max_width or dpi(500))
|
constraint:set_width(beautiful.notification_max_width or dpi(500))
|
||||||
|
|
||||||
rawset(constraint, "set_notification", function(_, notif)
|
rawset(constraint, "set_notification", function(_, notif)
|
||||||
constraint._private.notification = notif
|
constraint._private.notification = setmetatable({notif}, {__mode = "v"})
|
||||||
local s = false
|
local s = false
|
||||||
|
|
||||||
if notif.width and notif.width ~= beautiful.notification_max_width then
|
if notif.width and notif.width ~= beautiful.notification_max_width then
|
||||||
|
@ -37,6 +37,10 @@ local function notif_size()
|
||||||
constraint.strategy = s and "exact" or "max"
|
constraint.strategy = s and "exact" or "max"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
rawset(constraint, "get_notification", function()
|
||||||
|
return constraint._private.notification[1]
|
||||||
|
end)
|
||||||
|
|
||||||
return constraint
|
return constraint
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -83,10 +83,12 @@ end
|
||||||
-- @propemits true false
|
-- @propemits true false
|
||||||
|
|
||||||
function icon:set_notification(notif)
|
function icon:set_notification(notif)
|
||||||
if self._private.notification == notif then return end
|
local old = (self._private.notification or {})[1]
|
||||||
|
|
||||||
if self._private.notification then
|
if old == notif then return end
|
||||||
self._private.notification:disconnect_signal("destroyed",
|
|
||||||
|
if old then
|
||||||
|
old:disconnect_signal("destroyed",
|
||||||
self._private.icon_changed_callback)
|
self._private.icon_changed_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -96,7 +98,7 @@ function icon:set_notification(notif)
|
||||||
self:set_image(icn)
|
self:set_image(icn)
|
||||||
end
|
end
|
||||||
|
|
||||||
self._private.notification = notif
|
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||||
|
|
||||||
notif:connect_signal("property::icon", self._private.icon_changed_callback)
|
notif:connect_signal("property::icon", self._private.icon_changed_callback)
|
||||||
self:emit_signal("property::notification", notif)
|
self:emit_signal("property::notification", notif)
|
||||||
|
@ -154,10 +156,14 @@ local function new(args)
|
||||||
local tb = imagebox()
|
local tb = imagebox()
|
||||||
|
|
||||||
gtable.crush(tb, icon, true)
|
gtable.crush(tb, icon, true)
|
||||||
|
tb._private.notification = {}
|
||||||
|
|
||||||
function tb._private.icon_changed_callback()
|
function tb._private.icon_changed_callback()
|
||||||
|
local n = tb._private.notification[1]
|
||||||
|
|
||||||
local icn = gsurface.load_silently(tb._private.notification.icon)
|
if not n then return end
|
||||||
|
|
||||||
|
local icn = gsurface.load_silently(n.icon)
|
||||||
|
|
||||||
if icn then
|
if icn then
|
||||||
tb:set_image(icn)
|
tb:set_image(icn)
|
||||||
|
|
|
@ -27,18 +27,20 @@ local message = {}
|
||||||
-- @propemits true false
|
-- @propemits true false
|
||||||
|
|
||||||
function message:set_notification(notif)
|
function message:set_notification(notif)
|
||||||
if self._private.notification == notif then return end
|
local old = self._private.notification[1]
|
||||||
|
|
||||||
if self._private.notification then
|
if old == notif then return end
|
||||||
self._private.notification:disconnect_signal("property::message",
|
|
||||||
|
if old then
|
||||||
|
old:disconnect_signal("property::message",
|
||||||
self._private.message_changed_callback)
|
self._private.message_changed_callback)
|
||||||
self._private.notification:disconnect_signal("property::fg",
|
old:disconnect_signal("property::fg",
|
||||||
self._private.message_changed_callback)
|
self._private.message_changed_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
markup(self, notif.message, notif.fg, notif.font)
|
markup(self, notif.message, notif.fg, notif.font)
|
||||||
|
|
||||||
self._private.notification = notif
|
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||||
|
|
||||||
notif:connect_signal("property::message", self._private.message_changed_callback)
|
notif:connect_signal("property::message", self._private.message_changed_callback)
|
||||||
notif:connect_signal("property::fg" , self._private.message_changed_callback)
|
notif:connect_signal("property::fg" , self._private.message_changed_callback)
|
||||||
|
@ -57,16 +59,23 @@ local function new(args)
|
||||||
local tb = textbox()
|
local tb = textbox()
|
||||||
tb:set_wrap("word")
|
tb:set_wrap("word")
|
||||||
tb:set_font(beautiful.notification_font)
|
tb:set_font(beautiful.notification_font)
|
||||||
|
tb._private.notification = {}
|
||||||
|
|
||||||
gtable.crush(tb, message, true)
|
gtable.crush(tb, message, true)
|
||||||
|
|
||||||
function tb._private.message_changed_callback()
|
function tb._private.message_changed_callback()
|
||||||
|
local n = tb._private.notification[1]
|
||||||
|
|
||||||
|
if n then
|
||||||
markup(
|
markup(
|
||||||
tb,
|
tb,
|
||||||
tb._private.notification.message,
|
n.message,
|
||||||
tb._private.notification.fg,
|
n.fg,
|
||||||
tb._private.notification.font
|
n.font
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
markup(tb, nil, nil)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.notification then
|
if args.notification then
|
||||||
|
|
|
@ -27,18 +27,20 @@ local title = {}
|
||||||
-- @propemits true false
|
-- @propemits true false
|
||||||
|
|
||||||
function title:set_notification(notif)
|
function title:set_notification(notif)
|
||||||
if self._private.notification == notif then return end
|
local old = self._private.notification[1]
|
||||||
|
|
||||||
if self._private.notification then
|
if old == notif then return end
|
||||||
self._private.notification:disconnect_signal("property::message",
|
|
||||||
|
if old then
|
||||||
|
old:disconnect_signal("property::message",
|
||||||
self._private.title_changed_callback)
|
self._private.title_changed_callback)
|
||||||
self._private.notification:disconnect_signal("property::fg",
|
old:disconnect_signal("property::fg",
|
||||||
self._private.title_changed_callback)
|
self._private.title_changed_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
markup(self, notif.title, notif.fg, notif.font)
|
markup(self, notif.title, notif.fg, notif.font)
|
||||||
|
|
||||||
self._private.notification = notif
|
self._private.notification = setmetatable({notif}, {__mode="v"})
|
||||||
self._private.title_changed_callback()
|
self._private.title_changed_callback()
|
||||||
|
|
||||||
notif:connect_signal("property::title", self._private.title_changed_callback)
|
notif:connect_signal("property::title", self._private.title_changed_callback)
|
||||||
|
@ -58,16 +60,23 @@ local function new(args)
|
||||||
local tb = textbox()
|
local tb = textbox()
|
||||||
tb:set_wrap("word")
|
tb:set_wrap("word")
|
||||||
tb:set_font(beautiful.notification_font)
|
tb:set_font(beautiful.notification_font)
|
||||||
|
tb._private.notification = {}
|
||||||
|
|
||||||
gtable.crush(tb, title, true)
|
gtable.crush(tb, title, true)
|
||||||
|
|
||||||
function tb._private.title_changed_callback()
|
function tb._private.title_changed_callback()
|
||||||
|
local n = tb._private.notification[1]
|
||||||
|
|
||||||
|
if n then
|
||||||
markup(
|
markup(
|
||||||
tb,
|
tb,
|
||||||
tb._private.notification.title,
|
n.title,
|
||||||
tb._private.notification.fg,
|
n.fg,
|
||||||
tb._private.notification.font
|
n.font
|
||||||
)
|
)
|
||||||
|
else
|
||||||
|
markup("", nil, nil)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.notification then
|
if args.notification then
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
local spawn = require("awful.spawn")
|
local spawn = require("awful.spawn")
|
||||||
|
local gtimer = require("gears.timer")
|
||||||
|
|
||||||
local lua_executable = os.getenv("LUA")
|
local lua_executable = os.getenv("LUA")
|
||||||
if lua_executable == nil or lua_executable == "" then
|
if lua_executable == nil or lua_executable == "" then
|
||||||
|
@ -11,8 +12,9 @@ end
|
||||||
local test_client_source = [[
|
local test_client_source = [[
|
||||||
pcall(require, 'luarocks.loader')
|
pcall(require, 'luarocks.loader')
|
||||||
local lgi = require 'lgi'
|
local lgi = require 'lgi'
|
||||||
|
local GLib = lgi.require('GLib')
|
||||||
local Gdk = lgi.require('Gdk')
|
local Gdk = lgi.require('Gdk')
|
||||||
local Gtk = lgi.require('Gtk')
|
local Gtk = lgi.require('Gtk', '3.0')
|
||||||
local Gio = lgi.require('Gio')
|
local Gio = lgi.require('Gio')
|
||||||
Gtk.init()
|
Gtk.init()
|
||||||
|
|
||||||
|
@ -40,6 +42,8 @@ local function open_window(class, title, options)
|
||||||
end
|
end
|
||||||
if options.maximize_before then
|
if options.maximize_before then
|
||||||
window:maximize()
|
window:maximize()
|
||||||
|
elseif options.unminimize_after then
|
||||||
|
window:iconify()
|
||||||
end
|
end
|
||||||
window:set_wmclass(class, class)
|
window:set_wmclass(class, class)
|
||||||
window:show_all()
|
window:show_all()
|
||||||
|
@ -47,6 +51,14 @@ local function open_window(class, title, options)
|
||||||
window:maximize()
|
window:maximize()
|
||||||
elseif options.unmaximize_after then
|
elseif options.unmaximize_after then
|
||||||
window:unmaximize()
|
window:unmaximize()
|
||||||
|
elseif options.minimize_after then
|
||||||
|
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, function()
|
||||||
|
window:iconify()
|
||||||
|
end)
|
||||||
|
elseif options.unminimize_after then
|
||||||
|
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, function()
|
||||||
|
window:deiconify()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
if options.resize_after_width and options.resize_after_height then
|
if options.resize_after_width and options.resize_after_height then
|
||||||
window:resize(
|
window:resize(
|
||||||
|
@ -107,13 +119,15 @@ local lgi = require("lgi")
|
||||||
local Gio = lgi.require("Gio")
|
local Gio = lgi.require("Gio")
|
||||||
|
|
||||||
local initialized = false
|
local initialized = false
|
||||||
local pipe
|
local pipe, pid
|
||||||
|
|
||||||
local function init()
|
local function init()
|
||||||
if initialized then return end
|
if initialized then return end
|
||||||
initialized = true
|
initialized = true
|
||||||
local cmd = { lua_executable, "-e", test_client_source }
|
local cmd = { lua_executable, "-e", test_client_source }
|
||||||
local _, _, stdin, stdout, stderr = awesome.spawn(cmd, false, true, true, true)
|
local _pid, _, stdin, stdout, stderr = awesome.spawn(cmd, false, true, true, true)
|
||||||
pipe = Gio.UnixOutputStream.new(stdin, true)
|
pipe = Gio.UnixOutputStream.new(stdin, true)
|
||||||
|
pid = _pid
|
||||||
stdout = Gio.UnixInputStream.new(stdout, true)
|
stdout = Gio.UnixInputStream.new(stdout, true)
|
||||||
stderr = Gio.UnixInputStream.new(stderr, true)
|
stderr = Gio.UnixInputStream.new(stderr, true)
|
||||||
spawn.read_lines(stdout, function(...) print("_client", ...) end)
|
spawn.read_lines(stdout, function(...) print("_client", ...) end)
|
||||||
|
@ -128,7 +142,29 @@ local function get_snid(sn_rules, callback)
|
||||||
return snid
|
return snid
|
||||||
end
|
end
|
||||||
|
|
||||||
return function(class, title, sn_rules, callback, resize_increment, args)
|
local module = {}
|
||||||
|
|
||||||
|
function module.terminate()
|
||||||
|
if not initialized then return end
|
||||||
|
|
||||||
|
for _, c in ipairs(client.get()) do
|
||||||
|
c:kill()
|
||||||
|
end
|
||||||
|
|
||||||
|
pipe:close()
|
||||||
|
initialized, pipe = false, nil
|
||||||
|
|
||||||
|
-- Make a copy to avoid the re-initialized race condition.
|
||||||
|
local original_pid = pid
|
||||||
|
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
awesome.kill(original_pid, 9)
|
||||||
|
end)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function new(_, class, title, sn_rules, callback, resize_increment, args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
class = class or "test_app"
|
class = class or "test_app"
|
||||||
title = title or "Awesome test client"
|
title = title or "Awesome test client"
|
||||||
|
@ -152,6 +188,13 @@ return function(class, title, sn_rules, callback, resize_increment, args)
|
||||||
if args.unmaximize_after then
|
if args.unmaximize_after then
|
||||||
options = options .. "unmaximize_after,"
|
options = options .. "unmaximize_after,"
|
||||||
end
|
end
|
||||||
|
if args.unminimize_after then
|
||||||
|
options = options .. "unminimize_after,"
|
||||||
|
end
|
||||||
|
if args.minimize_after then
|
||||||
|
options = options .. "minimize_after,"
|
||||||
|
end
|
||||||
|
|
||||||
if args.size then
|
if args.size then
|
||||||
options = table.concat {
|
options = table.concat {
|
||||||
options,
|
options,
|
||||||
|
@ -182,4 +225,6 @@ return function(class, title, sn_rules, callback, resize_increment, args)
|
||||||
return snid
|
return snid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return setmetatable(module, {__call = new })
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -11,6 +11,18 @@ runner.run_steps{
|
||||||
assert(type(a) == "number", a)
|
assert(type(a) == "number", a)
|
||||||
end
|
end
|
||||||
if #client.get() == 1 then
|
if #client.get() == 1 then
|
||||||
|
local c = client.get()[1]
|
||||||
|
|
||||||
|
local geo = c:geometry()
|
||||||
|
|
||||||
|
-- Resize it to test shape change events.
|
||||||
|
c:geometry {
|
||||||
|
x = geo.x,
|
||||||
|
y = geo.y,
|
||||||
|
width = geo.width * 2,
|
||||||
|
height = geo.height * 2,
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -27,8 +39,15 @@ runner.run_steps{
|
||||||
assert(not surface.load_silently(c.client_shape_clip, false))
|
assert(not surface.load_silently(c.client_shape_clip, false))
|
||||||
assert(not surface.load_silently(c.shape_clip, false))
|
assert(not surface.load_silently(c.shape_clip, false))
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
|
||||||
|
function()
|
||||||
|
client.get()[1]:kill()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -243,8 +243,20 @@ for _, type_name in ipairs { "key", "button" } do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Cleanup (otherwise there is a race with the root.buttons tests)
|
-- Cleanup (otherwise there is a race with the root.buttons tests)
|
||||||
table.insert(steps, function()
|
table.insert(steps, function(count)
|
||||||
if #mouse.screen.clients ~= 0 then return end
|
if #mouse.screen.clients ~= 0 then
|
||||||
|
if count > 5 then
|
||||||
|
-- It's stuck, kill it.
|
||||||
|
test_client.terminate()
|
||||||
|
else
|
||||||
|
for _, c in pairs(client.get()) do
|
||||||
|
c:kill()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end)
|
end)
|
||||||
|
@ -372,6 +384,8 @@ table.insert(steps, function()
|
||||||
return true
|
return true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, test_client.terminate)
|
||||||
|
|
||||||
runner.run_steps(steps)
|
runner.run_steps(steps)
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -371,8 +371,38 @@ gears.table.merge(steps, {
|
||||||
|
|
||||||
if not c or counter ~= 2 then return end
|
if not c or counter ~= 2 then return end
|
||||||
|
|
||||||
|
c:kill()
|
||||||
|
|
||||||
|
client.disconnect_signal("request::geometry", geometry_handler)
|
||||||
|
|
||||||
|
test_client(nil,nil,nil,nil,nil,{minimize_after=true})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end,
|
||||||
|
function()
|
||||||
|
-- Test minimization.
|
||||||
|
if #client.get() ~= 1 or not client.get()[1].minimized then return end
|
||||||
|
|
||||||
|
assert(client.get()[1].minimized)
|
||||||
|
client.get()[1]:kill()
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
if #client.get() > 0 then return end
|
||||||
|
|
||||||
|
test_client(nil,nil,nil,nil,nil,{unminimize_after=true})
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
if #client.get() ~= 1 or client.get()[1].minimized then return end
|
||||||
|
|
||||||
|
assert(not client.get()[1].minimized)
|
||||||
|
client.get()[1]:kill()
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
runner.run_steps(steps)
|
runner.run_steps(steps)
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* A simple client icon that "does nothing".
|
||||||
|
*
|
||||||
|
* Copyright © 2021 Uli Schlachter <psychon@znc.in>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_atom.h>
|
||||||
|
#include <xcb/xcb_aux.h>
|
||||||
|
|
||||||
|
#include "common/atoms.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
|
// Include all the C code we might need directly into this file - I am lazy
|
||||||
|
#include "common/atoms.c"
|
||||||
|
#include "common/util.c"
|
||||||
|
|
||||||
|
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
||||||
|
|
||||||
|
static xcb_atom_t systray_atom(xcb_connection_t *conn, int screen) {
|
||||||
|
char *atom_name;
|
||||||
|
xcb_intern_atom_reply_t *reply;
|
||||||
|
xcb_atom_t atom;
|
||||||
|
|
||||||
|
atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", screen);
|
||||||
|
if(!atom_name)
|
||||||
|
fatal("Error getting systray atom name\n");
|
||||||
|
|
||||||
|
reply = xcb_intern_atom_reply(conn, xcb_intern_atom(conn, 0, strlen(atom_name), atom_name), NULL);
|
||||||
|
free(atom_name);
|
||||||
|
if (!reply)
|
||||||
|
fatal("Error interning systray icon\n");
|
||||||
|
|
||||||
|
atom = reply->atom;
|
||||||
|
free(reply);
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xcb_window_t find_systray(xcb_connection_t *conn, xcb_atom_t net_system_tray) {
|
||||||
|
xcb_get_selection_owner_reply_t* reply = xcb_get_selection_owner_reply(conn, xcb_get_selection_owner(conn, net_system_tray), NULL);
|
||||||
|
if (!reply)
|
||||||
|
fatal("Failed to request selection owner\n");
|
||||||
|
xcb_window_t owner = reply->owner;
|
||||||
|
if (owner == XCB_NONE)
|
||||||
|
fatal("No systray running\n");
|
||||||
|
free(reply);
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_color(xcb_connection_t *conn, xcb_screen_t *screen, uint16_t red, uint16_t green, uint16_t blue) {
|
||||||
|
xcb_alloc_color_reply_t *reply = xcb_alloc_color_reply(conn, xcb_alloc_color(conn, screen->default_colormap, red, green, blue), NULL);
|
||||||
|
if (!reply)
|
||||||
|
fatal("Error allocating color");
|
||||||
|
uint32_t pixel = reply->pixel;
|
||||||
|
free(reply);
|
||||||
|
return pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int default_screen;
|
||||||
|
xcb_connection_t* conn = xcb_connect(NULL, &default_screen);
|
||||||
|
if (xcb_connection_has_error(conn)) {
|
||||||
|
fatal("Could not connect to X11 server: %d\n", xcb_connection_has_error(conn));
|
||||||
|
}
|
||||||
|
atoms_init(conn);
|
||||||
|
xcb_screen_t* screen = xcb_aux_get_screen(conn, default_screen);
|
||||||
|
|
||||||
|
// Create a window for the systray icon
|
||||||
|
xcb_window_t window = xcb_generate_id(conn);
|
||||||
|
xcb_create_window(conn, screen->root_depth, window, screen->root, 0, 0, 10, 10, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
screen->root_visual, XCB_CW_BACK_PIXEL, (uint32_t[]) { get_color(conn, screen, 0xffff, 0x9999, 0x0000) });
|
||||||
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, window, _XEMBED_INFO, _XEMBED_INFO, 32, 2, (uint32_t[]) { 0, 1 });
|
||||||
|
|
||||||
|
// Make our window a systray icon
|
||||||
|
xcb_window_t systray_owner = find_systray(conn, systray_atom(conn, default_screen));
|
||||||
|
xcb_client_message_event_t ev;
|
||||||
|
|
||||||
|
p_clear(&ev, 1);
|
||||||
|
ev.response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
ev.window = systray_owner;
|
||||||
|
ev.format = 32;
|
||||||
|
ev.data.data32[0] = XCB_CURRENT_TIME;
|
||||||
|
ev.data.data32[1] = SYSTEM_TRAY_REQUEST_DOCK;
|
||||||
|
ev.data.data32[2] = window;
|
||||||
|
ev.data.data32[3] = 0;
|
||||||
|
ev.data.data32[4] = 0;
|
||||||
|
ev.type = _NET_SYSTEM_TRAY_OPCODE;
|
||||||
|
xcb_send_event(conn, false, systray_owner, XCB_EVENT_MASK_NO_EVENT, (char *) &ev);
|
||||||
|
|
||||||
|
xcb_flush(conn);
|
||||||
|
xcb_generic_event_t *event;
|
||||||
|
while ((event = xcb_wait_for_event(conn)) != NULL) {
|
||||||
|
free(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_disconnect(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,90 @@
|
||||||
|
local spawn = require("awful.spawn")
|
||||||
|
local wibox = require("wibox")
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
|
||||||
|
local steps, pid1, pid2, draw_w, st = {}
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
screen[1].mywibox:remove()
|
||||||
|
|
||||||
|
local widget = wibox.widget.base.make_widget()
|
||||||
|
|
||||||
|
function widget:fit(_, w, h)
|
||||||
|
return w, h
|
||||||
|
end
|
||||||
|
|
||||||
|
function widget:draw(_, _, width)
|
||||||
|
draw_w = width
|
||||||
|
end
|
||||||
|
|
||||||
|
local wb = wibox {
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
width = 100,
|
||||||
|
height = 20,
|
||||||
|
visible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
st = wibox.widget.systray()
|
||||||
|
|
||||||
|
wb.widget = {
|
||||||
|
st,
|
||||||
|
widget,
|
||||||
|
layout = wibox.layout.fixed.horizontal
|
||||||
|
}
|
||||||
|
|
||||||
|
pid1 = spawn("./test-systray")
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
if draw_w ~= 80 then return end
|
||||||
|
|
||||||
|
pid2 = spawn("./test-systray")
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
if draw_w ~= 60 then return end
|
||||||
|
|
||||||
|
st.reverse = true
|
||||||
|
st.horizontal = false
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
st.horizontal = true
|
||||||
|
|
||||||
|
beautiful.systray_icon_spacing = 10
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
if draw_w ~= 50 then return end
|
||||||
|
|
||||||
|
st.base_size = 5
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
if draw_w ~= 80 then return end
|
||||||
|
|
||||||
|
awesome.kill(pid1, 9)
|
||||||
|
awesome.kill(pid2, 9)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
table.insert(steps, function()
|
||||||
|
if draw_w ~= 100 then return end
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
|
||||||
|
require("_runner").run_steps(steps)
|
|
@ -29,7 +29,7 @@ window.decorated = false
|
||||||
]])
|
]])
|
||||||
}
|
}
|
||||||
|
|
||||||
local found_font = nil
|
local found_font, events, next_pos = nil, {}, {}
|
||||||
|
|
||||||
-- Use the test client props
|
-- Use the test client props
|
||||||
local dep = gdebug.deprecate
|
local dep = gdebug.deprecate
|
||||||
|
@ -44,6 +44,20 @@ local function kill_client(c)
|
||||||
awesome.kill(c.pid, 9)
|
awesome.kill(c.pid, 9)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function click()
|
||||||
|
local x, y= next_pos.x, next_pos.y
|
||||||
|
mouse.coords{x=x, y=y}
|
||||||
|
assert(mouse.coords().x == x and mouse.coords().y == y)
|
||||||
|
root.fake_input("button_press", 1)
|
||||||
|
awesome.sync()
|
||||||
|
root.fake_input("button_release", 1)
|
||||||
|
awesome.sync()
|
||||||
|
next_pos = nil
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Too bad there's no way to disconnect the rc.lua request::titlebars function
|
-- Too bad there's no way to disconnect the rc.lua request::titlebars function
|
||||||
|
|
||||||
local steps = {
|
local steps = {
|
||||||
|
@ -183,6 +197,48 @@ local steps = {
|
||||||
|
|
||||||
assert(found_font == "sans 10")
|
assert(found_font == "sans 10")
|
||||||
|
|
||||||
|
-- Test the events.
|
||||||
|
for _, event in ipairs { "button::press", "button::release", "mouse::move" } do
|
||||||
|
c:connect_signal(event, function()
|
||||||
|
table.insert(events, event)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
next_pos = { x = c:geometry().x + 5, y = c:geometry().y + 5 }
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
click,
|
||||||
|
function()
|
||||||
|
if #events == 0 then return end
|
||||||
|
|
||||||
|
events = {}
|
||||||
|
|
||||||
|
local c = client.get()[1]
|
||||||
|
|
||||||
|
next_pos = { x = c:geometry().x + 5, y = c:geometry().y + c:geometry().height - 5 }
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
click,
|
||||||
|
function()
|
||||||
|
if #events == 0 then return end
|
||||||
|
|
||||||
|
local c = client.get()[1]
|
||||||
|
|
||||||
|
next_pos = {
|
||||||
|
x = c:geometry().x + c:geometry().width/2,
|
||||||
|
y = c:geometry().y + c:geometry().height/2
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
click,
|
||||||
|
function()
|
||||||
|
if #events == 0 then return end
|
||||||
|
|
||||||
|
local c = client.get()[1]
|
||||||
|
|
||||||
kill_client(c)
|
kill_client(c)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -270,7 +270,6 @@ end)
|
||||||
table.insert(steps, function(count)
|
table.insert(steps, function(count)
|
||||||
if count == 1 then return end
|
if count == 1 then return end
|
||||||
|
|
||||||
print(paint_width, paint_height, screen[1].geometry.width, screen[1].geometry.height)
|
|
||||||
assert(paint_width == screen[1].geometry.width)
|
assert(paint_width == screen[1].geometry.width)
|
||||||
assert(paint_height == screen[1].geometry.height)
|
assert(paint_height == screen[1].geometry.height)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue