fix: enable IME input by working around bevy_winit bug (#19)

* fix: enable IME input by working around bevy_winit initialization bug
This commit is contained in:
elm
2026-02-06 00:43:49 +09:00
committed by GitHub
parent 22210c664b
commit 2afc7bb0de
2 changed files with 40 additions and 0 deletions

View File

@@ -14,6 +14,9 @@ impl Plugin for KeyboardPlugin {
app.init_resource::<IsImeCommiting>().add_systems(
Update,
(
// Workaround for bevy_winit not calling `set_ime_allowed` on initial window
// creation when `Window::ime_enabled` is `true` from the start.
activate_ime,
ime_event.run_if(on_message::<Ime>),
send_key_event.run_if(on_message::<KeyboardInput>),
)
@@ -22,6 +25,42 @@ impl Plugin for KeyboardPlugin {
}
}
/// Workaround: bevy_winit does not call `winit::Window::set_ime_allowed()` during initial window
/// creation when `Window::ime_enabled` is `true`. This means `Ime` events are never generated.
///
/// To trigger bevy_winit's own `changed_windows` system, we temporarily toggle `ime_enabled` off
/// then back on over two frames, which causes the change detection to fire and call
/// `set_ime_allowed(true)` internally.
fn activate_ime(mut windows: Query<&mut Window>, mut state: Local<ImeActivationState>) {
match *state {
ImeActivationState::Pending => {
for mut window in windows.iter_mut() {
if window.ime_enabled {
window.ime_enabled = false;
*state = ImeActivationState::Toggled;
}
}
}
ImeActivationState::Toggled => {
for mut window in windows.iter_mut() {
if !window.ime_enabled {
window.ime_enabled = true;
*state = ImeActivationState::Done;
}
}
}
ImeActivationState::Done => {}
}
}
#[derive(Default)]
enum ImeActivationState {
#[default]
Pending,
Toggled,
Done,
}
#[derive(Resource, Default, Serialize, Deserialize, Reflect)]
#[reflect(Default, Serialize, Deserialize)]
struct IsImeCommiting(bool);