Skip to content

Experimental IBus support for X11 backend built on top of the IME API#10

Draft
ashie wants to merge 6 commits into
im-supportfrom
im-support-ibus
Draft

Experimental IBus support for X11 backend built on top of the IME API#10
ashie wants to merge 6 commits into
im-supportfrom
im-support-ibus

Conversation

@ashie

@ashie ashie commented Jun 20, 2026

Copy link
Copy Markdown
Member

This PR is an experiment built on top of the IME API introduced by PR #2130: Add IME support for each platform.

One motivation for this work is that the traditional X11 XIM protocol is relatively limited compared to modern IME frameworks and can make it difficult to provide functionality comparable to IME implementations available on other platforms.

While XIM remains useful as a baseline solution, as GLFW's IME support evolves, it may be desirable to investigate alternatives that can expose richer IME functionality on X11.

The goal of this experiment is therefore not to propose IBus support for GLFW itself, but to evaluate whether the abstractions introduced by PR glfw#2130 are flexible enough to support an alternative X11 IME backend without modifying the GLFW event loop.

The prototype uses:

  • a dynamically loaded IME module
  • a dedicated D-Bus worker thread
  • IBus input contexts

and currently supports:

  • preedit
  • commit
  • candidate window positioning

on X11.

This implementation should be viewed as a research prototype rather than an upstream proposal.

See docs/ime-ibus-prototype.md for architecture details, design rationale, limitations and future work.

Additional prerequisites

  • Dev package of DBus
  • IBus or Fcitx5 via its IBus compatibility frontend (untested)

Build:

$ cmake -B build
$ cmake --build build --target glfw glfw-ibus

Run demo:

$ GLFW_IM_MODULE=$PWD/build/src/glfw-ibus.so ./build/tests/input_text

@ashie ashie changed the title Im support ibus Experimental IBus support for X11 backend built on top of the IME API Jun 20, 2026
@ashie ashie force-pushed the im-support-ibus branch from c1d8b43 to fcb9c12 Compare June 20, 2026 08:00
@ashie ashie force-pushed the im-support-ibus branch from fcb9c12 to 536fbb4 Compare June 24, 2026 08:11
@ashie

ashie commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

New experimental build switches

I've added two more optional build switches for experiments with applications that already use GLFW with glfw#2130.

These options are not intended as an upstream API proposal. They are provided to make it easier to evaluate the IBus backend with existing applications and prebuilt GLFW binaries.

GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS

When this CMake option is enabled, glfwSetInputMode(window, GLFW_IME, value) is routed through GLFW's text input focus path (glfwSetTextInputFocus() API propsed at glfw#2130 (comment)) instead of the native platform IME open/close state.

This is useful for applications that already toggle GLFW_IME, but really want to express whether text input should currently be focused. The runtime environment variable GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS can also be used to enable or disable this behavior without rebuilding GLFW.

Update (2026-07-14): Something wrong, it doesn't work as expected yet.
Update (2026-07-14): Fixed. Please see #10 (comment)
Update (2026-07-16): Renamed to GLFW_INFER_TEXT_INPUT_FOCUS. Please see #10 (comment)

GLFW_EMBED_IBUS_MODULE

When this CMake option is enabled, the IBus backend is built into the X11 GLFW library instead of requiring glfw-ibus.so to be loaded with GLFW_IM_MODULE.
This removes the need to ask end users to set GLFW_IM_MODULE when testing a prebuilt GLFW build with IBus support. If GLFW_IM_MODULE is still set, the external module takes precedence over the embedded backend.


Example build:

$ cmake -B build \
    -D GLFW_EMBED_IBUS_MODULE=ON \
    -D BUILD_SHARED_LIBS=ON
$ cmake --build build --target glfw

With these options enabled, applications can test the IBus path without setting GLFW_IM_MODULE:

$ ./build/tests/input_text

@ashie ashie force-pushed the im-support-ibus branch 4 times, most recently from 4acec7d to 7d530be Compare July 13, 2026 13:43
@ashie

ashie commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

I've also import soft fullscreen patch in im-support-fullscreen branch described in glfw#2130 (comment) to work with Minecraft. Without this patch, Minecraft causes an exception.

GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS

When I enable this option, I can't use IM on both X11 and Wayland.
It seems that something wrong, I'll investigate it later.

On the other hand, when I use this branch without GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS, I can confirm that IBus works fine with Minecraft. IME's preedit string embedded in the game window is now available also on X11.

$ cmake -B build \
    -D GLFW_EMBED_IBUS_MODULE=ON \
    -D BUILD_SHARED_LIBS=ON
$ cmake --build build --target glfw

Then install it as described in Mincraft Wiki

@ashie ashie force-pushed the im-support-ibus branch 3 times, most recently from 3ad5ce3 to f266d4a Compare July 14, 2026 13:46
@ashie

ashie commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

To prove the text-input-focus concept described in glfw#2130 (comment) and implemented in #11, I've added a mode to implicitly use this feature. It intends to work with Minecraft as a representative application. To work well with it, some required features have also been added in this branch. These features are intentionally excluded from glfw#2130 because each of them is separate issues from the addition of the basic IME API (Please see Related issues in glfw#2130 (comment) for more detail).

You can enable it by a build flag GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS=ON.

e.g. for GNU/Linux)

$ cmake -B build \
    -D GLFW_EMBED_IBUS_MODULE=ON \
    -D GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS=ON \
    -D BUILD_SHARED_LIBS=ON
$ cmake --build build --target glfw

e.g. for macOS)

$ cmake -B build \
    -D GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS=ON \
    -D BUILD_SHARED_LIBS=ON
$ cmake --build build --target glfw

Windows isn't confirmed yet.

Then add -Dorg.lwjgl.glfw.libname=/path/to/libglfw to your JVM option when launching Minecraft.

ashie added 4 commits July 15, 2026 08:44
Add a private X11 IME module ABI and an experimental glfw-ibus.so
backend for feasibility testing.  The module owns D-Bus communication,
IBus input contexts and its worker thread, while GLFW drains queued IME
events on the main thread without modifying the event loop architecture.

The prototype handles ProcessKeyEvent, CommitText, UpdatePreeditText,
focus changes, reset, IME status signals and cursor location updates.
Key events are passed to IBus with the keysym translated from the X key
event so printable shifted keys such as Shift+1 reach IBus as the
expected key value.

IBus preedit text, caret position and attribute ranges are mapped onto
GLFW preedit text, block sizes, focused block and caret index.  Candidate
window placement uses SetCursorLocation with X11 root-window coordinates,
including the startup/focus ordering workaround for the first candidate
window.

This is a research prototype, not an upstream-ready feature.  It keeps
GLFW_IME_DEBUG instrumentation and documentation for measuring latency,
timeouts and late IBus replies or text signals.
Keep XFilterEvent as the suppressor for the XIM path, but do not
call it before the experimental IME module sees KeyPress events.

When the module reports a key as handled, return before normal GLFW
key and character processing. This gives the IME module path the same
kind of duplicate-input suppression that XFilterEvent provides for the
XIM path, while keeping the XIM behavior unchanged.

This effectively extends the duplicate-input suppression addressed by
PR glfw#1972 to the experimental IME module path.
Map glfwSetTextInputFocus to the experimental X11 IME module path.

When text input focus is enabled for a focused X11 window, send FocusIn to
the module so IBus resumes routing text input. When it is disabled, reset
composition and send FocusOut, keeping GLFW window focus separate from the
text input focus abstraction.

Also gate the module KeyPress path on GLFW's text input focus state so
FocusOut actually stops routing input through IBus. Applications that never
opt into explicit text input focus keep the legacy behavior.

Document the prototype mapping without adding a new module ABI entry.
Document the current state of the experimental X11 IBus module after
adding text input focus gating and richer preedit handling.

The prototype now maps IBus caret and attribute ranges to GLFW preedit
state, gates ProcessKeyEvent on explicit text input focus, and is close to
usable for application testing while still remaining experimental.
@ashie ashie force-pushed the im-support-ibus branch from f266d4a to ea91cb0 Compare July 14, 2026 23:46
ashie and others added 2 commits July 16, 2026 08:32
Add two switches for game/application compatibility testing.

GLFW_INFER_TEXT_INPUT_FOCUS infers text input focus from legacy IME and cursor input state, and also acts as the runtime override environment variable.  This lets applications that already toggle GLFW_IME or cursor mode use the more portable text-input-focus semantics without code changes.

