Skip to content

Input and selection

Keyboard input goes to the focused session. Clicking a screen focuses its session; a session can also take focus from script with session.Focus() and give it up with session.Blur(). One session holds focus at a time, and TerminalSession.FocusChanged reports each move.

A session takes focus when it starts; turn off Focus On Start for one that waits for a click. TerminalSession.Focused is the session with focus, or null.

Focus stays put until something moves it. In a game where the same keys also drive the player:

The game needs Use
The terminal to let go when the player clicks elsewhere Release Focus On Outside Click
Typing stopped with focus kept, for a pause menu or a cutscene session.AcceptsKeyboard = false
Focus tied to game state, such as sitting down at a desk session.Focus() and session.Blur()
One key kept for the game while the terminal has focus session.SkipKeyboardThisFrame(), under Keyboard

While a uGUI or TextMeshPro input field is selected, the session leaves the keyboard to it.

The session encodes keys the way a VT or xterm keyboard does, following the host’s current modes (application cursor keys, and so on). Printable text, control combinations, the arrows, the function keys, Home, End, Page Up, Page Down, Insert, and Delete are all sent, and a held key repeats. On Windows and Linux, left Alt is Meta: it sends ESC and then the key, and right Alt types the characters the keyboard layout composes with it. On macOS, Option types the characters it composes.

To use a key yourself and keep it from the terminal, call session.SkipKeyboardThisFrame() in the frame it is pressed, from a script that updates before the session; [DefaultExecutionOrder(-100)] on the script does that. The demo frees its mouse look on Esc this way.

When the host turns on mouse tracking, pointer events are reported to it in the X10 or SGR encoding it asked for. Holding Shift bypasses tracking for local use: the wheel scrolls the scrollback, and a drag selects text. Shift, Page Up and Shift, Page Down page through history.

A scene screen turns the camera’s mouse ray into cell coordinates, so a terminal across the room is clickable, out to the screen’s Max Pointer Distance; a mouse over a uGUI element is left to the UI. Pointer Camera picks the camera the ray starts from, the main camera when empty. Turn off Use Mouse Pointer and drive it from any ray instead, such as an XR controller:

var screen = GetComponent<TerminalScreen3D>();
screen.PointFromRay(ray, out int col, out int row); // hover
screen.ButtonFromRay(ray, TermMouseButton.Left, pressed: triggerDown);
screen.ScrollFromRay(ray, thumbstick.y);

With the Physics module in the project, the ray meets the screen’s collider, and a mesh collider follows a curved or cut mesh; the screen adds a mesh collider when it has none, and Pointer Occluders names the layers whose colliders block the pointer. Without the module, the ray meets the plane of the object as a flat unit quad, and nothing occludes it.

The pointer indicator is per screen: None draws nothing and only routes the input, for a setup where a game reticle or the OS cursor is already visible; Outline, Block, or Underline draw a marker on the hovered cell.

With mouse tracking off (or Shift held), dragging selects a run of text, line by line. Ctrl+Shift+C copies the selection, Ctrl+Shift+V pastes, and on macOS Cmd+C and Cmd+V do the same. Paste is wrapped for bracketed paste mode when the host asked for it. session.Renderer.Selection is the selected CellRange, and session.Emulator.GetText(range) reads any range as a string.

A surface program or an interface takes the keyboard and the pointer as events. Selection, scrollback, and copy are off until it exits, and a paste goes to the program. See Interfaces.

The session exposes the send calls, so a gamepad, an on-screen keyboard, or a script can drive the terminal:

To send Call
Text, as if typed session.SendText
A key: an arrow, a function key, Enter session.Send with InputEncoder.Key
A paste session.Send with InputEncoder.Paste
A click, a drag, or the wheel at a cell session.SendMouse
A pointer from a world ray PointFromRay, ButtonFromRay, and ScrollFromRay, under Mouse
session.SendText("ls -la\n");
session.Send(InputEncoder.Key(TermKey.Up, TermModifiers.None, session.Emulator.ApplicationCursorKeys));
session.SendMouse(TermMouseButton.Left, press: true, motion: false, col, row, TermModifiers.None);

Rendering and painting covers the texture, the overlay API, and reflowing to fill a window.