Merge pull request #3484 from Elv13/2012_misc_fixes

Miscellaneous small bug fixes
This commit is contained in:
Emmanuel Lepage Vallée 2021-10-28 12:26:47 -07:00 committed by GitHub
commit c8ada80fb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 362 additions and 41 deletions

View File

@ -984,6 +984,7 @@ capi.client.connect_signal("property::fullscreen", update_implicitly_floating)
capi.client.connect_signal("property::maximized_vertical", update_implicitly_floating) capi.client.connect_signal("property::maximized_vertical", update_implicitly_floating)
capi.client.connect_signal("property::maximized_horizontal", update_implicitly_floating) capi.client.connect_signal("property::maximized_horizontal", update_implicitly_floating)
capi.client.connect_signal("property::maximized", update_implicitly_floating) capi.client.connect_signal("property::maximized", update_implicitly_floating)
capi.client.connect_signal("property::fullscreen", update_implicitly_floating)
capi.client.connect_signal("property::size_hints", update_implicitly_floating) capi.client.connect_signal("property::size_hints", update_implicitly_floating)
capi.client.connect_signal("request::manage", update_implicitly_floating) capi.client.connect_signal("request::manage", update_implicitly_floating)

View File

@ -608,32 +608,39 @@ end, "mouse_enter")
function permissions.update_border(c, context) function permissions.update_border(c, context)
if not pcommon.check(c, "client", "border", context) then return end if not pcommon.check(c, "client", "border", context) then return end
local suffix, fallback = "", "" local suffix, fallback1, fallback2 = "", ""
-- Add the sub-namespace. -- Add the sub-namespace.
if c.fullscreen then if c.fullscreen then
suffix, fallback = "_fullscreen", "_fullscreen" suffix, fallback1 = "_fullscreen", "_fullscreen"
elseif c.maximized then elseif c.maximized then
suffix, fallback = "_maximized", "_maximized" suffix, fallback1 = "_maximized", "_maximized"
elseif c.floating then elseif c.floating then
suffix, fallback = "_floating", "_floating" suffix, fallback1 = "_floating", "_floating"
end end
-- Add the state suffix. -- Add the state suffix.
if c.urgent then if c.urgent then
suffix = suffix .. "_urgent" suffix, fallback2 = suffix .. "_urgent", "_urgent"
elseif c.active then elseif c.active then
suffix = suffix .. "_active" suffix, fallback2 = suffix .. "_active", "_active"
elseif context == "added" then elseif context == "added" then
suffix = suffix .. "_new" suffix, fallback2 = suffix .. "_new", "_new"
else else
suffix = suffix .. "_normal" suffix, fallback2 = suffix .. "_normal", "_normal"
end end
if not c._private._user_border_width then if not c._private._user_border_width then
c._border_width = beautiful["border_width"..suffix] local bw = beautiful["border_width"..suffix]
or beautiful["border_width"..fallback] or beautiful["border_width"..fallback1]
or beautiful.border_width or beautiful["border_width"..fallback2]
-- The default `awful.permissions.geometry` handler removes the border.
if (not bw) and (c.fullscreen or c.maximized) then
bw = 0
end
c._border_width = bw or beautiful.border_width
end end
if not c._private._user_border_color then if not c._private._user_border_color then
@ -657,8 +664,12 @@ function permissions.update_border(c, context)
local tv = beautiful["border_color"..suffix] local tv = beautiful["border_color"..suffix]
if fallback ~= "" and not tv then if (not tv) and fallback1 ~= "" then
tv = beautiful["border_color"..fallback] tv = beautiful["border_color"..fallback1]
end
if (not tv) and (fallback2 ~= "") then
tv = beautiful["border_color"..fallback2]
end end
-- The old theme variable did not have "color" in its name. -- The old theme variable did not have "color" in its name.
@ -688,8 +699,12 @@ function permissions.update_border(c, context)
if not c._private._user_opacity then if not c._private._user_opacity then
local tv = beautiful["opacity"..suffix] local tv = beautiful["opacity"..suffix]
if fallback ~= "" and not tv then if fallback1 ~= "" and not tv then
tv = beautiful["opacity"..fallback] tv = beautiful["opacity"..fallback1]
end
if fallback2 ~= "" and not tv then
tv = beautiful["opacity"..fallback2]
end end
if tv then if tv then

View File

