summaryrefslogtreecommitdiffhomepage
path: root/packages/kernel/src/vt_core.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'packages/kernel/src/vt_core.hpp')
-rw-r--r--packages/kernel/src/vt_core.hpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/packages/kernel/src/vt_core.hpp b/packages/kernel/src/vt_core.hpp
new file mode 100644
index 0000000..d08837d
--- /dev/null
+++ b/packages/kernel/src/vt_core.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <optional>
+
+#include <xkbcommon/xkbcommon.h>
+
+// Pure decision core for the kernel's VT-switch escape hatch — NO wlroots / GL,
+// so it is doctest-able with nothing running (AGENTS.md: effects at the edges,
+// pure cores tested hard). The keyboard glue (input.cpp) injects the effect
+// (wlr_session_change_vt) around this.
+//
+// xkbcommon is allowed here: it is a pure value library (a keysym is an
+// integer), not a wlroots/GL/wayland effect surface — the wlroots-include rule
+// targets <wlr/...> + <wayland-server*.h>, and input.cpp already includes
+// <xkbcommon/xkbcommon.h> for keysym resolution.
+
+namespace unbox::kernel {
+
+// Map a resolved keysym to the Linux VT it requests, or nullopt if it is not a
+// VT-switch keysym. Ctrl+Alt+Fn is delivered by xkb as the contiguous range
+// XKB_KEY_XF86Switch_VT_1 (0x1008FE01) .. XKB_KEY_XF86Switch_VT_12
+// (0x1008FE0C); the returned value is the 1-based VT number (1..12). These
+// keysyms are ONLY produced with Ctrl+Alt held, so matching the keysym is
+// sufficient — no separate modifier-mask check. Plain F1..F12 resolve to the
+// ordinary XKB_KEY_F1.. keysyms and are NOT in this range, so they pass through.
+[[nodiscard]] constexpr auto vt_for_keysym(xkb_keysym_t keysym) -> std::optional<unsigned> {
+ if (keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12) {
+ return static_cast<unsigned>(keysym - XKB_KEY_XF86Switch_VT_1) + 1U;
+ }
+ return std::nullopt;
+}
+
+} // namespace unbox::kernel