Input

Input belongs to a window and arrives in the event stream with the notifications, in the order the platform delivered it.

Storage and resets

Each window keeps input in four classes, each with room for inputPerWindow records: discrete records (keys, text, buttons, touches and pen contacts beginning or ending), motion (cursor, touch and pen), raw deltas, and the wheel.

Keys

A key record names two things:

mwinContext_MapKeyCode asks the layout what a code types, mwinContext_GetKeyboardLayout gives the layout's name, and mwin_eventKeyboardLayoutChanged says it changed. On iOS and Android a printing key's meaning is known only once it has been pressed under the current layout.

Some chords never reach a program: Alt+Tab and Control+Alt+Delete on Windows, Command+Tab on Apple's systems, Control+W in Chromium. mwinContext_GetKeyReach answers, for a key with modifiers, whether it is delivered, shared (the records arrive and the platform acts too, as Alt+F4 on Windows), uncertain (the desktop's configurable shortcuts may take it) or never delivered, so a rebinding screen can refuse or warn. The answers come from tables of what each platform keeps; a desktop may keep more.

Text and input methods

Typed text is not keys. It arrives as mwin_eventTextInput, never empty, valid UTF-8 with no control characters (U+0000 to U+001F, U+007F to U+009F), while the window accepts text: mwinWindow_RequestTextInput turns it on and off, and mwinWindow_RequestTextInputCaret gives the caret's rectangle, where the platform places the input method's candidate window. The window keeps its caret while text input is off, so a program asks again only when the caret moves. A tab or a line break that an input method or an on-screen keyboard types arrives as the Tab or Enter key's press and release instead. A carriage return and line feed within one commit are one Enter; a carriage return that ends one commit and a line feed that starts the next are two. The text of a record stays valid until the frame that drained it returns.

An input method's composition arrives as mwin_eventImePreedit with its text, caret, selection and styled segments; a newer composition replaces one still waiting. Every offset lies on a character boundary within the text and the selection is in order, whatever the input method handed over, so the text can be sliced at any offset. While the input method composes, the keys it takes produce no key records, and no press arrives without its release. A reset ends the composition the program shows, not the input method's: the keys it takes stay left out until it ends its composition with an empty preedit (stopping text input ends it too) or the focus leaves.

On X11 the input method is IBus or Fcitx 5, reached over the session bus; without either, text comes from the keymap and its compose sequences. Wayland uses text-input-v3 and Windows its input methods through IMM32, the system drawing the candidate list.

mwinWindow_RequestVirtualKeyboard shows or hides the on-screen keyboard where there is one, with a purpose (text, number, e-mail, password, URL) that picks its layout. MWIN_INPUT_PURPOSES counts the purposes; a value from it on is not one, and the request fails. mwin_eventVirtualKeyboardChanged gives the part of the window it covers. On a Windows desktop with a hardware keyboard the request is denied, and Wayland shows its keyboard when text input is on. Android shows it only for this request, never by itself when the window gains the focus, and commits a composition in progress when the keyboard or another purpose is asked for: only stopping text input drops a composition. The request asks the platform, which may not show the keyboard for long: an input method may hide its keyboard by itself, as a user can. Gboard on Android 11 does when it runs behind, after the keyboard was asked for several purposes in quick succession. mwin_eventVirtualKeyboardChanged tells the program, which may ask again.

The pointer

Cursors

mwinWindow_RequestCursorShape picks one of the system's shapes. mwinCreateCursor makes a cursor from one to four RGBA images (the first at scale 1, each next one wider for higher scales, at most 128 pixels a side) and a hotspot; mwinWindow_RequestCursorImage shows it over a window, which takes the image for its scale. A shape and an image replace each other, and destroying a cursor in use leaves its windows the default shape. iOS shows no cursor and answers unsupported, though the cursor is still made, so portable code needs no branch.

Touch and pens

Touches and pens are records of their own, never made into mouse records.