Skip to main content

Module input

Module input 

Source
Expand description

§Input

Keys, pastes and the pointer reach a UI plugin as events on its surfaces (event-types in the SDK’s wit/plugin.wit). The SDK types them: Event::Key(Key), Event::Paste { surface, text }, Event::Pointer(Pointer).

§Which surface hears what

  • An open stage, panel.popover or pane.overlay takes every key but Escape, every paste, and the pointer over it. A column opens with focus and keeps it until Escape (which closes it) or a press elsewhere; a press on it gives it focus again. A pane has input focus while its workspace pane has focus: keys reach it as they reach a terminal pane (the viewer keeps its leader and pane navigation keys), and a press on it focuses its pane. Escape (or a click outside) closes it: the plugin sees Event::Focus { focused: false } and the surface’s visibility go.
  • Any surface receives the pointer over it. A press on a surface whose manifest sets "input": true gives it focus (Event::Focus); keys and pastes then go to it until Escape or a press elsewhere.
  • A key, a paste, a pointer press and a command are gestures: while it handles one, the plugin may open its stage with cx.open(id) (the surface it handles the gesture on becomes the opener, which places a popover and colours a column; see the manifest), and while it handles one or within a second after, open one web page with cx.open_url(url) (grant url.open:<host>; see grants).
  • A gesture reaches only the viewer the user acts in, so a call sent while handling one goes out once. A call sent from anything else (a value change, a plugin event, a resize, frame()) goes out once per open viewer: the double-play mistake. Send calls from gestures only, and move other effects to the companion (working together).

§Keys

Key { surface, code, text, modifiers, phase }:

FieldValues
codeKeyCode::Char(c) for a character key (the character it types: a, A, 1, ?); Enter, Tab, BackTab, Backspace, Delete, Insert, Space, Left, Right, Up, Down, Home, End, PageUp, PageDown, F(1)..F(12). On the wire: the character, or enter, tab, backtab, backspace, delete, insert, space, left, right, up, down, home, end, pageup, pagedown, f1..f12
textWhat the key types, when it types text (not with Ctrl or Super)
modifiersModifiers: shift 1, ctrl 2, alt 4, super 8 (.shift(), .ctrl(), …)
phasePress, Repeat, and Release where the terminal reports releases

Escape never arrives. Shift+Enter arrives as Enter with shift in every browser. A native viewer delivers it with shift while a text field has the keys: the surface that takes keys has set a caret (text fields) and the terminal speaks the kitty keyboard protocol. Terminals report Shift on Enter only when they send every key as an escape code, so the viewer asks for that mode while such a caret has the keys and asks for its usual mode when the caret lets them go. Typed text stays the same in that mode, Caps Lock and Option or AltGr characters included. Without a caret, or on a terminal without the protocol (Terminal.app among them), Shift+Enter arrives as a plain Enter and Alt+Enter as Enter with alt, so a composer that starts a line on Shift+Enter should accept Alt+Enter too.

§Text fields and the caret

A text field draws no cursor of its own: it tells the viewer where its caret stands with surface.set_caret(Some((col, row))) (or cx.set_caret(id, ...)), in cells of the surface, and None when no field of the surface has the caret. While that surface takes keys (an open stage, popover or pane overlay, or the surface with input focus) the viewer draws its own cursor at that cell and its cursor trail moves there from the pane, and back when the surface lets the keys go. The caret stays until set again, so set it whenever the field repaints. In a native viewer the caret is also what makes Shift+Enter arrive with shift (keys).

§The pointer

Pointer { surface, x, y, col, row, button, kind, modifiers }:

FieldValues
x, yThe position in the surface’s units: cells for a cells surface; surface pixels for a pixels surface. The browser reports the exact pixel, and motion inside a cell; a terminal reports cells, so a native viewer sends the cell’s centre
col, rowThe cell under the pointer
kindDown, Up, Move (no button), Drag (a button held), Wheel; Enter when the pointer moves onto the surface (before its first Move) and Leave when it moves off, or the surface stops showing under it (at the last position on it), so a hover begins and ends exactly
buttonLeft, Middle, Right, None; for Wheel: WheelUp, WheelDown, WheelLeft, WheelRight (wire numbers 1, 2, 3, 0, 4 to 7)

A sidebar surface (sidebar.card, machine.after, project.after, project.before) receives no vertical Wheel: the sidebar scrolls instead, so a surface row that scrolls under a resting pointer never stops the list. No surface receives a sideways Wheel; it scrolls the workspace.

§Repainting after input

A commit made in event is not a frame request. Repaint and call cx.request_frame(), or change the state frame() reads and request a frame; see rendering.