Skip to content

Commit

Permalink
Draft input_method support
Browse files Browse the repository at this point in the history
  • Loading branch information
kenz-gelsoft authored and hecrj committed Feb 2, 2025
1 parent 599d8b5 commit 043efc0
Show file tree
Hide file tree
Showing 13 changed files with 419 additions and 27 deletions.
4 changes: 4 additions & 0 deletions core/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Handle events of a user interface.
use crate::input_method;
use crate::keyboard;
use crate::mouse;
use crate::touch;
Expand All @@ -23,6 +24,9 @@ pub enum Event {

/// A touch event
Touch(touch::Event),

/// A input method event
InputMethod(input_method::Event),
}

/// The status of an [`Event`] after being processed.
Expand Down
24 changes: 24 additions & 0 deletions core/src/input_method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Listen to input method events.
/// A input method event.
///
/// _**Note:** This type is largely incomplete! If you need to track
/// additional events, feel free to [open an issue] and share your use case!_
///
/// [open an issue]: https://github.com/iced-rs/iced/issues
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Event {
// These events correspond to underlying winit ime events.
// https://docs.rs/winit/latest/winit/event/enum.Ime.html
/// the IME was enabled.
Enabled,

/// new composing text should be set at the cursor position.
Preedit(String, Option<(usize, usize)>),

/// text should be inserted into the editor widget.
Commit(String),

/// the IME was disabled.
Disabled,
}
2 changes: 2 additions & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod event;
pub mod font;
pub mod gradient;
pub mod image;
pub mod input_method;
pub mod keyboard;
pub mod layout;
pub mod mouse;
Expand Down Expand Up @@ -72,6 +73,7 @@ pub use renderer::Renderer;
pub use rotation::Rotation;
pub use settings::Settings;
pub use shadow::Shadow;
pub use shell::CaretInfo;
pub use shell::Shell;
pub use size::Size;
pub use svg::Svg;
Expand Down
25 changes: 24 additions & 1 deletion core/src/shell.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
use crate::event;
use crate::time::Instant;
use crate::window;
use crate::{event, Point};

/// TODO
#[derive(Clone, Copy, Debug)]
pub struct CaretInfo {
/// TODO
pub position: Point,
/// TODO
pub input_method_allowed: bool,
}

/// A connection to the state of a shell.
///
Expand All @@ -15,6 +24,7 @@ pub struct Shell<'a, Message> {
redraw_request: Option<window::RedrawRequest>,
is_layout_invalid: bool,
are_widgets_invalid: bool,
caret_info: Option<CaretInfo>,
}

impl<'a, Message> Shell<'a, Message> {
Expand All @@ -26,6 +36,7 @@ impl<'a, Message> Shell<'a, Message> {
redraw_request: None,
is_layout_invalid: false,
are_widgets_invalid: false,
caret_info: None,
}
}

Expand Down Expand Up @@ -80,6 +91,16 @@ impl<'a, Message> Shell<'a, Message> {
self.redraw_request
}

/// TODO
pub fn update_caret_info(&mut self, caret_info: Option<CaretInfo>) {
self.caret_info = caret_info.or(self.caret_info);
}

/// TODO
pub fn caret_info(&self) -> Option<CaretInfo> {
self.caret_info
}

/// Returns whether the current layout is invalid or not.
pub fn is_layout_invalid(&self) -> bool {
self.is_layout_invalid
Expand Down Expand Up @@ -130,6 +151,8 @@ impl<'a, Message> Shell<'a, Message> {
);
}

self.update_caret_info(other.caret_info());

self.is_layout_invalid =
self.is_layout_invalid || other.is_layout_invalid;

Expand Down
14 changes: 12 additions & 2 deletions runtime/src/user_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use crate::core::mouse;
use crate::core::renderer;
use crate::core::widget;
use crate::core::window;
use crate::core::{Clipboard, Element, Layout, Rectangle, Shell, Size, Vector};
use crate::core::{
CaretInfo, Clipboard, Element, Layout, Rectangle, Shell, Size, Vector,
};
use crate::overlay;

/// A set of interactive graphical elements with a specific [`Layout`].
Expand Down Expand Up @@ -187,6 +189,7 @@ where

let mut outdated = false;
let mut redraw_request = None;
let mut caret_info = None;

let mut manual_overlay = ManuallyDrop::new(
self.root
Expand Down Expand Up @@ -230,6 +233,7 @@ where
}
_ => {}
}
caret_info = caret_info.or(shell.caret_info());

if shell.is_layout_invalid() {
let _ = ManuallyDrop::into_inner(manual_overlay);
Expand Down Expand Up @@ -332,6 +336,7 @@ where
}
_ => {}
}
caret_info = caret_info.or(shell.caret_info());

shell.revalidate_layout(|| {
self.base = self.root.as_widget().layout(
Expand All @@ -355,7 +360,10 @@ where
if outdated {
State::Outdated
} else {
State::Updated { redraw_request }
State::Updated {
redraw_request,
caret_info,
}
},
event_statuses,
)
Expand Down Expand Up @@ -646,5 +654,7 @@ pub enum State {
Updated {
/// The [`window::RedrawRequest`] when a redraw should be performed.
redraw_request: Option<window::RedrawRequest>,
/// TODO
caret_info: Option<CaretInfo>,
},
}
6 changes: 5 additions & 1 deletion widget/src/combo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ where
}
}
}
shell.update_caret_info(local_shell.caret_info());

