From f781e131662f8f9320429999656e6f391b532409 Mon Sep 17 00:00:00 2001 From: Aaron Muir Hamilton Date: Wed, 13 Nov 2024 07:13:09 -0500 Subject: [PATCH] X11: Use bottom-right corner of IME cursor area as caret position XIM servers currently do not support preedit area reporting from clients and there may be no standard way to report it. Fcitx and iBus both place the candidate window descending descending from the caret, with the reported X font; but since winit does not report a font, the height of the line is assumed 0, so when we report the top left corner of the cursor area they will tend to obscure it. Taking this into account, the best default option is to report the bottom right corner of the cursor area, because it will tend not to obscure the preedit area when using `Window::set_ime_cursor_area` in the way suggested by documentation. --- src/changelog/unreleased.md | 1 + src/platform_impl/linux/x11/window.rs | 15 +++++++++++---- src/window.rs | 3 ++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 5bf152f5..2b04d1a6 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -157,6 +157,7 @@ changelog entry. identify a finger in a multi-touch interaction. Replaces the old `Touch::id`. - In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`. - Remove `Force::Calibrated::altitude_angle`. + - On X11, use bottom-right corner for IME hotspot in `Window::set_ime_cursor_area`. ### Removed diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index c4d35bce..1866bf8d 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -2031,12 +2031,19 @@ impl UnownedWindow { } #[inline] - pub fn set_ime_cursor_area(&self, spot: Position, _size: Size) { - let (x, y) = spot.to_physical::(self.scale_factor()).into(); + pub fn set_ime_cursor_area(&self, spot: Position, size: Size) { + let PhysicalPosition { x, y } = spot.to_physical::(self.scale_factor()); + let PhysicalSize { width, height } = size.to_physical::(self.scale_factor()); + // We only currently support reporting a caret position via XIM. + // No IM servers currently process preedit area information from XIM clients + // and it is unclear this is even part of the standard protocol. + // Fcitx and iBus both assume that the position reported is at the insertion + // caret, and by default will place the candidate window under and to the + // right of the reported point. let _ = self.ime_sender.lock().unwrap().send(ImeRequest::Position( self.xwindow as ffi::Window, - x, - y, + x.saturating_add(width), + y.saturating_add(height), )); } diff --git a/src/window.rs b/src/window.rs index f6070188..22af8cbc 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1005,7 +1005,8 @@ pub trait Window: AsAny + Send + Sync { /// /// ## Platform-specific /// - /// - **X11:** - area is not supported, only position. + /// - **X11:** Area is not supported, only position. The bottom-right corner of the provided + /// area is reported as the position. /// - **iOS / Android / Web / Orbital:** Unsupported. /// /// [chinese]: https://support.apple.com/guide/chinese-input-method/use-the-candidate-window-cim12992/104/mac/12.0