@ -383,7 +383,7 @@ end
area_common = function(d, new_geo, ignore_border_width, args) area_common = function(d, new_geo, ignore_border_width, args)
-- The C side expect no arguments, nil isn't valid -- The C side expect no arguments, nil isn't valid
if new_geo and args.zap_border_width then if new_geo and args.zap_border_width then
d.border_width = 0 d._border_width = 0
end end
local geometry = new_geo and d:geometry(new_geo) or d:geometry() local geometry = new_geo and d:geometry(new_geo) or d:geometry()
local border = ignore_border_width and 0 or d.border_width or 0 local border = ignore_border_width and 0 or d.border_width or 0
@ -1633,7 +1633,7 @@ function placement.restore(d, args)
end end
d.border_width = memento.border_width d._border_width = memento.border_width
-- Don't use the memento as it would be "destructive", since `x`, `y` -- Don't use the memento as it would be "destructive", since `x`, `y`
-- and `screen` have to be modified. -- and `screen` have to be modified.

View File

@ -583,6 +583,7 @@ local function new(c, args)
bars[position] = { bars[position] = {
args = args, args = args,
drawable = ret, drawable = ret,
font = args.font or beautiful.titlebar_font,
update_colors = update_colors update_colors = update_colors
} }
@ -683,6 +684,20 @@ local function update_on_signal(c, signal, widget)
table.insert(widgets, widget) table.insert(widgets, widget)
end end
--- Honor the font.
local function draw_title(self, ctx, cr, width, height)
if ctx.position and ctx.client then
local bars = all_titlebars[ctx.client]
local data = bars and bars[ctx.position]
if data and data.font then
self:set_font(data.font)
end
end
textbox.draw(self, ctx, cr, width, height)
end
--- Create a new title widget. --- Create a new title widget.
-- --
-- A title widget displays the name of a client. -- A title widget displays the name of a client.
@ -694,6 +709,9 @@ end
-- @constructorfct awful.titlebar.widget.titlewidget -- @constructorfct awful.titlebar.widget.titlewidget
function titlebar.widget.titlewidget(c) function titlebar.widget.titlewidget(c)
local ret = textbox() local ret = textbox()
rawset(ret, "draw", draw_title)
local function update() local function update()
ret:set_text(c.name or titlebar.fallback_name) ret:set_text(c.name or titlebar.fallback_name)
end end

View File

@ -245,7 +245,7 @@ local layoutlist = {}
--- The space between the layouts. --- The space between the layouts.
-- @beautiful beautiful.layoutlist_spacing -- @beautiful beautiful.layoutlist_spacing
-- @tparam[opt=0] number spacing The spacing between tasks. -- @tparam[opt=0] number spacing The spacing between layouts.
--- The default layoutlist elements shape. --- The default layoutlist elements shape.
-- @beautiful beautiful.layoutlist_shape -- @beautiful beautiful.layoutlist_shape
@ -314,10 +314,10 @@ function layoutlist:set_base_layout(layout)
layout or wibox.layout.fixed.horizontal layout or wibox.layout.fixed.horizontal
) )
if self._private.layout.set_spacing then local spacing = self._private.style.spacing or beautiful.tasklist_spacing
self._private.layout:set_spacing(
self._private.style.spacing or beautiful.tasklist_spacing or 0 if self._private.layout.set_spacing and spacing then
) self._private.layout:set_spacing(spacing)
end end
assert(self._private.layout.is_widget) assert(self._private.layout.is_widget)
@ -363,7 +363,7 @@ end
--- Create a layout list. --- Create a layout list.
-- --
-- @tparam table args -- @tparam table args
-- @tparam widget args.layout The widget layout (not to be confused with client -- @tparam widget args.base_layout The widget layout (not to be confused with client
-- layout). -- layout).
-- @tparam table args.buttons A table with buttons binding to set. -- @tparam table args.buttons A table with buttons binding to set.
-- @tparam[opt=awful.widget.layoutlist.source.for_screen] function args.source A -- @tparam[opt=awful.widget.layoutlist.source.for_screen] function args.source A
@ -400,6 +400,8 @@ local function update_common()
end end
local function new(_, args) local function new(_, args)
args = args or {}
local ret = wibox.widget.base.make_widget(nil, nil, { local ret = wibox.widget.base.make_widget(nil, nil, {
enable_properties = true, enable_properties = true,
}) })
@ -413,11 +415,15 @@ local function new(_, args)
reload_cache(ret) reload_cache(ret)
-- Apply all args properties -- Apply all args properties. Make sure "set_layout" doesn't override
gtable.crush(ret, args) -- the widget `layout` method.
local l = args.layout
args.layout = nil
gtable.crush(ret, args, false)
args.layout = l
if not ret._private.layout then if not ret._private.layout then
ret:set_base_layout() ret:set_base_layout(args.layout)
end end
assert(ret._private.layout) assert(ret._private.layout)

