input

package
v0.24.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package input provides keyboard event handling and modal input mode management.

Package input provides keyboard event handling and modal input mode management.

Package input provides keyboard event handling and modal input mode management.

Index

Constants

View Source
const (
	KeycodeDigit1 uint = 10 // Physical '1' key position
	KeycodeDigit2 uint = 11 // Physical '2' key position
	KeycodeDigit3 uint = 12 // Physical '3' key position
	KeycodeDigit4 uint = 13 // Physical '4' key position
	KeycodeDigit5 uint = 14 // Physical '5' key position
	KeycodeDigit6 uint = 15 // Physical '6' key position
	KeycodeDigit7 uint = 16 // Physical '7' key position
	KeycodeDigit8 uint = 17 // Physical '8' key position
	KeycodeDigit9 uint = 18 // Physical '9' key position
	KeycodeDigit0 uint = 19 // Physical '0' key position

	KeycodeBracketLeft  uint = 34 // Physical '[' key position (US layout)
	KeycodeBracketRight uint = 35 // Physical ']' key position (US layout)
)

Hardware keycodes for the number row keys. These are XKB keycodes (evdev + 8) representing physical key positions, independent of keyboard layout. This enables shortcuts like Alt+1 to work on non-QWERTY layouts (AZERTY, QWERTZ, etc.) where the number keys produce different characters without Shift.

For example, on French AZERTY:

  • Physical "1" key produces "&" (keyval=ampersand)
  • But the hardware keycode is still 10
  • So Alt + physical "1" can be detected via keycode even though keyval differs
View Source
const (
	// HoverFocusDelay is the delay before switching focus on hover.
	HoverFocusDelay = 150 * time.Millisecond
)

Variables

View Source
var KeycodeToBracketAction = map[uint]struct {
	NoShift   Action
	WithShift Action
}{
	KeycodeBracketLeft: {
		NoShift:   ActionConsumeOrExpelLeft,
		WithShift: ActionConsumeOrExpelUp,
	},
	KeycodeBracketRight: {
		NoShift:   ActionConsumeOrExpelRight,
		WithShift: ActionConsumeOrExpelDown,
	},
}

KeycodeToTabAction maps hardware keycodes for the number row to tab switch actions. This enables Alt+1-9/0 shortcuts to work on non-QWERTY keyboards by matching the physical key position rather than the translated keyval.

Functions

func KeycodeToDigitIndex added in v0.21.0

func KeycodeToDigitIndex(keycode uint) (index int, ok bool)

KeycodeToDigitIndex converts a hardware keycode to a digit index (0-9). Returns the index and true if the keycode is a number row key, or -1 and false otherwise. This is useful for components like omnibox that need Ctrl+1-9/0 shortcuts.

Mapping:

  • Keycode 10 (physical '1') -> index 0
  • Keycode 11 (physical '2') -> index 1
  • ...
  • Keycode 18 (physical '9') -> index 8
  • Keycode 19 (physical '0') -> index 9

func ShouldAutoExitMode

func ShouldAutoExitMode(action Action) bool

ShouldAutoExitMode returns true if the action should cause modal mode to exit.

Types

type AccentHandler added in v0.23.0

type AccentHandler interface {
	// OnKeyPressed is called when a key is pressed.
	// Returns true if the accent handler is handling this key (picker visible or will show).
	OnKeyPressed(ctx context.Context, char rune, shiftHeld bool) bool
	// OnKeyReleased is called when a key is released.
	OnKeyReleased(ctx context.Context, char rune)
	// IsPickerVisible returns true if the accent picker is currently visible.
	IsPickerVisible() bool
	// Cancel cancels any pending long-press detection.
	Cancel(ctx context.Context)
}

AccentHandler handles long-press accent detection. Called for character keys that may have accent variants.

type Action

type Action string

Action represents what happens when a shortcut is triggered.

