mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 14:37:45 +00:00
LibGUI+WindowServer: Add app-global keyboard shortcuts.
This patch adds a GShortcut class. Each GAction can have a GShortcut which will cause the event loop to listen for that key combination app-globally and activate the event in case it's pressed. The shortcut will also be displayed when the action is added to a menu. Use this to hook up Alt+Up with the "open parent directory" action in the FileManager app. :^)
This commit is contained in:
parent
5c0fca0a95
commit
596a5ce5a4
17 changed files with 263 additions and 17 deletions
|
@ -166,6 +166,8 @@ struct WSAPI_ClientMessage {
|
|||
int menubar_id;
|
||||
int menu_id;
|
||||
unsigned identifier;
|
||||
char shortcut_text[32];
|
||||
int shortcut_text_length;
|
||||
} menu;
|
||||
struct {
|
||||
WSAPI_Rect rect;
|
||||
|
|
|
@ -210,14 +210,13 @@ void WSClientConnection::handle_request(WSAPIAddMenuItemRequest& request)
|
|||
{
|
||||
int menu_id = request.menu_id();
|
||||
unsigned identifier = request.identifier();
|
||||
String text = request.text();
|
||||
auto it = m_menus.find(menu_id);
|
||||
if (it == m_menus.end()) {
|
||||
post_error("Bad menu ID");
|
||||
return;
|
||||
}
|
||||
auto& menu = *(*it).value;
|
||||
menu.add_item(make<WSMenuItem>(identifier, move(text)));
|
||||
menu.add_item(make<WSMenuItem>(identifier, request.text(), request.shortcut_text()));
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidAddMenuItem;
|
||||
response.menu.menu_id = menu_id;
|
||||
|
|
|
@ -29,8 +29,13 @@ int WSMenu::width() const
|
|||
{
|
||||
int longest = 0;
|
||||
for (auto& item : m_items) {
|
||||
if (item->type() == WSMenuItem::Text)
|
||||
longest = max(longest, font().width(item->text()));
|
||||
if (item->type() == WSMenuItem::Text) {
|
||||
int item_width = font().width(item->text());
|
||||
if (!item->shortcut_text().is_empty())
|
||||
item_width += padding_between_text_and_shortcut() + font().width(item->shortcut_text());
|
||||
|
||||
longest = max(longest, item_width);
|
||||
}
|
||||
}
|
||||
|
||||
return max(longest, rect_in_menubar().width()) + horizontal_padding();
|
||||
|
@ -91,6 +96,9 @@ void WSMenu::draw()
|
|||
text_color = Color::White;
|
||||
}
|
||||
painter.draw_text(item->rect().translated(left_padding(), 0), item->text(), TextAlignment::CenterLeft, text_color);
|
||||
if (!item->shortcut_text().is_empty()) {
|
||||
painter.draw_text(item->rect().translated(-right_padding(), 0), item->shortcut_text(), TextAlignment::CenterRight, text_color);
|
||||
}
|
||||
} else if (item->type() == WSMenuItem::Separator) {
|
||||
Point p1(1, item->rect().center().y());
|
||||
Point p2(width() - 2, item->rect().center().y());
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
void close();
|
||||
|
||||
private:
|
||||
int padding_between_text_and_shortcut() const { return 50; }
|
||||
void did_activate(WSMenuItem&);
|
||||
WSClientConnection* m_client { nullptr };
|
||||
int m_menu_id { 0 };
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include "WSMenuItem.h"
|
||||
|
||||
WSMenuItem::WSMenuItem(unsigned identifier, const String& text)
|
||||
WSMenuItem::WSMenuItem(unsigned identifier, const String& text, const String& shortcut_text)
|
||||
: m_type(Text)
|
||||
, m_identifier(identifier)
|
||||
, m_text(text)
|
||||
, m_shortcut_text(shortcut_text)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
Separator,
|
||||
};
|
||||
|
||||
explicit WSMenuItem(unsigned identifier, const String& text);
|
||||
explicit WSMenuItem(unsigned identifier, const String& text, const String& shortcut_text = { });
|
||||
explicit WSMenuItem(Type);
|
||||
~WSMenuItem();
|
||||
|
||||
|
@ -20,6 +20,7 @@ public:
|
|||
bool enabled() const { return m_enabled; }
|
||||
|
||||
String text() const { return m_text; }
|
||||
String shortcut_text() const { return m_shortcut_text; }
|
||||
|
||||
void set_rect(const Rect& rect) { m_rect = rect; }
|
||||
Rect rect() const { return m_rect; }
|
||||
|
@ -31,6 +32,7 @@ private:
|
|||
bool m_enabled { true };
|
||||
unsigned m_identifier { 0 };
|
||||
String m_text;
|
||||
String m_shortcut_text;
|
||||
Rect m_rect;
|
||||
};
|
||||
|
||||
|
|
|
@ -189,22 +189,25 @@ private:
|
|||
|
||||
class WSAPIAddMenuItemRequest : public WSAPIClientRequest {
|
||||
public:
|
||||
WSAPIAddMenuItemRequest(int client_id, int menu_id, unsigned identifier, const String& text)
|
||||
WSAPIAddMenuItemRequest(int client_id, int menu_id, unsigned identifier, const String& text, const String& shortcut_text)
|
||||
: WSAPIClientRequest(WSMessage::APIAddMenuItemRequest, client_id)
|
||||
, m_menu_id(menu_id)
|
||||
, m_identifier(identifier)
|
||||
, m_text(text)
|
||||
, m_shortcut_text(shortcut_text)
|
||||
{
|
||||
}
|
||||
|
||||
int menu_id() const { return m_menu_id; }
|
||||
unsigned identifier() const { return m_identifier; }
|
||||
String text() const { return m_text; }
|
||||
String shortcut_text() const { return m_shortcut_text; }
|
||||
|
||||
private:
|
||||
int m_menu_id { 0 };
|
||||
unsigned m_identifier { 0 };
|
||||
String m_text;
|
||||
String m_shortcut_text;
|
||||
};
|
||||
|
||||
class WSAPIAddMenuSeparatorRequest : public WSAPIClientRequest {
|
||||
|
|
|
@ -294,7 +294,8 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess
|
|||
break;
|
||||
case WSAPI_ClientMessage::Type::AddMenuItem:
|
||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
||||
post_message(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length)));
|
||||
ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_text));
|
||||
post_message(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length)));
|
||||
break;
|
||||
case WSAPI_ClientMessage::Type::CreateWindow:
|
||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue