From cac61a50fd38b39c3e49580ca6b4088b7b26d011 Mon Sep 17 00:00:00 2001 From: Elden Park Date: Tue, 5 May 2026 20:32:42 -0700 Subject: [PATCH] feat(webkitgtk): make input method preedit configurable Add `WebViewBuilderExtUnix::with_input_method_preedit(bool)` so apps on Linux can opt in to inline IME preedit. Defaults to `false`, preserving the behavior introduced in 0.29.0 (tauri-apps/tauri#5986) where `set_enable_preedit(false)` was added unconditionally to work around fcitx popup positioning on older webkit2gtk. On modern webkit2gtk-4.1 (>= 2.50) inline preedit works correctly with the major Linux IMEs, and disabling it forces CJK users into a detached popup that doesn't match the IME UX of native GTK, Firefox, or Chromium-based apps. Enabling this lets webkit's GtkIMContext report `compositionstart` / `compositionupdate` / `compositionend` to the DOM so editable elements render the preedit string with its underline inline at the cursor. Verified manually on Ubuntu 24.04 (X11) + webkit2gtk-4.1 2.50.x with fcitx5-hangul (Korean) and fcitx5-anthy (Japanese): inline preedit renders, candidate selection commits cleanly, and repeated send-and-clear works without dropped composition. Link: https://github.com/tauri-apps/tauri/issues/11412 --- .changes/configurable-input-method-preedit.md | 5 ++++ src/lib.rs | 26 +++++++++++++++++++ src/webkitgtk/mod.rs | 17 +++++++++--- 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 .changes/configurable-input-method-preedit.md diff --git a/.changes/configurable-input-method-preedit.md b/.changes/configurable-input-method-preedit.md new file mode 100644 index 000000000..4954b7ad3 --- /dev/null +++ b/.changes/configurable-input-method-preedit.md @@ -0,0 +1,5 @@ +--- +"wry": minor +--- + +On Linux, add `WebViewBuilderExtUnix::with_input_method_preedit(bool)` to make the input method preedit configurable. Defaults to `false`, preserving the behavior introduced in wry 0.29.0 (see tauri-apps/tauri#5986). Apps targeting modern webkit2gtk (≥ 2.50) can opt in to inline preedit, which CJK IMEs use to render composition state inside editable elements. diff --git a/src/lib.rs b/src/lib.rs index bec4295ea..4ee7f9210 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1920,6 +1920,7 @@ impl WebViewBuilderExtAndroid for WebViewBuilder<'_> { pub(crate) struct PlatformSpecificWebViewAttributes { extension_path: Option, related_view: Option, + input_method_preedit: bool, } #[cfg(any( @@ -1950,6 +1951,26 @@ pub trait WebViewBuilderExtUnix<'a> { /// Creates a new webview sharing the same web process with the provided webview. /// Useful if you need to link a webview to another, for instance when using the [`WebViewBuilder::with_new_window_req_handler`]. fn with_related_view(self, webview: webkit2gtk::WebView) -> Self; + + /// Set whether the WebView's input method context should report + /// preedit text to the application during composition. + /// + /// When `true`, IME composition events (`compositionstart`, + /// `compositionupdate`, `compositionend`) fire in the DOM and + /// CJK input methods can render their preedit inline in editable + /// elements. When `false` (the default), preedit is suppressed + /// and the IM falls back to its own popup UI; this matches the + /// behavior introduced in wry 0.29.0 to mitigate + /// popup-positioning issues on older webkit2gtk versions (see + /// [tauri-apps/tauri#5986]). + /// + /// On modern webkit2gtk-4.1 (≥ 2.50) inline preedit works + /// correctly with major IMEs (fcitx5, ibus, etc.); apps targeting + /// those environments can opt in here to match the IME UX of + /// native GTK / Firefox / Chromium-based apps. + /// + /// [tauri-apps/tauri#5986]: https://github.com/tauri-apps/tauri/issues/5986 + fn with_input_method_preedit(self, enabled: bool) -> Self; } #[cfg(any( @@ -1979,6 +2000,11 @@ impl<'a> WebViewBuilderExtUnix<'a> for WebViewBuilder<'a> { self.platform_specific.related_view.replace(webview); self } + + fn with_input_method_preedit(mut self, enabled: bool) -> Self { + self.platform_specific.input_method_preedit = enabled; + self + } } /// The fundamental type to present a [`WebView`]. diff --git a/src/webkitgtk/mod.rs b/src/webkitgtk/mod.rs index 761e27229..acabe0edc 100644 --- a/src/webkitgtk/mod.rs +++ b/src/webkitgtk/mod.rs @@ -301,7 +301,7 @@ impl InnerWebView { } // Webview Settings - Self::set_webview_settings(&webview, &attributes); + Self::set_webview_settings(&webview, &attributes, &pl_attrs); // Webview handlers Self::attach_handlers(&webview, web_context, &mut attributes); @@ -411,10 +411,19 @@ impl InnerWebView { builder.build() } - fn set_webview_settings(webview: &WebView, attributes: &WebViewAttributes) { - // Disable input preedit,fcitx input editor can anchor at edit cursor position + fn set_webview_settings( + webview: &WebView, + attributes: &WebViewAttributes, + pl_attrs: &super::PlatformSpecificWebViewAttributes, + ) { + // Configure input method preedit per the platform-specific + // attribute. Default is `false` (disabled) — fcitx-style IMEs + // anchor their popup at the edit cursor (see + // tauri-apps/tauri#5986 for the original motivation). When + // `true`, WebKit reports composition events to the DOM and + // CJK IMEs render preedit inline. if let Some(input_context) = webview.input_method_context() { - input_context.set_enable_preedit(false); + input_context.set_enable_preedit(pl_attrs.input_method_preedit); } // use system scrollbars