Skip to content

Commit 3d3c006

Browse files
committed
Added support for system window menu
Implemented showing the titlebar menu Added required methods in the ClassDB Wayland support for show_titlebar_menu Implemented showing the titlebar menu under Wayland
1 parent 9dde568 commit 3d3c006

10 files changed

+79
-0
lines changed

platform/linuxbsd/wayland/display_server_wayland.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,11 @@ void DisplayServerWayland::window_start_resize(WindowResizeEdge p_edge, WindowID
14321432
wayland_thread.window_start_resize(p_edge, p_window);
14331433
}
14341434

1435+
void DisplayServerWayland::window_show_system_menu(WindowID p_window) {
1436+
MutexLock mutex_lock(wayland_thread.mutex);
1437+
wayland_thread.window_show_system_menu(p_window);
1438+
}
1439+
14351440
void DisplayServerWayland::cursor_set_shape(CursorShape p_shape) {
14361441
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
14371442

platform/linuxbsd/wayland/display_server_wayland.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ class DisplayServerWayland : public DisplayServer {
321321

322322
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
323323
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window) override;
324+
virtual void window_show_system_menu(WindowID p_window = MAIN_WINDOW_ID) override;
324325

325326
virtual void cursor_set_shape(CursorShape p_shape) override;
326327
virtual CursorShape cursor_get_shape() const override;

platform/linuxbsd/wayland/wayland_thread.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,6 +3800,22 @@ void WaylandThread::window_start_resize(DisplayServer::WindowResizeEdge p_edge,
38003800
#endif
38013801
}
38023802

3803+
void WaylandThread::window_show_system_menu(DisplayServer::WindowID p_window) {
3804+
ERR_FAIL_COND(!windows.has(p_window));
3805+
3806+
WindowState &ws = windows[p_window];
3807+
SeatState *ss = wl_seat_get_seat_state(wl_seat_current);
3808+
if (ws.wl_surface && ws.xdg_toplevel) {
3809+
xdg_toplevel_show_window_menu(ws.xdg_toplevel, wl_seat_current, ss->pointer_data.button_serial, ss->pointer_data.position.x, ss->pointer_data.position.y);
3810+
}
3811+
3812+
#ifdef LIBDECOR_ENABLED
3813+
if (ws.libdecor_frame) {
3814+
libdecor_frame_show_window_menu(ws.libdecor_frame, wl_seat_current, ss->pointer_data.button_serial, ss->pointer_data.position.x, ss->pointer_data.position.y);
3815+
}
3816+
#endif
3817+
}
3818+
38033819
void WaylandThread::window_set_parent(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id) {
38043820
ERR_FAIL_COND(!windows.has(p_window_id));
38053821
ERR_FAIL_COND(!windows.has(p_parent_id));

platform/linuxbsd/wayland/wayland_thread.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ class WaylandThread {
10331033
WindowState *window_get_state(DisplayServer::WindowID p_window_id);
10341034

10351035
void window_start_resize(DisplayServer::WindowResizeEdge p_edge, DisplayServer::WindowID p_window);
1036+
virtual void window_show_system_menu(WindowID p_window = MAIN_WINDOW_ID) override;
10361037

10371038
void window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size);
10381039
void window_set_min_size(DisplayServer::WindowID p_window_id, const Size2i &p_size);

platform/linuxbsd/x11/display_server_x11.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5961,6 +5961,38 @@ void DisplayServerX11::window_start_resize(WindowResizeEdge p_edge, WindowID p_w
59615961
XSync(x11_display, 0);
59625962
}
59635963

5964+
void DisplayServerX11::window_show_system_menu(WindowID p_window) {
5965+
_THREAD_SAFE_METHOD_
5966+
5967+
ERR_FAIL_COND(!windows.has(p_window));
5968+
5969+
WindowData &wd = windows[p_window];
5970+
// `_GTK_SHOW_WINDOW_MENU` used for compatibility in most WMs.
5971+
Atom wmState = XInternAtom(x11_display, "_GTK_SHOW_WINDOW_MENU", True);
5972+
XClientMessageEvent xev;
5973+
5974+
memset(&xev, 0, sizeof(xev));
5975+
5976+
int root_x, root_y;
5977+
5978+
Bool xquerypointer_result = XQueryPointer(x11_display, wd.x11_window, NULL, NULL, &root_x, &root_y, NULL, NULL, NULL);
5979+
5980+
xev.type = ClientMessage;
5981+
xev.window = wd.x11_window;
5982+
xev.message_type = wmState;
5983+
5984+
if (xquerypointer_result) {
5985+
// `2` is the default device ID.
5986+
// TODO: Properly get the device ID somehow.
5987+
xev.data.l[0] = 2;
5988+
xev.data.l[1] = root_x;
5989+
xev.data.l[2] = root_y;
5990+
}
5991+
5992+
xev.format = 32;
5993+
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev);
5994+
}
5995+
59645996
pid_t get_window_pid(Display *p_display, Window p_window) {
59655997
Atom atom = XInternAtom(p_display, "_NET_WM_PID", False);
59665998
Atom actualType;

platform/linuxbsd/x11/display_server_x11.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ class DisplayServerX11 : public DisplayServer {
547547

548548
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
549549
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window) override;
550+
virtual void window_show_system_menu(WindowID p_window = MAIN_WINDOW_ID) override;
550551

551552
virtual Error embed_process(WindowID p_window, OS::ProcessID p_pid, const Rect2i &p_rect, bool p_visible, bool p_grab_focus) override;
552553
virtual Error request_close_embedded_process(OS::ProcessID p_pid) override;

platform/windows/display_server_windows.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4354,6 +4354,25 @@ void DisplayServerWindows::window_start_resize(WindowResizeEdge p_edge, WindowID
43544354
}
43554355
}
43564356

4357+
void DisplayServerWindows::window_show_system_menu(WindowID p_window) {
4358+
_THREAD_SAFE_METHOD_
4359+
4360+
ERR_FAIL_COND(!windows.has(p_window));
4361+
WindowData &wd = windows[p_window];
4362+
HMENU system_menu = GetSystemMenu(wd.hWnd, false);
4363+
4364+
POINT coords;
4365+
GetCursorPos(&coords);
4366+
4367+
// Retrieve menu identifier for later.
4368+
int menu_ident = TrackPopupMenu(system_menu, TPM_LEFTALIGN | TPM_TOPALIGN, coords.x, coords.y, 0, wd.hWnd, 0);
4369+
4370+
if (menu_ident != 0) {
4371+
SendMessage(wd.hWnd, WM_SYSCOMMAND, menu_ident, 0);
4372+
}
4373+
4374+
}
4375+
43574376
void DisplayServerWindows::set_context(Context p_context) {
43584377
}
43594378

platform/windows/display_server_windows.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ class DisplayServerWindows : public DisplayServer {
662662

663663
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
664664
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) override;
665+
virtual void window_show_system_menu(WindowID p_window = MAIN_WINDOW_ID) override;
665666

666667
virtual void cursor_set_shape(CursorShape p_shape) override;
667668
virtual CursorShape cursor_get_shape() const override;

servers/display_server.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,7 @@ void DisplayServer::_bind_methods() {
14751475

14761476
ClassDB::bind_method(D_METHOD("window_start_drag", "window_id"), &DisplayServer::window_start_drag, DEFVAL(MAIN_WINDOW_ID));
14771477
ClassDB::bind_method(D_METHOD("window_start_resize", "edge", "window_id"), &DisplayServer::window_start_resize, DEFVAL(MAIN_WINDOW_ID));
1478+
ClassDB::bind_method(D_METHOD("window_show_system_menu", "window_id"), &DisplayServer::window_show_system_menu, DEFVAL(MAIN_WINDOW_ID));
14781479

14791480
ClassDB::bind_method(D_METHOD("accessibility_should_increase_contrast"), &DisplayServer::accessibility_should_increase_contrast);
14801481
ClassDB::bind_method(D_METHOD("accessibility_should_reduce_animation"), &DisplayServer::accessibility_should_reduce_animation);

servers/display_server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ class DisplayServer : public Object {
539539

540540
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) {}
541541

542+
virtual void window_show_system_menu(WindowID p_window = MAIN_WINDOW_ID) {}
543+
542544
// Accessibility.
543545

544546
enum AccessibilityMode {

0 commit comments

Comments
 (0)