Skip to content

Commit 2f9cd56

Browse files
committed
docs(linux): add documentation how input methods work in GTK
Build-bot: skip Test-bot: skip
1 parent 103de2b commit 2f9cd56

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Input Methods in GTK
2+
3+
This document describes how Keyman is connected to a client app, in other words
4+
how a keypress in the app ends up being processed by the Keyman engine.
5+
6+
For text input, GTK (or rather the app) will add input method support to a widget.
7+
How the input method gets loaded depends on the GTK version.
8+
9+
IBus provides input modules for GTK 2, GTK 3, GTK 4, X11, and Wayland.
10+
However, the Wayland one is not used with Gnome because GTK provides
11+
its own implementation.
12+
13+
Which input modules are available depends on the GTK version. Apps that
14+
don't use the Gnome/GTK framework use different ways for input method
15+
support.
16+
17+
## GTK 4
18+
19+
```mermaid
20+
flowchart LR
21+
subgraph GTK
22+
app(application)
23+
im-module["im-module
24+
(IBusIMContext)"]
25+
app --- im-module
26+
end
27+
28+
subgraph ibus[ibus-daemon]
29+
direction LR
30+
IBusInputContext <--> IBusEngine
31+
end
32+
33+
subgraph keyman
34+
ibus-engine-keyman
35+
end
36+
37+
GTK <--> ibus <--> keyman
38+
39+
style app color:#FFFFFF, stroke:#00C853, fill:#00C853
40+
```
41+
42+
The im-module implements a [GIOExtensionPoint](https://docs.gtk.org/gio/struct.IOExtensionPoint.html)
43+
"gtk-im-module". The type extends `GtkIMContext`.
44+
When loading the app, GTK dynamically loads and starts the extension
45+
specified by the environment variable `GTK_IM_MODULE` (or the default which is
46+
probably the one with the highest priority).
47+
48+
External modules are located in `/usr/lib/x86_64-linux-gnu/gtk-4.0/4.0.0/immodules`
49+
and named `lib*.so`.
50+
51+
Each module has a priority, a name and the type that implements it.
52+
53+
GTK4 has built-in support for Wayland (`GtkIMContextWayland`), Broadway
54+
(`GtkIMContextBroadway`, irrelevant for Keyman) and gtk-im-context-simple
55+
(`GtkIMContextSimple`, irrelevant for Keyman). `GtkIMContextWayland` is
56+
implemented as part of GTK 4, the source code can be found in
57+
<https://github.com/GNOME/gtk/blob/main/gtk/gtkimcontextwayland.c>.
58+
59+
The input method for ibus is implemented as an external module
60+
(type `IBusIMContext`). Source code is in
61+
<https://github.com/ibus/ibus/tree/main/client/gtk4>.
62+
63+
The IBus communication between `IBusIMContext`, ibus-daemon and the ibus
64+
engine (aka Keyman) happens with DBus messages on a separate IBus DBus
65+
instance.
66+
67+
## GTK 2/GTK 3
68+
69+
With older GTK versions basically the same components are involved,
70+
although a different mechanism to discover and load the
71+
im-modules is used.
72+
73+
GTK caches the available modules in a module database located in
74+
`/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache` or whereever
75+
the `GTK_IM_MODULE_FILE` environment variable points. This database is
76+
read, or if necessary initialized, on application startup.
77+
78+
For each module the database contains an id, the name, the path, i18n domain(?)
79+
and default locales.
80+
81+
GTK then determines what input module to load based on the `GTK_IM_MODULE`
82+
environment variable (which can contain more than one module separated by
83+
colons) or the `XSETTINGS` `gtk-im-module` property. It then checks that
84+
the currently running display type is compatible with the module, and that
85+
the current locale matches the locales supported by the module. An exact match
86+
(`en_US` vs `en_US`) gets 4 points, a match of the language (`en_US` vs `en`)
87+
gets 3 points, a match with a different region (`en_US` vs `en_UK`) 2 points,
88+
and a wildcard (`en_US` vs `*`) 1 point.
89+
90+
Each input module implements a subclass of `GTKIMContext` plus the 4 required
91+
entry points:
92+
93+
- `im_module_init()` - Initialize module
94+
- `im_module_list()` - Describe available contexts
95+
- `im_module_create()` - Create context instance
96+
- `im_module_exit()` - Cleanup on unload
97+
98+
GTK uses `GModule` to dynamically load the module's `.so` file and then calls
99+
`im_module_init()` on the module, followed by `im_module_create()` to instantiate
100+
the actual `GtkIMContext` subclass.
101+
102+
If no module matches or loading fails, GTK falls back to `GtkIMContextSimple`.
103+
104+
GTK3 provides support for several input methods, more than with GTK4. Those
105+
can be found in <https://github.com/GNOME/gtk/tree/gtk-3-24/modules/input>.
106+
Among the built-in modules are `im-wayland` (for Wayland), `im-xim` (for X11),
107+
`im-thai` (for Thai), and `im-ime` (for Windows).
108+
109+
The input method for ibus is implemented as an external module
110+
(type `IBusIMContext`). Source code is in
111+
<https://github.com/ibus/ibus/tree/main/client/gtk3>.
112+
113+
All modules are located in `/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules`
114+
and named `*.so`, e.g. `im-ibus.so`.
115+
116+
## Tips
117+
118+
- GTK has a built-in
119+
[inspection/debugging tool](https://developer.gnome.org/documentation/tools/inspector.html)
120+
which can be opened with <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd>, or
121+
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd>, or by setting the
122+
environment variable `GTK_DEBUG=interactive`.
123+
- Available GTK3 IM modules can be listed with
124+
`/usr/lib/x86_64-linux-gnu/libgtk-3-0t64/gtk-query-immodules-3.0` or by
125+
looking at `/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache`.
126+
127+
## Links
128+
129+
- [GTK4 Input Handling](https://docs.gtk.org/gtk4/input-handling.html)

0 commit comments

Comments
 (0)