mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Provide a way to set cursor area for IME cursor
Rename `Window::set_ime_position` to `Window::set_ime_cursor_area` adding a way to create cursor exclusive zone. Fixes #2886.
This commit is contained in:
parent
66ff52b012
commit
05444628e6
|
@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
- **Breaking:** Rename `Window::set_ime_position` to `Window::set_ime_cursor_area` adding a way to set exclusize zone.
|
||||||
- On Android, changed default behavior of Android to ignore volume keys letting the operating system handle them.
|
- On Android, changed default behavior of Android to ignore volume keys letting the operating system handle them.
|
||||||
- On Android, added `EventLoopBuilderExtAndroid::handle_volume_keys` to indicate that the application will handle the volume keys manually.
|
- On Android, added `EventLoopBuilderExtAndroid::handle_volume_keys` to indicate that the application will handle the volume keys manually.
|
||||||
- **Breaking:** Rename `DeviceEventFilter` to `DeviceEvents` reversing the behavior of variants.
|
- **Breaking:** Rename `DeviceEventFilter` to `DeviceEvents` reversing the behavior of variants.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::PhysicalPosition,
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
event::{ElementState, Event, Ime, WindowEvent},
|
event::{ElementState, Event, Ime, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
keyboard::{Key, KeyCode},
|
keyboard::{Key, KeyCode},
|
||||||
|
@ -66,7 +66,7 @@ fn main() {
|
||||||
);
|
);
|
||||||
ime_pos = cursor_position;
|
ime_pos = cursor_position;
|
||||||
if may_show_ime {
|
if may_show_ime {
|
||||||
window.set_ime_position(ime_pos);
|
window.set_ime_cursor_area(ime_pos, PhysicalSize::new(10, 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::WindowEvent {
|
Event::WindowEvent {
|
||||||
|
@ -76,7 +76,7 @@ fn main() {
|
||||||
println!("{event:?}");
|
println!("{event:?}");
|
||||||
may_show_ime = event != Ime::Disabled;
|
may_show_ime = event != Ime::Disabled;
|
||||||
if may_show_ime {
|
if may_show_ime {
|
||||||
window.set_ime_position(ime_pos);
|
window.set_ime_cursor_area(ime_pos, PhysicalSize::new(10, 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::WindowEvent {
|
Event::WindowEvent {
|
||||||
|
|
|
@ -1034,7 +1034,7 @@ impl From<ModifiersState> for Modifiers {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Additionally, certain input devices are configured to display a candidate box that allow the user to select the
|
/// Additionally, certain input devices are configured to display a candidate box that allow the user to select the
|
||||||
/// desired character interactively. (To properly position this box, you must use [`Window::set_ime_position`].)
|
/// desired character interactively. (To properly position this box, you must use [`Window::set_ime_cursor_area`].)
|
||||||
///
|
///
|
||||||
/// An example of a keyboard layout which uses candidate boxes is pinyin. On a latin keyboard the following event
|
/// An example of a keyboard layout which uses candidate boxes is pinyin. On a latin keyboard the following event
|
||||||
/// sequence could be obtained:
|
/// sequence could be obtained:
|
||||||
|
@ -1058,7 +1058,7 @@ pub enum Ime {
|
||||||
///
|
///
|
||||||
/// After getting this event you could receive [`Preedit`](Self::Preedit) and
|
/// After getting this event you could receive [`Preedit`](Self::Preedit) and
|
||||||
/// [`Commit`](Self::Commit) events. You should also start performing IME related requests
|
/// [`Commit`](Self::Commit) events. You should also start performing IME related requests
|
||||||
/// like [`Window::set_ime_position`].
|
/// like [`Window::set_ime_cursor_area`].
|
||||||
Enabled,
|
Enabled,
|
||||||
|
|
||||||
/// Notifies when a new composing text should be set at the cursor position.
|
/// Notifies when a new composing text should be set at the cursor position.
|
||||||
|
@ -1079,7 +1079,7 @@ pub enum Ime {
|
||||||
///
|
///
|
||||||
/// After receiving this event you won't get any more [`Preedit`](Self::Preedit) or
|
/// After receiving this event you won't get any more [`Preedit`](Self::Preedit) or
|
||||||
/// [`Commit`](Self::Commit) events until the next [`Enabled`](Self::Enabled) event. You should
|
/// [`Commit`](Self::Commit) events until the next [`Enabled`](Self::Enabled) event. You should
|
||||||
/// also stop issuing IME related requests like [`Window::set_ime_position`] and clear pending
|
/// also stop issuing IME related requests like [`Window::set_ime_cursor_area`] and clear pending
|
||||||
/// preedit text.
|
/// preedit text.
|
||||||
Disabled,
|
Disabled,
|
||||||
}
|
}
|
||||||
|
|
|
@ -872,7 +872,7 @@ impl Window {
|
||||||
|
|
||||||
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
|
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
|
||||||
|
|
||||||
pub fn set_ime_position(&self, _position: Position) {}
|
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
|
||||||
|
|
||||||
pub fn set_ime_allowed(&self, _allowed: bool) {}
|
pub fn set_ime_allowed(&self, _allowed: bool) {}
|
||||||
|
|
||||||
|
|
|
@ -295,8 +295,8 @@ impl Inner {
|
||||||
warn!("`Window::set_window_icon` is ignored on iOS")
|
warn!("`Window::set_window_icon` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ime_position(&self, _position: Position) {
|
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {
|
||||||
warn!("`Window::set_ime_position` is ignored on iOS")
|
warn!("`Window::set_ime_cursor_area` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ime_allowed(&self, _allowed: bool) {
|
pub fn set_ime_allowed(&self, _allowed: bool) {
|
||||||
|
|
|
@ -512,8 +512,8 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, position: Position) {
|
pub fn set_ime_cursor_area(&self, position: Position, size: Size) {
|
||||||
x11_or_wayland!(match self; Window(w) => w.set_ime_position(position))
|
x11_or_wayland!(match self; Window(w) => w.set_ime_cursor_area(position, size))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -534,12 +534,13 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, position: Position) {
|
pub fn set_ime_cursor_area(&self, position: Position, size: Size) {
|
||||||
let window_state = self.window_state.lock().unwrap();
|
let window_state = self.window_state.lock().unwrap();
|
||||||
if window_state.ime_allowed() {
|
if window_state.ime_allowed() {
|
||||||
let scale_factor = window_state.scale_factor();
|
let scale_factor = window_state.scale_factor();
|
||||||
let position = position.to_logical(scale_factor);
|
let position = position.to_logical(scale_factor);
|
||||||
window_state.set_ime_position(position);
|
let size = size.to_logical(scale_factor);
|
||||||
|
window_state.set_ime_cursor_area(position, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -741,13 +741,14 @@ impl WindowState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the IME position.
|
/// Set the IME position.
|
||||||
pub fn set_ime_position(&self, position: LogicalPosition<u32>) {
|
pub fn set_ime_cursor_area(&self, position: LogicalPosition<u32>, size: LogicalSize<u32>) {
|
||||||
// XXX This won't fly unless user will have a way to request IME window per seat, since
|
// XXX This won't fly unless user will have a way to request IME window per seat, since
|
||||||
// the ime windows will be overlapping, but winit doesn't expose API to specify for
|
// the ime windows will be overlapping, but winit doesn't expose API to specify for
|
||||||
// which seat we're setting IME position.
|
// which seat we're setting IME position.
|
||||||
let (x, y) = (position.x as i32, position.y as i32);
|
let (x, y) = (position.x as i32, position.y as i32);
|
||||||
|
let (width, height) = (size.width as i32, size.height as i32);
|
||||||
for text_input in self.text_inputs.iter() {
|
for text_input in self.text_inputs.iter() {
|
||||||
text_input.set_cursor_rectangle(x, y, 0, 0);
|
text_input.set_cursor_rectangle(x, y, width, height);
|
||||||
text_input.commit();
|
text_input.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1510,7 +1510,7 @@ impl UnownedWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, spot: Position) {
|
pub fn set_ime_cursor_area(&self, spot: Position, _size: Size) {
|
||||||
let (x, y) = spot.to_physical::<i32>(self.scale_factor()).into();
|
let (x, y) = spot.to_physical::<i32>(self.scale_factor()).into();
|
||||||
let _ = self
|
let _ = self
|
||||||
.ime_sender
|
.ime_sender
|
||||||
|
|
|
@ -202,11 +202,15 @@ pub(crate) fn close_sync(window: &NSWindow) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_ime_position_sync(window: &WinitWindow, logical_spot: LogicalPosition<f64>) {
|
pub(crate) fn set_ime_cursor_area_sync(
|
||||||
|
window: &WinitWindow,
|
||||||
|
logical_spot: LogicalPosition<f64>,
|
||||||
|
size: LogicalSize<f64>,
|
||||||
|
) {
|
||||||
let window = MainThreadSafe(window);
|
let window = MainThreadSafe(window);
|
||||||
run_on_main(move || {
|
run_on_main(move || {
|
||||||
// TODO(madsmtm): Remove the need for this
|
// TODO(madsmtm): Remove the need for this
|
||||||
unsafe { Id::from_shared(window.view()) }.set_ime_position(logical_spot);
|
unsafe { Id::from_shared(window.view()) }.set_ime_cursor_area(logical_spot, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ fn get_left_modifier_code(key: &Key) -> KeyCode {
|
||||||
pub(super) struct ViewState {
|
pub(super) struct ViewState {
|
||||||
pub cursor_state: Mutex<CursorState>,
|
pub cursor_state: Mutex<CursorState>,
|
||||||
ime_position: LogicalPosition<f64>,
|
ime_position: LogicalPosition<f64>,
|
||||||
|
ime_size: LogicalSize<f64>,
|
||||||
pub(super) modifiers: Modifiers,
|
pub(super) modifiers: Modifiers,
|
||||||
phys_modifiers: HashMap<Key, ModLocationMask>,
|
phys_modifiers: HashMap<Key, ModLocationMask>,
|
||||||
tracking_rect: Option<NSTrackingRectTag>,
|
tracking_rect: Option<NSTrackingRectTag>,
|
||||||
|
@ -167,6 +168,7 @@ declare_class!(
|
||||||
let state = ViewState {
|
let state = ViewState {
|
||||||
cursor_state: Default::default(),
|
cursor_state: Default::default(),
|
||||||
ime_position: LogicalPosition::new(0.0, 0.0),
|
ime_position: LogicalPosition::new(0.0, 0.0),
|
||||||
|
ime_size: Default::default(),
|
||||||
modifiers: Default::default(),
|
modifiers: Default::default(),
|
||||||
phys_modifiers: Default::default(),
|
phys_modifiers: Default::default(),
|
||||||
tracking_rect: None,
|
tracking_rect: None,
|
||||||
|
@ -416,11 +418,8 @@ declare_class!(
|
||||||
let base_y = (content_rect.origin.y + content_rect.size.height) as f64;
|
let base_y = (content_rect.origin.y + content_rect.size.height) as f64;
|
||||||
let x = base_x + self.state.ime_position.x;
|
let x = base_x + self.state.ime_position.x;
|
||||||
let y = base_y - self.state.ime_position.y;
|
let y = base_y - self.state.ime_position.y;
|
||||||
// This is not ideal: We _should_ return a different position based on
|
let LogicalSize { width, height } = self.state.ime_size;
|
||||||
// the currently selected character (which varies depending on the type
|
NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(width, height))
|
||||||
// and size of the character), but in the current `winit` API there is
|
|
||||||
// no way to express this. Same goes for the `NSSize`.
|
|
||||||
NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(0.0, 0.0))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sel(insertText:replacementRange:)]
|
#[sel(insertText:replacementRange:)]
|
||||||
|
@ -871,8 +870,13 @@ impl WinitView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_ime_position(&mut self, position: LogicalPosition<f64>) {
|
pub(super) fn set_ime_cursor_area(
|
||||||
|
&mut self,
|
||||||
|
position: LogicalPosition<f64>,
|
||||||
|
size: LogicalSize<f64>,
|
||||||
|
) {
|
||||||
self.state.ime_position = position;
|
self.state.ime_position = position;
|
||||||
|
self.state.ime_size = size;
|
||||||
let input_context = self.inputContext().expect("input context");
|
let input_context = self.inputContext().expect("input context");
|
||||||
input_context.invalidateCharacterCoordinates();
|
input_context.invalidateCharacterCoordinates();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1161,10 +1161,11 @@ impl WinitWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, spot: Position) {
|
pub fn set_ime_cursor_area(&self, spot: Position, size: Size) {
|
||||||
let scale_factor = self.scale_factor();
|
let scale_factor = self.scale_factor();
|
||||||
let logical_spot = spot.to_logical(scale_factor);
|
let logical_spot = spot.to_logical(scale_factor);
|
||||||
util::set_ime_position_sync(self, logical_spot);
|
let size = size.to_logical(scale_factor);
|
||||||
|
util::set_ime_cursor_area_sync(self, logical_spot, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -324,7 +324,7 @@ impl Window {
|
||||||
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
|
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, _position: Position) {}
|
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_allowed(&self, _allowed: bool) {}
|
pub fn set_ime_allowed(&self, _allowed: bool) {}
|
||||||
|
|
|
@ -327,7 +327,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, _position: Position) {
|
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {
|
||||||
// Currently a no-op as it does not seem there is good support for this on web
|
// Currently a no-op as it does not seem there is good support for this on web
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use std::{
|
use std::{
|
||||||
ffi::{c_void, OsString},
|
ffi::{c_void, OsString},
|
||||||
mem::zeroed,
|
|
||||||
os::windows::prelude::OsStringExt,
|
os::windows::prelude::OsStringExt,
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
};
|
};
|
||||||
|
|
||||||
use windows_sys::Win32::{
|
use windows_sys::Win32::{
|
||||||
Foundation::POINT,
|
Foundation::{POINT, RECT},
|
||||||
Globalization::HIMC,
|
Globalization::HIMC,
|
||||||
UI::{
|
UI::{
|
||||||
Input::Ime::{
|
Input::Ime::{
|
||||||
|
@ -19,7 +18,10 @@ use windows_sys::Win32::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{dpi::Position, platform::windows::HWND};
|
use crate::{
|
||||||
|
dpi::{Position, Size},
|
||||||
|
platform::windows::HWND,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct ImeContext {
|
pub struct ImeContext {
|
||||||
hwnd: HWND,
|
hwnd: HWND,
|
||||||
|
@ -109,17 +111,24 @@ impl ImeContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn set_ime_position(&self, spot: Position, scale_factor: f64) {
|
pub unsafe fn set_ime_cursor_area(&self, spot: Position, size: Size, scale_factor: f64) {
|
||||||
if !ImeContext::system_has_ime() {
|
if !ImeContext::system_has_ime() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (x, y) = spot.to_physical::<i32>(scale_factor).into();
|
let (x, y) = spot.to_physical::<i32>(scale_factor).into();
|
||||||
|
let (width, height): (i32, i32) = size.to_physical::<i32>(scale_factor).into();
|
||||||
|
let rc_area = RECT {
|
||||||
|
left: x,
|
||||||
|
top: y,
|
||||||
|
right: x + width,
|
||||||
|
bottom: y - height,
|
||||||
|
};
|
||||||
let candidate_form = CANDIDATEFORM {
|
let candidate_form = CANDIDATEFORM {
|
||||||
dwIndex: 0,
|
dwIndex: 0,
|
||||||
dwStyle: CFS_EXCLUDE,
|
dwStyle: CFS_EXCLUDE,
|
||||||
ptCurrentPos: POINT { x, y },
|
ptCurrentPos: POINT { x, y },
|
||||||
rcArea: zeroed(),
|
rcArea: rc_area,
|
||||||
};
|
};
|
||||||
|
|
||||||
ImmSetCandidateWindow(self.himc, &candidate_form);
|
ImmSetCandidateWindow(self.himc, &candidate_form);
|
||||||
|
|
|
@ -722,9 +722,9 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, spot: Position) {
|
pub fn set_ime_cursor_area(&self, spot: Position, size: Size) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ImeContext::current(self.hwnd()).set_ime_position(spot, self.scale_factor());
|
ImeContext::current(self.hwnd()).set_ime_cursor_area(spot, size, self.scale_factor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1017,37 +1017,45 @@ impl Window {
|
||||||
self.window.set_window_icon(window_icon)
|
self.window.set_window_icon(window_icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets location of IME candidate box in client area coordinates relative to the top left.
|
/// Set the IME cursor editing area, where the `position` is the top left corner of that area
|
||||||
|
/// and `size` is the size of this area starting from the position. An example of such area
|
||||||
|
/// could be a input field in the UI or line in the editor.
|
||||||
///
|
///
|
||||||
/// This is the window / popup / overlay that allows you to select the desired characters.
|
/// The windowing system could place a candidate box close to that area, but try to not obscure
|
||||||
/// The look of this box may differ between input devices, even on the same platform.
|
/// the specified area, so the user input to it stays visible.
|
||||||
|
///
|
||||||
|
/// The candidate box is the window / popup / overlay that allows you to select the desired
|
||||||
|
/// characters. The look of this box may differ between input devices, even on the same
|
||||||
|
/// platform.
|
||||||
///
|
///
|
||||||
/// (Apple's official term is "candidate window", see their [chinese] and [japanese] guides).
|
/// (Apple's official term is "candidate window", see their [chinese] and [japanese] guides).
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use winit::dpi::{LogicalPosition, PhysicalPosition};
|
/// # use winit::dpi::{LogicalPosition, PhysicalPosition, LogicalSize, PhysicalSize};
|
||||||
/// # use winit::event_loop::EventLoop;
|
/// # use winit::event_loop::EventLoop;
|
||||||
/// # use winit::window::Window;
|
/// # use winit::window::Window;
|
||||||
/// # let mut event_loop = EventLoop::new();
|
/// # let mut event_loop = EventLoop::new();
|
||||||
/// # let window = Window::new(&event_loop).unwrap();
|
/// # let window = Window::new(&event_loop).unwrap();
|
||||||
/// // Specify the position in logical dimensions like this:
|
/// // Specify the position in logical dimensions like this:
|
||||||
/// window.set_ime_position(LogicalPosition::new(400.0, 200.0));
|
/// window.set_ime_cursor_area(LogicalPosition::new(400.0, 200.0), LogicalSize::new(100, 100));
|
||||||
///
|
///
|
||||||
/// // Or specify the position in physical dimensions like this:
|
/// // Or specify the position in physical dimensions like this:
|
||||||
/// window.set_ime_position(PhysicalPosition::new(400, 200));
|
/// window.set_ime_cursor_area(PhysicalPosition::new(400, 200), PhysicalSize::new(100, 100));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
|
/// - **X11:** - area is not supported, only position.
|
||||||
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
///
|
///
|
||||||
/// [chinese]: https://support.apple.com/guide/chinese-input-method/use-the-candidate-window-cim12992/104/mac/12.0
|
/// [chinese]: https://support.apple.com/guide/chinese-input-method/use-the-candidate-window-cim12992/104/mac/12.0
|
||||||
/// [japanese]: https://support.apple.com/guide/japanese-input-method/use-the-candidate-window-jpim10262/6.3/mac/12.0
|
/// [japanese]: https://support.apple.com/guide/japanese-input-method/use-the-candidate-window-jpim10262/6.3/mac/12.0
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
|
pub fn set_ime_cursor_area<P: Into<Position>, S: Into<Size>>(&self, position: P, size: S) {
|
||||||
self.window.set_ime_position(position.into())
|
self.window
|
||||||
|
.set_ime_cursor_area(position.into(), size.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets whether the window should get IME events
|
/// Sets whether the window should get IME events
|
||||||
|
|
Loading…
Reference in a new issue