diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-06-21 11:03:43 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-06-21 11:03:43 +0200 |
commit | 2e9cc75d11dba67498b82fab31323688b1f5ccc5 (patch) | |
tree | 26986773a191202be3bf89194c3b4de12417d101 | |
parent | da475ce3f58e625b43448bc79a97d413b87eb684 (diff) | |
download | serenity-2e9cc75d11dba67498b82fab31323688b1f5ccc5.zip |
WindowServer+Taskbar: Let WindowServer manage the "window menus".
Taskbar now simply asks the WindowServer to popup a window menu when right
clicking on a taskbar button.
This patch also implements the "close" menu item, and furthermore makes the
window menu show up when you left-click a window's titlebar icon. :^)
-rw-r--r-- | Applications/Taskbar/TaskbarButton.cpp | 36 | ||||
-rw-r--r-- | Applications/Taskbar/TaskbarButton.h | 3 | ||||
-rw-r--r-- | Servers/WindowServer/WSAPITypes.h | 2 | ||||
-rw-r--r-- | Servers/WindowServer/WSClientConnection.cpp | 18 | ||||
-rw-r--r-- | Servers/WindowServer/WSClientConnection.h | 1 | ||||
-rw-r--r-- | Servers/WindowServer/WSEvent.h | 21 | ||||
-rw-r--r-- | Servers/WindowServer/WSEventLoop.cpp | 3 | ||||
-rw-r--r-- | Servers/WindowServer/WSWindow.cpp | 31 | ||||
-rw-r--r-- | Servers/WindowServer/WSWindow.h | 4 | ||||
-rw-r--r-- | Servers/WindowServer/WSWindowFrame.cpp | 8 |
10 files changed, 92 insertions, 35 deletions
diff --git a/Applications/Taskbar/TaskbarButton.cpp b/Applications/Taskbar/TaskbarButton.cpp index 18c7c57749..e821dc4e14 100644 --- a/Applications/Taskbar/TaskbarButton.cpp +++ b/Applications/Taskbar/TaskbarButton.cpp @@ -1,20 +1,8 @@ #include "TaskbarButton.h" #include <LibGUI/GAction.h> #include <LibGUI/GEventLoop.h> -#include <LibGUI/GMenu.h> #include <WindowServer/WSAPITypes.h> -static void set_window_minimized_state(const WindowIdentifier& identifier, bool minimized) -{ - WSAPI_ClientMessage message; - message.type = WSAPI_ClientMessage::Type::WM_SetWindowMinimized; - message.wm.client_id = identifier.client_id(); - message.wm.window_id = identifier.window_id(); - message.wm.minimized = minimized; - bool success = GEventLoop::post_message_to_server(message); - ASSERT(success); -} - TaskbarButton::TaskbarButton(const WindowIdentifier& identifier, GWidget* parent) : GButton(parent) , m_identifier(identifier) @@ -27,22 +15,10 @@ TaskbarButton::~TaskbarButton() void TaskbarButton::context_menu_event(GContextMenuEvent&) { - ensure_menu().popup(screen_relative_rect().location()); -} - -GMenu& TaskbarButton::ensure_menu() -{ - if (!m_menu) { - m_menu = make<GMenu>(""); - m_menu->add_action(GAction::create("Minimize", [this](auto&) { - set_window_minimized_state(m_identifier, true); - })); - m_menu->add_action(GAction::create("Unminimize", [this](auto&) { - set_window_minimized_state(m_identifier, false); - })); - m_menu->add_action(GAction::create("Close", [this](auto&) { - dbgprintf("FIXME: Close!\n"); - })); - } - return *m_menu; + WSAPI_ClientMessage request; + request.type = WSAPI_ClientMessage::Type::WM_PopupWindowMenu; + request.wm.client_id = m_identifier.client_id(); + request.wm.window_id = m_identifier.window_id(); + request.wm.position = screen_relative_rect().location(); + GEventLoop::post_message_to_server(request); } diff --git a/Applications/Taskbar/TaskbarButton.h b/Applications/Taskbar/TaskbarButton.h index 2a84b0b410..000f71be86 100644 --- a/Applications/Taskbar/TaskbarButton.h +++ b/Applications/Taskbar/TaskbarButton.h @@ -11,8 +11,5 @@ public: private: virtual void context_menu_event(GContextMenuEvent&) override; - GMenu& ensure_menu(); - WindowIdentifier m_identifier; - OwnPtr<GMenu> m_menu; }; diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index ad2b9fd1ca..0ecc11b0b0 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -222,6 +222,7 @@ struct WSAPI_ClientMessage { WM_SetActiveWindow, WM_SetWindowMinimized, WM_StartWindowResize, + WM_PopupWindowMenu, PopupMenu, DismissMenu, SetWindowIcon, @@ -251,6 +252,7 @@ struct WSAPI_ClientMessage { int client_id; int window_id; bool minimized; + WSAPI_Point position; } wm; struct { int menubar_id; diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index 830514e142..dd3efeedd3 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -695,6 +695,22 @@ void WSClientConnection::handle_request(const WSWMAPISetActiveWindowRequest& req WSWindowManager::the().move_to_front_and_make_active(window); } +void WSClientConnection::handle_request(const WSWMAPIPopupWindowMenuRequest& request) +{ + auto* client = WSClientConnection::from_client_id(request.target_client_id()); + if (!client) { + post_error("WSWMAPIPopupWindowMenuRequest: Bad client ID"); + return; + } + auto it = client->m_windows.find(request.target_window_id()); + if (it == client->m_windows.end()) { + post_error("WSWMAPIPopupWindowMenuRequest: Bad window ID"); + return; + } + auto& window = *(*it).value; + window.popup_window_menu(request.position()); +} + void WSClientConnection::handle_request(const WSWMAPIStartWindowResizeRequest& request) { auto* client = WSClientConnection::from_client_id(request.target_client_id()); @@ -792,6 +808,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request) return handle_request(static_cast<const WSWMAPISetWindowMinimizedRequest&>(request)); case WSEvent::WMAPIStartWindowResizeRequest: return handle_request(static_cast<const WSWMAPIStartWindowResizeRequest&>(request)); + case WSEvent::WMAPIPopupWindowMenuRequest: + return handle_request(static_cast<const WSWMAPIPopupWindowMenuRequest&>(request)); case WSEvent::APIPopupMenuRequest: return handle_request(static_cast<const WSAPIPopupMenuRequest&>(request)); case WSEvent::APIDismissMenuRequest: diff --git a/Servers/WindowServer/WSClientConnection.h b/Servers/WindowServer/WSClientConnection.h index 9f128f2586..1313295799 100644 --- a/Servers/WindowServer/WSClientConnection.h +++ b/Servers/WindowServer/WSClientConnection.h @@ -77,6 +77,7 @@ private: void handle_request(const WSWMAPISetActiveWindowRequest&); void handle_request(const WSWMAPISetWindowMinimizedRequest&); void handle_request(const WSWMAPIStartWindowResizeRequest&); + void handle_request(const WSWMAPIPopupWindowMenuRequest&); void handle_request(const WSAPIPopupMenuRequest&); void handle_request(const WSAPIDismissMenuRequest&); void handle_request(const WSAPISetWindowHasAlphaChannelRequest&); diff --git a/Servers/WindowServer/WSEvent.h b/Servers/WindowServer/WSEvent.h index d94693f54f..ec2a96f5f6 100644 --- a/Servers/WindowServer/WSEvent.h +++ b/Servers/WindowServer/WSEvent.h @@ -67,6 +67,7 @@ public: WMAPISetActiveWindowRequest, WMAPISetWindowMinimizedRequest, WMAPIStartWindowResizeRequest, + WMAPIPopupWindowMenuRequest, APIPopupMenuRequest, APIDismissMenuRequest, __End_API_Client_Requests, @@ -129,6 +130,26 @@ private: int m_target_window_id; }; +class WSWMAPIPopupWindowMenuRequest : public WSAPIClientRequest { +public: + WSWMAPIPopupWindowMenuRequest(int client_id, int target_client_id, int target_window_id, const Point& position) + : WSAPIClientRequest(WSEvent::WMAPIPopupWindowMenuRequest, client_id) + , m_target_client_id(target_client_id) + , m_target_window_id(target_window_id) + , m_position(position) + { + } + + int target_client_id() const { return m_target_client_id; } + int target_window_id() const { return m_target_window_id; } + Point position() const { return m_position; } + +private: + int m_target_client_id; + int m_target_window_id; + Point m_position; +}; + class WSWMAPISetActiveWindowRequest : public WSAPIClientRequest { public: WSWMAPISetActiveWindowRequest(int client_id, int target_client_id, int target_window_id) diff --git a/Servers/WindowServer/WSEventLoop.cpp b/Servers/WindowServer/WSEventLoop.cpp index 8c103c8b5a..7463ef4026 100644 --- a/Servers/WindowServer/WSEventLoop.cpp +++ b/Servers/WindowServer/WSEventLoop.cpp @@ -312,6 +312,9 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag case WSAPI_ClientMessage::Type::WM_StartWindowResize: post_event(client, make<WSWMAPIStartWindowResizeRequest>(client_id, message.wm.client_id, message.wm.window_id)); break; + case WSAPI_ClientMessage::Type::WM_PopupWindowMenu: + post_event(client, make<WSWMAPIPopupWindowMenuRequest>(client_id, message.wm.client_id, message.wm.window_id, message.wm.position)); + break; case WSAPI_ClientMessage::Type::MoveWindowToFront: post_event(client, make<WSAPIMoveWindowToFrontRequest>(client_id, message.window_id)); break; diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index 1eec834d73..ce03c90902 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -314,3 +314,34 @@ void WSWindow::request_update(const Rect& rect) } m_pending_paint_rects.add(rect); } + +void WSWindow::popup_window_menu(const Point& position) +{ + if (!m_window_menu) { + m_window_menu = make<WSMenu>(nullptr, -1, "(Window Menu)"); + m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 1, "Minimize")); + m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 2, "Unminimize")); + m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 3, "Close")); + + m_window_menu->on_item_activation = [&](auto& item) { + switch (item.identifier()) { + case 1: + set_minimized(true); + break; + case 2: + set_minimized(false); + break; + case 3: + request_close(); + break; + } + }; + } + m_window_menu->popup(position); +} + +void WSWindow::request_close() +{ + WSEvent close_request(WSEvent::WindowCloseRequest); + event(close_request); +} diff --git a/Servers/WindowServer/WSWindow.h b/Servers/WindowServer/WSWindow.h index 4e938b44a0..46fbee3132 100644 --- a/Servers/WindowServer/WSWindow.h +++ b/Servers/WindowServer/WSWindow.h @@ -21,6 +21,9 @@ public: WSWindow(CObject&, WSWindowType); virtual ~WSWindow() override; + void popup_window_menu(const Point&); + void request_close(); + unsigned wm_event_mask() const { return m_wm_event_mask; } void set_wm_event_mask(unsigned mask) { m_wm_event_mask = mask; } @@ -177,4 +180,5 @@ private: unsigned m_wm_event_mask { 0 }; DisjointRectSet m_pending_paint_rects; Rect m_unmaximized_rect; + OwnPtr<WSMenu> m_window_menu; }; diff --git a/Servers/WindowServer/WSWindowFrame.cpp b/Servers/WindowServer/WSWindowFrame.cpp index da3ea26715..c4ee2cca5c 100644 --- a/Servers/WindowServer/WSWindowFrame.cpp +++ b/Servers/WindowServer/WSWindowFrame.cpp @@ -91,8 +91,7 @@ WSWindowFrame::WSWindowFrame(WSWindow& window) s_unmaximize_button_bitmap = &CharacterBitmap::create_from_ascii(s_unmaximize_button_bitmap_data, s_unmaximize_button_bitmap_width, s_unmaximize_button_bitmap_height).leak_ref(); m_buttons.append(make<WSButton>(*this, *s_close_button_bitmap, [this](auto&) { - WSEvent close_request(WSEvent::WindowCloseRequest); - m_window.event(close_request); + m_window.request_close(); })); if (window.is_resizable()) { @@ -271,6 +270,11 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event) if (m_window.type() != WSWindowType::Normal) return; + if (event.type() == WSEvent::MouseDown && event.button() == MouseButton::Left && title_bar_icon_rect().contains(event.position())) { + m_window.popup_window_menu(event.position().translated(rect().location())); + return; + } + // This is slightly hackish, but expand the title bar rect by one pixel downwards, // so that mouse events between the title bar and window contents don't act like // mouse events on the border. |