From a24a7e928d81b8f12340aca376d49f468b77751c Mon Sep 17 00:00:00 2001 From: RAprogramm Date: Wed, 29 Jul 2026 17:36:43 +0700 Subject: [PATCH] #1866 fix: deduplicate binds by resolved combo and drop unreachable ones --- CHANGELOG.md | 4 ++ Configs/.local/share/hypr/lua/hyde/binds.lua | 57 ++++++++++++++-- Configs/.local/share/hypr/lua/key_binds.lua | 69 ++++++++++++-------- 3 files changed, 97 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fd7776db3..5bd19d7d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Fixed - Waybar `hyprland/workspaces` module adapted to use lua dispatchers +- Hyprland: `Super + Ctrl + arrows` no longer changes the group and the workspace at the same time. + Group navigation stays on `Super + Alt + arrows` +- Hyprland: the right Control key no longer hides Waybar on its own. Hiding moved to `Super + Ctrl + B` +- Hyprland: workspaces 11-20 on the numpad respond again ## v26.7.28 | End of April Release diff --git a/Configs/.local/share/hypr/lua/hyde/binds.lua b/Configs/.local/share/hypr/lua/hyde/binds.lua index 4b45d75620..1f925998ae 100644 --- a/Configs/.local/share/hypr/lua/hyde/binds.lua +++ b/Configs/.local/share/hypr/lua/hyde/binds.lua @@ -28,6 +28,48 @@ local function normalize(keycombo) return trim(keycombo:gsub("%s*%+%s*", " + ")) end +-- Modifier spellings Hyprland treats as the same bit. +local modifier_aliases = { + CONTROL = "CTRL", + WIN = "SUPER", + LOGO = "SUPER", + MOD1 = "ALT", + MOD4 = "SUPER" +} + +-- Reduces a combo to the form Hyprland actually matches on: modifiers are a +-- set, so spelling, order and case carry no meaning. "SUPER + CTRL + Left" +-- and "SUPER + CONTROL + LEFT" both become "CTRL + SUPER + LEFT", which is +-- what makes them collide at runtime. +local function canonicalize(keycombo) + local normalized = normalize(keycombo) + if normalized == "" then + return "" + end + + local tokens = {} + for token in normalized:gmatch("[^+]+") do + tokens[#tokens + 1] = trim(token) + end + + local key = table.remove(tokens) or "" + + local modifiers = {} + local seen = {} + for _, token in ipairs(tokens) do + local upper = token:upper() + local modifier = modifier_aliases[upper] or upper + if not seen[modifier] then + seen[modifier] = true + modifiers[#modifiers + 1] = modifier + end + end + table.sort(modifiers) + + modifiers[#modifiers + 1] = key:upper() + return table.concat(modifiers, " + ") +end + local function has_dedup_field(opts) if type(opts) ~= "table" then return false @@ -106,7 +148,11 @@ hyde.binds.dedup_fields = } hyde.binds.normalize = normalize +hyde.binds.canonicalize = canonicalize +-- Maps a canonical combo to the exact string the live bind was registered +-- with. Unbinding matches that string, not the resolved key and modifiers, so +-- the original spelling has to be kept around to remove a bind again. hyde.binds._active = hyde.binds._active or {} local orig_add = hl.bind @@ -115,14 +161,17 @@ hl.bind = function(keycombo, action, ...) local normalized = hyde.binds.normalize(keycombo) local opts = find_options(...) local signature = serialize_flags(opts) - local dedup_id = normalized .. "|" .. signature + local dedup_id = canonicalize(keycombo) .. "|" .. signature - if normalized ~= "" and hyde.binds.dedup and hyde.binds._active[dedup_id] then - hl.unbind(normalized) + if normalized ~= "" and hyde.binds.dedup then + local registered = hyde.binds._active[dedup_id] + if registered then + hl.unbind(registered) + end end if normalized ~= "" then - hyde.binds._active[dedup_id] = true + hyde.binds._active[dedup_id] = normalized keycombo = normalized end diff --git a/Configs/.local/share/hypr/lua/key_binds.lua b/Configs/.local/share/hypr/lua/key_binds.lua index 3a2193d8cb..2503159f3d 100644 --- a/Configs/.local/share/hypr/lua/key_binds.lua +++ b/Configs/.local/share/hypr/lua/key_binds.lua @@ -1,3 +1,11 @@ +-- * Enable bind deduplication so repeated key combos don't conflict. +-- * This has to run before the first bind below, otherwise the binds in this +-- * file are registered unchecked and only user overrides get deduplicated. +-- * For multiple dispatcher actions, wrap them in one function and bind that. +-- * If you set `hyde.binds.dedup = false`, unbind duplicates manually. +hyde.binds.dedup = true +-- hyde.binds.dedup_fields = {} + -- vars for easy access local _apps = hyde.config.app local MOD = hyde.config.modifiers.main @@ -73,15 +81,15 @@ _F = {description = "[Window Management] toggle pin"} hl.bind(MOD .. " + F", hl.dsp.exec_cmd(hyde.sh.window.pin()), _F) _F = {description = "[Window Management] logout menu"} hl.bind("CTRL + ALT + DELETE", hl.dsp.exec_cmd(hyde.sh.session.logout.launcher()), _F) +-- ALT_R is a keysym, not a modifier: "ALT_R + CONTROL_R" resolves to a bare +-- right Control, so every press of that key hid the bar. _F = {description = "[Window Management] hide waybar"} -hl.bind("ALT_R + CONTROL_R", hl.dsp.exec_cmd(hyde.sh.waybar("--hide")), _F) +hl.bind(MOD .. " + CTRL + B", hl.dsp.exec_cmd(hyde.sh.waybar("--hide")), _F) _F = {description = "[Window Management] lock session"} hl.bind(MOD .. " + L", hl.dsp.exec_cmd(hyde.sh.session.lock()), _F) -_F = {description = "[Window Management|Group Navigation] change active group backwards"} -hl.bind(MOD .. " + CTRL + Left", hl.dsp.group.prev(), _F) -_F = {description = "[Window Management|Group Navigation] change active group forwards"} -hl.bind(MOD .. " + CTRL + Right", hl.dsp.group.next(), _F) +-- Group navigation lives on ALT only. The CTRL variant collided with relative +-- workspace navigation further down, which binds the same combo. _F = {description = "[Window Management|Group Navigation] change active group backwards"} hl.bind(MOD .. " + ALT + Left", hl.dsp.group.prev(), _F) _F = {description = "[Window Management|Group Navigation] change active group forwards"} @@ -250,17 +258,20 @@ hl.bind(MOD .. "+ SHIFT + T", hl.dsp.exec_cmd(hyde.sh.menu.themes()), _F) -- bindd = $mainMod SHIFT, R, $d wallbash mode selector , exec, pkill -x rofi || hyde-shell wallbashtoggle.sh -m # launch wallbash mode select menu -- bindd = $mainMod SHIFT, T, $d select a theme, exec, pkill -x rofi || hyde-shell themeselect.sh # launch theme select menu +-- Numpad keys for workspaces 11-20. The Lua bind parser has no keycode form, +-- so each key is bound under both keysyms it can emit: the digit while Num +-- Lock is on, the navigation name while it is off. local kp = { - [1] = 87, - [2] = 88, - [3] = 89, - [4] = 83, - [5] = 84, - [6] = 85, - [7] = 79, - [8] = 80, - [9] = 81, - [0] = 90 + [1] = {"KP_1", "KP_End"}, + [2] = {"KP_2", "KP_Down"}, + [3] = {"KP_3", "KP_Next"}, + [4] = {"KP_4", "KP_Left"}, + [5] = {"KP_5", "KP_Begin"}, + [6] = {"KP_6", "KP_Right"}, + [7] = {"KP_7", "KP_Home"}, + [8] = {"KP_8", "KP_Up"}, + [9] = {"KP_9", "KP_Prior"}, + [10] = {"KP_0", "KP_Insert"} } for i = 1, 10 do @@ -269,8 +280,13 @@ for i = 1, 10 do end for i = 1, 10 do - local key = (i == 10) and 90 or kp[i] - hl.bind(MOD .. "+code:" .. key, hl.dsp.focus({workspace = tostring(i + 10)}), {description = "WS " .. (i + 10)}) + for _, key in ipairs(kp[i]) do + hl.bind( + MOD .. " + " .. key, + hl.dsp.focus({workspace = tostring(i + 10)}), + {description = "[Workspaces|Navigation] navigate to workspace " .. (i + 10)} + ) + end end _F = {description = "[Workspaces|Navigation|Relative workspace] change active workspace forwards"} @@ -287,12 +303,13 @@ for i = 1, 10 do end for i = 1, 10 do - local key = (i == 10) and 90 or kp[i] - hl.bind( - MOD .. "+SHIFT+code:" .. key, - hl.dsp.window.move({workspace = tostring(i + 10)}), - {description = "WS " .. (i + 10)} - ) + for _, key in ipairs(kp[i]) do + hl.bind( + MOD .. " + SHIFT + " .. key, + hl.dsp.window.move({workspace = tostring(i + 10)}), + {description = "[Workspaces|Move window to workspace] move focused window to workspace " .. (i + 10)} + ) + end end _F = {description = "[Workspaces|Move window to workspace|Relative workspace] move focused window to next workspace"} @@ -372,9 +389,3 @@ end -- bindk = Super ALT, F ,test device, exec , notify-send "Hyprland" "You just pressed Super + F again!2" -- # bindd = Alt, D , [Utilities] Enable Wayscriber ,exec, wayscriber --active - --- * Enable bind deduplication so repeated key combos don't conflict. --- * For multiple dispatcher actions, wrap them in one function and bind that. --- * If you set `hyde.bind.dedup = false`, unbind duplicates manually. -hyde.binds.dedup = true --- hyde.binds.dedup_fields = {}