diff --git a/src/event.rs b/src/event.rs index 4566c5a7f2..ce6791deaa 100644 --- a/src/event.rs +++ b/src/event.rs @@ -271,7 +271,7 @@ pub enum WindowEvent<'a> { ModifiersChanged(ModifiersState), /// An event from IME - Composition(CompositionEvent), + IME(IME), /// The cursor has moved on the window. CursorMoved { @@ -379,7 +379,7 @@ impl Clone for WindowEvent<'static> { input: *input, is_synthetic: *is_synthetic, }, - Composition(composition) => Composition(composition.clone()), + IME(preedit_state) => IME(preedit_state.clone()), ModifiersChanged(modifiers) => ModifiersChanged(modifiers.clone()), #[allow(deprecated)] CursorMoved { @@ -471,7 +471,7 @@ impl<'a> WindowEvent<'a> { is_synthetic, }), ModifiersChanged(modifiers) => Some(ModifiersChanged(modifiers)), - Composition(event) => Some(Composition(event)), + IME(event) => Some(IME(event)), #[allow(deprecated)] CursorMoved { device_id, @@ -627,12 +627,26 @@ pub struct KeyboardInput { pub modifiers: ModifiersState, } +/// Describes an event from input method. #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum CompositionEvent { - CompositionStart(String), - CompositionUpdate(String, usize), - CompositionEnd(String), +pub enum IME { + /// Notifies when the IME was enabled. + Enabled, + + /// Notifies when a new composing text should be set at the cursor position. + /// + /// The value represents a pair of the preedit string and the cursor begin position and end + /// position. When both indices are `None`, the cursor should be hidden. + /// + /// The cursor position is byte-wise indexed. + Preedit(String, Option, Option), + + /// Notifies when text should be inserted into the editor widget. + Commit(String), + + /// Notifies when the IME was disabled. + Disabled, } /// Describes touch-screen input state. diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 43cbddae72..03a2b06390 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -16,8 +16,8 @@ use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver}; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::{ - CompositionEvent, DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, - TouchPhase, WindowEvent, + DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, TouchPhase, WindowEvent, + IME, }, event_loop::EventLoopWindowTarget as RootELW, }; @@ -1238,22 +1238,28 @@ impl EventProcessor { } match self.ime_event_receiver.try_recv() { Ok((window, event)) => match event { + ImeEvent::Enabled => { + callback(Event::WindowEvent { + window_id: mkwid(window), + event: WindowEvent::IME(IME::Enabled), + }); + } ImeEvent::Start => { self.is_composing = true; self.composed_text = None; callback(Event::WindowEvent { window_id: mkwid(window), - event: WindowEvent::Composition(CompositionEvent::CompositionStart( - "".to_owned(), - )), + event: WindowEvent::IME(IME::Preedit("".to_owned(), None, None)), }); } ImeEvent::Update(text, position) => { if self.is_composing { callback(Event::WindowEvent { window_id: mkwid(window), - event: WindowEvent::Composition(CompositionEvent::CompositionUpdate( - text, position, + event: WindowEvent::IME(IME::Preedit( + text, + Some(position), + Some(position), )), }); } @@ -1262,7 +1268,7 @@ impl EventProcessor { self.is_composing = false; callback(Event::WindowEvent { window_id: mkwid(window), - event: WindowEvent::Composition(CompositionEvent::CompositionEnd( + event: WindowEvent::IME(IME::Commit( self.composed_text.take().unwrap_or("".to_owned()), )), }); diff --git a/src/platform_impl/linux/x11/ime/context.rs b/src/platform_impl/linux/x11/ime/context.rs index 4e9174768a..0761d40851 100644 --- a/src/platform_impl/linux/x11/ime/context.rs +++ b/src/platform_impl/linux/x11/ime/context.rs @@ -28,7 +28,7 @@ extern "C" fn preedit_start_callback( client_data .event_sender .send((client_data.window, ImeEvent::Start)) - .expect("failed to send composition start event"); + .expect("failed to send preedit start event"); -1 } @@ -42,7 +42,7 @@ extern "C" fn preedit_done_callback( client_data .event_sender .send((client_data.window, ImeEvent::End)) - .expect("failed to send composition end event"); + .expect("failed to send preedit end event"); } fn calc_byte_position(text: &Vec, pos: usize) -> usize { @@ -89,7 +89,7 @@ extern "C" fn preedit_draw_callback( .collect() }; let mut old_text_tail = client_data.text.split_off(chg_range.end); - client_data.text.split_off(chg_range.start); + let _ = client_data.text.split_off(chg_range.start); client_data.text.append(&mut new_chars); client_data.text.append(&mut old_text_tail); let cursor_byte_pos = calc_byte_position(&client_data.text, client_data.cursor_pos); @@ -100,7 +100,7 @@ extern "C" fn preedit_draw_callback( client_data.window, ImeEvent::Update(client_data.text.iter().collect(), cursor_byte_pos), )) - .expect("failed to send composition update event"); + .expect("failed to send preedit update event"); } extern "C" fn preedit_caret_callback( @@ -119,7 +119,7 @@ extern "C" fn preedit_caret_callback( client_data.window, ImeEvent::Update(client_data.text.iter().collect(), cursor_byte_pos), )) - .expect("failed to send composition update event"); + .expect("failed to send preedit update event"); } unsafe fn create_pre_edit_attr<'a>( diff --git a/src/platform_impl/linux/x11/ime/mod.rs b/src/platform_impl/linux/x11/ime/mod.rs index 04ed0f4857..e9a4089528 100644 --- a/src/platform_impl/linux/x11/ime/mod.rs +++ b/src/platform_impl/linux/x11/ime/mod.rs @@ -22,6 +22,7 @@ use self::{ #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ImeEvent { + Enabled, Start, Update(String, usize), End, @@ -105,6 +106,10 @@ impl Ime { // Create empty entry in map, so that when IME is rebuilt, this window has a context. None } else { + self.inner + .event_sender + .send((window, ImeEvent::Enabled)) + .expect("Failed to send enabled event"); Some(unsafe { ImeContext::new( &self.inner.xconn, diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 6253c94373..a2755b690e 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -83,8 +83,8 @@ impl Window { } else if ole_init_result == RPC_E_CHANGED_MODE { panic!( "OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`. \ - Make sure other crates are not using multithreaded COM library \ - on the same thread or disable drag and drop support." + Make sure other crates are not using multithreaded COM library \ + on the same thread or disable drag and drop support." ); }