Common input method
Cim stands for Common Input Method.
Input methods in Linux and BSD environments are currently fragmented. Applications and toolkits rely on different standards such as XIM, Gtk-IM, Qt-IM, and Wayland-IM, which makes integration complex and inconsistent.
Cim is designed to unify these disparate input method interfaces.
Instead of binding input methods to a specific GUI toolkit, Cim provides a toolkit-independent C API that applications and frameworks can use to access input methods in a consistent way.
Cim’s public interface is centered on the stable C ABI defined by cim.h.
The same input-method boundary can therefore be used by:
- GUI toolkits
- terminal applications
- console programs
- sandboxed applications
- software written in different programming languages
This makes Cim suitable as a common foundation for text input across diverse environments.
Architecture
Cim uses a plugin architecture.
Applications can use either form of the public Cim API library:
libcim.a
libcim.so
libcim.a is the position-independent static-pic form and may be embedded
in a shared module. libcim.so is the relocatable shared-library form.
Non-PIC static builds are unsupported.
Actual input method implementations are provided by plugin modules.
The following paths are examples of how plugins may be deployed. They do not mean that every listed plugin is implemented or distributed by the current public repository.
/usr/lib/input.d/im-sample.so
/usr/lib/input.d/im-nimf.so
/usr/lib/input.d/im-ibus.so
/usr/lib/input.d/im-uim.so
/usr/lib/input.d/im-fcitx.so
The current public tree includes im-libhangul.so as a native sample plugin.
Each plugin implements the Cim input context API defined in cim.h.
Plugins may be implemented in several ways:
-
Native engine plugins Implement a full IME engine directly.
-
Framework bridge plugins Connect Cim to existing input frameworks such as ibus or fcitx.
-
Service-backed plugins Communicate with a daemon or external service.
Regardless of the implementation strategy, all plugins expose a small descriptor called cim_plugin, which provides a CimIcVTable describing how input contexts are created and managed.
The current public ABI version is 2.1.1. A plugin records its Cim API
version in cim_plugin, and Cim rejects a plugin with an incompatible major
version. CimIcVTable.create and CimIcVTable.destroy are required.
Plugin init and fini callbacks are optional; when provided, each successful
host attachment initialization has one matching finalization.
Selecting the Active Plugin
The active plugin is selected using a symbolic link:
~/.config/cim/plugin
This link points to the desired plugin module.
Example:
mkdir -p ~/.config/cim
ln -sf /usr/lib/input.d/im-sample.so ~/.config/cim/plugin
For example, if an fcitx bridge plugin has been implemented and installed
at the following path, it could be selected like this. This is an example and
does not mean that the current public repository provides im-fcitx.so.
ln -sf /usr/lib/input.d/im-fcitx.so ~/.config/cim/plugin
This mechanism avoids relying on environment variables, which may not always be present depending on the application startup context. It also makes it easier to build graphical configuration tools.
For testing or controlled deployments, the CIM_PLUGIN environment variable
may temporarily override the symbolic link with an absolute plugin path.
Using Cim
Once configured, applications or GUI toolkits simply call the Cim API.
When the first CimIcHandle (input context) is created, the Cim runtime loads
the selected plugin, initializes a host attachment, and delegates input-method
operations to that plugin.
Multiple input contexts may be created within one attachment. After the last context is destroyed, Cim finalizes that attachment and unloads the plugin.
This design keeps the runtime lightweight while allowing flexible plugin implementations.
Integration with Existing Toolkits
Even if display servers or GUI toolkits do not adopt Cim directly, integration is still possible using bridge modules.
The following are examples of environment variables used by toolkit or input-system integration. The current public tree implements GTK 3 and Qt 6 bridges. The XIM setting illustrates a possible future or external integration.
QT_IM_MODULE="cim"
GTK_IM_MODULE="cim"
XMODIFIERS="@im=cim"
The following are example installation paths for bridge modules. The current public tree implements GTK 3 and Qt 6 bridges. The GTK 2, GTK 4, and Qt 5 paths illustrate possible extensions and do not imply current implementations.
/usr/local/lib/gtk-4.0/4.0.0/immodules/libim-cim-gtk4.so
/usr/local/lib/gtk-2.0/2.10.0/immodules/im-cim-gtk2.so
/usr/local/lib/gtk-3.0/3.0.0/immodules/im-cim-gtk3.so
/usr/local/lib/qt5/plugins/platforminputcontexts/libqt5im-cim.so
/usr/local/lib/qt6/plugins/platforminputcontexts/libqt6im-cim.so
These bridges allow existing applications to use Cim without modifying the application itself.
In the default static-pic configuration, the current GTK 3 and Qt 6 bridge
modules embed libcim.a while keeping the embedded Cim runtime symbols private
from the surrounding process.
Daemon-based Input Systems
Some input systems such as XIM or Wayland input methods require inter-process communication.
For these environments, Cim can use a daemon-style architecture. The cimd
binary and daemon plugin paths below are architectural examples and are not
implemented in the current public tree.
/usr/local/bin/cimd
Example daemon plugins:
/usr/local/lib/cimd/plugins/cim-xim.so
/usr/local/lib/cimd/plugins/cim-wayland.so
If implemented, these components would translate XIM or Wayland input events into the Cim API.
Benefits for Input Method Developers
Cim significantly reduces the integration burden for IME developers.
Traditionally, input methods must implement separate modules for:
- Gtk-IM
- Qt-IM
- XIM
- Wayland-IM
With Cim, the Cim input context API can serve as a common boundary reused by environment-specific integration layers. The current public tree implements GTK 3 and Qt 6 bridges; GTK 2, GTK 4, Qt 5, XIM, and Wayland integrations are not all implemented in the current public tree.
Another important advantage is low-friction integration.
Many existing IME libraries (such as libhangul, librime, libanthy, or libpinyin) already provide core input context logic.
In such cases, a Cim plugin can often be implemented with only a small adaptation layer that exposes the existing functionality through CimIcVTable.
If upstream projects choose not to include Cim support directly, a standalone bridge plugin can still be implemented externally with relatively little code.
This flexibility allows Cim to integrate with existing input ecosystems without requiring large architectural changes.
Summary
Cim provides:
- a toolkit-independent input method API
- a simple plugin architecture
- a versioned, stable C ABI
- low integration cost for existing IME implementations
- an architecture for compatibility with existing input frameworks through
bridge modules
- GTK 3 and Qt 6 bridges are implemented in the current public tree.
- Other bridge and daemon-based integrations are not all implemented yet.
By separating the input method API from GUI toolkits and display servers, Cim enables a more consistent and portable text input environment across Linux and BSD systems.
Technical Support for Cim / 1 year
Download
Cim is distributed as source code.