Harden display apply and recovery
This commit is contained in:
@@ -27,25 +27,78 @@ local prefs = require("prefs")
|
||||
-- (see the header) rather than preferences, and a settings page has no way to
|
||||
-- explain the screencopy tradeoff at the moment you would be changing it.
|
||||
local displays = prefs.get("displays", {})
|
||||
if type(displays) ~= "table" then
|
||||
displays = {}
|
||||
end
|
||||
|
||||
local function override(output, field, fallback)
|
||||
local function mode_dimensions(mode)
|
||||
if type(mode) ~= "string" then
|
||||
return nil, nil
|
||||
end
|
||||
local width, height, refresh = mode:match("^(%d+)x(%d+)@(%d+%.%d+)$")
|
||||
if width == nil then
|
||||
width, height, refresh = mode:match("^(%d+)x(%d+)@(%d+)$")
|
||||
end
|
||||
width, height, refresh = tonumber(width), tonumber(height), tonumber(refresh)
|
||||
if width == nil or height == nil or refresh == nil
|
||||
or width <= 0 or height <= 0 or refresh <= 0 then
|
||||
return nil, nil
|
||||
end
|
||||
return width, height
|
||||
end
|
||||
|
||||
local function valid_mode(mode)
|
||||
local width = mode_dimensions(mode)
|
||||
return width ~= nil
|
||||
end
|
||||
|
||||
local function valid_scale(mode, scale)
|
||||
local width, height = mode_dimensions(mode)
|
||||
if width == nil or type(scale) ~= "number" or scale ~= scale
|
||||
or scale <= 0 or scale > 4 then
|
||||
return false
|
||||
end
|
||||
local logical_width = width / scale
|
||||
local logical_height = height / scale
|
||||
return math.abs(logical_width - math.floor(logical_width + 0.5)) < 0.0001
|
||||
and math.abs(logical_height - math.floor(logical_height + 0.5)) < 0.0001
|
||||
end
|
||||
|
||||
local function valid_transform(transform)
|
||||
return type(transform) == "number"
|
||||
and transform == math.floor(transform)
|
||||
and transform >= 0
|
||||
and transform <= 3
|
||||
end
|
||||
|
||||
local function display_entry(output)
|
||||
if type(output) ~= "string" or output == ""
|
||||
or output:match("^[%w_.-]+$") == nil then
|
||||
return nil
|
||||
end
|
||||
local entry = displays[output]
|
||||
if type(entry) ~= "table" then
|
||||
return fallback
|
||||
return nil
|
||||
end
|
||||
local value = entry[field]
|
||||
if value == nil or type(value) ~= type(fallback) then
|
||||
return fallback
|
||||
if not valid_mode(entry.mode)
|
||||
or not valid_scale(entry.mode, entry.scale)
|
||||
or not valid_transform(entry.transform) then
|
||||
return nil
|
||||
end
|
||||
return value
|
||||
return entry
|
||||
end
|
||||
|
||||
local shipped_mode = "4500x3000@60"
|
||||
local shipped_scale = 1.5
|
||||
local shipped_transform = 0
|
||||
local dp2 = display_entry("DP-2")
|
||||
|
||||
hl.monitor({
|
||||
output = "DP-2",
|
||||
mode = override("DP-2", "mode", "4500x3000@60"),
|
||||
mode = dp2 and dp2.mode or shipped_mode,
|
||||
position = "0x0",
|
||||
scale = override("DP-2", "scale", 1.5),
|
||||
transform = override("DP-2", "transform", 0),
|
||||
scale = dp2 and dp2.scale or shipped_scale,
|
||||
transform = dp2 and dp2.transform or shipped_transform,
|
||||
|
||||
-- 10-bit output. 4500x3000@60 at 10bpc is ~24 Gbps, right at the edge of
|
||||
-- DP 1.4 HBR3, so this relies on DSC. If the display fails to light up or
|
||||
@@ -56,6 +109,24 @@ hl.monitor({
|
||||
cm = "auto",
|
||||
})
|
||||
|
||||
-- Other connected outputs use the same validated per-output store. They keep
|
||||
-- automatic placement and the compositor's normal colour policy; DP-2 alone
|
||||
-- carries the panel-specific 10-bit policy documented above.
|
||||
for output, _ in pairs(displays) do
|
||||
if output ~= "DP-2" then
|
||||
local entry = display_entry(output)
|
||||
if entry ~= nil then
|
||||
hl.monitor({
|
||||
output = output,
|
||||
mode = entry.mode,
|
||||
position = "auto",
|
||||
scale = entry.scale,
|
||||
transform = entry.transform,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Any monitor not named above: sane defaults rather than nothing.
|
||||
hl.monitor({
|
||||
output = "",
|
||||
|
||||
Reference in New Issue
Block a user