Files
dotfiles/user/dot_config/hypr/hyprland-monitors.lua
T
2026-08-09 16:14:55 +02:00

163 lines
5.3 KiB
Lua

-- if multiple profiles match, profile with highest priority wins.
-- if no profile match at all, the fallback_profile will be applied anyways.
local fallback_profile="laptop"
local profiles = {
home = {
priority = 10,
monitors = {
"desc:GIGA-BYTE TECHNOLOGY CO. LTD. M34WQ 0x00000B52",
"desc:Dell Inc. DELL U2724D DL7R834",
"desc:Dell Inc. DELL U2414H 292K475V26JL",
},
disable_other_monitors = true,
monitor_config = {
["desc:GIGA-BYTE TECHNOLOGY CO. LTD. M34WQ 0x00000B52"] = {disabled=false, scale=1, position="0x0", mode="3440x1440@60"},
["desc:Dell Inc. DELL U2724D DL7R834"] = {disabled=false, scale=1, position="3440x0", mode="2556x1440@60"},
["desc:Dell Inc. DELL U2414H 292K475V26JL"] = {disabled=false, scale=1, position="760x-1080", mode="1920x1080@60"},
},
workspace_rules = {
},
},
work = {
priority = 10,
monitors = {
"eDP-1",
"desc:Dell Inc. DELL U2724DE BD19MF4",
"desc:Dell Inc. DELL U2724D 1CQFMF4",
},
disable_other_monitors = false,
monitor_config = {
["eDP-1"] = {disabled=false, scale=1, position="0x0", mode="1920x1200@120"},
["desc:Dell Inc. DELL U2724DE BD19MF4"] = {disabled=false, scale=1, position="1920x0", mode="2560x1440@120"},
["desc:Dell Inc. DELL U2724D 1CQFMF4"] = {disabled=false, scale=1, position="4480x0", mode="2560x1440@120"},
},
workspace_rules = {
},
},
laptop = {
priority = 0,
monitors = {
"eDP-1",
},
disable_other_monitors = false,
monitor_config = {
["eDP-1"] = {disabled=false, scale=1, position="0x0", mode="1920x1200@120"},
},
workspace_rules = {
}
}
}
local apply_monitor_request_queue = {}
local function apply_selected_profile(profile_name, profile)
-- do we want to disable other monitors that are not used in this profile?
if profile.disable_other_monitors then
local monitors = hl.get_monitors()
table.insert(monitors, hl.get_monitor("eDP-1"))
for _, monitor in ipairs(monitors) do
if monitor ~= nil then
local name = monitor.name
local description = monitor.description
if not any(
profile.monitors,
function(wanted)
return
wanted == name or
wanted == "desc:"..description
end
) then
debug_notify("Disabling output "..name.." ("..description..")")
hl.monitor({output = name, disabled = true})
end
end
end
end
-- use the configuration in the profile and apply it to hyprland
for _, monitor_selector in ipairs(profile.monitors) do
local config = profile.monitor_config[monitor_selector] or {}
config.output = monitor_selector
hl.monitor(config)
end
debug_notify("Profile " .. profile_name .. " was applied")
end
local function apply_monitor_profile()
if #apply_monitor_request_queue < 1 then
return
end
table.remove(apply_monitor_request_queue)
-- try to find all profiles that match current monitors
local matching_profiles = {}
for profile_name, profile in pairs(profiles) do
if all(
profile.monitors,
function(monitor_selector)
local found =
-- if the monitor exists, hyprland should be able to return this monitor
hl.get_monitor(monitor_selector) ~= nil
if not found then
debug_notify("not able to find monitor "..monitor_selector.." for profile "..profile_name)
end
return found
end
)
then
table.insert(matching_profiles, {name = profile_name, profile = profile})
end
end
-- if no profile was found, do nothing
if #matching_profiles < 1 then
local profile = profiles[fallback_profile] or nil
if profile == nil then
debug_notify("No profiles are matching the current monitors and no fallback with name '"..fallback_profile.."' available!")
return
end
debug_notify("No profiles are matching the current monitors, applying fallback")
apply_selected_profile("fallback", profile)
return
end
-- if multiple profiles are matching, select the correct one by priority
table.sort(matching_profiles, function(a, b) return a.profile.priority > b.profile.priority end)
local matching_profile = matching_profiles[1]
local profile_name, profile = matching_profile.name, matching_profile.profile
debug_notify("Matching monitor profile found: " .. profile_name)
apply_selected_profile(profile_name, profile)
end
local monitor_profile_timer = nil
local function request_apply_monitor_profile(data)
debug_notify("requested monitor profile update")
table.insert(apply_monitor_request_queue, data or {})
if monitor_profile_timer == nil or not monitor_profile_timer:is_enabled() then
monitor_profile_timer = hl.timer(apply_monitor_profile, { timeout = 3000, type = "repeat" })
debug_notify("monitor profile apply timer has been restarted")
end
end
hl.on("hyprland.start", function()
debug_notify("hyprland start :)")
hl.timer(function()
hl.monitor({output = "eDP-1", disabled = false})
hl.dispatch(function() request_apply_monitor_profile() end)
end, { timeout = 1000, type = "oneshot" })
end)
hl.on("monitor.layout_changed", request_apply_monitor_profile)
hl.bind("SUPER + P", function()
hl.monitor({output = "eDP-1", disabled = true})
request_apply_monitor_profile()
end, {locked=true, description="Detect & Apply Monitor Profile"})
hl.bind("SUPER + SHIFT + P", function()
hl.monitor({output = "eDP-1", disabled = false})
hl.dispatch(function() request_apply_monitor_profile() end)
end, {locked=true, description="Detect & Apply Monitor Profile"})