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

Re-add IME support #762

Merged
merged 14 commits into from
Nov 30, 2024
26 changes: 21 additions & 5 deletions masonry/src/passes/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ use std::collections::HashSet;
use cursor_icon::CursorIcon;
use tracing::{info_span, trace};

use crate::passes::event::run_on_pointer_event_pass;
use crate::passes::event::{run_on_pointer_event_pass, run_on_text_event_pass};
use crate::passes::{enter_span, enter_span_if, merge_state_up, recurse_on_children};
use crate::render_root::{RenderRoot, RenderRootSignal, RenderRootState};
use crate::tree_arena::ArenaMut;
use crate::{
PointerEvent, QueryCtx, RegisterCtx, Update, UpdateCtx, Widget, WidgetId, WidgetState,
PointerEvent, QueryCtx, RegisterCtx, TextEvent, Update, UpdateCtx, Widget, WidgetId,
WidgetState,
};

// --- MARK: HELPERS ---
Expand Down Expand Up @@ -402,6 +403,19 @@ pub(crate) fn run_update_focus_pass(root: &mut RenderRoot) {
}

let prev_focused = root.global_state.focused_widget;
let was_ime_active = root.global_state.is_ime_active;

let synthesize_ime_disabled =
was_ime_active && prev_focused != root.global_state.next_focused_widget;
if synthesize_ime_disabled {
// IME was active, but the next focused widget is going to receive the
// Ime::Disabled event. Synthesize an Ime::Disabled event here and send it to
// the widget about to be unfocused.
run_on_text_event_pass(root, &TextEvent::Ime(winit::event::Ime::Disabled));
}
DJMcNab marked this conversation as resolved.
Show resolved Hide resolved

// Note: handling of the Ime::Disabled event sent above may have changed the next focused
// widget.
let next_focused = root.global_state.next_focused_widget;

// "Focused path" means the focused widget, and all its parents.
Expand Down Expand Up @@ -458,8 +472,10 @@ pub(crate) fn run_update_focus_pass(root: &mut RenderRoot) {
}
}

if prev_focused != next_focused {
let was_ime_active = root.global_state.is_ime_active;
// Refocus if the focused widget changed. Or, if the focused widget was going to change, the
// handling of the synthesized Ime::Disabled event above may have changed the focus back to the
// original widget. In that case, also refocus. This is messy.
if prev_focused != next_focused || synthesize_ime_disabled {
let is_ime_active = if let Some(id) = next_focused {
root.widget_arena.get_state(id).item.accepts_text_input
} else {
Expand Down Expand Up @@ -501,7 +517,7 @@ pub(crate) fn run_update_focus_pass(root: &mut RenderRoot) {
}
}

root.global_state.focused_widget = root.global_state.next_focused_widget;
root.global_state.focused_widget = next_focused;
root.global_state.focused_path = next_focused_path;
}

Expand Down
Loading