diff --git a/examples/integration_opengl/src/main.rs b/examples/integration_opengl/src/main.rs
index f161c8a0e0..bf1c6d5915 100644
--- a/examples/integration_opengl/src/main.rs
+++ b/examples/integration_opengl/src/main.rs
@@ -2,6 +2,7 @@ mod controls;
mod scene;
use controls::Controls;
+use iced_glutin::ime::IME;
use scene::Scene;
use glow::*;
@@ -77,7 +78,7 @@ pub fn main() {
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
-
+ let ime = IME::connect(windowed_context.window());
match event {
Event::WindowEvent { event, .. } => {
match event {
@@ -130,6 +131,7 @@ pub fn main() {
text_color: Color::WHITE,
},
&mut clipboard,
+ &ime,
&mut debug,
);
diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs
index 69d46c3ec0..00be03abff 100644
--- a/examples/integration_wgpu/src/main.rs
+++ b/examples/integration_wgpu/src/main.rs
@@ -6,8 +6,8 @@ use scene::Scene;
use iced_wgpu::{wgpu, Backend, Renderer, Settings, Viewport};
use iced_winit::{
- conversion, futures, program, renderer, winit, Clipboard, Color, Debug,
- Size,
+ conversion, futures, ime::IME, program, renderer, winit, Clipboard, Color,
+ Debug, Size,
};
use winit::{
@@ -147,7 +147,8 @@ pub fn main() {
event_loop.run(move |event, _, control_flow| {
// You should change this if you want to render continuosly
*control_flow = ControlFlow::Wait;
-
+ let ime = IME::connect(&window);
+ ime.set_ime_allowed(true);
match event {
Event::WindowEvent { event, .. } => {
match event {
@@ -189,6 +190,7 @@ pub fn main() {
&iced_wgpu::Theme::Dark,
&renderer::Style { text_color: Color::WHITE },
&mut clipboard,
+ & ime,
&mut debug,
);
diff --git a/examples/todos/Cargo.toml b/examples/todos/Cargo.toml
index 2326ffc6e1..57597f41d0 100644
--- a/examples/todos/Cargo.toml
+++ b/examples/todos/Cargo.toml
@@ -7,6 +7,7 @@ publish = false
[dependencies]
iced = { path = "../..", features = ["async-std", "debug"] }
+iced_native = {path="../../native/"}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
lazy_static = "1.4"
diff --git a/glutin/src/application.rs b/glutin/src/application.rs
index d38fa220f3..da782de9fc 100644
--- a/glutin/src/application.rs
+++ b/glutin/src/application.rs
@@ -10,6 +10,7 @@ use iced_winit::application;
use iced_winit::conversion;
use iced_winit::futures;
use iced_winit::futures::channel::mpsc;
+use iced_winit::ime::IME;
use iced_winit::renderer;
use iced_winit::user_interface;
use iced_winit::{Clipboard, Command, Debug, Proxy, Settings};
@@ -194,7 +195,7 @@ async fn run_instance(
{
use glutin::event;
use iced_winit::futures::stream::StreamExt;
-
+ let mut ime = IME::connect(context.window());
let mut clipboard = Clipboard::connect(context.window());
let mut cache = user_interface::Cache::default();
let mut state = application::State::new(&application, context.window());
@@ -208,6 +209,7 @@ async fn run_instance(
init_command,
&mut runtime,
&mut clipboard,
+ &ime,
&mut proxy,
&mut debug,
context.window(),
@@ -244,6 +246,7 @@ async fn run_instance(
state.cursor_position(),
&mut renderer,
&mut clipboard,
+ &ime,
&mut messages,
);
@@ -270,6 +273,7 @@ async fn run_instance(
&mut renderer,
&mut runtime,
&mut clipboard,
+ &ime,
&mut proxy,
&mut debug,
&mut messages,
@@ -339,6 +343,7 @@ async fn run_instance(
context = context
.make_current()
.expect("Make OpenGL context current");
+ ime = IME::connect(context.window());
}
}
diff --git a/graphics/src/widget/canvas.rs b/graphics/src/widget/canvas.rs
index b4afd99862..fff939fd63 100644
--- a/graphics/src/widget/canvas.rs
+++ b/graphics/src/widget/canvas.rs
@@ -30,9 +30,9 @@ pub use text::Text;
use crate::{Backend, Primitive, Renderer};
use iced_native::layout::{self, Layout};
-use iced_native::mouse;
use iced_native::renderer;
use iced_native::widget::tree::{self, Tree};
+use iced_native::{mouse, IME};
use iced_native::{
Clipboard, Element, Length, Point, Rectangle, Shell, Size, Vector, Widget,
};
@@ -165,6 +165,7 @@ where
cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
let bounds = layout.bounds();
diff --git a/lazy/src/component.rs b/lazy/src/component.rs
index 8987b9930f..83d98cfe9b 100644
--- a/lazy/src/component.rs
+++ b/lazy/src/component.rs
@@ -1,11 +1,11 @@
//! Build and reuse custom widgets using The Elm Architecture.
-use iced_native::event;
use iced_native::layout::{self, Layout};
use iced_native::mouse;
use iced_native::overlay;
use iced_native::renderer;
use iced_native::widget;
use iced_native::widget::tree::{self, Tree};
+use iced_native::{event, IME};
use iced_native::{
Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget,
};
@@ -178,6 +178,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
let mut local_messages = Vec::new();
@@ -191,6 +192,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
&mut local_shell,
)
});
@@ -455,6 +457,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> iced_native::event::Status {
let mut local_messages = Vec::new();
@@ -468,6 +471,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
&mut local_shell,
)
})
diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs
index 0b7ae6de10..f34f179cc6 100644
--- a/lazy/src/responsive.rs
+++ b/lazy/src/responsive.rs
@@ -1,10 +1,10 @@
-use iced_native::event;
use iced_native::layout::{self, Layout};
use iced_native::mouse;
use iced_native::overlay;
use iced_native::renderer;
use iced_native::widget::horizontal_space;
use iced_native::widget::tree::{self, Tree};
+use iced_native::{event, IME};
use iced_native::{
Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget,
};
@@ -150,6 +150,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
let state = tree.state.downcast_mut::();
@@ -168,6 +169,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
},
@@ -372,6 +374,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.with_overlay_mut_maybe(|overlay| {
@@ -381,6 +384,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
})
diff --git a/native/src/command/action.rs b/native/src/command/action.rs
index a6954f8f75..9b363c6454 100644
--- a/native/src/command/action.rs
+++ b/native/src/command/action.rs
@@ -1,4 +1,5 @@
use crate::clipboard;
+use crate::ime;
use crate::system;
use crate::widget;
use crate::window;
@@ -19,6 +20,9 @@ pub enum Action {
/// Run a clipboard action.
Clipboard(clipboard::Action),
+ /// Run a IME releated action.
+ IME(ime::Action),
+
/// Run a window action.
Window(window::Action),
@@ -46,6 +50,7 @@ impl Action {
match self {
Self::Future(future) => Action::Future(Box::pin(future.map(f))),
Self::Clipboard(action) => Action::Clipboard(action.map(f)),
+ Self::IME(action) => Action::IME(action),
Self::Window(window) => Action::Window(window.map(f)),
Self::System(system) => Action::System(system.map(f)),
Self::Widget(widget) => Action::Widget(widget.map(f)),
@@ -60,6 +65,9 @@ impl fmt::Debug for Action {
Self::Clipboard(action) => {
write!(f, "Action::Clipboard({:?})", action)
}
+ Self::IME(action) => {
+ write!(f, "Action::IME({:?})", action)
+ }
Self::Window(action) => write!(f, "Action::Window({:?})", action),
Self::System(action) => write!(f, "Action::System({:?})", action),
Self::Widget(_action) => write!(f, "Action::Widget"),
diff --git a/native/src/element.rs b/native/src/element.rs
index 074e422ef4..03d3a7bdca 100644
--- a/native/src/element.rs
+++ b/native/src/element.rs
@@ -1,10 +1,10 @@
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::widget;
use crate::widget::tree::{self, Tree};
+use crate::{layout, IME};
use crate::{
Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Widget,
};
@@ -330,6 +330,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, B>,
) -> event::Status {
let mut local_messages = Vec::new();
@@ -342,6 +343,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
&mut local_shell,
);
@@ -470,6 +472,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.element.widget.on_event(
@@ -479,6 +482,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
}
diff --git a/native/src/ime.rs b/native/src/ime.rs
new file mode 100644
index 0000000000..c88061e319
--- /dev/null
+++ b/native/src/ime.rs
@@ -0,0 +1,43 @@
+//! Access the IME.
+use std::fmt;
+
+///
+pub trait IME {
+ ///
+ fn set_ime_allowed(&self, allowed: bool);
+
+ ///
+ fn set_ime_position(&self, x: i32, y: i32);
+}
+
+/// A null implementation of the [`IME`] trait.
+#[derive(Debug, Clone, Copy)]
+pub struct Null;
+
+impl IME for Null {
+ fn set_ime_allowed(&self, _allowed: bool) {}
+
+ fn set_ime_position(&self, _x: i32, _y: i32) {}
+}
+
+/// A IME action to be performed by some [`Command`].
+///
+/// [`Command`]: crate::Command
+pub enum Action {
+ ///
+ Allow(bool),
+
+ ///
+ Position(i32, i32),
+}
+
+impl fmt::Debug for Action {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Action::Allow(_) => {
+ write!(f, "Action::Allow")
+ }
+ Action::Position(_, _) => write!(f, "Action::SetPosition"),
+ }
+ }
+}
diff --git a/native/src/lib.rs b/native/src/lib.rs
index 02269265f9..4d148bcd06 100644
--- a/native/src/lib.rs
+++ b/native/src/lib.rs
@@ -48,6 +48,7 @@ pub mod clipboard;
pub mod command;
pub mod event;
pub mod image;
+pub mod ime;
pub mod keyboard;
pub mod layout;
pub mod mouse;
@@ -96,6 +97,7 @@ pub use debug::Debug;
pub use element::Element;
pub use event::Event;
pub use hasher::Hasher;
+pub use ime::IME;
pub use layout::Layout;
pub use overlay::Overlay;
pub use program::Program;
diff --git a/native/src/overlay.rs b/native/src/overlay.rs
index 905d3389d9..8021175bf4 100644
--- a/native/src/overlay.rs
+++ b/native/src/overlay.rs
@@ -7,11 +7,11 @@ pub use element::Element;
pub use menu::Menu;
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::widget;
use crate::widget::tree::{self, Tree};
+use crate::{layout, IME};
use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size};
/// An interactive component that can be displayed on top of other widgets.
@@ -91,6 +91,7 @@ where
_cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
_shell: &mut Shell<'_, Message>,
) -> event::Status {
event::Status::Ignored
diff --git a/native/src/overlay/element.rs b/native/src/overlay/element.rs
index b919c221ee..5536d9c472 100644
--- a/native/src/overlay/element.rs
+++ b/native/src/overlay/element.rs
@@ -1,10 +1,10 @@
pub use crate::Overlay;
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::widget;
+use crate::{layout, IME};
use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size, Vector};
/// A generic [`Overlay`].
@@ -63,6 +63,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.overlay.on_event(
@@ -71,6 +72,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
}
@@ -148,6 +150,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, B>,
) -> event::Status {
let mut local_messages = Vec::new();
@@ -159,6 +162,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
&mut local_shell,
);
diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs
index 0813587288..32538c579d 100644
--- a/native/src/overlay/menu.rs
+++ b/native/src/overlay/menu.rs
@@ -1,5 +1,4 @@
//! Build and show dropdown menus.
-use crate::alignment;
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
@@ -10,6 +9,7 @@ use crate::touch;
use crate::widget::container::{self, Container};
use crate::widget::scrollable::{self, Scrollable};
use crate::widget::tree::{self, Tree};
+use crate::{alignment, IME};
use crate::{
Clipboard, Color, Element, Layout, Length, Padding, Point, Rectangle,
Shell, Size, Vector, Widget,
@@ -251,6 +251,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.container.on_event(
@@ -260,6 +261,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
}
@@ -377,6 +379,7 @@ where
cursor_position: Point,
renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _: &dyn IME,
_shell: &mut Shell<'_, Message>,
) -> event::Status {
match event {
diff --git a/native/src/program/state.rs b/native/src/program/state.rs
index 8ae1cacbc8..80c538294a 100644
--- a/native/src/program/state.rs
+++ b/native/src/program/state.rs
@@ -1,8 +1,8 @@
-use crate::application;
use crate::event::{self, Event};
use crate::mouse;
use crate::renderer;
use crate::user_interface::{self, UserInterface};
+use crate::{application, IME};
use crate::{Clipboard, Command, Debug, Point, Program, Size};
/// The execution state of a [`Program`]. It leverages caching, event
@@ -94,6 +94,7 @@ where
theme: &::Theme,
style: &renderer::Style,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
debug: &mut Debug,
) -> (Vec, Option>) {
let mut user_interface = build_user_interface(
@@ -112,6 +113,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
&mut messages,
);
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 344ba4d6a6..3bb7b20055 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -1,10 +1,10 @@
//! Implement your own event loop to drive a user interface.
-use crate::application;
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::widget;
+use crate::{application, IME};
use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
/// A set of interactive graphical elements with a specific [`Layout`].
@@ -121,7 +121,7 @@ where
/// completing [the previous example](#example):
///
/// ```no_run
- /// use iced_native::{clipboard, Size, Point};
+ /// use iced_native::{clipboard,ime, Size, Point};
/// use iced_native::user_interface::{self, UserInterface};
/// use iced_wgpu::Renderer;
///
@@ -146,7 +146,7 @@ where
/// let mut window_size = Size::new(1024.0, 768.0);
/// let mut cursor_position = Point::default();
/// let mut clipboard = clipboard::Null;
- ///
+ /// let ime = ime::Null;
/// // Initialize our event storage
/// let mut events = Vec::new();
/// let mut messages = Vec::new();
@@ -167,6 +167,7 @@ where
/// cursor_position,
/// &mut renderer,
/// &mut clipboard,
+ /// &ime,
/// &mut messages
/// );
///
@@ -184,6 +185,7 @@ where
cursor_position: Point,
renderer: &mut Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
messages: &mut Vec,
) -> (State, Vec) {
use std::mem::ManuallyDrop;
@@ -212,6 +214,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
&mut shell,
);
@@ -282,6 +285,7 @@ where
base_cursor,
renderer,
clipboard,
+ ime,
&mut shell,
);
@@ -318,6 +322,7 @@ where
///
/// ```no_run
/// use iced_native::clipboard;
+ /// use iced_native::ime;
/// use iced_native::renderer;
/// use iced_native::user_interface::{self, UserInterface};
/// use iced_native::{Size, Point, Theme};
@@ -344,6 +349,7 @@ where
/// let mut window_size = Size::new(1024.0, 768.0);
/// let mut cursor_position = Point::default();
/// let mut clipboard = clipboard::Null;
+ /// let ime = ime::Null;
/// let mut events = Vec::new();
/// let mut messages = Vec::new();
///
@@ -363,6 +369,7 @@ where
/// cursor_position,
/// &mut renderer,
/// &mut clipboard,
+ /// &ime,
/// &mut messages
/// );
///
diff --git a/native/src/widget.rs b/native/src/widget.rs
index 8890b8e798..24f714de5f 100644
--- a/native/src/widget.rs
+++ b/native/src/widget.rs
@@ -89,7 +89,7 @@ use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
-use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell};
+use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell, IME};
/// A component that displays information and allows interaction.
///
@@ -187,6 +187,7 @@ where
_cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
_shell: &mut Shell<'_, Message>,
) -> event::Status {
event::Status::Ignored
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs
index 6c0b8f6e79..d7f3389140 100644
--- a/native/src/widget/button.rs
+++ b/native/src/widget/button.rs
@@ -2,13 +2,13 @@
//!
//! A [`Button`] has some local [`State`].
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::touch;
use crate::widget::tree::{self, Tree};
use crate::widget::Operation;
+use crate::{layout, IME};
use crate::{
Background, Clipboard, Color, Element, Layout, Length, Padding, Point,
Rectangle, Shell, Vector, Widget,
@@ -188,6 +188,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
if let event::Status::Captured = self.content.as_widget_mut().on_event(
@@ -197,6 +198,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
) {
return event::Status::Captured;
diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs
index dc3c0bd061..c52f998e40 100644
--- a/native/src/widget/checkbox.rs
+++ b/native/src/widget/checkbox.rs
@@ -1,5 +1,4 @@
//! Show toggle controls using checkboxes.
-use crate::alignment;
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
@@ -7,6 +6,7 @@ use crate::renderer;
use crate::text;
use crate::touch;
use crate::widget::{self, Row, Text, Tree};
+use crate::{alignment, IME};
use crate::{
Alignment, Clipboard, Element, Layout, Length, Point, Rectangle, Shell,
Widget,
@@ -174,6 +174,7 @@ where
cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
match event {
diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs
index a8b0f18307..b3ba95e2d3 100644
--- a/native/src/widget/column.rs
+++ b/native/src/widget/column.rs
@@ -1,10 +1,10 @@
//! Distribute content vertically.
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::widget::{Operation, Tree};
+use crate::{layout, IME};
use crate::{
Alignment, Clipboard, Element, Layout, Length, Padding, Point, Rectangle,
Shell, Widget,
@@ -168,6 +168,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.children
@@ -182,6 +183,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
})
diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs
index 2afad3f2d3..79fd3fece9 100644
--- a/native/src/widget/container.rs
+++ b/native/src/widget/container.rs
@@ -1,11 +1,11 @@
//! Decorate content and apply alignment.
use crate::alignment::{self, Alignment};
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::widget::{Operation, Tree};
+use crate::{layout, IME};
use crate::{
Background, Clipboard, Color, Element, Layout, Length, Padding, Point,
Rectangle, Shell, Widget,
@@ -188,6 +188,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.content.as_widget_mut().on_event(
@@ -197,6 +198,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
}
diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs
index b1fe596c17..6c185805a3 100644
--- a/native/src/widget/image/viewer.rs
+++ b/native/src/widget/image/viewer.rs
@@ -1,10 +1,10 @@
//! Zoom and pan on an image.
use crate::event::{self, Event};
-use crate::image;
use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::widget::tree::{self, Tree};
+use crate::{image, IME};
use crate::{
Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Vector,
Widget,
@@ -147,6 +147,7 @@ where
cursor_position: Point,
renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
_shell: &mut Shell<'_, Message>,
) -> event::Status {
let bounds = layout.bounds();
diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs
index d84fb7a0f9..154416930c 100644
--- a/native/src/widget/pane_grid.rs
+++ b/native/src/widget/pane_grid.rs
@@ -33,13 +33,13 @@ pub use title_bar::TitleBar;
pub use iced_style::pane_grid::{Line, StyleSheet};
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::touch;
use crate::widget::container;
use crate::widget::tree::{self, Tree};
+use crate::{layout, IME};
use crate::{
Clipboard, Color, Element, Layout, Length, Point, Rectangle, Shell, Size,
Vector, Widget,
@@ -272,6 +272,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
let action = tree.state.downcast_mut::();
@@ -306,6 +307,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
is_picked,
)
diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs
index 98ce2c4b96..0c665b4ae8 100644
--- a/native/src/widget/pane_grid/content.rs
+++ b/native/src/widget/pane_grid/content.rs
@@ -1,11 +1,11 @@
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::widget::container;
use crate::widget::pane_grid::{Draggable, TitleBar};
use crate::widget::Tree;
+use crate::{layout, IME};
use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
/// The content of a [`Pane`].
@@ -191,6 +191,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
is_picked: bool,
) -> event::Status {
@@ -206,6 +207,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
);
@@ -224,6 +226,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
};
diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs
index eb85f9249d..d374f89e86 100644
--- a/native/src/widget/pane_grid/title_bar.rs
+++ b/native/src/widget/pane_grid/title_bar.rs
@@ -1,10 +1,10 @@
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::widget::container;
use crate::widget::Tree;
+use crate::{layout, IME};
use crate::{
Clipboard, Element, Layout, Padding, Point, Rectangle, Shell, Size,
};
@@ -265,6 +265,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
let mut children = layout.children();
@@ -289,6 +290,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
} else {
@@ -303,6 +305,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
} else {
diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs
index c334804e38..826b208482 100644
--- a/native/src/widget/pick_list.rs
+++ b/native/src/widget/pick_list.rs
@@ -1,5 +1,4 @@
//! Display a dropdown list of selectable values.
-use crate::alignment;
use crate::event::{self, Event};
use crate::keyboard;
use crate::layout;
@@ -10,6 +9,7 @@ use crate::renderer;
use crate::text::{self, Text};
use crate::touch;
use crate::widget::tree::{self, Tree};
+use crate::{alignment, IME};
use crate::{
Clipboard, Element, Layout, Length, Padding, Point, Rectangle, Shell, Size,
Widget,
@@ -157,6 +157,7 @@ where
cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
update(
diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs
index cb83f745df..6640b2bc26 100644
--- a/native/src/widget/radio.rs
+++ b/native/src/widget/radio.rs
@@ -1,5 +1,4 @@
//! Create choices using radio buttons.
-use crate::alignment;
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
@@ -7,6 +6,7 @@ use crate::renderer;
use crate::text;
use crate::touch;
use crate::widget::{self, Row, Text, Tree};
+use crate::{alignment, IME};
use crate::{
Alignment, Clipboard, Color, Element, Layout, Length, Point, Rectangle,
Shell, Widget,
@@ -182,6 +182,7 @@ where
cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
match event {
diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs
index eda7c2d355..89b3c08d4c 100644
--- a/native/src/widget/row.rs
+++ b/native/src/widget/row.rs
@@ -1,10 +1,10 @@
//! Distribute content horizontally.
use crate::event::{self, Event};
use crate::layout::{self, Layout};
-use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::widget::{Operation, Tree};
+use crate::{mouse, IME};
use crate::{
Alignment, Clipboard, Element, Length, Padding, Point, Rectangle, Shell,
Widget,
@@ -155,6 +155,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.children
@@ -169,6 +170,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
})
diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs
index 4ebb07a065..8ab2ba17e9 100644
--- a/native/src/widget/scrollable.rs
+++ b/native/src/widget/scrollable.rs
@@ -1,6 +1,5 @@
//! Navigate an endless amount of content with a scrollbar.
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::overlay;
use crate::renderer;
@@ -8,6 +7,7 @@ use crate::touch;
use crate::widget;
use crate::widget::operation::{self, Operation};
use crate::widget::tree::{self, Tree};
+use crate::{layout, IME};
use crate::{
Background, Clipboard, Color, Command, Element, Layout, Length, Point,
Rectangle, Shell, Size, Vector, Widget,
@@ -187,6 +187,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
update(
@@ -208,6 +209,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
},
diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs
index 585d9c35c9..a0d54ceae6 100644
--- a/native/src/widget/slider.rs
+++ b/native/src/widget/slider.rs
@@ -2,11 +2,11 @@
//!
//! A [`Slider`] has some local [`State`].
use crate::event::{self, Event};
-use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::touch;
use crate::widget::tree::{self, Tree};
+use crate::{layout, IME};
use crate::{
Background, Clipboard, Color, Element, Layout, Length, Point, Rectangle,
Shell, Size, Widget,
@@ -188,6 +188,7 @@ where
cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
update(
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs
index 4479095e77..a55c37a849 100644
--- a/native/src/widget/text_input.rs
+++ b/native/src/widget/text_input.rs
@@ -11,7 +11,6 @@ pub use value::Value;
use editor::Editor;
-use crate::alignment;
use crate::event::{self, Event};
use crate::keyboard;
use crate::layout;
@@ -22,13 +21,12 @@ use crate::touch;
use crate::widget;
use crate::widget::operation::{self, Operation};
use crate::widget::tree::{self, Tree};
-use crate::window::Action;
+use crate::{alignment, IME};
use crate::{
Clipboard, Color, Command, Element, Layout, Length, Padding, Point,
Rectangle, Shell, Size, Vector, Widget,
};
pub use iced_style::text_input::{Appearance, StyleSheet};
-
/// A field that can be filled with text.
///
/// # Example
@@ -243,6 +241,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
update(
@@ -251,6 +250,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
&mut self.value,
self.size,
@@ -369,6 +369,7 @@ pub fn update<'a, Message, Renderer>(
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
value: &mut Value,
size: Option,
@@ -739,28 +740,48 @@ where
}
Event::Keyboard(keyboard::Event::IMEPreedit(text)) => {
let state = state();
+
let cursor_offset = state.cursor.start(value);
- let mut editor = Editor::new(value, &mut state.cursor);
- if state.is_ime_editing {
- editor.delete();
- }
- state.is_ime_editing = true;
+
+ // limit borrow life time.
let mut chars_count = 0;
+ let message = {
+ let mut editor = Editor::new(value, &mut state.cursor);
+ if state.is_ime_editing {
+ editor.delete();
+ }
+ state.is_ime_editing = true;
- let action: Action<()> = Action::MoveIMECandidateWindow {
- x: cursor_position.x as i32,
- y: cursor_position.y as i32,
+ for ch in text.chars() {
+ editor.insert(ch);
+ chars_count += 1;
+ }
+ (on_change)(editor.contents())
};
- let action = crate::command::Action::Window(action);
- let command = crate::command::Command::single(action);
- for ch in text.chars() {
- editor.insert(ch);
- chars_count += 1;
- }
- let message = (on_change)(editor.contents());
state
.cursor
.select_range(cursor_offset, cursor_offset + chars_count);
+ // calcurate where we need to place candidate window.
+ let text_bounds = layout.children().next().unwrap().bounds();
+ let size = size.unwrap_or_else(|| renderer.default_size());
+ let position = match state.cursor.state(value) {
+ cursor::State::Index(position) => position,
+ cursor::State::Selection { start, end } => start.min(end),
+ };
+ let position = measure_cursor_and_scroll_offset(
+ renderer,
+ text_bounds,
+ value,
+ size,
+ position,
+ font.clone(),
+ );
+ let position = (
+ (text_bounds.x + position.0) as i32,
+ (text_bounds.y) as i32 + size as i32,
+ );
+ ime.set_ime_position(position.0, position.1);
+
shell.publish(message);
return event::Status::Captured;
}
@@ -963,7 +984,8 @@ pub struct State {
last_click: Option,
cursor: Cursor,
keyboard_modifiers: keyboard::Modifiers,
- is_ime_editing: bool, // TODO: Add stateful horizontal scrolling offset
+ is_ime_editing: bool,
+ // TODO: Add stateful horizontal scrolling offset
}
impl State {
diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs
index 7893f78c79..987abd0cc0 100644
--- a/native/src/widget/toggler.rs
+++ b/native/src/widget/toggler.rs
@@ -6,6 +6,7 @@ use crate::mouse;
use crate::renderer;
use crate::text;
use crate::widget::{self, Row, Text, Tree};
+use crate::IME;
use crate::{
Alignment, Clipboard, Element, Event, Layout, Length, Point, Rectangle,
Shell, Widget,
@@ -186,6 +187,7 @@ where
cursor_position: Point,
_renderer: &Renderer,
_clipboard: &mut dyn Clipboard,
+ _ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
match event {
diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs
index 674f2ba687..0772feb893 100644
--- a/native/src/widget/tooltip.rs
+++ b/native/src/widget/tooltip.rs
@@ -8,6 +8,7 @@ use crate::widget;
use crate::widget::container;
use crate::widget::overlay;
use crate::widget::{Text, Tree};
+use crate::IME;
use crate::{
Clipboard, Element, Event, Layout, Length, Padding, Point, Rectangle,
Shell, Size, Vector, Widget,
@@ -138,6 +139,7 @@ where
cursor_position: Point,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
+ ime: &dyn IME,
shell: &mut Shell<'_, Message>,
) -> event::Status {
self.content.as_widget_mut().on_event(
@@ -147,6 +149,7 @@ where
cursor_position,
renderer,
clipboard,
+ ime,
shell,
)
}
diff --git a/native/src/window/action.rs b/native/src/window/action.rs
index ecdb0095fe..73338e2246 100644
--- a/native/src/window/action.rs
+++ b/native/src/window/action.rs
@@ -25,15 +25,6 @@ pub enum Action {
SetMode(Mode),
/// Fetch the current [`Mode`] of the window.
FetchMode(Box T + 'static>),
- /// Move IME candidate window
- MoveIMECandidateWindow {
- /// The new logical x location of the ime candidate window
- x: i32,
- /// The new logical x location of the ime candidate window
- y: i32,
- },
- /// Set IME allow
- SetIMEAllow(bool),
}
impl Action {
@@ -50,10 +41,6 @@ impl Action {
Self::Move { x, y } => Action::Move { x, y },
Self::SetMode(mode) => Action::SetMode(mode),
Self::FetchMode(o) => Action::FetchMode(Box::new(move |s| f(o(s)))),
- Self::SetIMEAllow(allow) => Action::SetIMEAllow(allow),
- Self::MoveIMECandidateWindow { x, y } => {
- Action::MoveIMECandidateWindow { x, y }
- }
}
}
}
@@ -71,16 +58,6 @@ impl fmt::Debug for Action {
}
Self::SetMode(mode) => write!(f, "Action::SetMode({:?})", mode),
Self::FetchMode(_) => write!(f, "Action::FetchMode"),
- Self::MoveIMECandidateWindow { x, y } => {
- write!(
- f,
- "Action::MoveIMECandidateWindow {{ x: {}, y: {} }}",
- x, y
- )
- }
- Self::SetIMEAllow(allow) => {
- write!(f, "Action::SetIMEAllow {{ allow : {} }}", allow)
- }
}
}
}
diff --git a/winit/src/application.rs b/winit/src/application.rs
index be7f9bb855..aed17dd78b 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -5,6 +5,7 @@ pub use state::State;
use crate::clipboard::{self, Clipboard};
use crate::conversion;
+use crate::ime::IME;
use crate::mouse;
use crate::renderer;
use crate::widget::operation;
@@ -239,6 +240,7 @@ async fn run_instance(
use winit::event;
let mut clipboard = Clipboard::connect(&window);
+ let ime = IME::connect(&window);
let mut cache = user_interface::Cache::default();
let mut surface = compositor.create_surface(&window);
@@ -261,6 +263,7 @@ async fn run_instance(
init_command,
&mut runtime,
&mut clipboard,
+ &ime,
&mut proxy,
&mut debug,
&window,
@@ -296,6 +299,7 @@ async fn run_instance(
state.cursor_position(),
&mut renderer,
&mut clipboard,
+ &ime,
&mut messages,
);
@@ -322,6 +326,7 @@ async fn run_instance(
&mut renderer,
&mut runtime,
&mut clipboard,
+ &ime,
&mut proxy,
&mut debug,
&mut messages,
@@ -534,13 +539,14 @@ where
/// Updates an [`Application`] by feeding it the provided messages, spawning any
/// resulting [`Command`], and tracking its [`Subscription`].
-pub fn update(
+pub fn update<'a, A: Application, E: Executor>(
application: &mut A,
cache: &mut user_interface::Cache,
state: &State,
renderer: &mut A::Renderer,
runtime: &mut Runtime, A::Message>,
clipboard: &mut Clipboard,
+ ime: &IME<'a>,
proxy: &mut winit::event_loop::EventLoopProxy,
debug: &mut Debug,
messages: &mut Vec,
@@ -564,6 +570,7 @@ pub fn update(
command,
runtime,
clipboard,
+ ime,
proxy,
debug,
window,
@@ -576,7 +583,7 @@ pub fn update(
}
/// Runs the actions of a [`Command`].
-pub fn run_command(
+pub fn run_command<'a, A, E>(
application: &A,
cache: &mut user_interface::Cache,
state: &State,
@@ -584,6 +591,7 @@ pub fn run_command(
command: Command,
runtime: &mut Runtime, A::Message>,
clipboard: &mut Clipboard,
+ ime: &IME<'a>,
proxy: &mut winit::event_loop::EventLoopProxy,
debug: &mut Debug,
window: &winit::window::Window,
@@ -614,6 +622,14 @@ pub fn run_command(
clipboard.write(contents);
}
},
+ command::Action::IME(action) => match action {
+ iced_native::ime::Action::Allow(allow) => {
+ ime.set_ime_allowed(allow);
+ }
+ iced_native::ime::Action::Position(x, y) => {
+ ime.set_ime_position(x, y);
+ }
+ },
command::Action::Window(action) => match action {
window::Action::Resize { width, height } => {
window.set_inner_size(winit::dpi::LogicalSize {
@@ -645,11 +661,6 @@ pub fn run_command(
.send_event(tag(mode))
.expect("Send message to event loop");
}
- window::Action::MoveIMECandidateWindow { x, y } => window
- .set_ime_position(winit::dpi::LogicalPosition { x, y }),
- window::Action::SetIMEAllow(allow) => {
- window.set_ime_allowed(allow)
- }
},
command::Action::System(action) => match action {
system::Action::QueryInformation(_tag) => {
diff --git a/winit/src/ime.rs b/winit/src/ime.rs
new file mode 100644
index 0000000000..6b36a2d9ad
--- /dev/null
+++ b/winit/src/ime.rs
@@ -0,0 +1,56 @@
+//! Access to winit ime related things.
+pub use iced_native::clipboard::Action;
+
+use crate::command::{self, Command};
+
+use winit::window::Window;
+
+/// IME related setting interface.
+///
+/// This is the wrapper of winit window reference so youd don't have to care about cost of initialize this struct.
+#[derive(Debug)]
+pub struct IME<'a> {
+ window: &'a Window,
+}
+
+impl<'a> IME<'a> {
+ /// connect to winit
+ pub fn connect(window: &'a Window) -> Self {
+ Self { window }
+ }
+}
+impl<'a> IME<'a> {
+ /// allow input by ime or not.
+ pub fn set_ime_allowed(&self, allowed: bool) {
+ self.window.set_ime_allowed(allowed)
+ }
+ /// set the logical position of IME candidate window.
+ pub fn set_ime_position(&self, x: i32, y: i32) {
+ self.window
+ .set_ime_position(winit::dpi::LogicalPosition { x, y })
+ }
+}
+
+impl<'a> iced_native::ime::IME for IME<'a> {
+ fn set_ime_allowed(&self, allowed: bool) {
+ self.set_ime_allowed(allowed)
+ }
+
+ fn set_ime_position(&self, x: i32, y: i32) {
+ self.set_ime_position(x, y)
+ }
+}
+
+/// allow input by ime or not.
+pub fn set_ime_allowed(allowed: bool) -> Command {
+ Command::single(command::Action::IME(iced_native::ime::Action::Allow(
+ allowed,
+ )))
+}
+
+/// set the logical position of IME candidate window.
+pub fn set_position(x: i32, y: i32) -> Command {
+ Command::single(command::Action::IME(iced_native::ime::Action::Position(
+ x, y,
+ )))
+}
diff --git a/winit/src/lib.rs b/winit/src/lib.rs
index edba887b22..4993666660 100644
--- a/winit/src/lib.rs
+++ b/winit/src/lib.rs
@@ -39,6 +39,7 @@ pub use winit;
pub mod application;
pub mod clipboard;
pub mod conversion;
+pub mod ime;
pub mod settings;
pub mod window;
diff --git a/winit/src/window.rs b/winit/src/window.rs
index aaa316c00b..265139f7ec 100644
--- a/winit/src/window.rs
+++ b/winit/src/window.rs
@@ -30,17 +30,3 @@ pub fn fetch_mode(
Box::new(f),
)))
}
-
-/// Set IME allowed on the window
-pub fn set_ime_allowed(allow: bool) -> Command {
- Command::single(command::Action::Window(window::Action::SetIMEAllow(allow)))
-}
-
-/// Set IME candidate position of the window.
-///
-/// position is logical position.
-pub fn set_ime_position(x: i32, y: i32) -> Command {
- Command::single(command::Action::Window(
- window::Action::MoveIMECandidateWindow { x, y },
- ))
-}