summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorZaggy1024 <zaggy1024@gmail.com>2022-10-24 19:05:40 -0500
committerSam Atkins <atkinssj@gmail.com>2022-11-14 16:08:11 +0000
commit967dfa79563f5fa83aa27275bd57fc616a57ce55 (patch)
treeeaf721787d55543ba48eed0752954c4c47662ed0 /Userland/Libraries
parent8e7c7e0a2a0279764c4aedd59e29943b7935039d (diff)
downloadserenity-967dfa79563f5fa83aa27275bd57fc616a57ce55.zip
LibGUI: Handle Action keyboard shortcuts in Widget keydown
Widgets can now prevent shortcut Actions from being called, which allows text input keydown handlers to override single key shortcuts.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibGUI/Action.cpp16
-rw-r--r--Userland/Libraries/LibGUI/Action.h1
-rw-r--r--Userland/Libraries/LibGUI/ConnectionToWindowServer.cpp10
-rw-r--r--Userland/Libraries/LibGUI/Widget.cpp12
-rw-r--r--Userland/Libraries/LibGUI/Window.cpp44
-rw-r--r--Userland/Libraries/LibGUI/Window.h2
6 files changed, 72 insertions, 13 deletions
diff --git a/Userland/Libraries/LibGUI/Action.cpp b/Userland/Libraries/LibGUI/Action.cpp
index 1ac2417b75..5408c02ac0 100644
--- a/Userland/Libraries/LibGUI/Action.cpp
+++ b/Userland/Libraries/LibGUI/Action.cpp
@@ -125,6 +125,22 @@ Action::~Action()
}
}
+void Action::process_event(Window& window, Event& event)
+{
+ if (is_enabled()) {
+ flash_menubar_menu(window);
+ activate();
+ event.accept();
+ return;
+ }
+ if (swallow_key_event_when_disabled()) {
+ event.accept();
+ return;
+ }
+
+ event.ignore();
+}
+
void Action::activate(Core::Object* activator)
{
if (!on_activation)
diff --git a/Userland/Libraries/LibGUI/Action.h b/Userland/Libraries/LibGUI/Action.h
index 87c5762b6b..efe0f1c5fe 100644
--- a/Userland/Libraries/LibGUI/Action.h
+++ b/Userland/Libraries/LibGUI/Action.h
@@ -97,6 +97,7 @@ public:
Function<void(Action&)> on_activation;
void activate(Core::Object* activator = nullptr);
+ void process_event(Window& window, Event& event);
void flash_menubar_menu(GUI::Window& window);
bool is_enabled() const { return m_enabled; }
diff --git a/Userland/Libraries/LibGUI/ConnectionToWindowServer.cpp b/Userland/Libraries/LibGUI/ConnectionToWindowServer.cpp
index 6a29e66a62..e9060080b9 100644
--- a/Userland/Libraries/LibGUI/ConnectionToWindowServer.cpp
+++ b/Userland/Libraries/LibGUI/ConnectionToWindowServer.cpp
@@ -188,16 +188,6 @@ void ConnectionToWindowServer::key_down(i32 window_id, u32 code_point, u32 key,
auto key_event = make<KeyEvent>(Event::KeyDown, (KeyCode)key, modifiers, code_point, scancode);
- if (auto* action = action_for_shortcut(*window, Shortcut(key_event->modifiers(), key_event->key()))) {
- if (action->is_enabled()) {
- action->flash_menubar_menu(*window);
- action->activate();
- return;
- }
- if (action->swallow_key_event_when_disabled())
- return;
- }
-
bool focused_widget_accepts_emoji_input = window->focused_widget() && window->focused_widget()->on_emoji_input;
if (!window->blocks_emoji_input() && focused_widget_accepts_emoji_input && (modifiers == (Mod_Ctrl | Mod_Alt)) && key == Key_Space) {
auto emoji_input_dialog = EmojiInputDialog::construct(window);
diff --git a/Userland/Libraries/LibGUI/Widget.cpp b/Userland/Libraries/LibGUI/Widget.cpp
index 1def39c505..b92e0e6a98 100644
--- a/Userland/Libraries/LibGUI/Widget.cpp
+++ b/Userland/Libraries/LibGUI/Widget.cpp
@@ -344,10 +344,22 @@ void Widget::event(Core::Event& event)
void Widget::handle_keydown_event(KeyEvent& event)
{
keydown_event(event);
+ if (event.is_accepted())
+ return;
+
+ if (auto action = Action::find_action_for_shortcut(*this, Shortcut(event.modifiers(), event.key()))) {
+ action->process_event(*window(), event);
+ if (event.is_accepted())
+ return;
+ }
+
if (event.key() == KeyCode::Key_Menu) {
ContextMenuEvent c_event(window_relative_rect().bottom_right(), screen_relative_rect().bottom_right());
dispatch_event(c_event);
+ return;
}
+
+ event.ignore();
}
void Widget::handle_paint_event(PaintEvent& event)
diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp
index 9d930f1cc2..417096cf12 100644
--- a/Userland/Libraries/LibGUI/Window.cpp
+++ b/Userland/Libraries/LibGUI/Window.cpp
@@ -454,6 +454,37 @@ void Window::handle_multi_paint_event(MultiPaintEvent& event)
ConnectionToWindowServer::the().async_did_finish_painting(m_window_id, rects);
}
+void Window::propagate_shortcuts_up_to_application(KeyEvent& event, Widget* widget)
+{
+ VERIFY(event.type() == Event::KeyDown);
+ auto shortcut = Shortcut(event.modifiers(), event.key());
+ Action* action = nullptr;
+
+ if (widget) {
+ VERIFY(widget->window() == this);
+
+ do {
+ action = widget->action_for_shortcut(shortcut);
+ if (action)
+ break;
+
+ widget = widget->parent_widget();
+ } while (widget);
+ }
+
+ if (!action)
+ action = action_for_shortcut(shortcut);
+ if (!action)
+ action = Application::the()->action_for_shortcut(shortcut);
+
+ if (action) {
+ action->process_event(*this, event);
+ return;
+ }
+
+ event.ignore();
+}
+
void Window::handle_key_event(KeyEvent& event)
{
if (!m_focused_widget && event.type() == Event::KeyDown && event.key() == Key_Tab && !event.ctrl() && !event.alt() && !event.super()) {
@@ -465,9 +496,16 @@ void Window::handle_key_event(KeyEvent& event)
return default_return_key_widget()->dispatch_event(event, this);
if (m_focused_widget)
- return m_focused_widget->dispatch_event(event, this);
- if (m_main_widget)
- return m_main_widget->dispatch_event(event, this);
+ m_focused_widget->dispatch_event(event, this);
+ else if (m_main_widget)
+ m_main_widget->dispatch_event(event, this);
+
+ if (event.is_accepted())
+ return;
+
+ // Only process shortcuts if this is a keydown event.
+ if (event.type() == Event::KeyDown)
+ propagate_shortcuts_up_to_application(event, nullptr);
}
void Window::handle_resize_event(ResizeEvent& event)
diff --git a/Userland/Libraries/LibGUI/Window.h b/Userland/Libraries/LibGUI/Window.h
index 68c4b372c8..55e60a26db 100644
--- a/Userland/Libraries/LibGUI/Window.h
+++ b/Userland/Libraries/LibGUI/Window.h
@@ -234,6 +234,8 @@ public:
void set_always_on_top(bool always_on_top = true);
+ void propagate_shortcuts_up_to_application(KeyEvent& event, Widget* widget);
+
protected:
Window(Core::Object* parent = nullptr);
virtual void wm_event(WMEvent&);