Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions src/window/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@ impl WindowHandle {
ImeRequest::Disable
};

self.window.request_ime_update(ime).unwrap();
self.request_ime(ime);
}
}
UpdateMessage::SetImeCursorArea { position, size } => {
Expand All @@ -1286,11 +1286,9 @@ impl WindowHandle {
size.width * self.window_state.user_scale,
size.height * self.window_state.user_scale,
));
self.window
.request_ime_update(ImeRequest::Update(
ImeRequestData::default().with_cursor_area(position, size),
))
.unwrap();
self.request_ime(ImeRequest::Update(
ImeRequestData::default().with_cursor_area(position, size),
));
}
}
UpdateMessage::Inspect => {
Expand Down Expand Up @@ -1421,6 +1419,17 @@ impl WindowHandle {
})
}

/// Ask the window to enable, disable or move the IME.
///
/// A window that cannot provide an IME, such as the headless mock or a
/// platform without one, refuses the request. That is not fatal: the
/// view that asked still works, it just gets no composition input, so
/// the refusal is dropped rather than unwrapped. Before this, focusing
/// any text input under the headless harness panicked.
fn request_ime(&self, request: ImeRequest) {
let _ = self.window.request_ime_update(request);
}

fn set_cursor(&mut self) {
if self.window_state.needs_cursor_resolution {
let mut temp = None;
Expand Down
35 changes: 35 additions & 0 deletions tests/headless_ime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use floem::HasViewId;
use floem::headless::{HeadlessHarness, TestRoot};
use floem::reactive::{RwSignal, SignalGet};
use floem::views::{Decorators, TextInput};

/// Focusing a text input asks the window to enable the IME, and the
/// headless mock window cannot. That refusal used to be unwrapped, so any
/// test that clicked into a text input panicked; now the input takes focus
/// and the request is simply dropped.
#[test]
fn clicking_into_a_text_input_headlessly_does_not_panic() {
let root = TestRoot::new();
let value = RwSignal::new(String::from("hello"));
let input = TextInput::new(value).style(|s| s.size(200.0, 30.0));
let input_id = input.view_id();
let mut harness = HeadlessHarness::new_with_size(root, input, 400.0, 200.0);
harness.rebuild();
harness.paint();

// Down, then up: focus follows the press, and the FocusGained that
// reaches the input asks for IME.
harness.click(50.0, 15.0);
harness.rebuild();
harness.paint();

assert!(harness.is_focused(input_id), "the input took focus");
assert_eq!(value.get(), "hello", "and its text is untouched");

// Losing focus asks for the IME to be disabled, which is refused too.
harness.dispatch_event(floem::event::Event::Window(
floem::event::WindowEvent::FocusLost,
));
harness.rebuild();
harness.paint();
}