Files
Panama/config/dot/hypr/monitors.lua
T
Gabriel Brown d96863b687 Convert British spellings to American across the repo
colour -> color, behaviour -> behavior, centre -> center, favourite ->
favorite, and about twenty other pairs, applied consistently across
comments, docs, error/UI copy, and a handful of QML identifiers that
used the British spelling as their actual name: SystemSettings'
serialiseValue/serialiseTable/normaliseGradient, Displays'
normaliseModes, Wallpaper's normalisePolicy, SettingsBackup's
serialiseHomeState, DateTime's ntpSynchronised property, Clipboard's
_normalise helper, and ShortcutCapture's cancelled signal (with its
onCancelled handler in ShortcutsPage.qml). Every call site and the two
tests that assert on the literal source text (settings-ownership and
settings-backup-live contracts) were updated in lockstep.

Left untouched: config/dot/espanso/match/packages/misspell-en/ is a
vendored third-party autocorrect dictionary -- its entries are typo
corrections, not our prose, and rewriting them would fight the
package's own purpose (and any future re-sync from upstream).

The already-American `favorites` property (Home page pinned
accessories) was never actually misspelled -- only nearby comments and
error strings said "favourites" -- so no data migration was needed
there.

Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
2026-08-19 08:07:55 -04:00

176 lines
6.2 KiB
Lua

-- ─────────────────────────────────────────────────────────────────────────────
-- Monitors
--
-- Kuycon P20 on DP-2: 4500x3000 @ 60Hz, 1.5x fractional scale.
-- 4500/1.5 = 3000 and 3000/1.5 = 2000, both integers, so this is a "clean"
-- fractional scale and Hyprland will not complain.
--
-- On HDR --------------------------------------------------------------------
-- GNOME runs this panel in bt2100/HDR. Hyprland CAN do that (cm = "hdr"), but
-- on 0.56.x it currently breaks screencopy: grim screenshots come back empty,
-- and OBS/Sunshine capture and hyprlock's blurred background go with them.
-- Root cause is still open upstream. Since screen capture matters more here
-- than an HDR desktop, the desktop runs SDR at 10-bit and HDR is handed to
-- fullscreen games only, via render.cm_auto_hdr in looks.lua.
--
-- To try full-time HDR anyway, set cm = "hdr" below (or override it in
-- overrides.lua) and read the notes in that file first.
-- ─────────────────────────────────────────────────────────────────────────────
local prefs = require("prefs")
-- Per-output overrides written by Panama Settings, keyed by output name:
-- { ["DP-2"] = {
-- mode = "3840x2160@60", scale = 2, transform = 0,
-- x = 0, y = 0, primary = true,
-- } }
--
-- Only mode, scale, and transform are read. Color management and bit depth
-- stay here, because those are the settings with a documented reason attached
-- (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 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 valid_coordinate(value)
return type(value) == "number"
and value == value
and value == math.floor(value)
and value >= -100000
and value <= 100000
end
local function valid_position(entry)
return valid_coordinate(entry.x) and valid_coordinate(entry.y)
end
local function valid_primary(entry)
return type(entry.primary) == "boolean"
end
local function has_layout_fields(entry)
return entry.x ~= nil or entry.y ~= nil or entry.primary ~= nil
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 nil
end
if not valid_mode(entry.mode)
or not valid_scale(entry.mode, entry.scale)
or not valid_transform(entry.transform) then
return nil
end
-- Legacy records have none of the layout fields and keep automatic
-- placement. A partially written extended record is unsafe: accepting its
-- mode but guessing its position could overlap or strand another output.
if has_layout_fields(entry)
and (not valid_position(entry) or not valid_primary(entry)) then
return nil
end
return entry
end
local function display_position(entry, fallback)
if entry ~= nil and has_layout_fields(entry) then
return string.format("%dx%d", entry.x, entry.y)
end
return fallback
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 = dp2 and dp2.mode or shipped_mode,
position = display_position(dp2, "0x0"),
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
-- falls back to a lower mode, drop this line first.
bitdepth = 10,
-- "auto" = sRGB at 8bpc, wide gamut at 10bpc. Not HDR; see header.
cm = "auto",
})
-- Other connected outputs use the same validated per-output store. They keep
-- automatic placement and the compositor's normal color 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 = display_position(entry, "auto"),
scale = entry.scale,
transform = entry.transform,
})
end
end
end
-- Any monitor not named above: sane defaults rather than nothing.
hl.monitor({
output = "",
mode = "preferred",
position = "auto",
scale = "auto",
})
return true