From 0bd242cb1b0cf8ea34766b9effbc45b4fa8ffa87 Mon Sep 17 00:00:00 2001 From: FloVanGH Date: Tue, 3 Dec 2024 14:46:32 +0100 Subject: [PATCH] popup: close popup on escape press. (#6978) * Update internal/common/enums.rs Co-authored-by: Arnold Loubriat --------- Co-authored-by: Arnold Loubriat --- internal/common/enums.rs | 6 +- internal/core/window.rs | 14 +++ .../elements/popupwindow_close_policy.slint | 91 +++++++++++++++++-- tests/cases/elements/popupwindow_nested.slint | 15 +++ 4 files changed, 116 insertions(+), 10 deletions(-) diff --git a/internal/common/enums.rs b/internal/common/enums.rs index 48cf486187..b4794a1adc 100644 --- a/internal/common/enums.rs +++ b/internal/common/enums.rs @@ -434,13 +434,13 @@ macro_rules! for_each_enums { // This enum describes the close behaviour of [`PopupWindow`](elements.md#popupwindow) enum PopupClosePolicy { - /// Closes the `PopupWindow` when user clicks. + /// Closes the `PopupWindow` when user clicks or presses the escape key. CloseOnClick, - /// Closed the `PopupWindow` when user clicks outside of the popup. + /// Closes the `PopupWindow` when user clicks outside of the popup or presses the escape key. CloseOnClickOutside, - /// Does not close the `PopupWindow` automatically when user clicks + /// Does not close the `PopupWindow` automatically when user clicks. NoAutoClose, } ]; diff --git a/internal/core/window.rs b/internal/core/window.rs index 6912981d01..66475006cf 100644 --- a/internal/core/window.rs +++ b/internal/core/window.rs @@ -719,6 +719,20 @@ impl WindowInner { && !extra_mod { self.focus_previous_item(); + } else if event.event_type == KeyEventType::KeyPressed + && event.text.starts_with(key_codes::Escape) + { + // Closes top most popup on esc key pressed when policy is not no-auto-close + let close_on_escape = if let Some(popup) = self.active_popups.borrow().last() { + popup.close_policy == PopupClosePolicy::CloseOnClick + || popup.close_policy == PopupClosePolicy::CloseOnClickOutside + } else { + false + }; + + if close_on_escape { + self.close_top_popup(); + } } crate::properties::ChangeTracker::run_change_handlers(); } diff --git a/tests/cases/elements/popupwindow_close_policy.slint b/tests/cases/elements/popupwindow_close_policy.slint index 67df1e98fd..202676ce71 100644 --- a/tests/cases/elements/popupwindow_close_policy.slint +++ b/tests/cases/elements/popupwindow_close_policy.slint @@ -213,19 +213,25 @@ assert_eq!(instance.get_click_count(), 1); assert_eq!(instance.get_popup_created(), true); assert_eq!(instance.get_popup_clicked(), 1); +// Press esc nothing happen +slint_testing::send_keyboard_string_sequence(&instance, "\u{001b}"); +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq!(instance.get_click_count(), 1); +assert_eq!(instance.get_popup_clicked(), 1001); + // Click outside, nothing happens slint_testing::send_mouse_click(&instance, 1., 1.); assert_eq!(instance.get_click_count(), 1); -assert_eq!(instance.get_popup_clicked(), 1); +assert_eq!(instance.get_popup_clicked(), 1001); // Click on the popup, it's registered but nothing is done slint_testing::send_mouse_click(&instance, 15., 15.); assert_eq!(instance.get_click_count(), 1); -assert_eq!(instance.get_popup_clicked(), 1001); +assert_eq!(instance.get_popup_clicked(), 2001); // Click again to verify that it was _not_ closed slint_testing::send_mouse_click(&instance, 15., 15.); assert_eq!(instance.get_click_count(), 1); -assert_eq!(instance.get_popup_clicked(), 2001); +assert_eq!(instance.get_popup_clicked(), 3001); // Close manually and verify that subsequent click is passed through instance.invoke_do_close(); @@ -234,7 +240,7 @@ assert_eq!(instance.get_click_count(), 2); instance.invoke_do_close(); slint_testing::send_mouse_click(&instance, 15., 15.); assert_eq!(instance.get_click_count(), 3); -assert_eq!(instance.get_popup_clicked(), 2001); +assert_eq!(instance.get_popup_clicked(), 3001); // --------- Close outside click popup @@ -244,11 +250,11 @@ instance.set_click_count(0); slint_testing::send_mouse_click(&instance, 15., 15.); assert_eq!(instance.get_click_count(), 1); assert_eq!(instance.get_popup_created(), true); -assert_eq!(instance.get_popup_clicked(), 2001); +assert_eq!(instance.get_popup_clicked(), 3001); // click inside slint_testing::send_mouse_click(&instance, 15., 15.); -assert_eq!(instance.get_popup_clicked(), 2003); +assert_eq!(instance.get_popup_clicked(), 3003); // Click outside to close slint_testing::send_mouse_click(&instance, 5., 5.); @@ -256,9 +262,24 @@ assert_eq!(instance.get_click_count(), 1); // Subsequent click to verify that it was closed slint_testing::send_mouse_click(&instance, 5., 5.); assert_eq!(instance.get_click_count(), 2); -assert_eq!(instance.get_popup_clicked(), 2003); +assert_eq!(instance.get_popup_clicked(), 3003); +// --------- Close outside click popup by esc +instance.set_popup_selector(3); +instance.set_click_count(0); +slint_testing::send_mouse_click(&instance, 5., 5.); +assert_eq!(instance.get_click_count(), 1); + +// click inside +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq!(instance.get_popup_clicked(), 3005); + +// close by esc +slint_testing::send_keyboard_string_sequence(&instance, "\u{001b}"); +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq!(instance.get_click_count(), 2); + ``` ```cpp @@ -325,6 +346,8 @@ instance.set_popup_selector(1); instance.set_popup_created(false); instance.set_click_count(0); + + slint_testing::send_mouse_click(&instance, 15., 15.); assert_eq(instance.get_click_count(), 1); assert_eq(instance.get_popup_created(), true); @@ -379,6 +402,44 @@ instance.invoke_do_close(); slint_testing::send_mouse_click(&instance, 15., 15.); assert_eq(instance.get_click_count(), 3); assert_eq(instance.get_popup_clicked(), 2001); + + +// --------- Close outside click popup +instance.set_popup_selector(3); +instance.set_popup_created(false); +instance.set_click_count(0); +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq(instance.get_click_count(), 1); +assert_eq(instance.get_popup_created(), true); +assert_eq(instance.get_popup_clicked(), 2001); + +// click inside +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq(instance.get_popup_clicked(), 2003); + +// Click outside to close +slint_testing::send_mouse_click(&instance, 5., 5.); +assert_eq(instance.get_click_count(), 1); +// Subsequent click to verify that it was closed +slint_testing::send_mouse_click(&instance, 5., 5.); +assert_eq(instance.get_click_count(), 2); +assert_eq(instance.get_popup_clicked(), 2003); + + +// --------- Close outside click popup by esc +instance.set_popup_selector(3); +instance.set_click_count(0); +slint_testing::send_mouse_click(&instance, 5., 5.); +assert_eq(instance.get_click_count(), 1); + +// click inside +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq(instance.get_popup_clicked(), 2005); + +// close by esc +slint_testing::send_keyboard_string_sequence(&instance, "\u001b"); +slint_testing::send_mouse_click(&instance, 15., 15.); +assert_eq(instance.get_click_count(), 2); ``` ```disable-because-nodejs-runs-with-qt-and-send-mouse-click-wont-send-to-popup-qwindow @@ -450,6 +511,22 @@ assert.equal(instance.get_click_count(), 1); slintlib.private_api.send_mouse_click(instance, 15., 15.); assert.equal(instance.get_click_count(), 2); assert.equal(instance.get_popup_clicked(), 2003); + + +// --------- Close outside click popup by esc +instance.set_popup_selector(3); +instance.set_click_count(0); +slintlib.private_api.send_mouse_click(instance, 5., 5.); +assert.equal(instance.get_click_count(), 1); + +// click inside +slintlib.private_api.send_mouse_click(instance, 15., 15.); +assert.equal(instance.get_popup_clicked(), 2005); + +// close by esc +slintlib.private_api.send_keyboard_string_sequence(instance, "\u{001b}"); +slintlib.private_api.send_mouse_click(instance, 15., 15.); +assert.equal(instance.get_click_count(), 2); ``` */ diff --git a/tests/cases/elements/popupwindow_nested.slint b/tests/cases/elements/popupwindow_nested.slint index 02776dd367..7c8dc43812 100644 --- a/tests/cases/elements/popupwindow_nested.slint +++ b/tests/cases/elements/popupwindow_nested.slint @@ -290,6 +290,21 @@ instance.set_result("".into()); slint_testing::send_mouse_click(&instance, 210., 90.); assert_eq!(instance.get_result(), "P1"); instance.set_result("".into()); + +// close popup1 +slint_testing::send_mouse_click(&instance, 150., 210. + 40.); + +// open both popups +slint_testing::send_mouse_click(&instance, 380., 10.); + +// close popup1 by esc +slint_testing::send_keyboard_string_sequence(&instance, "\u{001b}"); + +// popup2 is still open +slint_testing::send_mouse_click(&instance, 40., 210. + 40.); +assert_eq!(instance.get_result(), "C2"); +instance.set_result("".into()); + ``` ```cpp