Selkie--Event
NAME
Selkie::Event - Keyboard, mouse, and resize event abstraction
SYNOPSIS
use Selkie::Event;
use Notcurses::Native::Types;
# In a widget's handle-event method:
method handle-event(Selkie::Event $ev --> Bool) {
return False unless $ev.event-type ~~ KeyEvent;
given $ev.id {
when NCKEY_UP { self!cursor-up; return True }
when NCKEY_DOWN { self!cursor-down; return True }
when NCKEY_ENTER { self!activate; return True }
}
# Printable character?
if $ev.char.defined && $ev.char.chars == 1 && $ev.char.ord >= 32 {
self!insert-char($ev.char);
return True;
}
False; # not consumed ā bubble to parent
}DESCRIPTION
Every input event ā keystrokes, mouse clicks, terminal resizes ā is wrapped in a Selkie::Event before reaching widgets. The event carries:
An
idā the keycode (NCKEY_*) or character codepointA
charā the effective printable character, if any (handles Shift correctly: Shift+1 ā'!')The
modifiersthat were held ā aSetofModifiervaluesThe
input-typeā PRESS, RELEASE, REPEAT (seeNcInputType)The
event-typeāKeyEvent,MouseEvent, orResizeEventMouse coordinates (
x,y) for mouse events
Widgets implement handle-event(Selkie::Event) returning Bool. True means the event was consumed; False lets it bubble to the parent chain and eventually to the app's global keybinds.
This module also exports Keybind ā the parsed form used by on-key on widgets and Selkie::App.
EXAMPLES
Character input
When the user types a printable character on a focused widget, you get it in $ev.char:
if $ev.char.defined && $ev.char.chars == 1 && $ev.char.ord >= 32 {
# Printable ā insert into buffer
$!buffer ~= $ev.char;
$!change-supplier.emit($!buffer);
return True;
}Note the .ord = 32> guard: that filters out control characters (which arrive with id in the 1ā26 range) so Ctrl+X combos aren't mistaken for typed input.
Checking modifiers
Use has-modifier to test for a specific modifier key:
if $ev.id == NCKEY_ENTER && $ev.has-modifier(Mod-Ctrl) {
self!submit; # Ctrl+Enter submits
return True;
} elsif $ev.id == NCKEY_ENTER {
self!insert-newline; # plain Enter inserts a newline
return True;
}Mouse events
For mouse events, id is one of the NCKEY_SCROLL_UP, NCKEY_BUTTON1, etc. constants, and x/y give the click coordinates:
if $ev.event-type ~~ MouseEvent {
given $ev.id {
when NCKEY_SCROLL_UP { self!scroll(-1); return True }
when NCKEY_SCROLL_DOWN { self!scroll(1); return True }
}
}KEYBIND SYNTAX
Keybind.parse and the on-key methods accept a string spec:
Single character:
'a','?','Q','+'Named keys:
'enter','tab','esc'(or'escape'),'space','backspace','delete','insert','home','end','pgup','pgdown','up','down','left','right'Function keys:
'f1'through'f60'Modifiers:
'ctrl+','alt+','shift+','super+','hyper+','meta+'ā combinable, e.g.'ctrl+shift+a'
Letter keybinds are case-insensitive ā 'a' matches both a and A (with Shift held).
The literal '+' key is bindable too: write it as '+' on its own, or as 'shift++', 'ctrl++', 'ctrl+shift++', etc. The parser recognises a trailing '+' as the key when the rest of the spec already supplies one or more modifiers.
SEE ALSO
Selkie::Widget ā widgets receive events via
handle-eventSelkie::App ā the event loop dispatches to focused widget first, then parent chain, then global keybinds
Category of event. KeyEvent for keystrokes, MouseEvent for clicks and scrolls, ResizeEvent for terminal resizes.
Modifier keys. Test with $ev.has-modifier(Mod-Ctrl), etc.
has UInt $.id
The keycode or character codepoint of the event. For named keys this is an NCKEY_* constant; for printable characters it's the ordinal.
has Str $.char
The effective printable character, if any. Respects Shift (Shift+1 ā '!'). Undefined for non-printable keys, synthesised events, and legacy control sequences.
has Set $.modifiers
The set of modifier keys held when the event fired. Test with has-modifier.
has NcInputType $.input-type
The input type: NCTYPE_PRESS, NCTYPE_RELEASE, NCTYPE_REPEAT, etc. The framework typically filters RELEASE events before dispatching.
has EventType $.event-type
Which category this event belongs to ā see EventType.
has Int $.y
Mouse Y coordinate for MouseEvent, -1 otherwise.
has Int $.x
Mouse X coordinate for MouseEvent, -1 otherwise.
has Int $.click-count
Click multiplicity for MouseEvent presses: 1 for a single click, 2 for a double-click, 3 for a triple-click. 0 for everything else (motion, drag, release, scroll, keyboard / resize events). Computed by Selkie::App from the inter-press timing and target cell ā widgets read this to distinguish e.g. "select" from "open" in Selkie::Widget::FileBrowser.
method has-modifier
method has-modifier(
Modifier $mod
) returns BoolTrue if the given modifier is part of the event's modifier set.
method with-click-count
method with-click-count(
Int $n
) returns Selkie::EventReturn a fresh Selkie::Event identical to this one but with the given click-count. Used by Selkie::App's mouse dispatcher to annotate a press event with its multiplicity before delivery.
method has-any-modifier
method has-any-modifier() returns BoolTrue if any modifier is held. Useful for "pass bare keys to the widget, bubble modified keys to global keybinds" branches.
method from-ncinput
method from-ncinput(
Notcurses::Native::Types::Ncinput $ni
) returns Selkie::EventBuild a Selkie::Event from a raw notcurses Ncinput struct. Called by Selkie::App inside the event loop ā you don't normally call this yourself. Handles: resize detection, mouse vs key classification, modifier bit decoding, effective character resolution for Shift + key combos, and legacy Ctrl+A..Z control-code remapping for terminals without the kitty keyboard protocol.
Keybind
A parsed keybind specification, produced by Keybind.parse and matched against events via matches. You don't normally construct or match these yourself ā on-key does it for you ā but the class is exposed so advanced code can inspect registered binds.
has UInt $.id
The target keycode / character codepoint.
has Str $.char
The target character, if the bind was for a single character.
has Set $.modifiers
The modifier set that must be held for a match.
has Str $.spec
The original spec string the bind was parsed from. Useful for help-overlay rendering ("Ctrl+L ā Lorebooks").
has Str $.description
Optional human-readable description of what the bind does. Set via the :description arg on Widget.on-key; surfaced by Selkie::Widget::HelpOverlay.
has Callable &.handler
The handler callable invoked on match.
method parse
method parse(
Str:D $spec,
&handler,
Str :$description = ""
) returns Selkie::Event::KeybindParse a keybind spec string into a Keybind. Spec grammar is described under KEYBIND SYNTAX in this module's main pod. Throws on unknown modifiers or unknown key names.
method matches
method matches(
Selkie::Event $ev
) returns BoolDoes the given event match this keybind? Letter binds are case-insensitive ā 'a' matches a typed A with Shift held. All other binds require an exact modifier-set match.
MouseHandler
A registered click / scroll / drag / mouse-down / mouse-up handler, produced by the on-click / on-scroll / etc. methods on Selkie::Widget. Surfaced via mouse-handlers so help overlays can list registered mouse interactions alongside keyboard binds. Apps don't normally construct these directly.
has Str $.kind
The kind of event this handler responds to: one of 'click', 'scroll', 'drag', 'mouse-down', 'mouse-up'.
has UInt $.button
The button this handler fires on (1=primary, 2=middle, 3=right). 0 is the wildcard "any button" ā used by on-scroll (where the wheel arrives as buttons 4 and 5) and by low-level handlers that want to see every press.
has Callable &.handler
The handler callable; receives the Selkie::Event.
has Str $.description
Optional human-readable description, surfaced in help overlays.
sub mouse-event-kinds
sub mouse-event-kinds(
Selkie::Event $ev
) returns ListClassify a mouse event into the list of MouseHandler.kinds it should fan out to. A press fires both 'click' and 'mouse-down' handlers; a release fires 'mouse-up'; drag motion fires 'drag'; scroll wheel fires 'scroll'. Empty list for events that don't match any kind (e.g. unknown id).
sub mouse-event-button
sub mouse-event-button(
Selkie::Event $ev
) returns UIntExtract the 1-indexed button number from a mouse event id. Scroll events are buttons 4 and 5 by encoding; pure motion (NCKEY_MOTION) has no associated button and returns 0.