In this mode, cursor mode changes are treated as text input focus hints.  GLFW keeps the application-requested text input focus state separate from the effective platform focus, so cursor-disabled gameplay can suppress text input while cursor-normal text entry can re-enable it.  This also helps applications that switch between gameplay and text entry with cursor mode only.

glfwGetInputMode(GLFW_IME) keeps reporting the native IME status until the inference path initializes text input focus state for the window.  After that it returns the application-requested text input focus state, preserving the old query behavior for applications that never use the compatibility mode.

GLFW_EMBED_IBUS_MODULE builds the IBus backend into the X11 GLFW library.  The embedded backend is used when GLFW_IM_MODULE is not set, while GLFW_IM_MODULE can still override it with an external module.
Add a new window hint: `GLFW_SOFT_FULLSCREEN`.
This is especially necessary for the IME(Input Method Editor/Engine) to display
properly on the fullscreen window.

**Win32**

By default, the fullscreen window is a strong exclusive exceeding HWND_TOPMOST
and it doen't display OS notifications such as the sound volumn changed.
This hint enables to display other views poping up on the fullscreen window.
This can also effect transparency to fullscreen.

**macOS**

By default, the fullscreen window is exclusive.
This hint uses macOS's default fullscreen (the behavior of the green button
on the window's header).

We don't need `monitor` in this mode, so it is not used.
Specifying `monitor` in `glfwCreateWindow` makes window fullscreened,
but the value is not used inside.
The args of `glfwSetWindowMonitor` are not used except for `window` and
the function just toggles the fullscreened state.

These specifications have been made so that we can use this mode as
similar to the normal default mode as possible.

**X11**

This hint manages XProperty: `NET_WM_BYPASS_COMPOSITOR`.
By default, the compositing of the window is disabled to improve rendering performance.
However, this can cause problems with other views poping up on the window, such as IME.
This hint enables the compositing and the views poping up on the fullscreen to be
displayed correctly.
@ashie ashie force-pushed the im-support-ibus branch from ea91cb0 to 4b3d29c Compare July 15, 2026 23:39
@ashie

ashie commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

You can enable it by a build flag GLFW_IME_MODE_AS_TEXT_INPUT_FOCUS=ON.

I've renamed it to GLFW_INFER_TEXT_INPUT_FOCUS to reflect the current implementation.

e.g. for GNU/Linux)

$ cmake -B build \
    -D GLFW_EMBED_IBUS_MODULE=ON \
    -D GLFW_INFER_TEXT_INPUT_FOCUS=ON \
    -D BUILD_SHARED_LIBS=ON
$ cmake --build build --target glfw

e.g. for macOS)

$ cmake -B build \
    -D GLFW_INFER_TEXT_INPUT_FOCUS=ON \
    -D BUILD_SHARED_LIBS=ON
$ cmake --build build --target glfw

Windows isn't confirmed yet.

Please add -Dorg.lwjgl.glfw.libname=/path/to/libglfw to your JVM option when launching Minecraft.
You don't need any additional environment variables on launching it, they are built-in by default by above build options.

Note that this mode makes GLFW infer the text-input-focus state that should ideally be managed explicitly by the application. Because of that, the inference may fail for some transitions, such as the first time Minecraft enters chat or command input, and the IME may not be enabled for that initial attempt.

In my testing, subsequent text input attempts work as expected.

@ashie

ashie commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

From glfw#2130 (comment)

Unfortunately, it never worked on my system. Pressing the Hankaku/Zenkaku key doesn't activate the IME. I thought it might not be compatible with Fcitx5, so I did a clean install of Ubuntu 26.04 to test it, but it still didn't work.

Thanks, I've also confirmed that it doesn't work on Ubuntu 26.04 (using IBus).
Something seems wrong with newer IBus, need more work for it...
In addition to this, Ubuntu doesn't seem provide ibusfrontend module of Fcitx5.

My current environment is Ubuntu 24.04, this branch works well on it.
In addition, now I've confirmed that ibusfrontend of Fcitx5 built by myself also works with it (even on Ubuntu 26.04). So IBus support of this branch doesn't seem so wrong.

I'll investigate the issue later...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants