winit-core/window: add Window::request_ime_update
Allow updating IME state atomically to make it easier for platforms where it's atomic by its nature, like Wayland. The old API is marked as deprecated and is routed to the new atomic API. Co-authored-by: dcz <gilapfco.dcz@porcupinefactory.org>
This commit is contained in:
parent
fa0795a50c
commit
08907148ec
19 changed files with 866 additions and 222 deletions
|
|
@ -21,6 +21,7 @@ use winit_core::event::{
|
|||
PointerKind, PointerSource, TouchPhase, WindowEvent,
|
||||
};
|
||||
use winit_core::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey};
|
||||
use winit_core::window::ImeCapabilities;
|
||||
|
||||
use super::app_state::AppState;
|
||||
use super::cursor::{default_cursor, invisible_cursor};
|
||||
|
|
@ -124,7 +125,7 @@ pub struct ViewState {
|
|||
/// True iff the application wants IME events.
|
||||
///
|
||||
/// Can be set using `set_ime_allowed`
|
||||
ime_allowed: Cell<bool>,
|
||||
ime_capabilities: Cell<Option<ImeCapabilities>>,
|
||||
|
||||
/// True if the current key event should be forwarded
|
||||
/// to the application, even during IME
|
||||
|
|
@ -456,7 +457,7 @@ define_class!(
|
|||
// we must send the `KeyboardInput` event during IME if it triggered
|
||||
// `doCommandBySelector`. (doCommandBySelector means that the keyboard input
|
||||
// is not handled by IME and should be handled by the application)
|
||||
if self.ivars().ime_allowed.get() {
|
||||
if self.ivars().ime_capabilities.get().is_some() {
|
||||
let events_for_nsview = NSArray::from_slice(&[&*event]);
|
||||
unsafe { self.interpretKeyEvents(&events_for_nsview) };
|
||||
|
||||
|
|
@ -797,7 +798,7 @@ impl WinitView {
|
|||
tracking_rect: Default::default(),
|
||||
ime_state: Default::default(),
|
||||
input_source: Default::default(),
|
||||
ime_allowed: Default::default(),
|
||||
ime_capabilities: Default::default(),
|
||||
forward_key_to_app: Default::default(),
|
||||
marked_text: Default::default(),
|
||||
accepts_first_mouse,
|
||||
|
|
@ -859,12 +860,13 @@ impl WinitView {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_ime_allowed(&self, ime_allowed: bool) {
|
||||
if self.ivars().ime_allowed.get() == ime_allowed {
|
||||
pub(super) fn set_ime_allowed(&self, capabilities: Option<ImeCapabilities>) {
|
||||
if self.ivars().ime_capabilities.get().is_some() {
|
||||
return;
|
||||
}
|
||||
self.ivars().ime_allowed.set(ime_allowed);
|
||||
if self.ivars().ime_allowed.get() {
|
||||
self.ivars().ime_capabilities.set(capabilities);
|
||||
|
||||
if capabilities.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -877,6 +879,10 @@ impl WinitView {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn ime_capabilities(&self) -> Option<ImeCapabilities> {
|
||||
self.ivars().ime_capabilities.get()
|
||||
}
|
||||
|
||||
pub(super) fn set_ime_cursor_area(&self, position: NSPoint, size: NSSize) {
|
||||
self.ivars().ime_position.set(position);
|
||||
self.ivars().ime_size.set(size);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ use winit_core::error::RequestError;
|
|||
use winit_core::icon::Icon;
|
||||
use winit_core::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use winit_core::window::{
|
||||
ImePurpose, Theme, UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons,
|
||||
WindowId, WindowLevel,
|
||||
ImeCapabilities, ImeRequest, ImeRequestError, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
use super::event_loop::ActiveEventLoop;
|
||||
|
|
@ -233,16 +233,12 @@ impl CoreWindow for Window {
|
|||
self.maybe_wait_on_main(|delegate| delegate.set_window_icon(window_icon));
|
||||
}
|
||||
|
||||
fn set_ime_cursor_area(&self, position: Position, size: Size) {
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_ime_cursor_area(position, size));
|
||||
fn request_ime_update(&self, request: ImeRequest) -> Result<(), ImeRequestError> {
|
||||
self.maybe_wait_on_main(|delegate| delegate.request_ime_update(request))
|
||||
}
|
||||
|
||||
fn set_ime_allowed(&self, allowed: bool) {
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_ime_allowed(allowed));
|
||||
}
|
||||
|
||||
fn set_ime_purpose(&self, purpose: ImePurpose) {
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_ime_purpose(purpose));
|
||||
fn ime_capabilities(&self) -> Option<ImeCapabilities> {
|
||||
self.maybe_wait_on_main(|delegate| delegate.ime_capabilities())
|
||||
}
|
||||
|
||||
fn focus_window(&self) {
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ use winit_core::event::{SurfaceSizeWriter, WindowEvent};
|
|||
use winit_core::icon::Icon;
|
||||
use winit_core::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle, MonitorHandleProvider};
|
||||
use winit_core::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
|
||||
WindowButtons, WindowId, WindowLevel,
|
||||
CursorGrabMode, ImeCapabilities, ImeRequest, ImeRequestError, ResizeDirection, Theme,
|
||||
UserAttentionType, WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
use super::app_state::AppState;
|
||||
|
|
@ -1674,26 +1674,50 @@ impl WindowDelegate {
|
|||
// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/WinPanel/Tasks/SettingWindowTitle.html
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_ime_cursor_area(&self, spot: Position, size: Size) {
|
||||
let scale_factor = self.scale_factor();
|
||||
let logical_spot = spot.to_logical(scale_factor);
|
||||
let logical_spot = NSPoint::new(logical_spot.x, logical_spot.y);
|
||||
pub fn request_ime_update(&self, request: ImeRequest) -> Result<(), ImeRequestError> {
|
||||
let current_caps = self.view().ime_capabilities();
|
||||
let request_data = match request {
|
||||
ImeRequest::Enable(enable) => {
|
||||
let (capabilities, request_data) = enable.into_raw();
|
||||
if current_caps.is_some() {
|
||||
return Err(ImeRequestError::AlreadyEnabled);
|
||||
}
|
||||
self.view().set_ime_allowed(Some(capabilities));
|
||||
request_data
|
||||
},
|
||||
ImeRequest::Update(request_data) => {
|
||||
if current_caps.is_none() {
|
||||
return Err(ImeRequestError::NotEnabled);
|
||||
}
|
||||
request_data
|
||||
},
|
||||
ImeRequest::Disable => {
|
||||
self.view().set_ime_allowed(None);
|
||||
return Ok(());
|
||||
},
|
||||
};
|
||||
|
||||
let size = size.to_logical(scale_factor);
|
||||
let size = NSSize::new(size.width, size.height);
|
||||
if let Some((spot, size)) = request_data.cursor_area {
|
||||
if self.view().ime_capabilities().unwrap().contains(ImeCapabilities::CURSOR_AREA) {
|
||||
let scale_factor = self.scale_factor();
|
||||
let logical_spot = spot.to_logical(scale_factor);
|
||||
let logical_spot = NSPoint::new(logical_spot.x, logical_spot.y);
|
||||
|
||||
self.view().set_ime_cursor_area(logical_spot, size);
|
||||
let size = size.to_logical(scale_factor);
|
||||
let size = NSSize::new(size.width, size.height);
|
||||
self.view().set_ime_cursor_area(logical_spot, size);
|
||||
} else {
|
||||
warn!("discarding IME cursor area update without capability enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_ime_allowed(&self, allowed: bool) {
|
||||
self.view().set_ime_allowed(allowed);
|
||||
pub fn ime_capabilities(&self) -> Option<ImeCapabilities> {
|
||||
self.view().ime_capabilities()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_ime_purpose(&self, _purpose: ImePurpose) {}
|
||||
|
||||
#[inline]
|
||||
pub fn focus_window(&self) {
|
||||
let mtm = MainThreadMarker::from(self);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue