Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-116225

API for showing window system menu

    XMLWordPrintable

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

      Attachments

        1. GNOME.png
          GNOME.png
          291 kB
        2. image-2023-08-22-16-35-14-405.png
          image-2023-08-22-16-35-14-405.png
          164 kB
        3. KDE.png
          KDE.png
          67 kB
        4. MATE.png
          MATE.png
          170 kB
        5. Xfce.png
          Xfce.png
          358 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            vestbo Tor Arne Vestbø
            ilya-fedin Ilya Fedin
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes