Skip to content

Commit

Permalink
Implement IME support (#204)
Browse files Browse the repository at this point in the history
Co-authored-by: mvlabat <[email protected]>
  • Loading branch information
EReeves and vladbat00 committed Oct 4, 2024
1 parent 8b4a8cb commit 437eade
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
25 changes: 23 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ pub struct EguiContext {
ctx: egui::Context,
mouse_position: egui::Pos2,
pointer_touch_id: Option<u64>,
has_sent_ime_enabled: bool,
}

impl EguiContext {
Expand Down Expand Up @@ -363,7 +364,7 @@ type EguiContextsFilter = With<Window>;
type EguiContextsFilter = Or<(With<Window>, With<EguiRenderToTextureHandle>)>;

#[derive(SystemParam)]
/// A helper SystemParam that provides a way to get `[EguiContext]` with less boilerplate and
/// A helper SystemParam that provides a way to get [`EguiContext`] with less boilerplate and
/// combines a proxy interface to the [`EguiUserTextures`] resource.
pub struct EguiContexts<'w, 's> {
q: Query<
Expand All @@ -380,7 +381,7 @@ pub struct EguiContexts<'w, 's> {
user_textures: ResMut<'w, EguiUserTextures>,
}

impl<'w, 's> EguiContexts<'w, 's> {
impl EguiContexts<'_, '_> {
/// Egui context of the primary window.
#[must_use]
pub fn ctx_mut(&mut self) -> &mut egui::Context {
Expand Down Expand Up @@ -809,6 +810,26 @@ pub struct EguiContextQuery {
pub render_to_texture: Option<&'static mut EguiRenderToTextureHandle>,
}

impl EguiContextQueryItem<'_> {
fn ime_event_enable(&mut self) {
if !self.ctx.has_sent_ime_enabled {
self.egui_input
.events
.push(egui::Event::Ime(egui::ImeEvent::Enabled));
self.ctx.has_sent_ime_enabled = true;
}
}

fn ime_event_disable(&mut self) {
if self.ctx.has_sent_ime_enabled {
self.egui_input
.events
.push(egui::Event::Ime(egui::ImeEvent::Disabled));
self.ctx.has_sent_ime_enabled = false;
}
}
}

/// Contains textures allocated and painted by Egui.
#[cfg(feature = "render")]
#[derive(bevy::ecs::system::Resource, Deref, DerefMut, Default)]
Expand Down
49 changes: 46 additions & 3 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use bevy::{
log::{self, error},
prelude::{Entity, EventReader, NonSend, Query, Resource, Time},
time::Real,
window::{CursorMoved, RequestRedraw},
window::{CursorMoved, Ime, RequestRedraw},
winit::{EventLoopProxy, WakeUp},
};
use std::{marker::PhantomData, time::Duration};
Expand All @@ -37,9 +37,10 @@ pub struct InputEvents<'w, 's> {
pub ev_keyboard_input: EventReader<'w, 's, KeyboardInput>,
pub ev_touch: EventReader<'w, 's, TouchInput>,
pub ev_focus: EventReader<'w, 's, KeyboardFocusLost>,
pub ev_ime_input: EventReader<'w, 's, Ime>,
}

impl<'w, 's> InputEvents<'w, 's> {
impl InputEvents<'_, '_> {
/// Consumes all the events.
pub fn clear(&mut self) {
self.ev_cursor.clear();
Expand All @@ -48,6 +49,7 @@ impl<'w, 's> InputEvents<'w, 's> {
self.ev_keyboard_input.clear();
self.ev_touch.clear();
self.ev_focus.clear();
self.ev_ime_input.clear();
}
}

Expand Down Expand Up @@ -84,7 +86,7 @@ pub struct ContextSystemParams<'w, 's> {
_marker: PhantomData<&'s ()>,
}

impl<'w, 's> ContextSystemParams<'w, 's> {
impl ContextSystemParams<'_, '_> {
fn window_context(&mut self, window: Entity) -> Option<EguiContextQueryItem> {
match self.contexts.get_mut(window) {
Ok(context) => Some(context),
Expand Down Expand Up @@ -240,6 +242,47 @@ pub fn process_input_system(
});
}

for event in input_events.ev_ime_input.read() {
let window = match &event {
Ime::Preedit { window, .. }
| Ime::Commit { window, .. }
| Ime::Disabled { window }
| Ime::Enabled { window } => *window,
};

let Some(mut window_context) = context_params.window_context(window) else {
continue;
};

// Aligned with the egui-winit implementation: https://github.com/emilk/egui/blob/0f2b427ff4c0a8c68f6622ec7d0afb7ba7e71bba/crates/egui-winit/src/lib.rs#L348
match event {
Ime::Enabled { window: _ } => {
window_context.ime_event_enable();
}
Ime::Preedit {
value,
window: _,
cursor: _,
} => {
window_context.ime_event_enable();
window_context
.egui_input
.events
.push(egui::Event::Ime(egui::ImeEvent::Preedit(value.clone())));
}
Ime::Commit { value, window: _ } => {
window_context
.egui_input
.events
.push(egui::Event::Ime(egui::ImeEvent::Commit(value.clone())));
window_context.ime_event_disable();
}
Ime::Disabled { window: _ } => {
window_context.ime_event_disable();
}
}
}

for event in keyboard_input_events {
let text_event_allowed = !command && !win || !*context_params.is_macos && ctrl && alt;
let Some(mut window_context) = context_params.window_context(event.window) else {
Expand Down

0 comments on commit 437eade

Please sign in to comment.