const (
	// Mode management
	ActionEnterTabMode     Action = "enter_tab_mode"
	ActionEnterPaneMode    Action = "enter_pane_mode"
	ActionEnterSessionMode Action = "enter_session_mode"
	ActionEnterResizeMode  Action = "enter_resize_mode"
	ActionExitMode         Action = "exit_mode"

	// Tab actions (global and modal)
	ActionNewTab           Action = "new_tab"
	ActionCloseTab         Action = "close_tab"
	ActionNextTab          Action = "next_tab"
	ActionPreviousTab      Action = "previous_tab"
	ActionRenameTab        Action = "rename_tab"
	ActionSwitchLastTab    Action = "switch_last_tab" // Alt+Tab style switching
	ActionSwitchTabIndex1  Action = "switch_tab_1"
	ActionSwitchTabIndex2  Action = "switch_tab_2"
	ActionSwitchTabIndex3  Action = "switch_tab_3"
	ActionSwitchTabIndex4  Action = "switch_tab_4"
	ActionSwitchTabIndex5  Action = "switch_tab_5"
	ActionSwitchTabIndex6  Action = "switch_tab_6"
	ActionSwitchTabIndex7  Action = "switch_tab_7"
	ActionSwitchTabIndex8  Action = "switch_tab_8"
	ActionSwitchTabIndex9  Action = "switch_tab_9"
	ActionSwitchTabIndex10 Action = "switch_tab_10"

	// Pane actions (modal)
	ActionSplitRight Action = "split_right"
	ActionSplitLeft  Action = "split_left"
	ActionSplitUp    Action = "split_up"
	ActionSplitDown  Action = "split_down"
	ActionClosePane  Action = "close_pane"
	ActionStackPane  Action = "stack_pane"

	ActionMovePaneToTab     Action = "move_pane_to_tab"
	ActionMovePaneToNextTab Action = "move_pane_to_next_tab"

	ActionConsumeOrExpelLeft  Action = "consume_or_expel_left"
	ActionConsumeOrExpelRight Action = "consume_or_expel_right"
	ActionConsumeOrExpelUp    Action = "consume_or_expel_up"
	ActionConsumeOrExpelDown  Action = "consume_or_expel_down"

	// Pane focus navigation
	ActionFocusRight Action = "focus_right"
	ActionFocusLeft  Action = "focus_left"
	ActionFocusUp    Action = "focus_up"
	ActionFocusDown  Action = "focus_down"

	// Resize actions (modal)
	ActionResizeIncreaseLeft  Action = "resize_increase_left"
	ActionResizeIncreaseRight Action = "resize_increase_right"
	ActionResizeIncreaseUp    Action = "resize_increase_up"
	ActionResizeIncreaseDown  Action = "resize_increase_down"
	ActionResizeDecreaseLeft  Action = "resize_decrease_left"
	ActionResizeDecreaseRight Action = "resize_decrease_right"
	ActionResizeDecreaseUp    Action = "resize_decrease_up"
	ActionResizeDecreaseDown  Action = "resize_decrease_down"
	ActionResizeIncrease      Action = "resize_increase"
	ActionResizeDecrease      Action = "resize_decrease"

	// Stack navigation (within stacked panes)
	ActionStackNavUp   Action = "stack_nav_up"
	ActionStackNavDown Action = "stack_nav_down"

	// Page navigation
	ActionGoBack     Action = "go_back"
	ActionGoForward  Action = "go_forward"
	ActionReload     Action = "reload"
	ActionHardReload Action = "hard_reload"
	ActionStop       Action = "stop"

	// Zoom
	ActionZoomIn    Action = "zoom_in"
	ActionZoomOut   Action = "zoom_out"
	ActionZoomReset Action = "zoom_reset"

	// UI
	ActionOpenOmnibox      Action = "open_omnibox"
	ActionOpenFind         Action = "open_find"
	ActionFindNext         Action = "find_next"
	ActionFindPrev         Action = "find_prev"
	ActionCloseFind        Action = "close_find"
	ActionOpenDevTools     Action = "open_devtools"
	ActionToggleFullscreen Action = "toggle_fullscreen"

	// Clipboard
	ActionCopyURL Action = "copy_url"

	// Session management
	ActionOpenSessionManager Action = "open_session_manager"

	// Application
	ActionQuit Action = "quit"
)

Predefined actions for the keyboard system.

type ActionHandler

type ActionHandler func(ctx context.Context, action Action) error

ActionHandler is called when a keyboard action is triggered. It receives the context and the action to perform. Return an error if the action fails.

type GestureHandler

type GestureHandler struct {
	// contains filtered or unexported fields
}

GestureHandler handles mouse button gestures for navigation. It recognizes mouse buttons 8 (back) and 9 (forward) on WebView widgets.

func NewGestureHandler

func NewGestureHandler(ctx context.Context) *GestureHandler

NewGestureHandler creates a new gesture handler.

func (*GestureHandler) AttachTo

func (h *GestureHandler) AttachTo(widget *gtk.Widget)

AttachTo attaches the gesture handler to a GTK widget. Typically called with a WebView widget to enable mouse button navigation.

func (*GestureHandler) Detach

func (h *GestureHandler) Detach()

Detach removes the gesture handler. Note: GTK handles cleanup when the widget is destroyed, but we clear our reference here.

func (*GestureHandler) SetOnAction

func (h *GestureHandler) SetOnAction(fn ActionHandler)

SetOnAction sets the callback for when navigation actions are triggered.

type GlobalShortcutHandler added in v0.20.1

