Summary
On the GTK backend, a TextBox/TextArea/PasswordBox silently drops the initial keystrokes the first time it is focused if a KeyDown (or KeyUp/TextInput? haven't tested those) handler is attached to it. The KeyDown event still fires for those keys, but no text is inserted and TextChanged does not fire. A text control with no key handler is unaffected.
Input sometimes starts working after focusing away and back, but this recovery is inconsistent.
Environment
- OS: Linux (X11)
- Backend:
Eto.Platform.Gtk (GTK3)
- GtkSharp: 3.24.24.95
- Runtime: .NET 10
- Input method: ibus active (
GTK_IM_MODULE=ibus, XMODIFIERS=@im=ibus)
Steps to reproduce
In the test gallery add one line to LogEvents in test/Eto.Test/Sections/Controls/TextAreaSection.cs, then run Controls → TextArea and type on first focus:
control.KeyDown += (sender, e) => Log.Write(control, "KeyDown: {0}", e.Key);
Expected
Typing into the focused control inserts the characters, regardless of whether a KeyDown handler is attached.
Actual
On first focus the initial keystroke(s) are silently dropped — KeyDown fires but nothing is inserted and TextChanged does not fire. Removing the key handler makes typing work normally, which isolates the trigger.
Confirmed affected: TextBox (Gtk.Entry) and TextArea (Gtk.TextView); should apply to anything routed through GtkControl (e.g. PasswordBox).
Root cause
The shared IM context in src/Eto.Gtk/Forms/GtkControl.cs was changed from Gtk.IMContextSimple to Gtk.IMMulticontext (in the change that added the Drawable TextComposition/TextInsertionBoundsRequested APIs):
context = new Gtk.IMMulticontext();
HandleKeyPressEvent runs that IM context's FilterKeypress for every control that has a key handler attached (the [GLib.ConnectBefore] handler is wired up whenever KeyDownEvent/TextInputEvent is attached):
if (e == null || !e.Handled)
{
commitHandled = false;
UpdateDrawableInputMethodLocation(handler);
if (Context.FilterKeypress(args.Event)) // runs for native Entry/TextView too
args.RetVal = commitHandled;
}
For a native Gtk.Entry/Gtk.TextView, this means two IM contexts process the same key events: Eto's IMMulticontext (which delegates to the system IME, ibus here) and the widget's own built-in one. With the old IMContextSimple this was harmless — it returns false from FilterKeypress for ordinary characters, so the native widget handled them. IMMulticontext instead consumes them via the system IME and commits them through Eto's Commit handler (which only raises TextInput — it does not insert into the native widget), so the native widget never receives the input.
It manifests on first focus because the IM context is only focus-managed (FocusIn/FocusOut) when shouldFocusInputContext is true — i.e. when TextInput is handled or it's a Drawable composition — yet FilterKeypress is called regardless. So for a plain native text control the context filters keys while never being properly focused.
Suggested fix
Gate the IM-context key filtering on the same condition that already gates its focus management, so Eto's IM context is only engaged for controls that actually consume it (custom TextInput handlers or Drawable composition). Native text widgets then fall through to their own IM, as before the regression:
bool ShouldUseInputContext(GtkControl<TControl, TWidget, TCallback> handler)
=> handler.IsEventHandled(Eto.Forms.Control.TextInputEvent) || HandlesDrawableComposition(handler);
// HandleKeyPressEvent
if ((e == null || !e.Handled) && ShouldUseInputContext(handler))
{
commitHandled = false;
UpdateDrawableInputMethodLocation(handler);
if (Context.FilterKeypress(args.Event))
args.RetVal = commitHandled;
}
(and use the same ShouldUseInputContext for the existing shouldFocusInputContext check in FocusInEvent). This keeps the new Drawable composition feature intact while restoring first-focus input on native text controls.
Summary
On the GTK backend, a
TextBox/TextArea/PasswordBoxsilently drops the initial keystrokes the first time it is focused if aKeyDown(orKeyUp/TextInput? haven't tested those) handler is attached to it. TheKeyDownevent still fires for those keys, but no text is inserted andTextChangeddoes not fire. A text control with no key handler is unaffected.Input sometimes starts working after focusing away and back, but this recovery is inconsistent.
Environment
Eto.Platform.Gtk(GTK3)GTK_IM_MODULE=ibus,XMODIFIERS=@im=ibus)Steps to reproduce
In the test gallery add one line to
LogEventsintest/Eto.Test/Sections/Controls/TextAreaSection.cs, then run Controls → TextArea and type on first focus:Expected
Typing into the focused control inserts the characters, regardless of whether a
KeyDownhandler is attached.Actual
On first focus the initial keystroke(s) are silently dropped —
KeyDownfires but nothing is inserted andTextChangeddoes not fire. Removing the key handler makes typing work normally, which isolates the trigger.Confirmed affected:
TextBox(Gtk.Entry) andTextArea(Gtk.TextView); should apply to anything routed throughGtkControl(e.g.PasswordBox).Root cause
The shared IM context in
src/Eto.Gtk/Forms/GtkControl.cswas changed fromGtk.IMContextSimpletoGtk.IMMulticontext(in the change that added the DrawableTextComposition/TextInsertionBoundsRequestedAPIs):HandleKeyPressEventruns that IM context'sFilterKeypressfor every control that has a key handler attached (the[GLib.ConnectBefore]handler is wired up wheneverKeyDownEvent/TextInputEventis attached):For a native
Gtk.Entry/Gtk.TextView, this means two IM contexts process the same key events: Eto'sIMMulticontext(which delegates to the system IME, ibus here) and the widget's own built-in one. With the oldIMContextSimplethis was harmless — it returnsfalsefromFilterKeypressfor ordinary characters, so the native widget handled them.IMMulticontextinstead consumes them via the system IME and commits them through Eto'sCommithandler (which only raisesTextInput— it does not insert into the native widget), so the native widget never receives the input.It manifests on first focus because the IM context is only focus-managed (
FocusIn/FocusOut) whenshouldFocusInputContextis true — i.e. whenTextInputis handled or it's a Drawable composition — yetFilterKeypressis called regardless. So for a plain native text control the context filters keys while never being properly focused.Suggested fix
Gate the IM-context key filtering on the same condition that already gates its focus management, so Eto's IM context is only engaged for controls that actually consume it (custom
TextInputhandlers or Drawable composition). Native text widgets then fall through to their own IM, as before the regression:(and use the same
ShouldUseInputContextfor the existingshouldFocusInputContextcheck inFocusInEvent). This keeps the new Drawable composition feature intact while restoring first-focus input on native text controls.