Skip to content

Adding text_input_v3 and text_input_v2 in order to add IME support - #766

Open
myf wants to merge 1 commit into
trip-zip:mainfrom
myf:text-input-v3
Open

Adding text_input_v3 and text_input_v2 in order to add IME support#766
myf wants to merge 1 commit into
trip-zip:mainfrom
myf:text-input-v3

Conversation

@myf

@myf myf commented Sep 8, 2026

Copy link
Copy Markdown

to Chinese input methods (fctix5, ibus).

zwp_text_input_v3 for clients and zwp_input_method_v2 are implementd.

ref: #765

Changes
- input_method.c / input_method.h — the relay. Adapted from sway's sway/input/text_input.c (MIT), with three departures for somewm: a single global relay rather than per-seat; focus tracked via seat->keyboard_state.events.focus_change instead of patching the nine wlr_seat_keyboard_notify_enter call sites; and IME popups parented onto the existing client_t::popups / LayerSurface::popups trees, which avoids sway's scene_descriptor machinery.
- input.c — routes keys and modifiers to the input method's keyboard grab in keypress() / keypressmod(), after keybinding handling so compositor bindings still win. Records the originating virtual keyboard on KeyboardGroup so an IME's own injected keys aren't fed back to it.
- wlr_compat.h — 0.20 renamed the manager new_text_input / new_input_method signals; macros keep 0.19 building.
- somewm.c, somewm_types.h, meson.build — manager creation, relay init/finish, struct field, source entry.

AI disclosure: written with Claude Code. The relay module was AI-drafted against sway as a reference and reviewed/modified by me; a NULL-deref crash in the keyboard-grab destroy handler was diagnosed from coredumps and fixed.

Description

Test Plan

AI Usage

Checklist

  • Lua libraries (lua/awful/, lua/gears/, lua/wibox/, lua/naughty/) are not modified — if a bug surfaces in Lua, the fix belongs in C
  • Tests pass (make test-unit && make test-integration)

@JimmyCozza JimmyCozza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. There are some things I'm trying to make sure I understand and think about.

Could you also add some tests? Nothing in the suite speaks text-input-v3 or input-method-v2 yet, so this needs a small test client that can act as both a text input and a fake input method.

Comment thread input_method.c
}

static void
handle_focused_surface_unmap(struct wl_listener *listener, void *data)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The popup tree is a child of c->popups, which unmapnotify already destroys. Does this run after that and destroy it a second time?

Comment thread input_method.c
* from the input method instead; the input method itself may already be
* gone if the grab is being torn down as part of its destruction. */
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
im_relay.input_method ? im_relay.input_method->keyboard_grab : NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On wlroots 0.19 the IM destroy fires before the grab destroy, so this is NULL right when fcitx5 exits. Should the grab be stored at grab time instead?

Comment thread input_method.c
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;

wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
wlr_seat_get_keyboard(seat));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When fcitx5's virtual keyboard was the last one used, isn't this the IME's own keyboard? Why not the physical group?

Comment thread input_method.c
}

static void
relay_handle_new_text_input(struct wl_listener *listener, void *data)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the surface already has keyboard focus when this is created, what sends enter? Sway checks the focused surface here.

Comment thread input_method.c
popup_height = popup->popup_surface->surface->current.height;

/* Layout-space edges of the cursor rectangle */
x1 = parent_lx + cursor_area.x;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For XDG clients c->popups sits at the window-geometry origin, but cursor_rectangle is surface-local. Is this off by geometry.x/y for CSD clients?

Comment thread input_method.c
x = x1;
y = y2;

output = wlr_output_layout_output_at(output_layout, x1, y1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

popup_unconstrain in window.c uses the monitor workarea. Should this reuse it so the candidate window avoids the wibar?

Comment thread input.c

/* An input method holding the keyboard grab consumes what the compositor
* did not. Checked after keybindings so bindings still win over the IME. */
if ((kb_grab = input_method_get_keyboard_grab(group))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handled only latches on presses. Does a release for a consumed keybinding still reach the grab, and then come back through the vk?

Comment thread input.c

/* An input method holding the keyboard grab consumes what the compositor
* did not. Checked after keybindings so bindings still win over the IME. */
if ((kb_grab = input_method_get_keyboard_grab(group))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also
Should this be gated on locked like the keybinding branch above?

Comment thread input.c

/* Modifiers follow the keys: while an input method holds the grab they go
* to the IME rather than the focused client. */
if ((kb_grab = input_method_get_keyboard_grab(group))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same lock question as line 1229.

to Chinese input methods (fctix5, ibus).

`zwp_text_input_v3` for clients and `zwp_input_method_v2` are
implementd.

ref: trip-zip#765

Changes
    - input_method.c / input_method.h — the relay. Adapted from sway's sway/input/text_input.c (MIT), with three departures for somewm: a single global relay rather than per-seat; focus tracked via seat->keyboard_state.events.focus_change instead of patching the nine wlr_seat_keyboard_notify_enter call sites; and IME popups parented onto the existing client_t::popups / LayerSurface::popups trees, which avoids sway's scene_descriptor machinery.
    - input.c — routes keys and modifiers to the input method's keyboard grab in keypress() / keypressmod(), after keybinding handling so compositor bindings still win. Records the originating virtual keyboard on KeyboardGroup so an IME's own injected keys aren't fed back to it.
    - wlr_compat.h — 0.20 renamed the manager new_text_input / new_input_method signals; macros keep 0.19 building.
    - somewm.c, somewm_types.h, meson.build — manager creation, relay init/finish, struct field, source entry.

 AI disclosure: written with Claude Code. The relay module was AI-drafted against sway as a reference and reviewed/modified by me; a NULL-deref crash in the keyboard-grab destroy handler was diagnosed from coredumps and fixed.
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