mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-12 17:37:53 +03: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:
parent
725b57fe1f
commit
5e40aa4f1a
Notes:
sideshowbarker
2024-07-19 15:33:48 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/5e40aa4f1a4
@ -113,6 +113,8 @@ enum KeyModifier {
|
||||
Mod_Alt = 0x01,
|
||||
Mod_Ctrl = 0x02,
|
||||
Mod_Shift = 0x04,
|
||||
Mod_Mask = 0x07,
|
||||
|
||||
Is_Press = 0x80,
|
||||
};
|
||||
|
||||
@ -123,5 +125,6 @@ struct KeyEvent {
|
||||
bool alt() const { return flags & Mod_Alt; }
|
||||
bool ctrl() const { return flags & Mod_Ctrl; }
|
||||
bool shift() const { return flags & Mod_Shift; }
|
||||
unsigned modifiers() const { return flags & Mod_Mask; }
|
||||
bool is_press() const { return flags & Is_Press; }
|
||||
};
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 };
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <SharedGraphics/Rect.h>
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/KeyCode.h>
|
||||
|
||||
class WSMessage {
|
||||
public:
|
||||
@ -450,27 +451,27 @@ enum class MouseButton : byte {
|
||||
|
||||
class WSKeyEvent final : public WSMessage {
|
||||
public:
|
||||
WSKeyEvent(Type type, int key, char character)
|
||||
WSKeyEvent(Type type, int key, char character, byte modifiers)
|
||||
: WSMessage(type)
|
||||
, m_key(key)
|
||||
, m_character(character)
|
||||
, 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; }
|
||||
char character() const { return m_character; }
|
||||
|
||||
private:
|
||||
friend class WSMessageLoop;
|
||||
friend class WSScreen;
|
||||
int m_key { 0 };
|
||||
bool m_ctrl { false };
|
||||
bool m_alt { false };
|
||||
bool m_shift { false };
|
||||
char m_character { 0 };
|
||||
byte m_modifiers { 0 };
|
||||
};
|
||||
|
||||
class WSMouseEvent final : public WSMessage {
|
||||
|
@ -94,10 +94,7 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool righ
|
||||
|
||||
void WSScreen::on_receive_keyboard_data(KeyEvent kernel_event)
|
||||
{
|
||||
auto message = make<WSKeyEvent>(kernel_event.is_press() ? WSMessage::KeyDown : WSMessage::KeyUp, kernel_event.key, kernel_event.character);
|
||||
message->m_shift = kernel_event.shift();
|
||||
message->m_ctrl = kernel_event.ctrl();
|
||||
message->m_alt = kernel_event.alt();
|
||||
auto message = make<WSKeyEvent>(kernel_event.is_press() ? WSMessage::KeyDown : WSMessage::KeyUp, kernel_event.key, kernel_event.character, kernel_event.modifiers());
|
||||
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
|
||||
}
|
||||
|
||||
|
@ -98,17 +98,13 @@ void WSWindow::on_message(WSMessage& message)
|
||||
server_message.type = WSAPI_ServerMessage::Type::KeyDown;
|
||||
server_message.key.character = static_cast<WSKeyEvent&>(message).character();
|
||||
server_message.key.key = static_cast<WSKeyEvent&>(message).key();
|
||||
server_message.key.alt = static_cast<WSKeyEvent&>(message).alt();
|
||||
server_message.key.ctrl = static_cast<WSKeyEvent&>(message).ctrl();
|
||||
server_message.key.shift = static_cast<WSKeyEvent&>(message).shift();
|
||||
server_message.key.modifiers = static_cast<WSKeyEvent&>(message).modifiers();
|
||||
break;
|
||||
case WSMessage::KeyUp:
|
||||
server_message.type = WSAPI_ServerMessage::Type::KeyUp;
|
||||
server_message.key.character = static_cast<WSKeyEvent&>(message).character();
|
||||
server_message.key.key = static_cast<WSKeyEvent&>(message).key();
|
||||
server_message.key.alt = static_cast<WSKeyEvent&>(message).alt();
|
||||
server_message.key.ctrl = static_cast<WSKeyEvent&>(message).ctrl();
|
||||
server_message.key.shift = static_cast<WSKeyEvent&>(message).shift();
|
||||
server_message.key.modifiers = static_cast<WSKeyEvent&>(message).modifiers();
|
||||
break;
|
||||
case WSMessage::WindowActivated:
|
||||
server_message.type = WSAPI_ServerMessage::Type::WindowActivated;
|
||||
|
Loading…
Reference in New Issue
Block a user