Add head follow: the pointer comes along when you turn your head

Off by default. With POINTER_FOLLOW=1 (a switch on the Pointer page of
Frametop Input Settings, or a mouse button mapped to Head follow on/off),
the cursor rides on a reference direction leashed POINTER_LEASH_DEG (10)
from where you face. Within the leash it stays put in the room; past it,
it turns with your head and keeps its offset. A leash of 0 locks it to
your view. Head roll is ignored, the cursor stays within 40 degrees of
the reference, and it holds still in the room while the left button is
down so the head can't nudge a click or a drag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DeeJanuzandClaude Opus 5.5 committed 2026-09-27 21:52:21 -06:00
1 parent 8f051db083
commit 137705cbfd
8 files changed
+100 -13

No files matched your search

+6 -3
View File
@@ -19,8 +19,8 @@ keyboard node for its extra buttons). Roles, from ~/.config/frametop-input.json
ignore not grabbed, only observed for identification in the settings app
Buttons and keys of pointer devices go through a per-device map to actions
(left, right, middle, back, scroll_up, scroll_down, dashboard, recenter,
pointer_toggle, sens_up, sens_down, layout_reset = put the desktop screens back in
their saved layout, screens_toggle = hide or show the desktop screens, key = pass
pointer_toggle, follow_toggle = head follow on or off, sens_up, sens_down,
layout_reset = put the desktop screens back in their saved layout, screens_toggle = hide or show the desktop screens, key = pass
through as a key, none).
Keys also go to ft-screens (@ft_screens, the Frametop desktop's compositor), which
@@ -140,7 +140,7 @@ def eviocguniq(length):
VIRTUAL_PREFIX = "frametop virtual"
RULES_PATH = os.path.expanduser("~/.config/frametop-input.json")
ACTIONS = ("left", "right", "middle", "back", "scroll_up", "scroll_down", "dashboard", "recenter",
"pointer_toggle", "sens_up", "sens_down", "layout_reset", "screens_toggle", "key", "none")
"pointer_toggle", "follow_toggle", "sens_up", "sens_down", "layout_reset", "screens_toggle", "key", "none")
SCREENS = "\0ft_screens"
KEYS = "\0frametop_keys" # keys of keyboards grabbed for the desktop, for other readers
FT_LAYOUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "layout", "ft-layout")
@@ -406,6 +406,9 @@ class Pointer:
log("pointer off (toggle)")
else:
self.wake(now)
elif name == "follow_toggle":
self.send("follow toggle") # until the next restart; the setting is POINTER_FOLLOW
log("head follow toggled")
elif name == "screens_toggle":
try:
self.sock.sendto(b"toggle", SCREENS)