Skip to content

Commit 09526d4

Browse files
Merge branch 'iced-rs:master' into mouse_area_position
2 parents 49596cd + 782b96b commit 09526d4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1048
-356
lines changed

Cargo.lock

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/element.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ where
311311
fn update(
312312
&mut self,
313313
tree: &mut Tree,
314-
event: Event,
314+
event: &Event,
315315
layout: Layout<'_>,
316316
cursor: mouse::Cursor,
317317
renderer: &Renderer,
@@ -447,7 +447,7 @@ where
447447
fn update(
448448
&mut self,
449449
state: &mut Tree,
450-
event: Event,
450+
event: &Event,
451451
layout: Layout<'_>,
452452
cursor: mouse::Cursor,
453453
renderer: &Renderer,

core/src/event.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Handle events of a user interface.
2+
use crate::input_method;
23
use crate::keyboard;
34
use crate::mouse;
45
use crate::touch;
@@ -23,6 +24,9 @@ pub enum Event {
2324

2425
/// A touch event
2526
Touch(touch::Event),
27+
28+
/// An input method event
29+
InputMethod(input_method::Event),
2630
}
2731

2832
/// The status of an [`Event`] after being processed.

core/src/input_method.rs

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
//! Listen to input method events.
2+
use crate::Point;
3+
4+
use std::ops::Range;
5+
6+
/// The input method strategy of a widget.
7+
#[derive(Debug, Clone, PartialEq)]
8+
pub enum InputMethod<T = String> {
9+
/// No input method strategy has been specified.
10+
None,
11+
/// No input method is allowed.
12+
Disabled,
13+
/// Input methods are allowed, but not open yet.
14+
Allowed,
15+
/// Input method is open.
16+
Open {
17+
/// The position at which the input method dialog should be placed.
18+
position: Point,
19+
/// The [`Purpose`] of the input method.
20+
purpose: Purpose,
21+
/// The preedit to overlay on top of the input method dialog, if needed.
22+
///
23+
/// Ideally, your widget will show pre-edits on-the-spot; but, since that can
24+
/// be tricky, you can instead provide the current pre-edit here and the
25+
/// runtime will display it as an overlay (i.e. "Over-the-spot IME").
26+
preedit: Option<Preedit<T>>,
27+
},
28+
}
29+
30+
/// The pre-edit of an [`InputMethod`].
31+
#[derive(Debug, Clone, PartialEq, Default)]
32+
pub struct Preedit<T = String> {
33+
/// The current content.
34+
pub content: T,
35+
/// The selected range of the content.
36+
pub selection: Option<Range<usize>>,
37+
}
38+
39+
impl<T> Preedit<T> {
40+
/// Creates a new empty [`Preedit`].
41+
pub fn new() -> Self
42+
where
43+
T: Default,
44+
{
45+
Self::default()
46+
}
47+
48+
/// Turns a [`Preedit`] into its owned version.
49+
pub fn to_owned(&self) -> Preedit
50+
where
51+
T: AsRef<str>,
52+
{
53+
Preedit {
54+
content: self.content.as_ref().to_owned(),
55+
selection: self.selection.clone(),
56+
}
57+
}
58+
}
59+
60+
impl Preedit {
61+
/// Borrows the contents of a [`Preedit`].
62+
pub fn as_ref(&self) -> Preedit<&str> {
63+
Preedit {
64+
content: &self.content,
65+
selection: self.selection.clone(),
66+
}
67+
}
68+
}
69+
70+
/// The purpose of an [`InputMethod`].
71+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
72+
pub enum Purpose {
73+
/// No special hints for the IME (default).
74+
#[default]
75+
Normal,
76+
/// The IME is used for secure input (e.g. passwords).
77+
Secure,
78+
/// The IME is used to input into a terminal.
79+
///
80+
/// For example, that could alter OSK on Wayland to show extra buttons.
81+
Terminal,
82+
}
83+
84+
impl InputMethod {
85+
/// Merges two [`InputMethod`] strategies, prioritizing the first one when both open:
86+
/// ```
87+
/// # use iced_core::input_method::{InputMethod, Purpose, Preedit};
88+
/// # use iced_core::Point;
89+
///
90+
/// let open = InputMethod::Open {
91+
/// position: Point::ORIGIN,
92+
/// purpose: Purpose::Normal,
93+
/// preedit: Some(Preedit { content: "1".to_owned(), selection: None }),
94+
/// };
95+
///
96+
/// let open_2 = InputMethod::Open {
97+
/// position: Point::ORIGIN,
98+
/// purpose: Purpose::Secure,
99+
/// preedit: Some(Preedit { content: "2".to_owned(), selection: None }),
100+
/// };
101+
///
102+
/// let mut ime = InputMethod::Disabled;
103+
///
104+
/// ime.merge(&InputMethod::<String>::Allowed);
105+
/// assert_eq!(ime, InputMethod::Allowed);
106+
///
107+
/// ime.merge(&InputMethod::<String>::Disabled);
108+
/// assert_eq!(ime, InputMethod::Allowed);
109+
///
110+
/// ime.merge(&open);
111+
/// assert_eq!(ime, open);
112+
///
113+
/// ime.merge(&open_2);
114+
/// assert_eq!(ime, open);
115+
/// ```
116+
pub fn merge<T: AsRef<str>>(&mut self, other: &InputMethod<T>) {
117+
match (&self, other) {
118+
(InputMethod::Open { .. }, _)
119+
| (
120+
InputMethod::Allowed,
121+
InputMethod::None | InputMethod::Disabled,
122+
)
123+
| (InputMethod::Disabled, InputMethod::None) => {}
124+
_ => {
125+
*self = other.to_owned();
126+
}
127+
}
128+
}
129+
130+
/// Returns true if the [`InputMethod`] is open.
131+
pub fn is_open(&self) -> bool {
132+
matches!(self, Self::Open { .. })
133+
}
134+
}
135+
136+
impl<T> InputMethod<T> {
137+
/// Turns an [`InputMethod`] into its owned version.
138+
pub fn to_owned(&self) -> InputMethod
139+
where
140+
T: AsRef<str>,
141+
{
142+
match self {
143+
Self::None => InputMethod::None,
144+
Self::Disabled => InputMethod::Disabled,
145+
Self::Allowed => InputMethod::Allowed,
146+
Self::Open {
147+
position,
148+
purpose,
149+
preedit,
150+
} => InputMethod::Open {
151+
position: *position,
152+
purpose: *purpose,
153+
preedit: preedit.as_ref().map(Preedit::to_owned),
154+
},
155+
}
156+
}
157+
}
158+
159+
/// Describes [input method](https://en.wikipedia.org/wiki/Input_method) events.
160+
///
161+
/// This is also called a "composition event".
162+
///
163+
/// Most keypresses using a latin-like keyboard layout simply generate a
164+
/// [`keyboard::Event::KeyPressed`](crate::keyboard::Event::KeyPressed).
165+
/// However, one couldn't possibly have a key for every single
166+
/// unicode character that the user might want to type. The solution operating systems employ is
167+
/// to allow the user to type these using _a sequence of keypresses_ instead.
168+
///
169+
/// A prominent example of this is accents—many keyboard layouts allow you to first click the
170+
/// "accent key", and then the character you want to apply the accent to. In this case, some
171+
/// platforms will generate the following event sequence:
172+
///
173+
/// ```ignore
174+
/// // Press "`" key
175+
/// Ime::Preedit("`", Some((0, 0)))
176+
/// // Press "E" key
177+
/// Ime::Preedit("", None) // Synthetic event generated to clear preedit.
178+
/// Ime::Commit("é")
179+
/// ```
180+
///
181+
/// Additionally, certain input devices are configured to display a candidate box that allow the
182+
/// user to select the desired character interactively. (To properly position this box, you must use
183+
/// [`Shell::request_input_method`](crate::Shell::request_input_method).)
184+
///
185+
/// An example of a keyboard layout which uses candidate boxes is pinyin. On a latin keyboard the
186+
/// following event sequence could be obtained:
187+
///
188+
/// ```ignore
189+
/// // Press "A" key
190+
/// Ime::Preedit("a", Some((1, 1)))
191+
/// // Press "B" key
192+
/// Ime::Preedit("a b", Some((3, 3)))
193+
/// // Press left arrow key
194+
/// Ime::Preedit("a b", Some((1, 1)))
195+
/// // Press space key
196+
/// Ime::Preedit("啊b", Some((3, 3)))
197+
/// // Press space key
198+
/// Ime::Preedit("", None) // Synthetic event generated to clear preedit.
199+
/// Ime::Commit("啊不")
200+
/// ```
201+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
202+
pub enum Event {
203+
/// Notifies when the IME was opened.
204+
///
205+
/// After getting this event you could receive [`Preedit`][Self::Preedit] and
206+
/// [`Commit`][Self::Commit] events. You should also start performing IME related requests
207+
/// like [`Shell::request_input_method`].
208+
///
209+
/// [`Shell::request_input_method`]: crate::Shell::request_input_method
210+
Opened,
211+
212+
/// Notifies when a new composing text should be set at the cursor position.
213+
///
214+
/// The value represents a pair of the preedit string and the cursor begin position and end
215+
/// position. When it's `None`, the cursor should be hidden. When `String` is an empty string
216+
/// this indicates that preedit was cleared.
217+
///
218+
/// The cursor range is byte-wise indexed.
219+
Preedit(String, Option<Range<usize>>),
220+
221+
/// Notifies when text should be inserted into the editor widget.
222+
///
223+
/// Right before this event, an empty [`Self::Preedit`] event will be issued.
224+
Commit(String),
225+
226+
/// Notifies when the IME was disabled.
227+
///
228+
/// After receiving this event you won't get any more [`Preedit`][Self::Preedit] or
229+
/// [`Commit`][Self::Commit] events until the next [`Opened`][Self::Opened] event. You should
230+
/// also stop issuing IME related requests like [`Shell::request_input_method`] and clear
231+
/// pending preedit text.
232+
///
233+
/// [`Shell::request_input_method`]: crate::Shell::request_input_method
234+
Closed,
235+
}

core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub mod event;
1717
pub mod font;
1818
pub mod gradient;
1919
pub mod image;
20+
pub mod input_method;
2021
pub mod keyboard;
2122
pub mod layout;
2223
pub mod mouse;
@@ -61,6 +62,7 @@ pub use event::Event;
6162
pub use font::Font;
6263
pub use gradient::Gradient;
6364
pub use image::Image;
65+
pub use input_method::InputMethod;
6466
pub use layout::Layout;
6567
pub use length::Length;
6668
pub use overlay::Overlay;

0 commit comments

Comments
 (0)