Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Make QML subwindow behave like a context menu

Make QML subwindow behave like a context menu

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 2 Posters 1.9k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    alexej.k
    wrote on last edited by alexej.k
    #1

    I have a QML window with a custom dropdown menu implemented as a separate window:

    import QtQuick 2.2
    import QtQuick.Window 2.1
    
    Window { 
        id: mainWindow
        width: 200
        height: 200
        MouseArea {
            anchors.fill: parent
            hoverEnabled: true
    
            Text {
                text: "click here"
            }
    
            onClicked: {
                if(dropdown.visible) {
                    dropdown.close();
                } else {
    
                    dropdown.x = mainWindow.x + 50;
                    dropdown.y = mainWindow.y + 50;
                    dropdown.visible = true;
                    dropdown.requestActivate();
                }
    
            }
        }
    
        Window {
            id: dropdown
            height: 200
            width: 200
            flags: Qt.Popup
            color: 'green'
            visible: false
    
            Text {
                text: "I should disappear when you click anywhere outside me"
                wrapMode: Text.WrapAnywhere
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.margins: 5
                color: "white"
            }
    
            onActiveChanged: {
                if (!active) {
                    dropdown.close();
                }
            }
        }
    }
    

    I want the dropdown window to behave like a native context menu, this means it should be closed when the user clicks ANYWHERE outside the menu. It already works when you click on the desktop or switch to a different application (onActiveChanged), but it doesn't recognize when you click on the title bar of mainWindow, which it should (try right-clicking somewhere in your browser and then click the title bar, the menu will disappear).
    I also tried setting modality: Qt.ApplicationModal on the dropdown menu, which didn't work either.

    1 Reply Last reply
    0
    • A Offline
      A Offline
      alexej.k
      wrote on last edited by alexej.k
      #2

      Using Qt Widgets, it works as expected:

      #include <QWindow>
      #include <QApplication>
      #include <QMainWindow>
      
      int main(int argc, char **argv)
      {
        QApplication app(argc, argv);
      
        QMainWindow qWin;
        qWin.setFixedSize(640, 400);
        qWin.show();
      
        QWidget qPopup(&qWin, Qt::Popup);
      
        qPopup.setFixedSize(320, 200);
      
        qPopup.show();
      
      
        return app.exec();
      }
      
      

      Why does a Qt::Popup window in QML behave differently than a Qt::Popup window in Qt Widgets? Is this intentional or a bug?

      As a workaround, I guess I will use the Qt Widgets approach to display a QQuickWidget with my custom QML menu, unless someone can tell me how to do this in pure QML?

      1 Reply Last reply
      0
      • A Offline
        A Offline
        ambershark
        wrote on last edited by ambershark
        #3

        First off, nice example. It's always nice to get something that actually works easily to test with. :)

        Second, I did some playing and research and found out that when clicking the titlebar the active window is not changed. That is why your window isn't closing. It never gets notified it is inactive because it is not considered inactive when clicking the title bar.

        Here is a bug with the same issue that was closed as a non issues because popup windows are not considered active:
        https://bugreports.qt.io/browse/QTBUG-37010

        As for a solution, you are probably going to need to use C++ or at least a mouse handler in your C++ that reports the click on the title bar.

        Also, it literally only happens with the title bar for me. Anywhere else I click either in the application window or outside of it causes the window to close. So you could just live with the fact it doesn't close if someone clicks the title bar only.

        There may be some QML thing you can do to catch that titlebar click but I don't know it. You could use a mouse exit even when the mouse leaves the window it closes, but that isn't like a normal context menu either. Maybe some sort of mouse click handler that checks the mouse cursor position and if it is outside the popup, then close it.

        My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

        1 Reply Last reply
        0
        • A Offline
          A Offline
          alexej.k
          wrote on last edited by alexej.k
          #4

          Thanks for the answer. I filed a new bug about this issue yesterday: https://bugreports.qt.io/browse/QTBUG-69777
          There seems to be a lot of similar known bugs.

          As a workaround, I decided to use a Qt Widgets window for the popup containing a QQuickWidget which displays my QML content.

          Something seems to go wrong in reporting the Qt::Popup flag correctly to the window manager. X11 usually displays (correctly implemented) popups together with a transparent overlay which does not even let mouseover events through to the underlying windows until the popup is closed. This does not happen with a QML popup, which indicates that Qt Quick is not producing a "real" popup but some kind of normal frameless window.

          Also, I think it is not possible to listen for mouse events on the title bar, or at least that's not the way Qt registers the "click outside" the window. The click outside should be detected by the window manager which then reports to the Qt application that the popup window got "out of focus" or something similar. I'm not sure how this works internally, though.

          EDIT
          I read about the concept of mouse grabbing. Qt Widgets popups call grabMouse(), this will cause the window manager to forward all mouse events to the widget, even if they are issued outside of the widget, until the mouse is ungrabbed again when the popup is closed.
          There is also a method QQuickItem::grabMouse(). Maybe this function should be called, but isn't for Popup windows?

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved