mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
ContextMenu on the LineEdit and TextEdit
With usual copy/paste entries We need to make sure that showing the popup window don't clear the selection in the TextInput which happens if the TextInput gets a FocusOut event.
This commit is contained in:
parent
9195f3e265
commit
c85b20d431
7 changed files with 223 additions and 139 deletions
|
@ -67,38 +67,57 @@ export component LineEditBase inherits Rectangle {
|
|||
accessible-role: none;
|
||||
}
|
||||
|
||||
text-input := TextInput {
|
||||
property <length> computed-x;
|
||||
ContextMenu {
|
||||
MenuItem {
|
||||
title: @tr("Cut");
|
||||
activated => { text-input.cut(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Copy");
|
||||
activated => { text-input.copy(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Paste");
|
||||
activated => { text-input.paste(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Select All");
|
||||
activated => { text-input.select-all(); }
|
||||
}
|
||||
|
||||
x: min(0px, max(parent.width - self.width - self.text-cursor-width, self.computed-x));
|
||||
width: max(parent.width - self.text-cursor-width, self.preferred-width);
|
||||
height: 100%;
|
||||
vertical-alignment: center;
|
||||
single-line: true;
|
||||
color: root.text-color;
|
||||
text-input := TextInput {
|
||||
property <length> computed-x;
|
||||
|
||||
cursor-position-changed(cursor-position) => {
|
||||
if cursor-position.x + self.computed_x < root.margin {
|
||||
self.computed_x = - cursor-position.x + root.margin;
|
||||
} else if cursor-position.x + self.computed_x > parent.width - root.margin - self.text-cursor-width {
|
||||
self.computed_x = parent.width - cursor-position.x - root.margin - self.text-cursor-width;
|
||||
x: min(0px, max(parent.width - self.width - self.text-cursor-width, self.computed-x));
|
||||
width: max(parent.width - self.text-cursor-width, self.preferred-width);
|
||||
height: 100%;
|
||||
vertical-alignment: center;
|
||||
single-line: true;
|
||||
color: root.text-color;
|
||||
|
||||
cursor-position-changed(cursor-position) => {
|
||||
if cursor-position.x + self.computed_x < root.margin {
|
||||
self.computed_x = - cursor-position.x + root.margin;
|
||||
} else if cursor-position.x + self.computed_x > parent.width - root.margin - self.text-cursor-width {
|
||||
self.computed_x = parent.width - cursor-position.x - root.margin - self.text-cursor-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
accepted => {
|
||||
root.accepted(self.text);
|
||||
}
|
||||
accepted => {
|
||||
root.accepted(self.text);
|
||||
}
|
||||
|
||||
edited => {
|
||||
root.edited(self.text);
|
||||
}
|
||||
edited => {
|
||||
root.edited(self.text);
|
||||
}
|
||||
|
||||
key-pressed(event) => {
|
||||
root.key-pressed(event)
|
||||
}
|
||||
key-pressed(event) => {
|
||||
root.key-pressed(event)
|
||||
}
|
||||
|
||||
key-released(event) => {
|
||||
root.key-released(event)
|
||||
key-released(event) => {
|
||||
root.key-released(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,48 +58,68 @@ export component TextEditBase inherits Rectangle {
|
|||
|
||||
forward-focus: text-input;
|
||||
|
||||
scroll-view := ScrollView {
|
||||
x: root.scroll-view-padding;
|
||||
y: root.scroll-view-padding;
|
||||
width: parent.width - 2 * root.scroll-view-padding;
|
||||
height: parent.height - 2 * root.scroll-view-padding;
|
||||
viewport-width: root.wrap == TextWrap.no-wrap ? max(self.visible-width, text-input.preferred-width) : self.visible-width;
|
||||
viewport-height: max(self.visible-height, text-input.preferred-height);
|
||||
ContextMenu {
|
||||
MenuItem {
|
||||
title: @tr("Cut");
|
||||
activated => { text-input.cut(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Copy");
|
||||
activated => { text-input.copy(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Paste");
|
||||
activated => { text-input.paste(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Select All");
|
||||
activated => { text-input.select-all(); }
|
||||
}
|
||||
|
||||
text-input := TextInput {
|
||||
enabled: true;
|
||||
single-line: false;
|
||||
wrap: word-wrap;
|
||||
selection-background-color: root.selection-background-color;
|
||||
selection-foreground-color: root.selection-foreground-color;
|
||||
page-height: scroll-view.visible-height;
|
||||
scroll-view := ScrollView {
|
||||
x: root.scroll-view-padding;
|
||||
y: root.scroll-view-padding;
|
||||
width: parent.width - 2 * root.scroll-view-padding;
|
||||
height: parent.height - 2 * root.scroll-view-padding;
|
||||
viewport-width: root.wrap == TextWrap.no-wrap ? max(self.visible-width, text-input.preferred-width) : self.visible-width;
|
||||
viewport-height: max(self.visible-height, text-input.preferred-height);
|
||||
|
||||
edited => {
|
||||
root.edited(self.text);
|
||||
}
|
||||
text-input := TextInput {
|
||||
enabled: true;
|
||||
single-line: false;
|
||||
wrap: word-wrap;
|
||||
selection-background-color: root.selection-background-color;
|
||||
selection-foreground-color: root.selection-foreground-color;
|
||||
page-height: scroll-view.visible-height;
|
||||
|
||||
key-pressed(event) => {
|
||||
root.key-pressed(event)
|
||||
}
|
||||
|
||||
key-released(event) => {
|
||||
root.key-released(event)
|
||||
}
|
||||
|
||||
cursor-position-changed(cpos) => {
|
||||
if (cpos.x + root.viewport-x < 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, - cpos.x + 12px));
|
||||
} else if (cpos.x + root.viewport-x > parent.visible-width - 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, parent.visible-width - cpos.x - 12px));
|
||||
edited => {
|
||||
root.edited(self.text);
|
||||
}
|
||||
if (cpos.y + root.viewport-y < 12px) {
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, - cpos.y + 12px));
|
||||
} else if (cpos.y + root.viewport-y > parent.visible-height - 12px - 20px) {
|
||||
// FIXME: font-height hardcoded to 20px
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, parent.visible-height - cpos.y - 12px - 20px));
|
||||
|
||||
key-pressed(event) => {
|
||||
root.key-pressed(event)
|
||||
}
|
||||
|
||||
key-released(event) => {
|
||||
root.key-released(event)
|
||||
}
|
||||
|
||||
cursor-position-changed(cpos) => {
|
||||
if (cpos.x + root.viewport-x < 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, - cpos.x + 12px));
|
||||
} else if (cpos.x + root.viewport-x > parent.visible-width - 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, parent.visible-width - cpos.x - 12px));
|
||||
}
|
||||
if (cpos.y + root.viewport-y < 12px) {
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, - cpos.y + 12px));
|
||||
} else if (cpos.y + root.viewport-y > parent.visible-height - 12px - 20px) {
|
||||
// FIXME: font-height hardcoded to 20px
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, parent.visible-height - cpos.y - 12px - 20px));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
placeholder := Text {
|
||||
|
|
|
@ -138,48 +138,67 @@ export component TextEdit {
|
|||
border-width: 1px;
|
||||
}
|
||||
|
||||
scroll-view := ScrollView {
|
||||
x: 8px;
|
||||
y: 8px;
|
||||
width: parent.width - 16px;
|
||||
height: parent.height - 16px;
|
||||
viewport-width: root.wrap == TextWrap.no-wrap ? max(self.visible-width, text-input.preferred-width) : self.visible-width;
|
||||
viewport-height: max(self.visible-height, text-input.preferred-height);
|
||||
ContextMenu {
|
||||
MenuItem {
|
||||
title: @tr("Cut");
|
||||
activated => { text-input.cut(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Copy");
|
||||
activated => { text-input.copy(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Paste");
|
||||
activated => { text-input.paste(); }
|
||||
}
|
||||
MenuItem {
|
||||
title: @tr("Select All");
|
||||
activated => { text-input.select-all(); }
|
||||
}
|
||||
|
||||
text-input := TextInput {
|
||||
enabled: true;
|
||||
color: CupertinoPalette.foreground;
|
||||
font-size: CupertinoFontSettings.body.font-size;
|
||||
font-weight: CupertinoFontSettings.body.font-weight;
|
||||
selection-background-color: CupertinoPalette.selection-background;
|
||||
selection-foreground-color: self.color;
|
||||
single-line: false;
|
||||
wrap: word-wrap;
|
||||
page-height: scroll-view.visible-height;
|
||||
scroll-view := ScrollView {
|
||||
x: 8px;
|
||||
y: 8px;
|
||||
width: parent.width - 16px;
|
||||
height: parent.height - 16px;
|
||||
viewport-width: root.wrap == TextWrap.no-wrap ? max(self.visible-width, text-input.preferred-width) : self.visible-width;
|
||||
viewport-height: max(self.visible-height, text-input.preferred-height);
|
||||
|
||||
edited => {
|
||||
root.edited(self.text);
|
||||
}
|
||||
text-input := TextInput {
|
||||
enabled: true;
|
||||
color: CupertinoPalette.foreground;
|
||||
font-size: CupertinoFontSettings.body.font-size;
|
||||
font-weight: CupertinoFontSettings.body.font-weight;
|
||||
selection-background-color: CupertinoPalette.selection-background;
|
||||
selection-foreground-color: self.color;
|
||||
single-line: false;
|
||||
wrap: word-wrap;
|
||||
page-height: scroll-view.visible-height;
|
||||
|
||||
key-pressed(event) => {
|
||||
root.key-pressed(event)
|
||||
}
|
||||
|
||||
key-released(event) => {
|
||||
root.key-released(event)
|
||||
}
|
||||
|
||||
cursor-position-changed(cpos) => {
|
||||
if (cpos.x + root.viewport-x < 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, - cpos.x + 12px));
|
||||
} else if (cpos.x + root.viewport-x > parent.visible-width - 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, parent.visible-width - cpos.x - 12px));
|
||||
edited => {
|
||||
root.edited(self.text);
|
||||
}
|
||||
if (cpos.y + root.viewport-y < 12px) {
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, - cpos.y + 12px));
|
||||
} else if (cpos.y + root.viewport-y > parent.visible-height - 12px - 20px) {
|
||||
// FIXME: font-height hardcoded to 20px
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, parent.visible-height - cpos.y - 12px - 20px));
|
||||
|
||||
key-pressed(event) => {
|
||||
root.key-pressed(event)
|
||||
}
|
||||
|
||||
key-released(event) => {
|
||||
root.key-released(event)
|
||||
}
|
||||
|
||||
cursor-position-changed(cpos) => {
|
||||
if (cpos.x + root.viewport-x < 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, - cpos.x + 12px));
|
||||
} else if (cpos.x + root.viewport-x > parent.visible-width - 12px) {
|
||||
root.viewport-x = min(0px, max(parent.visible-width - self.width, parent.visible-width - cpos.x - 12px));
|
||||
}
|
||||
if (cpos.y + root.viewport-y < 12px) {
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, - cpos.y + 12px));
|
||||
} else if (cpos.y + root.viewport-y > parent.visible-height - 12px - 20px) {
|
||||
// FIXME: font-height hardcoded to 20px
|
||||
root.viewport-y = min(0px, max(parent.visible-height - self.height, parent.visible-height - cpos.y - 12px - 20px));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -466,7 +466,7 @@ pub enum FocusEvent {
|
|||
FocusOut,
|
||||
/// This event is sent when the window receives the keyboard focus.
|
||||
WindowReceivedFocus,
|
||||
/// This event is sent when the window looses the keyboard focus.
|
||||
/// This event is sent when the window looses the keyboard focus. (including if this is because of a popup)
|
||||
WindowLostFocus,
|
||||
}
|
||||
|
||||
|
|
|
@ -640,7 +640,7 @@ impl Item for TextInput {
|
|||
|
||||
return InputEventResult::GrabMouse;
|
||||
}
|
||||
MouseEvent::Pressed { .. } => {
|
||||
MouseEvent::Pressed { button: PointerEventButton::Middle, .. } => {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.ensure_focus_and_ime(window_adapter, self_rc);
|
||||
}
|
||||
|
@ -663,8 +663,6 @@ impl Item for TextInput {
|
|||
);
|
||||
self.paste_clipboard(window_adapter, self_rc, Clipboard::SelectionClipboard);
|
||||
}
|
||||
// Other mouse buttons should still be accepted even if we don't handle them
|
||||
MouseEvent::Released { .. } => {}
|
||||
MouseEvent::Exit => {
|
||||
if let Some(x) = window_adapter.internal(crate::InternalToken) {
|
||||
x.set_mouse_cursor(super::MouseCursor::Default);
|
||||
|
|
|
@ -11,8 +11,8 @@ use crate::api::{
|
|||
WindowPosition, WindowSize,
|
||||
};
|
||||
use crate::input::{
|
||||
key_codes, ClickState, InternalKeyboardModifierState, KeyEvent, KeyEventType, MouseEvent,
|
||||
MouseInputState, TextCursorBlinker,
|
||||
key_codes, ClickState, FocusEvent, InternalKeyboardModifierState, KeyEvent, KeyEventType,
|
||||
MouseEvent, MouseInputState, TextCursorBlinker,
|
||||
};
|
||||
use crate::item_tree::{ItemRc, ItemTreeRc, ItemTreeRef, ItemTreeVTable, ItemTreeWeak, ItemWeak};
|
||||
use crate::items::{ColorScheme, InputType, ItemRef, MouseCursor, PopupClosePolicy};
|
||||
|
@ -719,7 +719,7 @@ impl WindowInner {
|
|||
|
||||
if item.as_ref().is_some_and(|i| !i.is_visible()) {
|
||||
// Reset the focus... not great, but better than keeping it.
|
||||
self.take_focus_item();
|
||||
self.take_focus_item(&FocusEvent::FocusOut);
|
||||
item = None;
|
||||
}
|
||||
|
||||
|
@ -820,7 +820,7 @@ impl WindowInner {
|
|||
}
|
||||
}
|
||||
|
||||
let old = self.take_focus_item();
|
||||
let old = self.take_focus_item(&FocusEvent::FocusOut);
|
||||
let new =
|
||||
if set_focus { self.move_focus(new_focus_item.clone(), next_focus_item) } else { None };
|
||||
let window_adapter = self.window_adapter();
|
||||
|
@ -831,13 +831,14 @@ impl WindowInner {
|
|||
|
||||
/// Take the focus_item out of this Window
|
||||
///
|
||||
/// This sends the FocusOut event!
|
||||
fn take_focus_item(&self) -> Option<ItemRc> {
|
||||
/// This sends the event whiwh must be either FocusOut or WindowLostFocus for popups
|
||||
fn take_focus_item(&self, event: &FocusEvent) -> Option<ItemRc> {
|
||||
let focus_item = self.focus_item.take();
|
||||
assert!(matches!(event, FocusEvent::FocusOut | FocusEvent::WindowLostFocus));
|
||||
|
||||
if let Some(focus_item_rc) = focus_item.upgrade() {
|
||||
focus_item_rc.borrow().as_ref().focus_event(
|
||||
&crate::input::FocusEvent::FocusOut,
|
||||
event,
|
||||
&self.window_adapter(),
|
||||
&focus_item_rc,
|
||||
);
|
||||
|
@ -855,7 +856,7 @@ impl WindowInner {
|
|||
Some(item) => {
|
||||
*self.focus_item.borrow_mut() = item.downgrade();
|
||||
item.borrow().as_ref().focus_event(
|
||||
&crate::input::FocusEvent::FocusIn,
|
||||
&FocusEvent::FocusIn,
|
||||
&self.window_adapter(),
|
||||
item,
|
||||
)
|
||||
|
@ -889,15 +890,16 @@ impl WindowInner {
|
|||
|
||||
/// Move keyboard focus to the next item
|
||||
pub fn focus_next_item(&self) {
|
||||
let start_item = self.take_focus_item().map(next_focus_item).unwrap_or_else(|| {
|
||||
ItemRc::new(
|
||||
self.active_popups
|
||||
.borrow()
|
||||
.last()
|
||||
.map_or_else(|| self.component(), |p| p.component.clone()),
|
||||
0,
|
||||
)
|
||||
});
|
||||
let start_item =
|
||||
self.take_focus_item(&FocusEvent::FocusOut).map(next_focus_item).unwrap_or_else(|| {
|
||||
ItemRc::new(
|
||||
self.active_popups
|
||||
.borrow()
|
||||
.last()
|
||||
.map_or_else(|| self.component(), |p| p.component.clone()),
|
||||
0,
|
||||
)
|
||||
});
|
||||
let end_item = self.move_focus(start_item.clone(), next_focus_item);
|
||||
let window_adapter = self.window_adapter();
|
||||
if let Some(window_adapter) = window_adapter.internal(crate::InternalToken) {
|
||||
|
@ -907,15 +909,16 @@ impl WindowInner {
|
|||
|
||||
/// Move keyboard focus to the previous item.
|
||||
pub fn focus_previous_item(&self) {
|
||||
let start_item = previous_focus_item(self.take_focus_item().unwrap_or_else(|| {
|
||||
ItemRc::new(
|
||||
self.active_popups
|
||||
.borrow()
|
||||
.last()
|
||||
.map_or_else(|| self.component(), |p| p.component.clone()),
|
||||
0,
|
||||
)
|
||||
}));
|
||||
let start_item =
|
||||
previous_focus_item(self.take_focus_item(&FocusEvent::FocusOut).unwrap_or_else(|| {
|
||||
ItemRc::new(
|
||||
self.active_popups
|
||||
.borrow()
|
||||
.last()
|
||||
.map_or_else(|| self.component(), |p| p.component.clone()),
|
||||
0,
|
||||
)
|
||||
}));
|
||||
let end_item = self.move_focus(start_item.clone(), previous_focus_item);
|
||||
let window_adapter = self.window_adapter();
|
||||
if let Some(window_adapter) = window_adapter.internal(crate::InternalToken) {
|
||||
|
@ -931,11 +934,8 @@ impl WindowInner {
|
|||
pub fn set_active(&self, have_focus: bool) {
|
||||
self.pinned_fields.as_ref().project_ref().active.set(have_focus);
|
||||
|
||||
let event = if have_focus {
|
||||
crate::input::FocusEvent::WindowReceivedFocus
|
||||
} else {
|
||||
crate::input::FocusEvent::WindowLostFocus
|
||||
};
|
||||
let event =
|
||||
if have_focus { FocusEvent::WindowReceivedFocus } else { FocusEvent::WindowLostFocus };
|
||||
|
||||
if let Some(focus_item) = self.focus_item.borrow().upgrade() {
|
||||
focus_item.borrow().as_ref().focus_event(&event, &self.window_adapter(), &focus_item);
|
||||
|
@ -1163,7 +1163,10 @@ impl WindowInner {
|
|||
}
|
||||
};
|
||||
|
||||
let focus_item = self.take_focus_item().map(|item| item.downgrade()).unwrap_or_default();
|
||||
let focus_item = self
|
||||
.take_focus_item(&FocusEvent::WindowLostFocus)
|
||||
.map(|item| item.downgrade())
|
||||
.unwrap_or_default();
|
||||
|
||||
self.active_popups.borrow_mut().push(PopupWindow {
|
||||
popup_id,
|
||||
|
|
|
@ -14,7 +14,10 @@ export component TestCase inherits Window {
|
|||
forward-focus: edit;
|
||||
out property <bool> textedit-focused <=> edit.has_focus;
|
||||
callback edited <=> edit.edited;
|
||||
out property <string> text <=> edit.text;
|
||||
in-out property <string> text <=> edit.text;
|
||||
public function paste() {
|
||||
edit.paste();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -46,10 +49,10 @@ assert_eq!(edits.borrow().clone(), vec!["h", "he", "hel", "hell", "hello"]);
|
|||
use slint::{LogicalPosition, platform::{WindowEvent, PointerEventButton}};
|
||||
use slint::private_unstable_api::re_exports::MouseCursor;
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "after previous click");
|
||||
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(50.0, 50.0), button: PointerEventButton::Right });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "right button pressed");
|
||||
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(50.0, 50.0), button: PointerEventButton::Right });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "right button released");
|
||||
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(50.0, 50.0), button: PointerEventButton::Middle });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "Middle button pressed");
|
||||
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(50.0, 50.0), button: PointerEventButton::Middle });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Text, "Middle button released");
|
||||
instance.window().dispatch_event(WindowEvent::PointerExited { });
|
||||
assert_eq!(slint_testing::access_testing_window(instance.window(), |window| window.mouse_cursor.get()), MouseCursor::Default);
|
||||
|
||||
|
@ -68,6 +71,28 @@ slint_testing::send_keyboard_string_sequence(&instance, "XX");
|
|||
let test = instance.get_text();
|
||||
// The exact position depends on the size of the content which depends on the style, but it should be in the middle
|
||||
assert!(test.contains("\nThis iXXs line"));
|
||||
|
||||
// use the menu key to pen the menu and choose select call
|
||||
instance.set_text("Hello👋".into());
|
||||
assert_eq!(instance.get_text(), "Hello👋");
|
||||
// select all
|
||||
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(slint::platform::Key::Menu));
|
||||
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(slint::platform::Key::UpArrow));
|
||||
slint_testing::send_keyboard_string_sequence(&instance, "\n");
|
||||
assert_eq!(instance.get_text(), "Hello👋");
|
||||
// copy
|
||||
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(slint::platform::Key::Menu));
|
||||
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(slint::platform::Key::DownArrow));
|
||||
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(slint::platform::Key::DownArrow));
|
||||
slint_testing::send_keyboard_string_sequence(&instance, "\n");
|
||||
assert_eq!(instance.get_text(), "Hello👋");
|
||||
|
||||
slint_testing::send_keyboard_string_sequence(&instance, "Xxx");
|
||||
assert_eq!(instance.get_text(), "Xxx");
|
||||
instance.invoke_paste();
|
||||
assert_eq!(instance.get_text(), "XxxHello👋");
|
||||
|
||||
|
||||
```
|
||||
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue