Skip to content

Commit

Permalink
add composition event support (#1404)
Browse files Browse the repository at this point in the history
* WIP: add composition event suppor prototype

This change requires x11-dl crate
Also, I should send actual string in IME

* send actual preedit string

* run cargo fmt

* update cargo.toml

* remove warning

* address comments in PR

* follow web spec

After the discussion on the PR, I decided to follow the Web
specification for the composition events. I added a few states to filter
out unnecessary events.

* remove println

* fix cursor pos calc

* Re-run CI

Co-authored-by: Murarth <[email protected]>
  • Loading branch information
2 people authored and Osspial committed Jun 30, 2020
1 parent b1e22aa commit d3bcee3
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 15 deletions.
14 changes: 13 additions & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ pub enum WindowEvent<'a> {
/// issue, and it should get fixed - but it's the current state of the API.
ModifiersChanged(ModifiersState),

/// An event from IME
Composition(CompositionEvent),

/// The cursor has moved on the window.
CursorMoved {
device_id: DeviceId,
Expand Down Expand Up @@ -376,7 +379,7 @@ impl Clone for WindowEvent<'static> {
input: *input,
is_synthetic: *is_synthetic,
},

Composition(composition) => Composition(composition.clone()),
ModifiersChanged(modifiers) => ModifiersChanged(modifiers.clone()),
#[allow(deprecated)]
CursorMoved {
Expand Down Expand Up @@ -468,6 +471,7 @@ impl<'a> WindowEvent<'a> {
is_synthetic,
}),
ModifiersChanged(modifiers) => Some(ModifiersChanged(modifiers)),
Composition(event) => Some(Composition(event)),
#[allow(deprecated)]
CursorMoved {
device_id,
Expand Down Expand Up @@ -623,6 +627,14 @@ pub struct KeyboardInput {
pub modifiers: ModifiersState,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum CompositionEvent {
CompositionStart(String),
CompositionUpdate(String, usize),
CompositionEnd(String),
}

/// Describes touch-screen input state.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down
45 changes: 44 additions & 1 deletion src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@ use super::{

use util::modifiers::{ModifierKeyState, ModifierKeymap};

use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver};
use crate::{
dpi::{PhysicalPosition, PhysicalSize},
event::{
DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, TouchPhase, WindowEvent,
CompositionEvent, DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState,
TouchPhase, WindowEvent,
},
event_loop::EventLoopWindowTarget as RootELW,
};

pub(super) struct EventProcessor<T: 'static> {
pub(super) dnd: Dnd,
pub(super) ime_receiver: ImeReceiver,
pub(super) ime_event_receiver: ImeEventReceiver,
pub(super) randr_event_offset: c_int,
pub(super) devices: RefCell<HashMap<DeviceId, Device>>,
pub(super) xi2ext: XExtension,
Expand All @@ -34,6 +37,8 @@ pub(super) struct EventProcessor<T: 'static> {
pub(super) first_touch: Option<u64>,
// Currently focused window belonging to this process
pub(super) active_window: Option<ffi::Window>,
pub(super) is_composing: bool,
pub(super) composed_text: Option<String>,
}

impl<T: 'static> EventProcessor<T> {
Expand Down Expand Up @@ -606,6 +611,10 @@ impl<T: 'static> EventProcessor<T> {
};
callback(event);
}
if self.is_composing && !written.is_empty() {
self.composed_text = Some(written);
self.is_composing = false;
}
}
}

Expand Down Expand Up @@ -1218,6 +1227,40 @@ impl<T: 'static> EventProcessor<T> {
}
Err(_) => (),
}
match self.ime_event_receiver.try_recv() {
Ok((window, event)) => match event {
ImeEvent::Start => {
self.is_composing = true;
self.composed_text = None;
callback(Event::WindowEvent {
window_id: mkwid(window),
event: WindowEvent::Composition(CompositionEvent::CompositionStart(
"".to_owned(),
)),
});
}
ImeEvent::Update(text, position) => {
if self.is_composing {
callback(Event::WindowEvent {
window_id: mkwid(window),
event: WindowEvent::Composition(CompositionEvent::CompositionUpdate(
text, position,
)),
});
}
}
ImeEvent::End => {
self.is_composing = false;
callback(Event::WindowEvent {
window_id: mkwid(window),
event: WindowEvent::Composition(CompositionEvent::CompositionEnd(
self.composed_text.take().unwrap_or("".to_owned()),
)),
});
}
},
Err(_) => (),
}
}

fn handle_pressed_keys<F>(
Expand Down
8 changes: 7 additions & 1 deletion src/platform_impl/linux/x11/ime/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ unsafe fn replace_im(inner: *mut ImeInner) -> Result<(), ReplaceImError> {
for (window, old_context) in (*inner).contexts.iter() {
let spot = old_context.as_ref().map(|old_context| old_context.ic_spot);
let new_context = {
let result = ImeContext::new(xconn, new_im.im, *window, spot);
let result = ImeContext::new(
xconn,
new_im.im,
*window,
spot,
(*inner).event_sender.clone(),
);
if result.is_err() {
let _ = close_im(xconn, new_im.im);
}
Expand Down
Loading

0 comments on commit d3bcee3

Please sign in to comment.