type GlobalShortcutHandler struct {
	// contains filtered or unexported fields
}

GlobalShortcutHandler manages keyboard shortcuts that must work globally, even when WebView has focus. It uses GtkShortcutController with GTK_SHORTCUT_SCOPE_GLOBAL to intercept shortcuts before they reach the WebView.

func NewGlobalShortcutHandler added in v0.20.1

func NewGlobalShortcutHandler(
	ctx context.Context,
	window *gtk.ApplicationWindow,
	cfg *config.Config,
	onAction ActionHandler,
) *GlobalShortcutHandler

NewGlobalShortcutHandler creates a new global shortcut handler for shortcuts that need to work even when WebView has focus (like Alt+1-9 for tab switching).

func (*GlobalShortcutHandler) Detach added in v0.20.1

func (h *GlobalShortcutHandler) Detach()

Detach removes the global shortcut handler from the window. Note: GTK handles cleanup when the widget is destroyed, but we clear our references here.

type HoverCallback

type HoverCallback func(paneID entity.PaneID)

HoverCallback is called when a pane should receive focus from hover.

type HoverHandler

type HoverHandler struct {
	// contains filtered or unexported fields
}

HoverHandler handles mouse hover events for focus-follows-mouse behavior. It uses a debounce timer to avoid rapid focus switches.

func NewHoverHandler

func NewHoverHandler(ctx context.Context, paneID entity.PaneID) *HoverHandler

NewHoverHandler creates a new hover handler for a specific pane.

func (*HoverHandler) AttachTo

func (h *HoverHandler) AttachTo(widget *gtk.Widget)

AttachTo attaches the hover handler to a GTK widget.

func (*HoverHandler) Cancel added in v0.24.0

func (h *HoverHandler) Cancel()

Cancel cancels any pending focus switch. This can be called externally to cancel hover when keyboard navigation occurs.

func (*HoverHandler) Detach

func (h *HoverHandler) Detach()

Detach removes the hover handler.

func (*HoverHandler) SetOnEnter

func (h *HoverHandler) SetOnEnter(fn HoverCallback)

SetOnEnter sets the callback for when the pane should receive focus.

type KeyBinding

type KeyBinding struct {
	Keyval    uint     // GDK key value (e.g., gdk.KEY_t)
	Modifiers Modifier // Combined modifiers
}

KeyBinding represents a single key combination.

func ParseKeyString

func ParseKeyString(s string) (KeyBinding, bool)

ParseKeyString converts a config key string like "ctrl+t" to a KeyBinding. Returns false if the string cannot be parsed.

type KeyboardHandler

type KeyboardHandler struct {
	// contains filtered or unexported fields
}

KeyboardHandler processes keyboard events and dispatches actions. It manages modal input modes and routes key events to the appropriate handlers.

func NewKeyboardHandler

func NewKeyboardHandler(ctx context.Context, cfg *config.Config) *KeyboardHandler

NewKeyboardHandler creates a new keyboard handler.

func (*KeyboardHandler) AttachTo

func (h *KeyboardHandler) AttachTo(window *gtk.ApplicationWindow)

AttachTo attaches the keyboard handler to a GTK window. The handler will intercept key events in the capture phase.

func (*KeyboardHandler) Detach

func (h *KeyboardHandler) Detach()

Detach removes the keyboard handler. Note: GTK handles cleanup when the widget is destroyed, but we clear our reference here.

func (*KeyboardHandler) EnterPaneMode

func (h *KeyboardHandler) EnterPaneMode()

EnterPaneMode programmatically enters pane mode. Useful for testing or programmatic mode changes.

func (*KeyboardHandler) EnterSessionMode added in v0.21.0

func (h *KeyboardHandler) EnterSessionMode()

EnterSessionMode programmatically enters session mode. Useful for testing or programmatic mode changes.

func (*KeyboardHandler) EnterTabMode

func (h *KeyboardHandler) EnterTabMode()

EnterTabMode programmatically enters tab mode. Useful for testing or programmatic mode changes.

func (*KeyboardHandler) ExitMode

func (h *KeyboardHandler) ExitMode()

ExitMode programmatically exits modal mode. Useful for testing or programmatic mode changes.

func (*KeyboardHandler) Mode

func (h *KeyboardHandler) Mode() Mode

Mode returns the current input mode.

func (*KeyboardHandler) SetAccentHandler added in v0.23.0

func (h *KeyboardHandler) SetAccentHandler(handler AccentHandler)

SetAccentHandler sets the handler for long-press accent detection.

func (*KeyboardHandler) SetOnAction

func (h *KeyboardHandler) SetOnAction(fn ActionHandler)

SetOnAction sets the callback for when actions are triggered.

