-- ───────────────────────────────────────────────────────────────────────────── -- Input -- -- Deliberately GNOME-like: click-to-focus, no focus-follows-mouse, no mouse -- acceleration changes. The goal is that muscle memory transfers untouched. -- ───────────────────────────────────────────────────────────────────────────── local prefs = require("prefs") hl.config({ input = { kb_layout = prefs.get("keyboardLayout", "us"), kb_variant = prefs.get("keyboardVariant", ""), kb_model = "", kb_options = prefs.get("keyboardOptions", "caps:escape_shifted_capslock"), kb_rules = "", numlock_by_default = prefs.get("numlockByDefault", true), -- GNOME's defaults are 500ms delay / 33Hz repeat. repeat_delay = prefs.get("keyRepeatDelay", 500), repeat_rate = prefs.get("keyRepeatRate", 33), -- 1 = FOLLOW. The window under the pointer takes focus. This comment -- previously claimed 1 was "click to focus, GNOME's behavior", which -- is the opposite of what Hyprland does -- `hyprctl descriptions` gives -- map: [{"separate":3},{"detached":2},{"follow":1},{"disabled":0}], -- so click-to-focus is 0. Changing the shipped value is a behavior -- decision rather than a correction, so the value is left alone and -- only the description is fixed; Settings exposes all four. follow_mouse = prefs.getInt("followMouse", 1), -- Softens follow_mouse: with this off, focus changes only when the -- pointer crosses a window boundary, not on every movement inside one. -- Still focus-follows-pointer, just less twitchy. mouse_refocus = false, -- Flat pointer response by default, no acceleration. Matters for -- gaming; Settings offers adaptive for people who want it back. sensitivity = prefs.get("pointerSensitivity", 0), accel_profile = prefs.get("accelProfile", "flat"), natural_scroll = prefs.get("naturalScroll", false), scroll_factor = prefs.get("scrollFactor", 1.0), left_handed = prefs.get("leftHanded", false), -- Clicking a floating window raises and focuses it. float_switch_override_focus = 2, -- Every touchpad preference Settings offers is read here as well as -- applied live: the live half (hyprctl eval) reaches a running -- compositor, and THIS half is what survives `hyprctl reload` and the -- gap before the shell starts. A schema `hypr:` entry without a -- prefs.get() here is a control that quietly reverts -- the whole -- Mouse & Touchpad page once had exactly that bug. Defaults must -- match PreferenceSchema's; the hypr-prefs-contract checks both. touchpad = { tap_to_click = prefs.get("touchpadTapToClick", true), natural_scroll = prefs.get("touchpadNaturalScroll", true), disable_while_typing = prefs.get("touchpadDisableWhileTyping", true), scroll_factor = prefs.get("touchpadScrollFactor", 1.0), drag_lock = prefs.getInt("touchpadDragLock", 0), middle_button_emulation = prefs.get("touchpadMiddleButtonEmulation", false), }, }, -- Tuning for the three-finger gestures registered below. gestures = { workspace_swipe_distance = prefs.getInt("swipeDistance", 300), workspace_swipe_invert = prefs.get("swipeInvert", true), }, }) -- ── Touchpad gestures ─────────────────────────────────────────────────────── -- -- GNOME's gestures, reproduced: three fingers sideways moves between -- workspaces, three fingers up opens the overview, three fingers down closes -- it. That is the same muscle memory the keybinds were built to preserve. -- -- Registered unconditionally rather than behind a preference. Hyprland 0.56 -- dropped `gestures:workspace_swipe` in favour of this `gesture` keyword, and a -- registration is read at config time -- so a toggle would need a reload to -- take effect, which is worse than the nothing these cost on a machine with no -- touchpad. What IS tunable at runtime lives in Settings: how far a swipe has -- to travel, and which way round it goes. -- -- open and close rather than toggle twice: with a toggle on both directions, -- swiping up from an already-open overview would close it, and swiping down -- would reopen it. GNOME does not do that, and neither does this. local overview = function(fn) return function() hl.exec_cmd("qs ipc call overview " .. fn) end end hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" }) hl.gesture({ fingers = 3, direction = "up", action = overview("open") }) hl.gesture({ fingers = 3, direction = "down", action = overview("close") }) return true