Details
-
Suggestion
-
Resolution: Unresolved
-
Not Evaluated
-
None
-
None
-
None
Description
Would be nice to have a way to open system window menu given that there are QWindow::startSystemMove and QWindow::startSystemResize. Here are examples of implementations:
Windows:
void ShowWindowMenu(QWindow *window, const QPoint &point) { const auto handle = HWND(window->winId()); const auto mapped = point * window->devicePixelRatio(); POINT p{ mapped.x(), mapped.y() }; ClientToScreen(handle, &p); SendMessage( handle, 0x313 /* WM_POPUPSYSTEMMENU */, 0, MAKELPARAM(p.x, p.y)); }
Note: Qt has a re-implementation of standard menu which could be re-used or replaced by this code.
Wayland (note: there's QWaylandWindow::showWindowMenu already):
void ShowWindowMenu(QWindow *window, const QPoint &point) { const auto native = qApp->nativeInterface<QWaylandApplication>(); const auto nativeWindow = window->nativeInterface<QWaylandWindow>(); xdg_toplevel_show_window_menu( nativeWindow->surfaceRole<xdg_toplevel>(), native->lastInputSeat(), native->lastInputSerial(), point.x(), point.y()); }
X11 (note: this uses some references to application-specific XCB wrappers which I guess you should understand with no problem and replace with references to your ones):
void ShowWindowMenu(QWindow *window, const QPoint &point) { const auto connection = base::Platform::XCB::GetConnectionFromQt(); if (!connection) { return; } const auto root = base::Platform::XCB::GetRootWindow(connection); if (!root.has_value()) { return; } const auto showWindowMenuAtom = base::Platform::XCB::GetAtom( connection, "_GTK_SHOW_WINDOW_MENU"); if (!showWindowMenuAtom.has_value()) { return; } const auto windowGeometry = XCBWindowGeometry(window->winId()); if (windowGeometry.isNull()) { return; } const auto globalPos = point * window->devicePixelRatio() + windowGeometry.topLeft(); xcb_client_message_event_t xev; xev.response_type = XCB_CLIENT_MESSAGE; xev.type = *showWindowMenuAtom; xev.sequence = 0; xev.window = window->winId(); xev.format = 32; xev.data.data32[0] = 0; xev.data.data32[1] = globalPos.x(); xev.data.data32[2] = globalPos.y(); xev.data.data32[3] = 0; xev.data.data32[4] = 0; xcb_ungrab_pointer(connection, XCB_CURRENT_TIME); xcb_send_event( connection, false, *root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, reinterpret_cast<const char*>(&xev)); }
I don't know whether macOS has something for that but would be really surprised if it doesn't