func (*KeyboardHandler) SetOnModeChange

func (h *KeyboardHandler) SetOnModeChange(fn func(from, to Mode))

SetOnModeChange sets the callback for mode changes (for UI updates).

func (*KeyboardHandler) SetShouldBypassInput

func (h *KeyboardHandler) SetShouldBypassInput(fn func() bool)

SetShouldBypassInput sets a hook to bypass keyboard handling entirely. When true, events propagate to focused widgets instead.

type ModalState

type ModalState struct {
	// contains filtered or unexported fields
}

ModalState manages the current input mode with optional timeout.

func NewModalState

func NewModalState(ctx context.Context) *ModalState

NewModalState creates a new modal state manager.

func (*ModalState) EnterPaneMode

func (m *ModalState) EnterPaneMode(ctx context.Context, timeout time.Duration)

EnterPaneMode switches to pane mode with an optional timeout. If timeout is 0, the mode stays until explicitly exited.

func (*ModalState) EnterResizeMode added in v0.21.0

func (m *ModalState) EnterResizeMode(ctx context.Context, timeout time.Duration)

EnterResizeMode switches to resize mode with an optional timeout. If timeout is 0, the mode stays until explicitly exited.

func (*ModalState) EnterSessionMode added in v0.21.0

func (m *ModalState) EnterSessionMode(ctx context.Context, timeout time.Duration)

EnterSessionMode switches to session mode with an optional timeout. If timeout is 0, the mode stays until explicitly exited.

func (*ModalState) EnterTabMode

func (m *ModalState) EnterTabMode(ctx context.Context, timeout time.Duration)

EnterTabMode switches to tab mode with an optional timeout. If timeout is 0, the mode stays until explicitly exited.

func (*ModalState) ExitMode

func (m *ModalState) ExitMode(ctx context.Context)

ExitMode returns to normal mode.

func (*ModalState) Mode

func (m *ModalState) Mode() Mode

Mode returns the current mode (thread-safe).

func (*ModalState) ResetTimeout

func (m *ModalState) ResetTimeout(ctx context.Context)

ResetTimeout restarts the mode timeout (e.g., after a valid keystroke). Does nothing if not in a modal mode or if no timeout was set.

func (*ModalState) SetOnModeChange

func (m *ModalState) SetOnModeChange(fn func(from, to Mode))

SetOnModeChange sets the callback for mode changes. The callback is invoked synchronously under the lock.

type Mode

type Mode int

Mode represents the current input mode.

const (
	// ModeNormal is the default mode where keys pass through to WebView.
	ModeNormal Mode = iota
	// ModeTab is the modal tab management mode.
	ModeTab
	// ModePane is the modal pane management mode.
	ModePane
	// ModeSession is the modal session management mode.
	ModeSession
	// ModeResize is the modal pane resizing mode.
	ModeResize
)

func (Mode) DisplayName added in v0.22.0

func (m Mode) DisplayName() string

DisplayName returns the mode name for display in UI (e.g., toaster).

func (Mode) String

func (m Mode) String() string

String returns a human-readable mode name.

type Modifier

type Modifier uint

Modifier represents keyboard modifier flags.

const (
	// ModNone indicates no modifier is pressed.
	ModNone Modifier = 0
	// ModShift indicates the Shift key is pressed.
	ModShift Modifier = Modifier(gdk.ShiftMaskValue)
	// ModCtrl indicates the Control key is pressed.
	ModCtrl Modifier = Modifier(gdk.ControlMaskValue)
	// ModAlt indicates the Alt key is pressed.
	ModAlt Modifier = Modifier(gdk.AltMaskValue)
)

type ShortcutSet

type ShortcutSet struct {
	// Global shortcuts are always active regardless of mode.
	Global ShortcutTable
	// TabMode shortcuts are only active in tab mode.
	TabMode ShortcutTable
	// PaneMode shortcuts are only active in pane mode.
	PaneMode ShortcutTable
	// SessionMode shortcuts are only active in session mode.
	SessionMode ShortcutTable
	// ResizeMode shortcuts are only active in resize mode.
	ResizeMode ShortcutTable
}

ShortcutSet holds all shortcut tables organized by context.

func NewShortcutSet

func NewShortcutSet(ctx context.Context, cfg *config.Config) *ShortcutSet

NewShortcutSet creates a ShortcutSet from the configuration.

func (*ShortcutSet) Lookup

func (s *ShortcutSet) Lookup(binding KeyBinding, mode Mode) (Action, bool)

Lookup finds an action for the given key binding in the appropriate table. It first checks the mode-specific table, then falls back to global.

type ShortcutTable

type ShortcutTable map[KeyBinding]Action

ShortcutTable maps KeyBinding to Action.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL