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. image-2023-08-22-16-35-14-405.png
          image-2023-08-22-16-35-14-405.png
          164 kB
        2. KDE.png
          KDE.png
          67 kB
        3. GNOME.png
          GNOME.png
          291 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