summaryrefslogtreecommitdiff
path: root/Servers
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-06-21 11:03:43 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-06-21 11:03:43 +0200
commit2e9cc75d11dba67498b82fab31323688b1f5ccc5 (patch)
tree26986773a191202be3bf89194c3b4de12417d101 /Servers
parentda475ce3f58e625b43448bc79a97d413b87eb684 (diff)
downloadserenity-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. :^)
Diffstat (limited to 'Servers')
-rw-r--r--Servers/WindowServer/WSAPITypes.h2
-rw-r--r--Servers/WindowServer/WSClientConnection.cpp18
-rw-r--r--Servers/WindowServer/WSClientConnection.h1
-rw-r--r--Servers/WindowServer/WSEvent.h21
-rw-r--r--Servers/WindowServer/WSEventLoop.cpp3
-rw-r--r--Servers/WindowServer/WSWindow.cpp31
-rw-r--r--Servers/WindowServer/WSWindow.h4
-rw-r--r--Servers/WindowServer/WSWindowFrame.cpp8
8 files changed, 86 insertions, 2 deletions
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.