C
Qt Quick Ultralite Virtual Keyboard Overview
The Qt Quick Ultralite Virtual Keyboard module enables virtual keyboard support in an application.
The Qt Quick Ultralite Virtual Keyboard project provides an input framework and reference keyboard frontend. The input framework is extensible to allow custom input methods and keyboard layouts to be loaded at runtime.
The virtual keyboard is embedded within the application itself by instantiating an InputPanel item in QML. The following example shows how to create an InputPanel and how to divide the screen area with the application container.
InputPanel { id: keyboard width: StyleConstants.vkbScreenWidth y: root.height - keyboard.height }
The input panel height will be automatically updated according to the available width; the aspect ratio of the input panel is constant.
For complete example see Qt Quick Ultralite text_input Example.
This module is fully supported since Qt Quick Ultralite version 2.9.
Features
Key features of the Qt Quick Ultralite Virtual Keyboard include:
- Customizable keyboard layouts and styles.
- Scalability to different resolutions.
- Character preview and alternative character view.
- Pinyin input with word candidate view.
- Support for different character sets (Latin, Chinese, Hindi, Arabic, Hebrew, and others).
- Support for most common input languages, with possibility to easily extend the language support.
- Left-to-right and right-to-left input.
- Cross-platform functionality.
Supported languages
The Virtual Keyboard supports the following languages:
|
|
|
|
Note: English (United States), English (United Kingdom), Dutch, Malay, and Indonesian all use fallback/main.qml
in the bundled layouts. Spanish and Spanish (Mexican) are identical. Portuguese (Brazil) and Portuguese (Portugal) are identical.
To add support for an additional language, see Adding and Removing Languages and Adding new keyboard layouts.
Using the module
To use the Qt Quick Ultralite Virtual Keyboard QML types, add Qul::VirtualKeyboard to the list of module files in your .qmlproject
.
ModuleFiles { MCU.qulModules: ["Qul::VirtualKeyboard"] }
After adding the module files, add the following import statement to your .qml
file:
import QtQuick.VirtualKeyboard
For more information, see Qt Quick Ultralite text_input Example.
Input framework concepts
This section provides a brief overview of the key concepts behind the input framework. Understanding these concepts is essential for working with advanced use cases.
If you simply want to integrate the virtual keyboard into your application, refer to API for application developers.
Input context
Provides contextual information for the virtual keyboard and other input components. Acts as an interface to the underlying text input component.
The input context is used by the keyboard as well as concrete input methods. InputContext is a singleton instance. An application should not directly interact with the input context.
Input engine
Exposes an API to integrate user input events (key presses) and acts as a host for input methods.
The InputEngine object can be accessed by the inputEngine property in InputContext item. Like the InputContext, there is only one instance of the input engine. The input engine contains API functions which the keyboard uses to map user interactions, such as key press and release events, to the input method.
Input method
The input method is a concrete implementation of the keypress handler. It's main function is to handle keypress events and maintain state information for the user input. It interacts with the text editor through InputContext.
The input method instance can be created in various ways, depending on the use case:
- KeyboardLayout::inputMethod: the keyboard layout can create an input method instance solely for this keyboard layout.
- The input engine create default input method at startup. This instance will be used as the default input method across all keyboard layouts, unless the keyboard layout uses a custom input method.
Note: No public API currently is provided to write custom input methods.
Virtual keyboard scaling
Use MCU.Config.Experimental.vkbScreenWidth to set virtual keyboard screen width. This value is propagated to StyleConstants.vkbScreenWidth.
InputPanel { id: keyboard anchors.horizontalCenter: parent.horizontalCenter width: StyleConstants.vkbScreenWidth y: root.height - keyboard.height }
The earlier example assumes that physical screen width is 1000
. As you can see in the following images, on the left side, MCU.Config.Experimental.vkbScreenWidth is 800
and on right side it is 1000
.
MCU.Config.Experimental.vkbScreenWidth is 800 | MCU.Config.Experimental.vkbScreenWidth is 1000 |
---|---|
The earlier example also uses ImageFiles.MCU.Experimental.resourceSVGScale property to adjust the scale factor for the image assets of virtual keyboard’s default style.
Note: These scaling APIs are marked as experimental because there are no direct equivalents in Qt Quick.
Pinyin support
The Qt Quick Ultralite Virtual Keyboard supports the Pinyin input method for simplified Chinese. This input method requires a dictionary file and a large number of glyphs, which may have a large impact on the final binary size of the Qt for MCUs application. For this reason the Qt Quick Ultralite Virtual Keyboard module uses an empty dictionary by default, effectively disabling the Pinyin input method. Enable the Pinyin input method with a dictionary containing the most common words and characters using the MCU.Config.vkbPinyinSupport QmlProject property in your application's .qmlproject
file. In case you need to customize the dictionary file to either add or remove characters or words, use the qulpinyingenerator tool to generate a dictionary file from raw data, and configure the application to use the custom dictionary using the MCU.Config.vkbPinyinDictionary QmlProject property.
If everything is configured correctly, typing pinyin input should display suggestions to choose from, as demonstrated in the following image. Note that suggestions for input depends on the dictionary that was bundled with the application.
qulpinyingenerator
The qulpinyindgenerator
tool generates a header file which is usable as the Pinyin dictionary with the Qt Quick Ultralite Virtual Keyboard module based on a raw dictionary file. The dictionary file used to generate the default dictionary is found in ${QUL_ROOT}/src/3rdparty/pinyin/data/rawdict_utf16_65105_freq.txt
.
Input file
Use the --file
argument to specify the raw dictionary data from which to generate the custom dictionary. The data must have the same format as the dictionary used to generate the default Pinyin dictionary, located in ${QUL_ROOT}/src/3rdparty/pinyin/data/rawdict_utf16_65105_freq.txt
.
The raw data format places an entry on a single line, which starts with the hanzi character(s), followed by a number denoting the frequency of the character, then either a 0 or a 1 denoting whether the character uses GBK encoding, and finally the pinyin spelling of the entry.
// hanzi, frequency, GBK, spelling ... 嗒 322.010219858 0 da 哒 1540.35530331 0 da 搭 2238.62771494 0 da ...
Output path
Use the --outputPath
command-line argument to specify where to place the generated file. The file will be named "qul_pinyin_custom_dict.h" and placed directly in the given path. Specify this path in the MCU.Config.vkbPinyinDictionary property in your application's .qmlproject
file to use your custom dictionary in the application.
Minimum frequency
The raw dictionary data lists the frequency of each entry. The qulpinyingenerator
tool allows filtering out low frequency entries using the --minFrequency
command-line option. Only entries with a listed frequency higher than the slected minimum frequency are used in the generated dictionary.
Unicode ranges
In addition to the dictionary itself, the output file from the qulpinyingenerator
also contains the unicode ranges covering the glyphs used by the entries in the dictionary, for convenience. You can use these ranges to set the font.unicodeCoverage in QML and with the Monotype FontmapEditor Subsetter feature to modify your font file(s) to remove unused glyphs. If there are many short ranges with small gaps between them, the amount of entries in the list of entries can get very large. To simplify the list of unicode ranges to support, you can use the --unicodeRangeTolerance
command-line argument to merge adjacent ranges at the expense of including some unused glyphs. The --unicodeRangeTolerance
was introduced to circumvent a crash in the Monotype FontmapEditor Subsetter when the list of unicode ranges is too long.
Example usage:
qulpinyingenerator --file=${QUL_ROOT}/src/3rdparty/pinyin/data/rawdict_utf16_65105_freq.txt --outputPath=pinyin/my_custom_dict --minFrequency=1000 --unicodeRangeTolerance=6
See also Font Unicode coverage configuration.
Keyboard layouts
Keyboard layouts are located in the src/virtualkeyboard/layouts directory. Each subdirectory of the layout directory represents a locale. The locale directory is a QLocale::bcp47Name string that uniquely identifies keyboard layout. The locale information can be utilized to determine whether the input language is written left-to-right or right-to-left, identify the appropriate "comma" Unicode character for the specific language, and display the native name of the language.
The engine will recognize bcp47Name
names as listed in the locale table.
Layout types
Different keyboard layout types are used in different input modes. The default layout which is used for regular text input, is called the main
layout. The layout type is determined by the layout file name, which is main.qml
for main
layout.
Note: Due to internal technical reasons the layout names need to be prefixed with locale directory name. For example, ./uk/uk_main.qml
is the layout file for uk
locale.
List of supported layout types:
main
The main layout for normal text inputsymbols
Symbol layout for special characters etc. (activated from main layout)numbers
Numeric layout for formatted numbers (activated by Qt.ImhFormattedNumbersOnly)digits
Digits only layout (activated by Qt.ImhDigitsOnly)dialpad
Dialpad layout for phone number input (activated by Qt.ImhDialableCharactersOnly)
Input locale
The Virtual Keyboard engine generates the list of supported locales from locale-specific layout directories in src/virtualkeyboard/layouts/
. The layouts/
directory must contain a fallback/
sub-directory, that includes definitions for each layout type: dialpad
, digits
, main
, numbers
, and symbols
.
Each layout directory may contain the definition of one or more layout types. If the locale-specific layout is the same as that of the fallback locale, you can rely on the virtual keyboard to lookup this layout type from the fallback/
directory. If locale-specific directory does not provide the requested layout type, QULVkb uses one of fallback/
layouts instead.
For example, you may add a locale-specific layout for Finnish, defining its main layout in fi_main.qml
and opt for the fallback mechanism for other layout types. Your layouts/
tree will look like this:
. ├── fallback │ ├── dialpad.qml │ ├── digits.qml │ ├── handwriting.qml │ ├── main.qml │ ├── numbers.qml │ └── symbols.qml └── fi └── fi_main.qml
It's imperative that the src/virtualkeyboard/layouts/fallback
directory always contain a set of full implementation files.
The application can specify the active locale using VirtualKeyboardSettings.locale
. The KeyboardLayout can include ChangeLanguageKey button to enable users to toggle between available languages.
Adding new keyboard layouts
The keyboard layout element must be based on the KeyboardLayout QML type, which is the root item of the layout.
Add new rows to the keyboard layout using the KeyboardRow type. The key weight for its child elements is inherited from KeyboardLayout.keyWeight property.
Add keys to the new keyboard row using the Key type or one of the specialized key types. Below is the list of all built-in key types:
Backspace key for keyboard layouts | |
Change language key for keyboard layouts | |
Enter key for keyboard layouts | |
Filler key for keyboard layouts | |
Hide keyboard key for keyboard layouts | |
Input mode key for keyboard layouts | |
Regular character key for keyboard layouts | |
Generic mode key for keyboard layouts | |
Shift key for keyboard layouts | |
Space key for keyboard layouts | |
Symbol mode key for keyboard layouts |
For example, to add a regular key which sends a key event to the input method:
import QtQuick import QtQuick.VirtualKeyboard import QtQuick.VirtualKeyboard.Components KeyboardLayout { keyWeight: 160 KeyboardRow { Key { key: Qt.Key_Q text: "q" } } }
Key size calculation
The keyboard layouts are scalable, which means that there cannot be any fixed sizes set for any items in the layout. Instead, each key's width is calculated from its key weight in relation to other keys and its height, dividing the space equally among the keyboard rows.
In the earlier example, the key size is inherited from KeyboardLayout.
The effective value for the key weight will be 160. For the sake of the example, we add another key which specifies a custom key weight:
import QtQuick import QtQuick.VirtualKeyboard import QtQuick.VirtualKeyboard.Components KeyboardLayout { keyWeight: 160 KeyboardRow { Key { key: Qt.Key_Q text: "q" } Key { key: Qt.Key_W text: "w" weight: 200 } } }
Now the total key weight of a row is 160 + 200 = 360. When the keyboard layout is activated, the width of an individual key is calculated as follows:
key width in pixels = key weight / SUM(key weights in a row) * row width in pixels
This means that the keyboard can be scaled to any size, while the relative key sizes remain the same.
Alternative keys
Key can specify an alternativeKeys property, which QULVkb uses to show a popup listing the alternative keys when the user presses and holds the key.
The alternativeKeys can specify either a string, or a list of strings. If alternativeKeys is a string, the user can select between the characters in the string.
Styles and layouts
The keyboard layouts cannot specify any visual elements. Instead, the layout is visualized by the keyboard style. On the other hand, the keyboard style cannot affect the size of the keyboard layout.
Keyboard layouts with multiple pages of keys
Some keyboard layouts, such as symbol layouts, may contain more keys than it is feasible to present on a single keyboard layout. In such a cases, embed multiple keyboard layouts into the same context using the KeyboardLayoutLoader.
When the KeyboardLayoutLoader is used as a root item of a keyboard layout, the actual keyboard layouts are wrapped inside Component elements. The keyboard layout is activated by assigning the id of an active component to the sourceComponent property.
For example:
import QtQuick import QtQuick.VirtualKeyboard import QtQuick.VirtualKeyboard.Components KeyboardLayoutLoader { property bool secondPage onVisibleChanged: if (!visible) secondPage = false sourceComponent: secondPage ? page2 : page1 Component { id: page1 KeyboardLayout { KeyboardRow { Key { displayText: "1/2" functionKey: true onClicked: secondPage = !secondPage } } } } Component { id: page2 KeyboardLayout { KeyboardRow { Key { displayText: "2/2" functionKey: true onClicked: secondPage = !secondPage } } } } }
Adding and removing languages
You can add and remove layouts and languages built with the Qt Quick Ultralite Virtual Keyboard module. Layouts are built with the rest of the module, so changing adding or removing layouts requires re-exporting and building the module again. While the application can change the keyboard layout dynamically at runtime, it is not possible to add or remove new layouts after the module has been built.
To remove layouts you don't need from the Qt Quick Ultralite Virtual Keyboard build, comment out the layouts you want to exclude from the module's .qmlproject
file in the Qt Quick Ultralite install directory, located in src/virtualkeyboard/virtualkeyboard/VirtualKeyboardAssets.qmlproject
.
To add a new language or layout, create a directory in the Qt Quick Ultralite install directory under src/virtualkeyboard/layouts
named after the locale your layout should be used for. For example src/virtualkeyboard/layouts/nn
for Norwegian nynorsk. Add the layouts to support for your new language according to the instructions above. Finally, register the new locale directory with the Qt Quick Ultralite Virtual Keyboard build by adding an entry in the QmlFiles
node in the VirtualKeyboardAssets.qmlproject
file belonging to your Qt Quick Ultralite installation.
# Snippet from VirtualKeyboardAssets.qmlproject: ... QmlFiles { files: [ // styles "../styles/SelectionListItem.qml", "../styles/KeyboardStyle.qml", ... // layouts // Place your custom layouts here vvvv "../layouts/nn/nn_main.qml", "../layouts/nn/nn_symbols.qml", // Place your custom layouts here ^^^^ // Unused language/layout is commented out //"../layouts/nb/nb_main.qml", // The following built-in layouts will be included "../layouts/sr/sr_main.qml", "../layouts/pt/pt_main.qml", "../layouts/bg/bg_main.qml", "../layouts/sl/sl_main.qml", "../layouts/zh/zh_main.qml", "../layouts/zh/zh_symbols.qml", "../layouts/ru/ru_main.qml", "../layouts/tr/tr_main.qml", "../layouts/fa/fa_main.qml", "../layouts/fa/fa_digits.qml", "../layouts/fa/fa_symbols.qml", "../layouts/fa/fa_numbers.qml", "../layouts/pl/pl_main.qml", ... ] } ...
Note: This way of adding and excluding layouts from the Qt Quick Ultralite Virtual Keyboard module build is subject to change in upcoming Qt for MCUs releases.
Note: Some of the built-in languages rely purely on the fallback
locale. Build tools register such directories if alias.fallback
is found in the locale directory.
Keyboard styles
The Qt Quick Ultralite Virtual Keyboard styling system supports built-in styles as well as custom styles. When using the Qt Quick Ultralite Virtual Keyboard in an application, the virtual keyboard style, as well as any component in the module which uses the style directly is exported and built when building the Qt Quick Ultralite application. This means that only one style is available at a time, and changing the style requires re-exporting and building the application. It is not possible to load new styles at runtime.
Since Qt for MCUs 2.9, you can select the style of the virtual keyboard using file selectors. The module contains two built-in styles, the default style, and an alternative style named "retro". Select the style you want using file selectors, either in qul_add_target(), or using the --selector command-line argument when using qmlprojectexporter directly from the command-line.
## Applies the "retro" style to the VirtualKeyboard module qul_add_target(MyQulApp QML_PROJECT MyApp.qmlproject SELECTORS "retro" )
If no file selectors are provided, or no style matches the provided selectors, Qt Quick Ultralite Virtual Keyboard applies the default style.
Styling APIs
There are notable differences between Qt Virtual Keyboard Styling and Qt Quick Ultralite Virtual Keyboard styling setup.
In Qt:
- The entire style is defined by KeyboardStyle component.
- KeyboardStyle is a root item in a file named
style.qml
.
In Qt Quick Ultralite though, due to current limitations of QML language support, the KeyboardStyle API definition is split into several files. Thus, the styling API consists of the components listed in the following table. The built-in reference styles use a StyleConfig
singleton to store and share the common properties across the style components.
Note: This may change in future releases to support easier style reuse with projects using Qt Virtual Keyboard.
Template for the alternative keys list background | |
Template for the alternative keys list delegate | |
Template for the alternative keys list highlight | |
Template for the BackspaceKey | |
Template for the character preview popup | |
KeyboardStyle implementation for concrete style | |
Template for the EnterKey | |
Template for the HideKeyboardKey | |
Template for the regular Key | |
Template for the keyboard background | |
Provides a styling interface for the Virtual Keyboard | |
Template for the ChangeLanguageKey | |
Template for the selection list background | |
Template for the selection list delegate | |
Template for the selection list highlight | |
Template for the ShiftKey | |
Template for the SpaceKey | |
Singleton with keyboard styling constants | |
Template for the SymbolModeKey and InputModeKey |
Adding custom styles
The process of creating a new style begins by creating a new subdirectory for the style in the Qt for MCUs install directory, adjacent to the "retro"
style. Create a new directory under ${QUL_ROOT}/src/virtualkeyboard/styles/builtin
with the name of your style and a "+"
prefix, for example ${QUL_ROOT}/src/virtualkeyboard/styles/builtin/+my_style
.
Note: As of Qt for MCUs 2.9, custom styles must be placed next to the built-in styles in the Qt for MCUs install directory for the virtual keyboard module to be able to locate them. This may change in future releases.
A good starting point for creating a new style is to use an existing built-in style as a template and edit it. Copy the contents of one of the directories containing a built-in style into the directory you created for your style. The style directory should now contain all the QML files listed earlier, and a "images"
directory.
Your style is free to use any number of images, but the image files used by the style must be placed directly in the images
subdirectory of your style, not in other locations, or nested within the images
directory.
Note: The QML files of the style should not be renamed, as other parts of Qt Quick Ultralite Virtual Keyboard use them as components. It is not possible to add any new QML files in a custom style.
To test your style, set the keyboard background to a different color to make it obvious that the right style is applied:
## In your style's KeyboardBackground.qml: Rectangle { color: "#FF0000" }
The final step is to run the example application with your custom style:
## Applies the "my_style" custom style to the VirtualKeyboard module qul_add_target(MyQulApp_CustomStyle QML_PROJECT MyApp.qmlproject SELECTORS "my_style" )
Scaling in custom style
If your style needs to support different screen sizes, care should be taken when picking the size of image assets. The Qt Quick Ultralite Virtual Keyboard module gets information about virtual keyboard screen size from the MCU.Config.Experimental.vkbScreenWidth set in the target platform's BoardDefaults.qmlproject
. The same file also contains custom SVG image scaling factors to apply to selected SVG images to support different screen sizes. This is used by the built-in styles. This scaling will also be applied to any images used in custom styles, so make sure any SVG images used in the custom style have the right size after scaling.
Font Unicode coverage configuration
This section covers how to approach font.unicodeCoverage configuration when using static font engine. The responsibilty of providing suffient coverage is primarily on an application developer side. For optimal ROM consumtion it is important to understand what font configurations are used by the selected keyboard style and how they are used. The following sections explain this in more detail.
A good indication that font unicode coverage is not sufficiently configured is if the application displays box glyphs. Other reason could be that the selected fonts do not have the requested unicode value.
See also MCU.Config.autoGenerateGlyphs.
EnterKeyAction.label
If you use EnterKeyAction.label in the application, this will set displayText
property in the EnterKey. If keyboard style has a binding on displayText as in the following code snippet:
// EnterKeyPanel.qml Text { id: enterKeyText text: control.displayText font: StyleFonts.enterKeyFont
Then you need to ensure that the application has sufficient unicodeCoverage for the font configuration equivalent to the one used by the style, in this case StyleFonts.enterKeyFont
. Otherwise the text in the EnterKey may render only box glyphs.
CharacterPreviewDelegate
The built-in styles use the same font configuration in the button (KeyPanelDelegate) and in the preview popup (CharacterPreviewDelegate). You could use, for example, 2px bigger text in the preview popup if that fits your design vision, but that implies bundling two sets of glyphs (one for each size). The default styles try to optimize font storage in ROM.
Chinese glyphs
The set of Chinese glyphs usually can be large. The Qt Quick Ultralite text_input Example utilizes equivalent font configuration for text input field and SelectionListDelegate (used for displaying word candidates in the virtual keyboard UI) to prevent bundling two sets of Chinese glyphs. This is a good example on how application developer can greatly optimize ROM, by being familiar with virtual keyboard style implementation.
// CustomTextField.qml readonly property font textFieldFont: Qt.font({ // static font engine optimization: // Using the same font configuration for text input field as used by the keyboard style // so we can avoid bundling 2 sets of Chinese glyphs (one for each font configuration). // See PinyinSupport.qml pixelSize: StyleConstants.wordSuggestionSize * StyleConstants.scaleHint, unicodeCoverage: [ "..." ] }) // PinyinSupport.qml readonly property font unicodeRegister: Qt.font({ pixelSize: StyleConstants.wordSuggestionSize * StyleConstants.scaleHint, unicodeCoverage: [ // Chinese characters "..."
Coverage from keyboard layouts
Each of the bundled layout files include its own font configuration, which sets the unicode coverage for this layout. Example from src/virtualkeyboard/layouts/cs/cs_main.qml
:
readonly property font registerCoverage: Qt.font({ "pixelSize": StyleConstants.keyboardKeySize * StyleConstants.scaleHint, "unicodeCoverage": ["!,.?abcdefghijklmnopqrstuvwxyzáäåéíóöúýćčďěńřšťůž"], "unicodeCoverageIncludeUpperCase": true })
This has several advantages:
- If some layout is removed, the glyphs for this layout won't be registered and bundled with the application.
- The application developer does not have to manually register glyphs that are displayed on keyboard buttons. The built-in styles for buttons use font configuration that is equivalent to
registerCoverage
font from the example. Custom layouts should follow the same pattern or adapt code accordingly.
If the text input field in the application uses different font configuration, for example, bigger pixel size than the one defined in registerCoverage
font, the developer can copy the coverage from layout files that are expected to be used for inputting text into this text field.
When adding or modifying layouts, the unicode coverage can be conveniently extracted from .fonts
files for the specific layout file. At the top of .fonts
file you will find characters
field. This field contains sorted unique characters that were found in all strings in the qml file by the qmltocpp
tool.
Example characters
from el_main.fonts
for el_main.qml
file:
"characters": "!,.?@abcdefghijklmnopqrstuvwxyzàáâãäåçèéêëìíîïòóôõöøùúûüýÿćċčďđĝğġģĩīĺļľŀłńņňœŕřśşšţťŧũūűŷżžΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ"
Note: The .fonts
file content is not a part of public API.
Note: The font registration is not present in the layout files for languages that are not supported by static font engine.
Virtual Keyboard API for applications
The QML types can be imported into your application using the following import statements in your .qml file:
Virtual Keyboard
QML types from import QtQuick.VirtualKeyboard
Provides attached properties for customizing the enter key | |
Provides the virtual keyboard UI |
Virtual Keyboard Settings
QML types from import QtQuick.VirtualKeyboard.Settings
Provides settings for virtual keyboard |
Virtual Keyboard API for advanced use cases
These QML types fall under the categories of virtual keyboard extension vendors, style providers, and keyboard layouts. They should not be used by application or middleware.
QML types from import QtQuick.VirtualKeyboard
Provides access to an input context | |
Maps the user input to the input methods |
And all types from:
import QtQuick.VirtualKeyboard.Components
import QtQuick.VirtualKeyboard.Styles
Reference
To view the list of all modules and components of Virtual Keyboard go to the module overview page.
Available under certain Qt licenses.
Find out more.