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
          164 kB
          Tor Arne Vestbø
        2. KDE.png
          67 kB
          Ilya Fedin
        3. GNOME.png
          291 kB
          Ilya Fedin
        4. MATE.png
          170 kB
          Ilya Fedin
        5. Xfce.png
          358 kB
          Ilya Fedin
        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