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. sendEvent issue
QtWS25 Last Chance

sendEvent issue

Scheduled Pinned Locked Moved Solved QML and Qt Quick
18 Posts 2 Posters 1.8k Views
  • 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.
  • VStevenPV Offline
    VStevenPV Offline
    VStevenP
    wrote on last edited by VStevenP
    #1

    The following fails to send the specified key event to the focused QML control:

    QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

    QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

    I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

    Function keys from the attached QWERTY keyboard arrive just fine at the QML focused widget.

    I am trying to map panel events from my hardware device which is polled in the background to key events which could flow to the focused QML UI control.

    Thanks for your thoughts and suggestions.

    VStevenPV jeremy_kJ 2 Replies Last reply
    0
    • VStevenPV VStevenP

      The following fails to send the specified key event to the focused QML control:

      QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

      QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

      I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

      Function keys from the attached QWERTY keyboard arrive just fine at the QML focused widget.

      I am trying to map panel events from my hardware device which is polled in the background to key events which could flow to the focused QML UI control.

      Thanks for your thoughts and suggestions.

      VStevenPV Offline
      VStevenPV Offline
      VStevenP
      wrote on last edited by VStevenP
      #2

      @VStevenP I found that that the KeyEvent is being sent to the focused object after all, but there's a subsequent behavior difference that I was expecting that's not happening.

      I was expecting that if the event was not "accepted" by the QML Control, that the event would propagate up the object tree and could be handled by a parent. That is not happening.

      Is there a way to make manually injected key events like mine behave like actual input key events, and if they're not "accepted", propagate up the object tree, to possibly be handled by a parent?

      1 Reply Last reply
      0
      • VStevenPV VStevenP

        The following fails to send the specified key event to the focused QML control:

        QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

        QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

        I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

        Function keys from the attached QWERTY keyboard arrive just fine at the QML focused widget.

        I am trying to map panel events from my hardware device which is polled in the background to key events which could flow to the focused QML UI control.

        Thanks for your thoughts and suggestions.

        jeremy_kJ Offline
        jeremy_kJ Offline
        jeremy_k
        wrote on last edited by
        #3

        @VStevenP said in sendEvent issue:

        The following fails to send the specified key event to the focused QML control:

        QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

        QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

        I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

        QCoreApplication::postEvent() is thread-safe. QCoreApplication::sendEvent() is not. QGuiApplication::focusObject() is also not thread-safe. Even if it were, there is no guarantee made by Qt that the returned object pointer still points to the focus object, or that the object hasn't been destroyed.

        @VStevenP said in sendEvent issue:

        @VStevenP I found that that the KeyEvent is being sent to the focused object after all, but there's a subsequent behavior difference that I was expecting that's not happening.

        I was expecting that if the event was not "accepted" by the QML Control, that the event would propagate up the object tree and could be handled by a parent. That is not happening.

        Is there a way to make manually injected key events like mine behave like actual input key events, and if they're not "accepted", propagate up the object tree, to possibly be handled by a parent?

        https://doc.qt.io/qt-6/qtquick-input-focus.html presents the flow of the event. The important detail that isn't really spelled out is that the event is delivered to the window, and the window handles delivery to a parent if the child doesn't accept.

        Asking a question about code? http://eel.is/iso-c++/testcase/

        VStevenPV 1 Reply Last reply
        1
        • jeremy_kJ jeremy_k

          @VStevenP said in sendEvent issue:

          The following fails to send the specified key event to the focused QML control:

          QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

          QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

          I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

          QCoreApplication::postEvent() is thread-safe. QCoreApplication::sendEvent() is not. QGuiApplication::focusObject() is also not thread-safe. Even if it were, there is no guarantee made by Qt that the returned object pointer still points to the focus object, or that the object hasn't been destroyed.

          @VStevenP said in sendEvent issue:

          @VStevenP I found that that the KeyEvent is being sent to the focused object after all, but there's a subsequent behavior difference that I was expecting that's not happening.

          I was expecting that if the event was not "accepted" by the QML Control, that the event would propagate up the object tree and could be handled by a parent. That is not happening.

          Is there a way to make manually injected key events like mine behave like actual input key events, and if they're not "accepted", propagate up the object tree, to possibly be handled by a parent?

          https://doc.qt.io/qt-6/qtquick-input-focus.html presents the flow of the event. The important detail that isn't really spelled out is that the event is delivered to the window, and the window handles delivery to a parent if the child doesn't accept.

          VStevenPV Offline
          VStevenPV Offline
          VStevenP
          wrote on last edited by VStevenP
          #4

          @jeremy_k said in sendEvent issue:

          @VStevenP said in sendEvent issue:

          The following fails to send the specified key event to the focused QML control:

          QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

          QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

          I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

          QCoreApplication::postEvent() is thread-safe. QCoreApplication::sendEvent() is not. QGuiApplication::focusObject() is also not thread-safe. Even if it were, there is no guarantee made by Qt that the returned object pointer still points to the focus object, or that the object hasn't been destroyed.

          That explains why using postEvent with QGuiApplication::focusObject() was causing an Aborted condition. Thanks for explaining.

          @VStevenP said in sendEvent issue:

          @VStevenP I found that that the KeyEvent is being sent to the focused object after all, but there's a subsequent behavior difference that I was expecting that's not happening.

          I was expecting that if the event was not "accepted" by the QML Control, that the event would propagate up the object tree and could be handled by a parent. That is not happening.

          Is there a way to make manually injected key events like mine behave like actual input key events, and if they're not "accepted", propagate up the object tree, to possibly be handled by a parent?

          https://doc.qt.io/qt-6/qtquick-input-focus.html presents the flow of the event. The important detail that isn't really spelled out is that the event is delivered to the window, and the window handles delivery to a parent if the child doesn't accept.

          I read that doc last night, and came close to inferring that. Thanks for making it very clear to me. I'm going to revisit that document, but is there a thread-safe syntax I can use with postEvent to the main QML window, that would give the result I'm desiring? In the meantime, I'll see if I can figure it out myself.

          Thanks a million.

          VStevenPV 2 Replies Last reply
          0
          • VStevenPV VStevenP

            @jeremy_k said in sendEvent issue:

            @VStevenP said in sendEvent issue:

            The following fails to send the specified key event to the focused QML control:

            QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

            QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

            I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

            QCoreApplication::postEvent() is thread-safe. QCoreApplication::sendEvent() is not. QGuiApplication::focusObject() is also not thread-safe. Even if it were, there is no guarantee made by Qt that the returned object pointer still points to the focus object, or that the object hasn't been destroyed.

            That explains why using postEvent with QGuiApplication::focusObject() was causing an Aborted condition. Thanks for explaining.

            @VStevenP said in sendEvent issue:

            @VStevenP I found that that the KeyEvent is being sent to the focused object after all, but there's a subsequent behavior difference that I was expecting that's not happening.

            I was expecting that if the event was not "accepted" by the QML Control, that the event would propagate up the object tree and could be handled by a parent. That is not happening.

            Is there a way to make manually injected key events like mine behave like actual input key events, and if they're not "accepted", propagate up the object tree, to possibly be handled by a parent?

            https://doc.qt.io/qt-6/qtquick-input-focus.html presents the flow of the event. The important detail that isn't really spelled out is that the event is delivered to the window, and the window handles delivery to a parent if the child doesn't accept.

            I read that doc last night, and came close to inferring that. Thanks for making it very clear to me. I'm going to revisit that document, but is there a thread-safe syntax I can use with postEvent to the main QML window, that would give the result I'm desiring? In the meantime, I'll see if I can figure it out myself.

            Thanks a million.

            VStevenPV Offline
            VStevenPV Offline
            VStevenP
            wrote on last edited by VStevenP
            #5
            This post is deleted!
            1 Reply Last reply
            0
            • VStevenPV VStevenP

              @jeremy_k said in sendEvent issue:

              @VStevenP said in sendEvent issue:

              The following fails to send the specified key event to the focused QML control:

              QKeyEvent event(QKeyEvent::KeyPress, Qt::Key_F1, Qt::NoModifier, QString(""));

              QGuiApplication::sendEvent(QGuiApplication::focusObject(), &event);

              I am trying to send an F1 key event from a lower-priority data worker thread to the focused QML object in my QtQuick2 application. But it never gets through. I though this was the thread-safe way.

              QCoreApplication::postEvent() is thread-safe. QCoreApplication::sendEvent() is not. QGuiApplication::focusObject() is also not thread-safe. Even if it were, there is no guarantee made by Qt that the returned object pointer still points to the focus object, or that the object hasn't been destroyed.

              That explains why using postEvent with QGuiApplication::focusObject() was causing an Aborted condition. Thanks for explaining.

              @VStevenP said in sendEvent issue:

              @VStevenP I found that that the KeyEvent is being sent to the focused object after all, but there's a subsequent behavior difference that I was expecting that's not happening.

              I was expecting that if the event was not "accepted" by the QML Control, that the event would propagate up the object tree and could be handled by a parent. That is not happening.

              Is there a way to make manually injected key events like mine behave like actual input key events, and if they're not "accepted", propagate up the object tree, to possibly be handled by a parent?

              https://doc.qt.io/qt-6/qtquick-input-focus.html presents the flow of the event. The important detail that isn't really spelled out is that the event is delivered to the window, and the window handles delivery to a parent if the child doesn't accept.

              I read that doc last night, and came close to inferring that. Thanks for making it very clear to me. I'm going to revisit that document, but is there a thread-safe syntax I can use with postEvent to the main QML window, that would give the result I'm desiring? In the meantime, I'll see if I can figure it out myself.

              Thanks a million.

              VStevenPV Offline
              VStevenPV Offline
              VStevenP
              wrote on last edited by
              #6

              @VStevenP I did some more research and found a way to make it work.

              First, I saved off a pointer to the root QObject of my QML ApplicationEngine, which in my EGLFS app is the one and only Window.

              QQmlApplicationEngine engine;
              ...
              pMainQMLWindowObject = engine.rootObjects().at(0);

              Then I sent my events to this object.

              QCoreApplication::sendEvent(pMainQMLWindowObject, &event);

              The result is that if the event was not accepted by the focused object in the window, it propagated to parents for potential handling.

              1 Reply Last reply
              0
              • VStevenPV VStevenP has marked this topic as solved on
              • jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by jeremy_k
                #7

                If the application code can guarantee the lifetime of the window, posting an event directly to the window works.

                If not, create an intermediary object that will have the requisite lifetime. A queued signal connection would allow the intermediary to be deleted safely.

                Asking a question about code? http://eel.is/iso-c++/testcase/

                VStevenPV 1 Reply Last reply
                1
                • jeremy_kJ jeremy_k

                  If the application code can guarantee the lifetime of the window, posting an event directly to the window works.

                  If not, create an intermediary object that will have the requisite lifetime. A queued signal connection would allow the intermediary to be deleted safely.

                  VStevenPV Offline
                  VStevenPV Offline
                  VStevenP
                  wrote on last edited by
                  #8

                  @jeremy_k said in sendEvent issue:

                  If the application code can guarantee the lifetime of the window, posting an event directly to the window works.

                  Yes, the lifetime of the window is guaranteed.

                  Thanks for the additional tip in the other case.

                  VStevenPV 1 Reply Last reply
                  0
                  • VStevenPV VStevenP has marked this topic as unsolved on
                  • VStevenPV VStevenP

                    @jeremy_k said in sendEvent issue:

                    If the application code can guarantee the lifetime of the window, posting an event directly to the window works.

                    Yes, the lifetime of the window is guaranteed.

                    Thanks for the additional tip in the other case.

                    VStevenPV Offline
                    VStevenPV Offline
                    VStevenP
                    wrote on last edited by
                    #9

                    @VStevenP Unfortunately, there seems to be a limitation to the solution I described above.

                    Although the focused QML control now receives the KeyEvent that was sent to the main, persistent QML window via sendEvent(), the KeyEvent wrongly propagates up to the parent even when event.accepted was set to true during Keys.onPressed handling.

                    I found a workaround to this limitation: If I cause the sendEvent to occur from the QML-side rather than the C++-side, then the event.accepted processing occurs, and undesired propagation to the parent can be avoided.

                    I'm wondering if anyone has a comment about this behavior, or any tips if I can avoid this workaround.

                    jeremy_kJ 1 Reply Last reply
                    0
                    • VStevenPV VStevenP

                      @VStevenP Unfortunately, there seems to be a limitation to the solution I described above.

                      Although the focused QML control now receives the KeyEvent that was sent to the main, persistent QML window via sendEvent(), the KeyEvent wrongly propagates up to the parent even when event.accepted was set to true during Keys.onPressed handling.

                      I found a workaround to this limitation: If I cause the sendEvent to occur from the QML-side rather than the C++-side, then the event.accepted processing occurs, and undesired propagation to the parent can be avoided.

                      I'm wondering if anyone has a comment about this behavior, or any tips if I can avoid this workaround.

                      jeremy_kJ Offline
                      jeremy_kJ Offline
                      jeremy_k
                      wrote on last edited by
                      #10

                      @VStevenP said in sendEvent issue:

                      @VStevenP Unfortunately, there seems to be a limitation to the solution I described above.

                      Although the focused QML control now receives the KeyEvent that was sent to the main, persistent QML window via sendEvent(), the KeyEvent wrongly propagates up to the parent even when event.accepted was set to true during Keys.onPressed handling.

                      I found a workaround to this limitation: If I cause the sendEvent to occur from the QML-side rather than the C++-side, then the event.accepted processing occurs, and undesired propagation to the parent can be avoided.

                      I'm wondering if anyone has a comment about this behavior, or any tips if I can avoid this workaround.

                      I suspect that anything beyond a guess is going to require some code to discuss.

                      My first strategy is almost always to install an event filter on the application. Understanding the propagation has led me to read a lot of code that I was otherwise unaware of.

                      Asking a question about code? http://eel.is/iso-c++/testcase/

                      VStevenPV 1 Reply Last reply
                      0
                      • jeremy_kJ jeremy_k

                        @VStevenP said in sendEvent issue:

                        @VStevenP Unfortunately, there seems to be a limitation to the solution I described above.

                        Although the focused QML control now receives the KeyEvent that was sent to the main, persistent QML window via sendEvent(), the KeyEvent wrongly propagates up to the parent even when event.accepted was set to true during Keys.onPressed handling.

                        I found a workaround to this limitation: If I cause the sendEvent to occur from the QML-side rather than the C++-side, then the event.accepted processing occurs, and undesired propagation to the parent can be avoided.

                        I'm wondering if anyone has a comment about this behavior, or any tips if I can avoid this workaround.

                        I suspect that anything beyond a guess is going to require some code to discuss.

                        My first strategy is almost always to install an event filter on the application. Understanding the propagation has led me to read a lot of code that I was otherwise unaware of.

                        VStevenPV Offline
                        VStevenPV Offline
                        VStevenP
                        wrote on last edited by
                        #11

                        @jeremy_k Thanks for your thoughts.

                        Let me put together two things:

                        1. a minimal QML/C++ application that does sendEvent from the lower-priority worker thread and shows the undesired event propagation

                        2. another minimal QML/C++ application that sets a Q_PROPERTY which can trigger the sendEvent from the high priority UI thread (in the QML code) and shows the desired event propagation, where setting event.accepted = true blocks propagation.

                        Also, I am familiar with inheriting QGUIApplication to see all the events. I'm not sure I'd know how to debug this, but I'm guessing I could see the difference in the 2 cases and report that back, before providing the examples.

                        jeremy_kJ 1 Reply Last reply
                        0
                        • VStevenPV VStevenP

                          @jeremy_k Thanks for your thoughts.

                          Let me put together two things:

                          1. a minimal QML/C++ application that does sendEvent from the lower-priority worker thread and shows the undesired event propagation

                          2. another minimal QML/C++ application that sets a Q_PROPERTY which can trigger the sendEvent from the high priority UI thread (in the QML code) and shows the desired event propagation, where setting event.accepted = true blocks propagation.

                          Also, I am familiar with inheriting QGUIApplication to see all the events. I'm not sure I'd know how to debug this, but I'm guessing I could see the difference in the 2 cases and report that back, before providing the examples.

                          jeremy_kJ Offline
                          jeremy_kJ Offline
                          jeremy_k
                          wrote on last edited by
                          #12

                          @VStevenP said in sendEvent issue:

                          Also, I am familiar with inheriting QGUIApplication to see all the events. I'm not sure I'd know how to debug this, but I'm guessing I could see the difference in the 2 cases and report that back, before providing the examples.

                          There's no need to inherit from Q*Application.

                          class Filter: public QObject {
                              bool eventFilter(QObject *obj, QEvent *ev) override {
                                  qDebug() "Delivering event" << ev << "to" << obj;
                                  return false;
                              }
                          };
                          
                          QCoreApplication app(argc, argv);
                          app.installEventFilter(new Filter);
                          

                          Asking a question about code? http://eel.is/iso-c++/testcase/

                          VStevenPV 1 Reply Last reply
                          1
                          • jeremy_kJ jeremy_k

                            @VStevenP said in sendEvent issue:

                            Also, I am familiar with inheriting QGUIApplication to see all the events. I'm not sure I'd know how to debug this, but I'm guessing I could see the difference in the 2 cases and report that back, before providing the examples.

                            There's no need to inherit from Q*Application.

                            class Filter: public QObject {
                                bool eventFilter(QObject *obj, QEvent *ev) override {
                                    qDebug() "Delivering event" << ev << "to" << obj;
                                    return false;
                                }
                            };
                            
                            QCoreApplication app(argc, argv);
                            app.installEventFilter(new Filter);
                            
                            VStevenPV Offline
                            VStevenPV Offline
                            VStevenP
                            wrote on last edited by VStevenP
                            #13

                            @jeremy_k Thanks very much! For now I'm going to mark the issue as Solved again, and use my workaround. When time permits, I will try the event filter code you posted, and report back the results for the 2 cases. After that I could even prepare those 2 minimal example projects if it would still be helpful.

                            1 Reply Last reply
                            0
                            • VStevenPV VStevenP has marked this topic as solved on
                            • VStevenPV VStevenP has marked this topic as unsolved on
                            • VStevenPV Offline
                              VStevenPV Offline
                              VStevenP
                              wrote on last edited by VStevenP
                              #14

                              Here are the lists of events for an actual F6 QWERTY key press, versus an F6 key press generated in code via a call to sendEvent to the main persistent QML window.

                              Differences are highlighted in Bold.

                              Qt 5.12.12 event flow when KeyEvent comes from attached QWERTY keyboard and the key event is handled as expected.

                              Delivering event QEvent::ShortcutOverride to Main_QMLTYPE_51(0x5559e4ffc060, name = "window in Main.qml")
                              Delivering event QEvent::ShortcutOverride to KText_QMLTYPE_48(0x5559e55de270, name = "rectText in KText.qml")

                              Delivering event QEvent::KeyPress to Main_QMLTYPE_51(0x5559e4ffc060, name = "window in Main.qml")
                              Delivering event QEvent::KeyPress to KText_QMLTYPE_48(0x5559e55de270, name = "rectText in KText.qml")
                              Delivering event QEvent::KeyPress to QQuickItem(0x5559e55db7d0, name = "item in ProgramParamsValues.qml")
                              Delivering event QEvent::KeyPress to KClientContainer_QMLTYPE_49(0x5559e55c6a60, name = "KClientContainer")
                              Delivering event QEvent::KeyPress to QQuickRectangle(0x5559e55c57e0, name = "KClientArea")
                              Delivering event QEvent::KeyPress to QQuickRectangle(0x5559e55c3a50, name = "KPage in ProgramParams.qml")
                              Delivering event QEvent::KeyPress to QQuickRectangle(0x5559e55c2a90, name = "KPage in MenuProgramEdit.qml")
                              qml: setting isKeyAccepted to true in MenuProgramEdit.js handleExitSwitchPress()
                              qml: executing in MenuProgramEdit.js handleKeyPress(), returning isKeyAccepted true

                              Qt 5.12.12 event flow when KeyEvent comes programmatically to the main, persistent QML window and the KeyEvent propagates to the parent items even when event.accepted is being set to true.

                              executing in DataWorker::sendF6KeyPress()
                              Delivering event QEvent::KeyPress to Main_QMLTYPE_51(0x563e7edf5730, name = "window in Main.qml")
                              Delivering event QEvent::KeyPress to KText_QMLTYPE_45(0x563e7f3d6e50, name = "rectText in KText.qml")
                              Delivering event QEvent::KeyPress to QQuickItem(0x563e7f3d43b0, name = "item in ProgramParamsValues.qml")
                              Delivering event QEvent::KeyPress to KClientContainer_QMLTYPE_46(0x563e7f3bf6a0, name = "KClientContainer")
                              Delivering event QEvent::KeyPress to QQuickRectangle(0x563e7f3be420, name = "KClientArea")
                              Delivering event QEvent::KeyPress to QQuickRectangle(0x563e7f3bc690, name = "KPage in ProgramParams.qml")
                              Delivering event QEvent::KeyPress to QQuickRectangle(0x563e7f3bb6d0, name = "KPage in MenuProgramEdit.qml")
                              Delivering event QEvent::KeyPress to QQuickItem(0x563e7f08a540, name = "item in Main.qml")
                              Delivering event QEvent::KeyPress to QQuickRootItem(0x563e7f06d6b0)
                              Delivering event QEvent::MetaCall to QObject(0x7f536c002ea0)
                              Delivering event QEvent::MetaCall to QObject(0x7f536c003500)

                              qml: setting isKeyAccepted to true in MenuProgramEdit.js handleExitSwitchPress()
                              qml: executing in MenuProgramEdit.js handleKeyPress(), returning isKeyAccepted true

                              jeremy_kJ 1 Reply Last reply
                              0
                              • VStevenPV VStevenP

                                Here are the lists of events for an actual F6 QWERTY key press, versus an F6 key press generated in code via a call to sendEvent to the main persistent QML window.

                                Differences are highlighted in Bold.

                                Qt 5.12.12 event flow when KeyEvent comes from attached QWERTY keyboard and the key event is handled as expected.

                                Delivering event QEvent::ShortcutOverride to Main_QMLTYPE_51(0x5559e4ffc060, name = "window in Main.qml")
                                Delivering event QEvent::ShortcutOverride to KText_QMLTYPE_48(0x5559e55de270, name = "rectText in KText.qml")

                                Delivering event QEvent::KeyPress to Main_QMLTYPE_51(0x5559e4ffc060, name = "window in Main.qml")
                                Delivering event QEvent::KeyPress to KText_QMLTYPE_48(0x5559e55de270, name = "rectText in KText.qml")
                                Delivering event QEvent::KeyPress to QQuickItem(0x5559e55db7d0, name = "item in ProgramParamsValues.qml")
                                Delivering event QEvent::KeyPress to KClientContainer_QMLTYPE_49(0x5559e55c6a60, name = "KClientContainer")
                                Delivering event QEvent::KeyPress to QQuickRectangle(0x5559e55c57e0, name = "KClientArea")
                                Delivering event QEvent::KeyPress to QQuickRectangle(0x5559e55c3a50, name = "KPage in ProgramParams.qml")
                                Delivering event QEvent::KeyPress to QQuickRectangle(0x5559e55c2a90, name = "KPage in MenuProgramEdit.qml")
                                qml: setting isKeyAccepted to true in MenuProgramEdit.js handleExitSwitchPress()
                                qml: executing in MenuProgramEdit.js handleKeyPress(), returning isKeyAccepted true

                                Qt 5.12.12 event flow when KeyEvent comes programmatically to the main, persistent QML window and the KeyEvent propagates to the parent items even when event.accepted is being set to true.

                                executing in DataWorker::sendF6KeyPress()
                                Delivering event QEvent::KeyPress to Main_QMLTYPE_51(0x563e7edf5730, name = "window in Main.qml")
                                Delivering event QEvent::KeyPress to KText_QMLTYPE_45(0x563e7f3d6e50, name = "rectText in KText.qml")
                                Delivering event QEvent::KeyPress to QQuickItem(0x563e7f3d43b0, name = "item in ProgramParamsValues.qml")
                                Delivering event QEvent::KeyPress to KClientContainer_QMLTYPE_46(0x563e7f3bf6a0, name = "KClientContainer")
                                Delivering event QEvent::KeyPress to QQuickRectangle(0x563e7f3be420, name = "KClientArea")
                                Delivering event QEvent::KeyPress to QQuickRectangle(0x563e7f3bc690, name = "KPage in ProgramParams.qml")
                                Delivering event QEvent::KeyPress to QQuickRectangle(0x563e7f3bb6d0, name = "KPage in MenuProgramEdit.qml")
                                Delivering event QEvent::KeyPress to QQuickItem(0x563e7f08a540, name = "item in Main.qml")
                                Delivering event QEvent::KeyPress to QQuickRootItem(0x563e7f06d6b0)
                                Delivering event QEvent::MetaCall to QObject(0x7f536c002ea0)
                                Delivering event QEvent::MetaCall to QObject(0x7f536c003500)

                                qml: setting isKeyAccepted to true in MenuProgramEdit.js handleExitSwitchPress()
                                qml: executing in MenuProgramEdit.js handleKeyPress(), returning isKeyAccepted true

                                jeremy_kJ Offline
                                jeremy_kJ Offline
                                jeremy_k
                                wrote on last edited by
                                #15

                                @VStevenP said in sendEvent issue:

                                Here are the lists of events for an actual F6 QWERTY key press, versus an F6 key press generated in code via a call to sendEvent to the main persistent QML window.

                                Unless the design of sending from a worker thread has been altered, QCoreApplication::sendEvent is still the wrong API to use. sendEvent is not thread safe.

                                https://doc.qt.io/qt-6/qcoreapplication.html#sendEvent

                                Sends event event directly to receiver receiver, using the notify() function. Returns the value that was returned from the event handler.

                                What happens if the receiver is in the middle of another, incompatible operation?

                                example.cpp:

                                #include <QCoreApplication>
                                #include <QObject>
                                #include <QDebug>
                                #include <QtConcurrent>
                                
                                struct Receiver: public QObject {
                                    bool event(QEvent *event) override {
                                        qDebug() << "got event" << event->type() << "in" << QThread::currentThread();
                                        return true;
                                    }
                                };
                                
                                void runme(Receiver *r)
                                {
                                    QThread::currentThread()->setObjectName("Worker");
                                    QEvent sentEvent(QEvent::User);
                                    QCoreApplication::sendEvent(r, &sentEvent);
                                    QCoreApplication::postEvent(r, new QEvent(QEvent::Type::None));
                                }
                                
                                int main(int argc, char *argv[])
                                {
                                    QCoreApplication a(argc, argv);
                                    QThread::currentThread()->setObjectName("Main");
                                    QtConcurrent::run(&runme, new Receiver);
                                    return a.exec();
                                }
                                

                                output:

                                got event QEvent::User in QThreadPoolThread(0x600001105020, name = "Worker")
                                got event QEvent::None in QThread(0x600001d00180, name = "Main")
                                

                                Asking a question about code? http://eel.is/iso-c++/testcase/

                                VStevenPV 1 Reply Last reply
                                0
                                • jeremy_kJ jeremy_k

                                  @VStevenP said in sendEvent issue:

                                  Here are the lists of events for an actual F6 QWERTY key press, versus an F6 key press generated in code via a call to sendEvent to the main persistent QML window.

                                  Unless the design of sending from a worker thread has been altered, QCoreApplication::sendEvent is still the wrong API to use. sendEvent is not thread safe.

                                  https://doc.qt.io/qt-6/qcoreapplication.html#sendEvent

                                  Sends event event directly to receiver receiver, using the notify() function. Returns the value that was returned from the event handler.

                                  What happens if the receiver is in the middle of another, incompatible operation?

                                  example.cpp:

                                  #include <QCoreApplication>
                                  #include <QObject>
                                  #include <QDebug>
                                  #include <QtConcurrent>
                                  
                                  struct Receiver: public QObject {
                                      bool event(QEvent *event) override {
                                          qDebug() << "got event" << event->type() << "in" << QThread::currentThread();
                                          return true;
                                      }
                                  };
                                  
                                  void runme(Receiver *r)
                                  {
                                      QThread::currentThread()->setObjectName("Worker");
                                      QEvent sentEvent(QEvent::User);
                                      QCoreApplication::sendEvent(r, &sentEvent);
                                      QCoreApplication::postEvent(r, new QEvent(QEvent::Type::None));
                                  }
                                  
                                  int main(int argc, char *argv[])
                                  {
                                      QCoreApplication a(argc, argv);
                                      QThread::currentThread()->setObjectName("Main");
                                      QtConcurrent::run(&runme, new Receiver);
                                      return a.exec();
                                  }
                                  

                                  output:

                                  got event QEvent::User in QThreadPoolThread(0x600001105020, name = "Worker")
                                  got event QEvent::None in QThread(0x600001d00180, name = "Main")
                                  
                                  VStevenPV Offline
                                  VStevenPV Offline
                                  VStevenP
                                  wrote on last edited by
                                  #16

                                  @jeremy_k Thanks for all that information and guidance. I reworked my code to use postEvent() instead of sendEvent().

                                  I can send QEvent of type QEvent::Type::User (1000 and above) and it works, If I try to pass a QKeyEvent, it crashes. This is probably expected behavior.

                                  It seems the only way to directly post fully-defined Key events (events that have a type of pressed or released, a key code, and modifiers) was via a module called QtTest, which does not exist in my Qt 5.12.12 standard SDK.

                                  jeremy_kJ 1 Reply Last reply
                                  0
                                  • VStevenPV VStevenP

                                    @jeremy_k Thanks for all that information and guidance. I reworked my code to use postEvent() instead of sendEvent().

                                    I can send QEvent of type QEvent::Type::User (1000 and above) and it works, If I try to pass a QKeyEvent, it crashes. This is probably expected behavior.

                                    It seems the only way to directly post fully-defined Key events (events that have a type of pressed or released, a key code, and modifiers) was via a module called QtTest, which does not exist in my Qt 5.12.12 standard SDK.

                                    jeremy_kJ Offline
                                    jeremy_kJ Offline
                                    jeremy_k
                                    wrote on last edited by
                                    #17

                                    @VStevenP said in sendEvent issue:

                                    @jeremy_k Thanks for all that information and guidance. I reworked my code to use postEvent() instead of sendEvent().

                                    I can send QEvent of type QEvent::Type::User (1000 and above) and it works, If I try to pass a QKeyEvent, it crashes. This is probably expected behavior.

                                    Only if you do it the wrong way!

                                    But seriously, source and/or a stack trace is necessary for anything beyond guessing.

                                    As a first guess, sendEvent() is usually done with a stack-allocated event, because processing finished before the function call returns. postEvent() invocation uses heap-allocated events, and the event loop deletes them after delivery. Getting that wrong might work for simple tests but fail in more complex scenarios.

                                    It seems the only way to directly post fully-defined Key events (events that have a type of pressed or released, a key code, and modifiers) was via a module called QtTest, which does not exist in my Qt 5.12.12 standard SDK.

                                    Use of QtTest outside of testing is discouraged. I don't have a strong opinion on the matter.

                                    Asking a question about code? http://eel.is/iso-c++/testcase/

                                    VStevenPV 1 Reply Last reply
                                    0
                                    • jeremy_kJ jeremy_k

                                      @VStevenP said in sendEvent issue:

                                      @jeremy_k Thanks for all that information and guidance. I reworked my code to use postEvent() instead of sendEvent().

                                      I can send QEvent of type QEvent::Type::User (1000 and above) and it works, If I try to pass a QKeyEvent, it crashes. This is probably expected behavior.

                                      Only if you do it the wrong way!

                                      But seriously, source and/or a stack trace is necessary for anything beyond guessing.

                                      As a first guess, sendEvent() is usually done with a stack-allocated event, because processing finished before the function call returns. postEvent() invocation uses heap-allocated events, and the event loop deletes them after delivery. Getting that wrong might work for simple tests but fail in more complex scenarios.

                                      It seems the only way to directly post fully-defined Key events (events that have a type of pressed or released, a key code, and modifiers) was via a module called QtTest, which does not exist in my Qt 5.12.12 standard SDK.

                                      Use of QtTest outside of testing is discouraged. I don't have a strong opinion on the matter.

                                      VStevenPV Offline
                                      VStevenPV Offline
                                      VStevenP
                                      wrote on last edited by VStevenP
                                      #18

                                      @jeremy_k OK, I got it working by passing a heap-allocated key event rather than a stack-allocated key event.

                                      Thanks! Marking this topic as Solved again.

                                      1 Reply Last reply
                                      1
                                      • VStevenPV VStevenP has marked this topic as solved on

                                      • Login

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