From 0b6b794f012b5e82e0600cd4ed41f84f9fc76023 Mon Sep 17 00:00:00 2001 From: RandomScientist <37155686+Random-Scientist@users.noreply.github.com> Date: Fri, 13 Mar 2026 18:50:13 -0700 Subject: [PATCH] fix(macOS) "fix" toggling IME on appkit backend (#4512) Co-authored-by: Random-Scientist --- winit-appkit/src/view.rs | 33 ++++++++++++++++++----------- winit-appkit/src/window_delegate.rs | 4 ++-- winit/src/changelog/unreleased.md | 1 + 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/winit-appkit/src/view.rs b/winit-appkit/src/view.rs index 1b0c3ec9b..056ec93a2 100644 --- a/winit-appkit/src/view.rs +++ b/winit-appkit/src/view.rs @@ -872,24 +872,33 @@ impl WinitView { false } } + pub(super) fn enable_ime(&self, capabilities: ImeCapabilities) { + // This seems reasonable but the prior behavior of `set_ime_allowed` doesn't do this + // (it was also broken but let's not break things worse) - pub(super) fn set_ime_allowed(&self, capabilities: Option) { - if self.ivars().ime_capabilities.get().is_some() { - return; - } - self.ivars().ime_capabilities.set(capabilities); - - if capabilities.is_some() { - return; - } - - // Clear markedText - *self.ivars().marked_text.borrow_mut() = NSMutableAttributedString::new(); + // if self.ivars().ime_capabilities.get().is_none() { + // self.ivars().ime_state.set(ImeState::Ground); + // } + // why are we disabling things in an enable fn? who knows. it's what the previous one did + // though if self.ivars().ime_state.get() != ImeState::Disabled { self.ivars().ime_state.set(ImeState::Disabled); self.queue_event(WindowEvent::Ime(Ime::Disabled)); } + self.ivars().ime_capabilities.set(Some(capabilities)); + *self.ivars().marked_text.borrow_mut() = NSMutableAttributedString::new(); + } + pub(super) fn disable_ime(&self) { + // see above + self.ivars().ime_capabilities.set(None); + if self.ivars().ime_state.get() != ImeState::Disabled { + self.ivars().ime_state.set(ImeState::Disabled); + self.queue_event(WindowEvent::Ime(Ime::Disabled)); + } + // we probably don't need to do this, but again this mirrors the prior behavior of + // `set_ime_allowed` + *self.ivars().marked_text.borrow_mut() = NSMutableAttributedString::new(); } pub(super) fn ime_capabilities(&self) -> Option { diff --git a/winit-appkit/src/window_delegate.rs b/winit-appkit/src/window_delegate.rs index 262550f16..cdf198d17 100644 --- a/winit-appkit/src/window_delegate.rs +++ b/winit-appkit/src/window_delegate.rs @@ -1686,7 +1686,7 @@ impl WindowDelegate { if current_caps.is_some() { return Err(ImeRequestError::AlreadyEnabled); } - self.view().set_ime_allowed(Some(capabilities)); + self.view().enable_ime(capabilities); request_data }, ImeRequest::Update(request_data) => { @@ -1696,7 +1696,7 @@ impl WindowDelegate { request_data }, ImeRequest::Disable => { - self.view().set_ime_allowed(None); + self.view().disable_ime(); return Ok(()); }, }; diff --git a/winit/src/changelog/unreleased.md b/winit/src/changelog/unreleased.md index 1a4158644..86fc729f3 100644 --- a/winit/src/changelog/unreleased.md +++ b/winit/src/changelog/unreleased.md @@ -58,3 +58,4 @@ changelog entry. - On Windows, fix `WM_IME_SETCONTEXT` IME UI flag masking on `lParam`. - On macOS, fix crash in `set_marked_text` when native Pinyin IME sends out-of-bounds `selected_range`. - On X11, fix debug mode overflow panic in `set_timestamp`. +- On macOS, fix IME being locked on (regardless of requests to disable) after being enabled once. \ No newline at end of file