// Then finally react to them here
for message in local_messages {
Expand Down Expand Up @@ -742,6 +743,8 @@ where
published_message_to_shell = true;

// Unfocus the input
let mut local_messages = Vec::new();
let mut local_shell = Shell::new(&mut local_messages);
self.text_input.update(
&mut tree.children[0],
Event::Mouse(mouse::Event::ButtonPressed(
Expand All @@ -751,9 +754,10 @@ where
mouse::Cursor::Unavailable,
renderer,
clipboard,
&mut Shell::new(&mut vec![]),
&mut local_shell,
viewport,
);
shell.update_caret_info(local_shell.caret_info());
}
});

Expand Down
2 changes: 2 additions & 0 deletions widget/src/lazy/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ where
}
}
}
shell.update_caret_info(local_shell.caret_info());

if !local_messages.is_empty() {
let mut heads = self.state.take().unwrap().into_heads();
Expand Down Expand Up @@ -640,6 +641,7 @@ where
}
}
}
shell.update_caret_info(local_shell.caret_info());

if !local_messages.is_empty() {
let mut inner =
Expand Down
18 changes: 16 additions & 2 deletions widget/src/scrollable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ use crate::core::widget::operation::{self, Operation};
use crate::core::widget::tree::{self, Tree};
use crate::core::window;
use crate::core::{
self, Background, Clipboard, Color, Element, Event, Layout, Length,
Padding, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget,
self, Background, CaretInfo, Clipboard, Color, Element, Event, Layout,
Length, Padding, Pixels, Point, Rectangle, Shell, Size, Theme, Vector,
Widget,
};
use crate::runtime::task::{self, Task};
use crate::runtime::Action;
Expand Down Expand Up @@ -729,6 +730,7 @@ where
let translation =
state.translation(self.direction, bounds, content_bounds);

let children_may_have_caret = shell.caret_info().is_none();
self.content.as_widget_mut().update(
&mut tree.children[0],
event.clone(),
Expand All @@ -743,6 +745,18 @@ where
..bounds
},
);

if children_may_have_caret {
if let Some(caret_info) = shell.caret_info() {
shell.update_caret_info(Some(CaretInfo {
position: Point::new(
caret_info.position.x - translation.x,
caret_info.position.y - translation.y,
),
input_method_allowed: caret_info.input_method_allowed,
}));
}
}
};

if matches!(
Expand Down
69 changes: 66 additions & 3 deletions widget/src/text_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
//! ```
use crate::core::alignment;
use crate::core::clipboard::{self, Clipboard};
use crate::core::input_method;
use crate::core::keyboard;
use crate::core::keyboard::key;
use crate::core::layout::{self, Layout};
Expand All @@ -46,8 +47,8 @@ use crate::core::widget::operation;
use crate::core::widget::{self, Widget};
use crate::core::window;
use crate::core::{
Background, Border, Color, Element, Event, Length, Padding, Pixels, Point,
Rectangle, Shell, Size, SmolStr, Theme, Vector,
Background, Border, CaretInfo, Color, Element, Event, Length, Padding,
Pixels, Point, Rectangle, Shell, Size, SmolStr, Theme, Vector,
};

use std::borrow::Cow;
Expand Down Expand Up @@ -322,6 +323,46 @@ where
self.class = class.into();
self
}

fn caret_rect(
&self,
tree: &widget::Tree,
renderer: &Renderer,
layout: Layout<'_>,
) -> Option<Rectangle> {
let bounds = layout.bounds();

let internal = self.content.0.borrow_mut();
let state = tree.state.downcast_ref::<State<Highlighter>>();

let text_bounds = bounds.shrink(self.padding);
let translation = text_bounds.position() - Point::ORIGIN;

if let Some(_) = state.focus.as_ref() {
let position = match internal.editor.cursor() {
Cursor::Caret(position) => position,
Cursor::Selection(ranges) => ranges
.first()
.cloned()
.unwrap_or(Rectangle::default())
.position(),
};
Some(Rectangle::new(
position + translation,
Size::new(
1.0,
self.line_height
.to_absolute(
self.text_size
.unwrap_or_else(|| renderer.default_size()),
)
.into(),
),
))
} else {
None
}
}
}

/// The content of a [`TextEditor`].
Expand Down Expand Up @@ -605,7 +646,7 @@ where
event: Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
_renderer: &Renderer,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
_viewport: &Rectangle,
Expand Down Expand Up @@ -701,6 +742,11 @@ where
}));
shell.capture_event();
}
Update::Commit(text) => {
shell.publish(on_edit(Action::Edit(Edit::Paste(
Arc::new(text),
))));
}
Update::Binding(binding) => {
fn apply_binding<
H: text::Highlighter,
Expand Down Expand Up @@ -825,6 +871,19 @@ where
}
};

shell.update_caret_info(if state.is_focused() {
let rect = self
.caret_rect(tree, renderer, layout)
.unwrap_or(Rectangle::default());
let bottom_left = Point::new(rect.x, rect.y + rect.height);
Some(CaretInfo {
position: bottom_left,
input_method_allowed: true,
})
} else {
None
});

if is_redraw {
self.last_status = Some(status);
} else if self
Expand Down Expand Up @@ -1129,6 +1188,7 @@ enum Update<Message> {
Drag(Point),
Release,
Scroll(f32),
Commit(String),
Binding(Binding<Message>),
}

Expand Down Expand Up @@ -1191,6 +1251,9 @@ impl<Message> Update<Message> {
}
_ => None,
},
Event::InputMethod(input_method::Event::Commit(text)) => {
Some(Update::Commit(text))
}
Event::Keyboard(keyboard::Event::KeyPressed {
key,
modifiers,
Expand Down
Loading

0 comments on commit 043efc0

Please sign in to comment.