In this article I will try to talk about how to pass mouse and keyboard events to
QQuickWindow , if used in conjunction with
QQuickRenderControl . The reason that it is necessary to pay special attention is that in the case of using QQuickRenderControl, no window is actually created, respectively, QQuickWindow has absolutely no opportunity to receive any events, and they have to be emulated. The same applies to resizing - this operation also needs to be notified explicitly.
For those who missed the previous parts:How to trigger events in Qt
Sending an event to Qt is done using the method
bool QCoreApplication::sendEvent(QObject* receiver, QEvent* event)
Where,
- receiver - the recipient of the message, in our case it is an instance of QQuickWindow (or its descendant);
- event is an instance of a specific type of event;
Passing mouse events
For correct operation, it is enough to implement 3 mouse events:
QEvent :: MouseButtonPress:
QPointF mousePoint( 150, 201 ); Qt::MouseButton button = Qt::LeftButton; Qt::MouseButton buttons = Qt::LeftButton | Qt::RightButton; Qt::KeyboardModifiers modifiers = Qt::AltModifier; QMouseEvent mouseEvent( QEvent::MouseButtonPress, mousePoint, mousePoint, button, buttons, modifiers ); QCoreApplication::sendEvent( quickWindow, &mouseEvent );
Where,
- mousePoint - the current position of the mouse in coordinates QQuickWindow;
- button - the mouse button that caused this event;
- buttons - all mouse buttons pressed at the time of the event generation;
- modifiers - modifier keys pressed on the keyboard (Ctrl, Alt, Shift, etc.);
mousePoint is used twice, because it is passed in QQuckWindow coordinates for the first time, and in screen coordinates the second time. But since: a) the window itself is not created, b) it is always treated as a top-level window, c) we control its position by ourselves - we transmit the same value (as if the window is always in the upper left corner of the screen), and when installing the position of the window, just take this fact into account.
QEvent :: MouseMove:
QPointF mousePoint( 170, 198 ); Qt::MouseButton button = Qt::NoButton; Qt::MouseButton buttons = Qt::LeftButton | Qt::RightButton; Qt::KeyboardModifiers modifiers = Qt::AltModifier; QMouseEvent mouseEvent( QEvent::MouseMove, mousePoint, mousePoint, button, buttons, modifiers ); QCoreApplication::sendEvent( quickWindow, &mouseEvent );
Since the cause of the mouse movement event is the fact of the mouse movement itself, and not any of the buttons, the button variable is assigned the value Qt :: NoButton.
QEvent :: MouseButtonRelease:
QPointF mousePoint( 160, 251 ); Qt::MouseButton button = Qt::LeftButton; Qt::MouseButton buttons = Qt::RightButton; Qt::KeyboardModifiers modifiers = Qt::AltModifier; QMouseEvent mouseEvent( QEvent::MouseButtonRelease, mousePoint, mousePoint, button, buttons, modifiers ); QCoreApplication::sendEvent( quickWindow, &mouseEvent );
button in this case means the button that caused this event, but in this case it was released , so it can no longer be present in buttons (otherwise Qt starts processing this event incorrectly).Keyboard event transfer
Similarly, for correct handling of keyboard events, it is enough to implement 2 events:
')
QEvent :: KeyPress:
Qt::Key qtKey = Qt::Key_Space; QKeyEvent keyEvent( QEvent::KeyPress, qtKey, Qt::NoModifier ); QCoreApplication::sendEvent( quickWindow, &keyEvent );
QEvent :: KeyRelease:
Qt::Key qtKey = Qt::Key_Space; QKeyEvent keyEvent( QEvent::KeyRelease, qtKey, Qt::NoModifier ); QCoreApplication::sendEvent( quickWindow, &keyEvent );
Resizing
As mentioned above, offscreen windows in Qt are treated as top-level windows, so we use the appropriate method:
QSize newSize( 320, 240 ); quickWindow->setGeometry( 0, 0, newSize.width(), newSize.height() );
In addition to resizing the actual window, it is desirable to also resize the FBO, since otherwise, we will either get pixelation (with an increase in size), or useless use of resources (since the size of the FBO will be more than required):
if( context->makeCurrent( offscreenSurface ) ) { destroyFbo(); createFbo(); context->doneCurrent(); }
Since it is impossible to change the size of the FBO, simply delete the current one and create a new one (see details in
Part One ).
That's all.
Implementation examples, as usual, are available on
GitHubWell, as before, comments, questions, healthy criticism are welcome.
To be continued...