Give Input keycaps, a shortcut search, and the missing pointer basics

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 15:21:01 -04:00
parent b8f88a91f3
commit aba2d16ffa
25 changed files with 2346 additions and 191 deletions
@@ -757,6 +757,88 @@ Singleton {
detail: "Paste the primary selection in GTK and native Wayland applications",
hypr: { path: ["misc", "middle_click_paste"], option: "misc:middle_click_paste", readAs: "bool" }
},
{
key: "focusOnClose", type: "enum", def: 0, group: "pointer",
label: "Focus after closing",
detail: "Which window takes keyboard focus when the focused one goes away",
// Designed as a two-way choice; the compositor publishes three.
// map: [{"mru":2},{"cursor":1},{"next":0}]
// and 0 -- the value this desktop runs on today -- is "next in the
// stack", which is neither of the two the design named. Hiding it
// would make the shipped default unreachable from its own dropdown,
// and enum-hypr-map-contract refuses an enum that drops a published
// value for exactly that reason.
options: [
{ value: 0, label: "Next in the stack",
detail: "Whichever window Hyprland has next in the layout order" },
{ value: 1, label: "Under the pointer",
detail: "Whatever window the pointer happens to be over" },
{ value: 2, label: "Most recently used",
detail: "The window you were on before this one" }
],
hypr: { path: ["input", "focus_on_close"], option: "input:focus_on_close", readAs: "int" }
},
{
key: "scrollMethod", type: "enum", def: "", group: "pointer",
label: "Scroll method",
detail: "How a pointing device turns movement into scrolling",
// No `map` is published for this one -- it is a plain string option,
// and the words it accepts live in its description instead:
// [2fg/edge/on_button_down/no_scroll].
//
// Unset is a real state rather than an absence, and it is the state
// Panama ships: getoption answers "[[EMPTY]]" until something writes
// the option, and an empty value means "whatever libinput picks for
// this device", which is the branch every stock Hyprland takes. So
// empty is offered as a choice of its own -- without it the setting
// would be a one-way door, and its default would be unreachable.
// Writing "" reads back as "" with set:true, the same round trip
// input:kb_variant has made for as long as it has been empty.
options: [
{ value: "", label: "Whatever suits the device",
detail: "Two fingers on a touchpad, the wheel on a mouse" },
{ value: "2fg", label: "Two fingers" },
{ value: "edge", label: "Along the edge of the touchpad" },
{ value: "on_button_down", label: "While a button is held" },
{ value: "no_scroll", label: "Never scroll" }
],
hypr: { path: ["input", "scroll_method"], option: "input:scroll_method", readAs: "str" }
},
{
key: "scrollButton", type: "int", def: 0, min: 0, max: 300, step: 1,
group: "pointer",
label: "Scroll button",
detail: "Which button is held to scroll, as an evdev code; 0 lets the device choose",
// The range is the compositor's own rather than a guess: descriptions
// gives min 0, max 300. Only meaningful while Scroll method is
// "While a button is held", which is a UI condition, not a schema one
// -- the value stays valid and stored either way.
hypr: { path: ["input", "scroll_button"], option: "input:scroll_button", readAs: "int" }
},
{
key: "cursorHideWhileTyping", type: "bool", def: false, group: "pointer",
label: "Hide pointer while typing",
detail: "The pointer vanishes on the next keystroke and returns when you move it",
// A `cursor:` option rather than an `input:` one, so its read-back in
// the Lua sits in a cursor table of its own; see hypr/input.lua.
hypr: { path: ["cursor", "hide_on_key_press"], option: "cursor:hide_on_key_press", readAs: "bool" }
},
{
key: "cursorWarpOnWorkspaceChange", type: "bool", def: false, group: "pointer",
label: "Jump pointer to the focused display",
detail: "Moves the pointer to the last focused window after switching workspace",
// A switch here, an integer in the compositor -- the same shape
// autoHdr has, and `readAs: "int"` is what keeps the two sides in
// agreement. The published map is
// map: [{"force":2},{"enable":1},{"disable":0}]
// and "force" -- warp even when the pointer is already on that
// display -- is deliberately not offered: a third state would turn a
// switch into a dropdown for a distinction almost nobody wants.
// enum-hypr-map-contract governs enums only, so this is a decision
// rather than a violation, but it IS a decision: value 2 is not
// reachable from Settings.
hypr: { path: ["cursor", "warp_on_change_workspace"], option: "cursor:warp_on_change_workspace", readAs: "int" }
},
// ── Touchpad ────────────────────────────────────────────────────────
//
@@ -814,6 +896,28 @@ Singleton {
detail: "Pressing left and right together acts as a middle click",
hypr: { path: ["input", "touchpad", "middle_button_emulation"], option: "input:touchpad:middle_button_emulation", readAs: "bool" }
},
{
key: "touchpadClickfinger", type: "bool", def: false, group: "touchpad",
label: "Two-finger right-click",
detail: "One, two, or three fingers pressing down give left, right, and middle click, instead of clicking by which part of the pad you press",
hypr: { path: ["input", "touchpad", "clickfinger_behavior"], option: "input:touchpad:clickfinger_behavior", readAs: "bool" }
},
{
key: "touchpadTapAndDrag", type: "bool", def: true, group: "touchpad",
label: "Tap and drag",
detail: "A tap followed straight away by a tap-and-hold starts a drag, with nothing pressed down",
// Hyphens in the option name, underscores in the Lua path -- the same
// split tap-to-click documents above, and the only other option in
// the touchpad section spelled that way.
//
// `hyprctl descriptions` contradicts itself here: it reports current
// false while `hyprctl getoption` answers bool true with set:false,
// meaning nothing has ever written it and it is sitting on
// Hyprland's own default of true. getoption is the authority, since
// it is what the write path verifies against, so true is what ships
// and nothing changes on a machine that has a touchpad.
hypr: { path: ["input", "touchpad", "tap_and_drag"], option: "input:touchpad:tap-and-drag", readAs: "bool" }
},
// Tuning for the three-finger gestures registered in hypr/input.lua.
// The gestures themselves are not settings: Hyprland reads a gesture