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.
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.
-
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.
@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?
-
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.
@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.
-
@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.
@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.
-
@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.
-
@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.
@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.
-
V VStevenP has marked this topic as solved on
-
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.
-
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.
-
V VStevenP has marked this topic as unsolved on
-
@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.
@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.
-
@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.
@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.
-
@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.
@jeremy_k Thanks for your thoughts.
Let me put together two things:
-
a minimal QML/C++ application that does sendEvent from the lower-priority worker thread and shows the undesired event propagation
-
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_k Thanks for your thoughts.
Let me put together two things:
-
a minimal QML/C++ application that does sendEvent from the lower-priority worker thread and shows the undesired event propagation
-
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.
@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);
-
-
@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);
@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.
-
V VStevenP has marked this topic as solved on
-
V VStevenP has marked this topic as unsolved on
-
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 trueQt 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 -
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 trueQt 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@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")
-
@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")
@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_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.
@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.
-
@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.
-
V VStevenP has marked this topic as solved on