#include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WINDOWS #include #endif // Uncomment to activate the workaround using IgnoreMouseLeaveNativeEventFilter. //#define WORKAROUND_ACTIVE 1 // Example window which will be embedded into a widget // Copied from RasterWindow example. class RasterWindow : public QWindow { Q_OBJECT public: explicit RasterWindow(QWindow *parent = nullptr): QWindow{parent}, backingStore{new QBackingStore{this}} { setObjectName("RasterWindow"); setGeometry(0, 0, 500, 500); } virtual void render(QPainter* painter) { painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("Embedded QWindow")); } public slots: void renderLater() { requestUpdate(); } void renderNow() { if (!isExposed()) return; QRect rect(0, 0, width(), height()); backingStore->beginPaint(rect); QPaintDevice* device = backingStore->paintDevice(); QPainter painter(device); painter.fillRect(0, 0, width(), height(), QGradient::NightFade); render(&painter); painter.end(); backingStore->endPaint(); backingStore->flush(rect); } protected: bool event(QEvent* event) override { if (event->type() == QEvent::UpdateRequest) { renderNow(); return true; } return QWindow::event(event); } void resizeEvent(QResizeEvent* event) override { backingStore->resize(event->size()); } void exposeEvent(QExposeEvent* event) override { if (isExposed()) renderNow(); } private: QScopedPointer backingStore; }; class IgnoreMouseLeaveNativeEventFilter : public QAbstractNativeEventFilter { public: #ifdef Q_OS_WINDOWS bool nativeEventFilter(const QByteArray& eventType, void* message, qintptr*) override { if (!_ignoreNextEvent) { if (_removeFilterOnNextEvent) { qApp->removeNativeEventFilter(this); _removeFilterOnNextEvent = false; } return false; } if (message && eventType == "windows_generic_MSG") { MSG* msg = static_cast(message); if (msg->message == WM_MOUSELEAVE) { _ignoreNextEvent = false; _removeFilterOnNextEvent = true; return true; } } return false; } #else bool nativeEventFilter(const QByteArray& eventType, void* message, qintptr* p) override { return QAbstractNativeEventFilter::nativeEventFilter(eventType, message, p); } #endif void activate() { _ignoreNextEvent = true; _removeFilterOnNextEvent = false; qApp->installNativeEventFilter(this); } private: bool _ignoreNextEvent = false; bool _removeFilterOnNextEvent = false; }; static IgnoreMouseLeaveNativeEventFilter ignoreNextMouseLeaveFilter; // Creates widget containing an embedded RasterWindows QWidget* createEmbeddedWindow(QWidget* parent) { QWindow* embeddedWindow = new RasterWindow{}; embeddedWindow->setFlag(Qt::WindowType::WindowTransparentForInput, true); return QWidget::createWindowContainer(embeddedWindow, parent); } // Event filter which changes the cursor class MouseCursorEventFilter : public QObject { Q_OBJECT public: explicit MouseCursorEventFilter(QWidget* target): _target{target} {} bool eventFilter(QObject* object, QEvent* event) override { if (object && object == _target && event) { switch (event->type()) { case QEvent::MouseButtonPress: mouseIsDown = true; #ifdef WORKAROUND_ACTIVE ignoreNextMouseLeaveFilter.activate(); #endif break; case QEvent::MouseMove: if (mouseIsDown && !cursorIsSet) { _target->setCursor(QCursor{Qt::SizeAllCursor}); cursorIsSet = true; } break; case QEvent::MouseButtonRelease: mouseIsDown = false; if (cursorIsSet) { _target->unsetCursor(); cursorIsSet = false; } break; default: break; }; } return false; } private: QWidget* _target = nullptr; bool mouseIsDown = false; bool cursorIsSet = false; }; int main(int argc, char *argv[]) { // Create application with a main window QApplication app(argc, argv); QMainWindow mainWindow; mainWindow.setObjectName("MyMainWindow"); QWidget* centralWidget = new QWidget{&mainWindow}; mainWindow.setCentralWidget(centralWidget); QLayout* layout = new QHBoxLayout(centralWidget); // Add left widget containing an embedded RenderWindow window QWidget* embeddedWindowContainer = createEmbeddedWindow(centralWidget); embeddedWindowContainer->setObjectName("EmbeddedWindowContainer"); layout->addWidget(embeddedWindowContainer); // Add mouse cursor event filter to left widget MouseCursorEventFilter embeddedWindowEventFilter{embeddedWindowContainer}; embeddedWindowContainer->installEventFilter(&embeddedWindowEventFilter); // Add right widget: a simple label QLabel* label = new QLabel{centralWidget}; label->setObjectName("OrdinaryLabel"); label->setText(QStringLiteral("Ordinary widget")); label->setAlignment(Qt::AlignCenter); layout->addWidget(label); // Add mouse cursor event filter to right widget MouseCursorEventFilter labelEventFilter{label}; label->installEventFilter(&labelEventFilter); mainWindow.show(); return app.exec(); } #include "main.moc"