OnScreenKeyboard
OnScreenKeyboard is a keyboard on the screen for a player with a gamepad. It opens by itself when a gamepad moves the focus to a text field, or when the player presses A on a focused text field. It docks at the bottom of the workspace of the field, or of the panel outside a workspace.
The focus stays on the field. The keys send key events to the field, so the caret, the selection, maxLength and the number filter of a number field work as with a hardware keyboard. A hardware key, a pointer press outside the keyboard or a focus change closes the keyboard.
You do not have to add the keyboard. A Toolbox control in a panel, or a UIDocument in a loaded scene, makes the keyboard open by itself in that panel. The keyboard is made at the first open.
// A panel that the keyboard does not find, such as one made in code after the scene loaded
OnScreenKeyboard.Attach(document.rootVisualElement.panel);
// No automatic open anywhere
OnScreenKeyboard.AutoOpen = false;
// No automatic open for one field, and an open from code
OnScreenKeyboard.SetAutoOpen(chatLine, false);
keyboard.Open(chatLine);
A keyboard declared in UXML is used in place of the one that is made. Use it to set the attributes:
<UIToolbox.OnScreenKeyboard max-suggestions="4" />
Buttons
| Button | Action |
|---|---|
| D-pad | Moves between the keys. The suggestions are the top row. |
| A | Presses the current key or suggestion. |
| B | Backspace. On an empty field, B closes the keyboard. |
| X | Space. |
| Y | Shift. |
| LB, RB | Moves the caret left and right. |
| Right stick left and right | Chooses a suggestion. |
| Right stick click | Types the chosen suggestion, or the first one. |
| Start | Done: submits the field and closes the keyboard. |
- The D-pad, A and B are the UI navigation events, so they follow the input module of the project.
- X, Y, LB, RB, the right stick and Start need the Input System package. They are the actions of the
OnScreenKeyboardmap inResources/UIToolbox/ToolboxInputActions. Rebind them with the Input System rebinding APIs. Without the Input System, use the keys of the keyboard for space, shift and done. - A pointer press on a key also works, so a touch screen and a mouse can use the keyboard.
Kinds of field
The kind of the field picks the layout and turns the suggestions on or off.
| Kind | Field | Layout | Suggestions |
|---|---|---|---|
Text |
A TextField |
Letters and symbols. A capital at the start of the text and of each sentence. | Yes |
Name |
The class tb-osk-kind--name |
Letters and symbols. A capital at the start of each word. | Yes |
Email |
The class tb-osk-kind--email |
Letters and symbols, with @ and .com keys. |
Yes |
Url |
The class tb-osk-kind--url |
Letters and symbols, with / and .com keys. |
Yes |
Number |
An IntegerField, FloatField or other number field |
A number pad. | No |
Password |
A TextField with isPasswordField |
Letters and symbols. | No, and no learned words |
OnScreenKeyboard.SetKind(mailField, TextFieldKind.Email);
<ui:TextField label="Email" class="tb-osk-kind--email" />
<ui:TextField label="Seed" class="tb-osk-off" />
The class tb-osk-off on a field or on a parent of it turns the automatic open off for the field.
Word completion
The suggestions come from OnScreenKeyboard.Completer, a WordCompleter. The default is WordCompleter.English, which all keyboards share.
- The names of
Completer.Names, such as the characters and the places of the game. Their case stays. - The learned words, the most used first. A word is learned when the player types it and then a space or a punctuation mark, accepts it as a suggestion, or presses done after it.
- The words of the list, the most common first, then the shortest. The list is the word list of the spell checker, in six sections from common to rare.
A suggestion takes the case of the typed letters: "The" gives "Then", and "THE" gives "THEN".
var completer = WordCompleter.English;
completer.Names.UnionWith(new[] { "Aldebaran", "Mirefen", "Quillon" });
Keep the learned words
The learned words stay in memory and are lost when the game stops. The keyboard does not write files unless you set a store. Set Store to keep the words between sessions:
// A JSON file in Application.persistentDataPath/UIToolbox/learned-words.json
WordCompleter.English.Store = new JsonWordStore();
The keyboard saves the words when it closes. Call Save() to save them at another time, and ForgetLearnedWords() to remove them, such as from a privacy option.
For a cloud save or your own save file, write an IWordStore:
public sealed class SaveGameWordStore : IWordStore
{
public IReadOnlyDictionary<string, int> Load() => SaveGame.Current.LearnedWords;
public void Save(IReadOnlyDictionary<string, int> words) => SaveGame.Current.LearnedWords = new(words);
}
| Member | Description |
|---|---|
WordCompleter.English |
The US English completer. |
WordCompleter.FromText(text), new WordCompleter(words) |
A completer from another list. A "# n" line starts section n: the words of a lower section come first. |
Complete(prefix, max) |
Up to max words that start with the prefix. |
Names |
The names that come first. |
Learn(word), LearnedWords |
Counts a use of a word, and the learned words with their counts. A word with fewer than two letters, or with a digit, is not learned. |
Store, Save(), ForgetLearnedWords() |
Keep, save and remove the learned words. A store error is logged as a warning. |
Layouts
A KeyboardLayout is the keys of the keyboard as text. Make one with Create > UI Toolbox > Keyboard Layout and set it on the layout attribute, or make one in code with KeyboardLayout.FromText.
[letters ABC]
q w e r t y u i o p
a s d f g h j k l
{shift*1.5} z x c v b n m {backspace*1.5}
{>symbols*1.5} {left} , {space*4} . {right} {done*1.5}
[symbols ?123]
1 2 3 4 5 6 7 8 9 0
...
- A
[name label]line starts a page. The label is the text of the keys that open the page. The first page shows when the keyboard opens. - Each other line is a row. Spaces separate the keys.
- A key types its text, such as
q,,or.com. {id}or{id*width}is a special key:shift,backspace,space,done,left,right,gap(an empty space) or>page(opens the page). Another id in braces types itself, so{.com*2}is a wide key. The width is in key widths; the default is 1.- A bad layout throws a
FormatExceptionwith the cause.
// The layout of all letter fields, or of one kind
keyboard.Layout = germanLayout;
keyboard.SetLayout(TextFieldKind.Number, phonePad);
KeyboardLayout.Default(kind) gives the built-in US QWERTY layouts.
Platform keyboards
On a console or a Steam Deck, the platform has its own keyboard. Set OnScreenKeyboard.PlatformKeyboard to use it. When its TryOpen returns true, it opens in place of the on-screen keyboard. When it returns false, the on-screen keyboard opens.
public sealed class SteamKeyboard : IPlatformKeyboard
{
public bool TryOpen(string text, TextFieldKind kind, int maxLength, Action<string?> done)
{
if (!SteamUtils.IsSteamRunningOnSteamDeck()) return false;
// Your call to SteamUtils.ShowGamepadTextInput. Its dismissed callback calls done with the new text, or with null on a cancel.
return ShowSteamTextInput(text, kind == TextFieldKind.Password, maxLength, done);
}
}
OnScreenKeyboard.PlatformKeyboard = new SteamKeyboard();
The keyboard sets the value of a text field to the new text. A number field gets the text as typed keys, and commits it.
Events and members
| Member | Description |
|---|---|
Open(field), Close(), IsOpen |
Open the keyboard for a text field, close it, and whether it is open. Open throws an ArgumentException for an element that is not a text field. |
Target, Kind |
The field and its kind. |
MaxSuggestions |
The maximum number of suggestions. Default 3. |
KeyPressed |
A key was pressed: the id of a special key, such as "shift", or the text of the key. |
Submitted |
The player pressed done in the field. |
Closed |
The keyboard closed. |
OnScreenKeyboard.KindOf(field) |
The kind of a field. |
- The done key sends Return to the field, so a number field and a delayed field commit. A multiline field gets no Return.
- The text of the done key comes from
ToolboxText.DONE. - The keyboard can cover a field near the bottom of the screen. Put the text fields in the top part of a screen that a gamepad player uses.
Styling
| Class | Element |
|---|---|
tb-osk |
The keyboard. |
tb-osk__suggestions, tb-osk__suggestion |
The suggestion row and a suggestion. |
tb-osk__suggestion--chosen |
The suggestion that the right stick chose. |
tb-osk__keys, tb-osk__row, tb-osk__key |
The key rows, a row and a key. |
tb-osk__key--current |
The key or suggestion that A presses. |
tb-osk__key--glyph, tb-osk__key--page |
A key with a PromptFont glyph, such as shift, and a key that opens a page. |
tb-osk__key--shift, --backspace, --space, --left, --right, --done |
The special keys. |
tb-osk__gap |
An empty space in a row. |
tb-osk--shift |
Shift is on. |
tb-osk--no-suggestions |
The field gets no suggestions. The suggestion row hides. |
| Variable | Default | Use |
|---|---|---|
--tb-osk-background |
--tb-color-surface |
The keyboard background. |
--tb-osk-key |
--tb-color-surface-alt |
A key. |
--tb-osk-key-hover |
--tb-color-surface-hover |
A key under the pointer. |
--tb-osk-key-special |
--tb-color-surface-hover |
A special key. |
--tb-osk-key-text |
--tb-color-text |
The text of the keys. |
--tb-osk-current |
--tb-color-accent |
The current key, and the shift key when shift is on. |
--tb-osk-current-text |
--tb-color-accent-text |
The text of the current key. |
--tb-osk-key-height |
44px |
The height of a key. |
--tb-osk-max-width |
880px |
The maximum width of the rows. |
The variables are set on .tb-osk. Set them in a rule for .tb-osk in a style sheet that loads after the Toolbox sheet.