1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 15:37:46 +00:00

LibGUI+WindowServer: Add support for per-GWidget context menus.

You can now simply assign a GMenu as a GWidget's context menu and it will
automagically pop up on right click. :^)
This commit is contained in:
Andreas Kling 2019-04-12 17:10:30 +02:00
parent 8feecf6c77
commit c06a3bdeb4
12 changed files with 102 additions and 8 deletions

View file

@ -192,6 +192,7 @@ struct WSAPI_ClientMessage {
GetWallpaper,
SetWindowOverrideCursor,
WM_SetActiveWindow,
PopupMenu,
};
Type type { Invalid };
int window_id { -1 };
@ -214,6 +215,7 @@ struct WSAPI_ClientMessage {
char shortcut_text[32];
int shortcut_text_length;
bool enabled;
WSAPI_Point position;
} menu;
struct {
WSAPI_Rect rect;

View file

@ -223,6 +223,19 @@ void WSClientConnection::handle_request(const WSAPIAddMenuItemRequest& request)
post_message(response);
}
void WSClientConnection::handle_request(const WSAPIPopupMenuRequest& request)
{
int menu_id = request.menu_id();
auto position = request.position();
auto it = m_menus.find(menu_id);
if (it == m_menus.end()) {
post_error("WSAPIPopupMenuRequest: Bad menu ID");
return;
}
auto& menu = *(*it).value;
menu.popup(position);
}
void WSClientConnection::handle_request(const WSAPIUpdateMenuItemRequest& request)
{
int menu_id = request.menu_id();
@ -616,6 +629,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request)
return handle_request(static_cast<const WSAPISetWindowOverrideCursorRequest&>(request));
case WSMessage::WMAPISetActiveWindowRequest:
return handle_request(static_cast<const WSWMAPISetActiveWindowRequest&>(request));
case WSMessage::APIPopupMenuRequest:
return handle_request(static_cast<const WSAPIPopupMenuRequest&>(request));
default:
break;
}

View file

@ -70,6 +70,7 @@ private:
void handle_request(const WSAPIGetWallpaperRequest&);
void handle_request(const WSAPISetWindowOverrideCursorRequest&);
void handle_request(const WSWMAPISetActiveWindowRequest&);
void handle_request(const WSAPIPopupMenuRequest&);
void post_error(const String&);

View file

@ -178,4 +178,14 @@ WSMenuItem* WSMenu::item_at(const Point& position)
void WSMenu::close()
{
WSWindowManager::the().close_menu(*this);
};
if (menu_window())
menu_window()->set_visible(false);
}
void WSMenu::popup(const Point& position)
{
ASSERT(!is_empty());
auto& window = ensure_menu_window();
window.move_to(position);
window.set_visible(true);
}

View file

@ -73,6 +73,8 @@ public:
void close();
void popup(const Point&);
private:
virtual void on_message(const WSMessage&) override;

View file

@ -57,6 +57,7 @@ public:
APIGetWallpaperRequest,
APISetWindowOverrideCursorRequest,
WMAPISetActiveWindowRequest,
APIPopupMenuRequest,
__End_API_Client_Requests,
};
@ -189,6 +190,24 @@ private:
int m_menu_id { 0 };
};
class WSAPIPopupMenuRequest : public WSAPIClientRequest {
public:
WSAPIPopupMenuRequest(int client_id, int menu_id, const Point& position)
: WSAPIClientRequest(WSMessage::APIPopupMenuRequest, client_id)
, m_menu_id(menu_id)
, m_position(position)
{
}
int menu_id() const { return m_menu_id; }
Point position() const { return m_position; }
private:
int m_menu_id;
Point m_position;
};
class WSAPICreateMenuRequest : public WSAPIClientRequest {
public:
WSAPICreateMenuRequest(int client_id, const String& text)

View file

@ -290,6 +290,9 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::PopupMenu:
post_message(client, make<WSAPIPopupMenuRequest>(client_id, message.menu.menu_id, message.menu.position));
break;
case WSAPI_ClientMessage::Type::DestroyMenu:
post_message(client, make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id));
break;