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

24/7 email support $ 30

Download

Cim is distributed as source code.

Latest source code — public GitHub repository