View File

@ -332,12 +332,47 @@ end
--- Set a textbox font. --- Set a textbox font.
-- --
-- There is multiple valid font string representation. The most precise is
-- [XFT](https://wiki.archlinux.org/title/X_Logical_Font_Description). It
-- is also possible to use the family name, followed by the face and size
-- such as `Monospace Bold 10`. This script lists the fonts present
-- on your system:
--
-- #!/usr/bin/env lua
--
-- local lgi = require("lgi")
-- local pangocairo = lgi.PangoCairo
--
-- local font_map = pangocairo.font_map_get_default()
--
-- for k, v in pairs(font_map:list_families()) do
-- print(v:get_name(), "monospace?: "..tostring(v:is_monospace()))
-- for k2, v2 in ipairs(v:list_faces()) do
-- print(" ".. v2:get_face_name())
-- end
-- end
--
-- Save this script somewhere on your system, `chmod +x` it and run it. It
-- will list something like:
--
-- Sans monospace?: false
-- Regular
-- Bold
-- Italic
-- Bold Italic
--
-- In this case, the font could be `Sans 10` or `Sans Bold Italic 10`.
--
-- @property font -- @property font
-- @tparam string font The font description as string. -- @tparam string font The font description as string.
-- @propemits true false -- @propemits true false
-- @propbeautiful -- @propbeautiful
function textbox:set_font(font) function textbox:set_font(font)
if font == self._private.font then return end
self._private.font = font
self._private.layout:set_font_description(beautiful.get_font(font)) self._private.layout:set_font_description(beautiful.get_font(font))
self:emit_signal("widget::redraw_needed") self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed") self:emit_signal("widget::layout_changed")

View File

@ -0,0 +1,190 @@
-- Brute force every possible states and see what blows up.
--
-- The goal is to detect "other" code paths within the core
-- which have the side effect of accidentally marking the border
-- to be user-specified. When this happens, all theme variables
-- stop working.
--
-- For example, fullscreen caused an issue because the default
-- request::geometry modified the border_width.
local beautiful = require("beautiful")
local aclient = require("awful.client")
local test_client = require("_client")
local steps = {}
local used_colors = {}
local state_colors, state_widths = {}, {}
local state_setter = {}
local c = nil
-- Make sure it uses `beautiful.border_width` (default) again.
local function reset()
client.focus = nil
c.urgent = false
c.maximized = false
c.fullscreen = false
-- Use the low level API because `floating` has an implicit/explicit
-- mode just like the border.
aclient.property.set(c, "floating", nil)
end
local function gen_random_color(state)
while true do
local str = "#"
for _=1, 3 do
local part = string.format("%x", math.ceil(math.random() * 255))
part = #part == 1 and ("0"..part) or part
str = str .. part
end
if not used_colors[str] then
used_colors[str] = state
return str
end
end
end
local function check_state(state)
reset()
if state_setter[state] then
local col = "border_color" .. state
local w = "border_width" .. state
state_setter[state](client.get()[1])
assert(c.border_color ~= nil)
assert(c.border_width ~= nil)
assert(
c.border_color == state_colors[col],
"Expected "..state_colors[col].." for "..state.. " but got "..c.border_color..
" for "..(used_colors[c.border_color] or "nil")
)
if not state:find("full") then
assert(c.border_width == state_widths[w])
else
assert(c.border_width == 0)
end
assert(not c._private._user_border_width)
assert(not c._private._user_border_color)
end
return true
end
local function clear_theme()
for k in pairs(beautiful) do
if k:find("border_") then
beautiful[k] = nil
end
end
return true
end
for _, state1 in ipairs {"_fullscreen", "_maximized", "_floating" } do
local color = "border_color" .. state1
local width = "border_width" .. state1
state_widths[width] = math.floor(math.random() * 10)
state_colors[color] = gen_random_color(color)
for _, state2 in ipairs {"_urgent", "_active", "_new", "_normal" } do
color = "border_color" .. state1 .. state2
width = "border_width" .. state1 .. state2
state_widths[width] = math.floor(math.random() * 10)
state_colors[color] = gen_random_color(color)
end
end
for _, state in ipairs {"_urgent", "_active", "_new", "_normal" } do
local color = "border_color" .. state
local width = "border_width" .. state
state_widths[width] = math.floor(math.random() * 10)
state_colors[color] = gen_random_color(color)
beautiful[width] = state_widths[width]
beautiful[color] = state_colors[color]
end
function state_setter._urgent()
c.urgent = true
end
function state_setter._fullscreen()
c.fullscreen = true
end
function state_setter._floating()
c.floating = true
end
function state_setter._active()
client.focus = c
end
function state_setter._maximized()
c.maximized = true
end
function state_setter._normal()
-- no-op
end
test_client()
table.insert(steps, function()
c = client.get()[1]
return c and true or nil
end)
for _, state in ipairs {"_urgent", "_active", "_new", "_normal" } do
table.insert(steps, function()
return check_state(state)
end)
end
table.insert(steps, clear_theme)
table.insert(steps, function()
for _, state in ipairs {"_fullscreen", "_maximized", "_floating" } do
local color = "border_color" .. state
local width = "border_width" .. state
beautiful[width] = state_widths[width]
beautiful[color] = state_colors[color]
end
return true
end)
for _, state in ipairs {"_fullscreen", "_maximized", "_floating" } do
table.insert(steps, function()
return check_state(state)
end)
end
table.insert(steps, clear_theme)
table.insert(steps, function()
-- Add everything to the theme.
for _, mode in ipairs {state_colors, state_widths} do
for key, value in pairs(mode) do
beautiful[key] = value
end
end
return true
end)
for _, state1 in ipairs {"_fullscreen", "_maximized", "_floating" } do
for _, state2 in ipairs {"_urgent", "_active", "_new", "_normal" } do
table.insert(steps, function()
return check_state(state1 .. state2)
end)
end
end
require("_runner").run_steps(steps)

View File

@ -8,6 +8,8 @@ local lgi = require("lgi")
local Gio = lgi.Gio local Gio = lgi.Gio
local GdkPixbuf = lgi.GdkPixbuf local GdkPixbuf = lgi.GdkPixbuf
local pids = {}
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
lua_executable = "lua" lua_executable = "lua"
@ -53,8 +55,9 @@ runner.run_steps{
-- Clear the clipboard to get to a known state -- Clear the clipboard to get to a known state
function() function()
spawn.with_line_callback({ lua_executable, "-e", acquire_and_clear_clipboard }, local pid = spawn.with_line_callback({ lua_executable, "-e", acquire_and_clear_clipboard },
{ exit = function() continue = true end }) { exit = function() continue = true end })
table.insert(pids, pid)
return true return true
end, end,
@ -84,13 +87,15 @@ runner.run_steps{
-- Now set the clipboard to some text -- Now set the clipboard to some text
continue = false continue = false
spawn.with_line_callback({ lua_executable, "-e", acquire_clipboard_text }, local pid = spawn.with_line_callback({ lua_executable, "-e", acquire_clipboard_text },
{ stdout = function(line) { stdout = function(line)
assert(line == "initialisation done", assert(line == "initialisation done",
"Unexpected line: " .. line) "Unexpected line: " .. line)
continue = true continue = true
end }) end })
table.insert(pids, pid)
return true return true
end, end,
@ -148,13 +153,15 @@ runner.run_steps{
-- Now set the clipboard to an image -- Now set the clipboard to an image
continue = false continue = false
spawn.with_line_callback({ lua_executable, "-e", acquire_clipboard_pixbuf }, local pid = spawn.with_line_callback({ lua_executable, "-e", acquire_clipboard_pixbuf },
{ stdout = function(line) { stdout = function(line)
assert(line == "initialisation done", assert(line == "initialisation done",
"Unexpected line: " .. line) "Unexpected line: " .. line)
continue = true continue = true
end }) end })
table.insert(pids, pid)
return true return true
end, end,
@ -194,6 +201,12 @@ runner.run_steps{
return return
end end
-- There are now "windows", so they have no "clients", however,
-- they talk to X11 and wont exit by themselves and must be killed.
for _, pid in ipairs(pids) do
awesome.kill(pid, 9)
end
return true return true
end, end,
} }

View File

@ -3,6 +3,8 @@
local runner = require("_runner") local runner = require("_runner")
local spawn = require("awful.spawn") local spawn = require("awful.spawn")
local pids = {}
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
lua_executable = "lua" lua_executable = "lua"
@ -67,8 +69,11 @@ runner.run_steps{
-- Clear the clipboard to get to a known state -- Clear the clipboard to get to a known state
function() function()
check_state(0, 0) check_state(0, 0)
spawn.with_line_callback({ lua_executable, "-e", acquire_and_clear_clipboard }, local pid = spawn.with_line_callback({ lua_executable, "-e", acquire_and_clear_clipboard },
{ exit = function() continue = true end }) { exit = function() continue = true end })
table.insert(pids, pid)
return true return true
end, end,
@ -86,13 +91,15 @@ runner.run_steps{
-- Set the clipboard -- Set the clipboard
continue = false continue = false
spawn.with_line_callback({ lua_executable, "-e", acquire_clipboard }, local pid = spawn.with_line_callback({ lua_executable, "-e", acquire_clipboard },
{ stdout = function(line) { stdout = function(line)
assert(line == "initialisation done", assert(line == "initialisation done",
"Unexpected line: " .. line) "Unexpected line: " .. line)
continue = true continue = true
end }) end })
table.insert(pids, pid)
return true return true
end, end,
@ -105,9 +112,11 @@ runner.run_steps{
-- Now clear the clipboard again -- Now clear the clipboard again
continue = false continue = false
spawn.with_line_callback({ lua_executable, "-e", acquire_and_clear_clipboard }, local pid = spawn.with_line_callback({ lua_executable, "-e", acquire_and_clear_clipboard },
{ exit = function() continue = true end }) { exit = function() continue = true end })
table.insert(pids, pid)
return true return true
end, end,
@ -118,6 +127,13 @@ runner.run_steps{
end end
check_state(2, 1) check_state(2, 1)
-- There are now "windows", so they have no "clients", however,
-- they talk to X11 and wont exit by themselves and must be killed.
for _, pid in ipairs(pids) do
awesome.kill(pid, 9)
end
return true return true
end end
} }

View File

@ -3,6 +3,7 @@ local titlebar = require("awful.titlebar")
local rules = require("ruled.client") local rules = require("ruled.client")
local spawn = require("awful.spawn") local spawn = require("awful.spawn")
local gdebug = require("gears.debug") local gdebug = require("gears.debug")
local textbox = require("wibox.widget.textbox")
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
@ -17,10 +18,8 @@ window = Gtk.Window {default_width=100, default_height=100, title='title'}
%s %s
window:set_wmclass(class, class) window:set_wmclass(class, class)
local app = Gtk.Application {} local app = Gtk.Application {}
function app:on_activate() window:show_all()
window.application = self Gtk:main{...}
window:show_all()
end
app:run {''} app:run {''}
]] ]]
local tiny_client = { lua_executable, "-e", string.format(tiny_client_code_template, "") } local tiny_client = { lua_executable, "-e", string.format(tiny_client_code_template, "") }
@ -30,12 +29,21 @@ window.decorated = false
]]) ]])
} }
local found_font = nil
-- Use the test client props -- Use the test client props
local dep = gdebug.deprecate local dep = gdebug.deprecate
gdebug.deprecate = function() end gdebug.deprecate = function() end
rules.rules = {} rules.rules = {}
gdebug.deprecate = dep gdebug.deprecate = dep
local function kill_client(c)
-- 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)
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 = {
@ -69,7 +77,7 @@ local steps = {
titlebar.toggle(c, "top") titlebar.toggle(c, "top")
assert(c.height == 100) assert(c.height == 100)
c:kill() kill_client(c)
return true return true
end, end,
@ -100,7 +108,7 @@ local steps = {
assert(c.width == 100 and c.height == h) assert(c.width == 100 and c.height == h)
c:kill() kill_client(c)
return true return true
end, end,
@ -119,7 +127,7 @@ local steps = {
assert(c.width == 100 and c.height > 100) assert(c.width == 100 and c.height > 100)
assert(c._request_titlebars_called) assert(c._request_titlebars_called)
c:kill() kill_client(c)
return true return true
end, end,
@ -140,7 +148,7 @@ local steps = {
assert(c.width == 100 and c.height > 100) assert(c.width == 100 and c.height > 100)
assert(c._request_titlebars_called) assert(c._request_titlebars_called)
c:kill() kill_client(c)
return true return true
end, end,
@ -161,7 +169,26 @@ local steps = {
assert(not c._request_titlebars_called) assert(not c._request_titlebars_called)
assert(c.width == 100 and c.height == 100) assert(c.width == 100 and c.height == 100)
c:kill() function textbox:set_font(value)
found_font = value
end
local args = {size = 40, font = "sans 10", position = "bottom"}
titlebar(c, args).widget = titlebar.widget.titlewidget(c)
return true
end,
function()
local c = client.get()[1]
assert(found_font == "sans 10")
kill_client(c)
return true
end,
function()
if #client.get() > 0 then return end
return true return true
end, end,