1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 01:27:43 +00:00

LibGUI: Move shortcut actions from GEventLoop to GApplications.

I'm gonna want to have nested event loops sooner or later, so let's not
pollute GEventLoop with things that are meant to work globally.

This patch also changes key events to pass around their modifiers as a
bitfield all the way around the system instead of breaking them up.
This commit is contained in:
Andreas Kling 2019-03-03 12:32:15 +01:00
parent 725b57fe1f
commit 5e40aa4f1a
11 changed files with 63 additions and 55 deletions

View file

@ -1,5 +1,5 @@
#include <LibGUI/GAction.h>
#include <LibGUI/GEventLoop.h>
#include <LibGUI/GApplication.h>
GAction::GAction(const String& text, const String& custom_data, Function<void(const GAction&)> on_activation_callback)
: on_activation(move(on_activation_callback))
@ -32,13 +32,13 @@ GAction::GAction(const String& text, const GShortcut& shortcut, RetainPtr<Graphi
, m_icon(move(icon))
, m_shortcut(shortcut)
{
GEventLoop::register_action_with_shortcut(Badge<GAction>(), *this);
GApplication::the().register_shortcut_action(Badge<GAction>(), *this);
}
GAction::~GAction()
{
if (m_shortcut.is_valid())
GEventLoop::unregister_action_with_shortcut(Badge<GAction>(), *this);
GApplication::the().unregister_shortcut_action(Badge<GAction>(), *this);
}
void GAction::activate()

View file

@ -1,6 +1,7 @@
#include <LibGUI/GApplication.h>
#include <LibGUI/GEventLoop.h>
#include <LibGUI/GMenuBar.h>
#include <LibGUI/GAction.h>
static GApplication* s_the;
@ -42,3 +43,20 @@ void GApplication::set_menubar(OwnPtr<GMenuBar>&& menubar)
m_menubar->notify_added_to_application(Badge<GApplication>());
}
void GApplication::register_shortcut_action(Badge<GAction>, GAction& action)
{
m_shortcut_actions.set(action.shortcut(), &action);
}
void GApplication::unregister_shortcut_action(Badge<GAction>, GAction& action)
{
m_shortcut_actions.remove(action.shortcut());
}
GAction* GApplication::action_for_key_event(const GKeyEvent& event)
{
auto it = m_shortcut_actions.find(GShortcut(event.modifiers(), (KeyCode)event.key()));
if (it == m_shortcut_actions.end())
return nullptr;
return (*it).value;
}

View file

@ -1,7 +1,12 @@
#pragma once
#include <AK/Badge.h>
#include <AK/OwnPtr.h>
#include <AK/HashMap.h>
#include <LibGUI/GShortcut.h>
class GAction;
class GKeyEvent;
class GEventLoop;
class GMenuBar;
@ -15,8 +20,13 @@ public:
void quit(int);
void set_menubar(OwnPtr<GMenuBar>&&);
GAction* action_for_key_event(const GKeyEvent&);
void register_shortcut_action(Badge<GAction>, GAction&);
void unregister_shortcut_action(Badge<GAction>, GAction&);
private:
OwnPtr<GEventLoop> m_event_loop;
OwnPtr<GMenuBar> m_menubar;
HashMap<GShortcut, GAction*> m_shortcut_actions;
};

View file

@ -4,6 +4,7 @@
#include <SharedGraphics/Rect.h>
#include <AK/AKString.h>
#include <AK/Types.h>
#include <Kernel/KeyCode.h>
class GEvent {
public:
@ -112,24 +113,24 @@ enum GMouseButton : byte {
class GKeyEvent final : public GEvent {
public:
GKeyEvent(Type type, int key)
GKeyEvent(Type type, int key, byte modifiers)
: GEvent(type)
, m_key(key)
, m_modifiers(modifiers)
{
}
int key() const { return m_key; }
bool ctrl() const { return m_ctrl; }
bool alt() const { return m_alt; }
bool shift() const { return m_shift; }
bool ctrl() const { return m_modifiers & Mod_Ctrl; }
bool alt() const { return m_modifiers & Mod_Alt; }
bool shift() const { return m_modifiers & Mod_Shift; }
byte modifiers() const { return m_modifiers; }
String text() const { return m_text; }
private:
friend class GEventLoop;
int m_key { 0 };
bool m_ctrl { false };
bool m_alt { false };
bool m_shift { false };
byte m_modifiers { 0 };
String m_text;
};

View file

@ -2,6 +2,7 @@
#include "GEvent.h"
#include "GObject.h"
#include "GWindow.h"
#include <LibGUI/GApplication.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GNotifier.h>
#include <LibGUI/GMenu.h>
@ -153,20 +154,14 @@ void GEventLoop::handle_key_event(const WSAPI_ServerMessage& event, GWindow& win
#ifdef GEVENTLOOP_DEBUG
dbgprintf("WID=%x KeyEvent character=0x%b\n", event.window_id, event.key.character);
#endif
unsigned modifiers = (event.key.alt * Mod_Alt) + (event.key.ctrl * Mod_Ctrl) + (event.key.shift * Mod_Shift);
auto it = g_actions->find(GShortcut(modifiers, (KeyCode)event.key.key));
if (it != g_actions->end()) {
(*it).value->activate();
return;
}
auto key_event = make<GKeyEvent>(event.type == WSAPI_ServerMessage::Type::KeyDown ? GEvent::KeyDown : GEvent::KeyUp, event.key.key);
key_event->m_alt = event.key.alt;
key_event->m_ctrl = event.key.ctrl;
key_event->m_shift = event.key.shift;
auto key_event = make<GKeyEvent>(event.type == WSAPI_ServerMessage::Type::KeyDown ? GEvent::KeyDown : GEvent::KeyUp, event.key.key, event.key.modifiers);
if (event.key.character != '\0')
key_event->m_text = String(&event.key.character, 1);
if (auto* action = GApplication::the().action_for_key_event(*key_event)) {
action->activate();
return;
}
post_event(window, move(key_event));
}
@ -455,13 +450,3 @@ WSAPI_ServerMessage GEventLoop::sync_request(const WSAPI_ClientMessage& request,
ASSERT(success);
return response;
}
void GEventLoop::register_action_with_shortcut(Badge<GAction>, GAction& action)
{
g_actions->set(action.shortcut(), &action);
}
void GEventLoop::unregister_action_with_shortcut(Badge<GAction>, GAction& action)
{
g_actions->remove(action.shortcut());
}

View file

@ -41,9 +41,6 @@ public:
pid_t server_pid() const { return m_server_pid; }
static void register_action_with_shortcut(Badge<GAction>, GAction&);
static void unregister_action_with_shortcut(Badge<GAction>, GAction&);
private:
void wait_for_event();
bool drain_messages_from_server();

View file

@ -7,14 +7,14 @@
class GShortcut {
public:
GShortcut() { }
GShortcut(unsigned modifiers, KeyCode key)
GShortcut(byte modifiers, KeyCode key)
: m_modifiers(modifiers)
, m_key(key)
{
}
bool is_valid() const { return m_key != KeyCode::Key_Invalid; }
unsigned modifiers() const { return m_modifiers; }
byte modifiers() const { return m_modifiers; }
KeyCode key() const { return m_key; }
String to_string() const;
@ -25,7 +25,7 @@ public:
}
private:
unsigned m_modifiers { 0 };
byte m_modifiers { 0 };
KeyCode m_key { KeyCode::Key_Invalid };
};