Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic IME mapping #204

Merged
merged 1 commit into from
Oct 4, 2024
Merged
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
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
Loading