From b305702d1e38d72765325dd7b1f2a7fde14e5529 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 8 Aug 2016 11:37:43 +0200 Subject: eglfs: Support virtual desktops in the OpenGL cursor The GBM-based hardware cursor already has this. Let's implement it in the commonly used OpenGL cursor too. The main user will be the EGLDevice backend which does not currently have a hardware cursor but supports multiple screens. This also means QEglFSCursor must be capable of operating on different contexts (and what's more, non-sharing contexts). Task-number: QTBUG-55161 Change-Id: Ie23bba1e6aab34b04d689f26a84c19a2bde518da Reviewed-by: Andy Nichols --- src/plugins/platforms/eglfs/api/qeglfscursor.cpp | 163 +++++++++++++-------- src/plugins/platforms/eglfs/api/qeglfscursor_p.h | 27 ++-- .../eglfs/api/qeglfsdeviceintegration.cpp | 3 +- .../eglfs_kms_egldevice/qeglfskmsegldevice.cpp | 33 ++++- .../eglfs_kms_egldevice/qeglfskmsegldevice.h | 12 ++ .../qeglfskmsegldeviceintegration.cpp | 6 + .../qeglfskmsegldeviceintegration.h | 1 + .../qeglfskmsegldevicescreen.cpp | 22 +++ .../eglfs_kms_egldevice/qeglfskmsegldevicescreen.h | 7 + 9 files changed, 198 insertions(+), 76 deletions(-) diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp index 7c1f11372a..0040ecd59d 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp @@ -59,12 +59,11 @@ QT_BEGIN_NAMESPACE QEglFSCursor::QEglFSCursor(QPlatformScreen *screen) - : m_visible(true), - m_screen(static_cast(screen)), - m_program(0), - m_textureEntry(0), - m_deviceListener(0), - m_updateRequested(false) + : m_visible(true), + m_screen(static_cast(screen)), + m_activeScreen(nullptr), + m_deviceListener(0), + m_updateRequested(false) { QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); if (!hideCursorVal.isEmpty()) @@ -116,15 +115,14 @@ void QEglFSCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::Device void QEglFSCursor::resetResources() { - if (QOpenGLContext::currentContext()) { - delete m_program; - glDeleteTextures(1, &m_cursor.customCursorTexture); - glDeleteTextures(1, &m_cursorAtlas.texture); + if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) { + GraphicsContextData &gfx(m_gfx[ctx]); + delete gfx.program; + glDeleteTextures(1, &gfx.customCursorTexture); + glDeleteTextures(1, &gfx.atlasTexture); + gfx = GraphicsContextData(); } - m_program = 0; - m_cursor.customCursorTexture = 0; m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull(); - m_cursorAtlas.texture = 0; } void QEglFSCursor::createShaderPrograms() @@ -146,15 +144,16 @@ void QEglFSCursor::createShaderPrograms() " gl_FragColor = texture2D(texture, textureCoord).bgra;\n" "}\n"; - m_program = new QOpenGLShaderProgram; - m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_program->bindAttributeLocation("vertexCoordEntry", 0); - m_program->bindAttributeLocation("textureCoordEntry", 1); - m_program->link(); + GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]); + gfx.program = new QOpenGLShaderProgram; + gfx.program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); + gfx.program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); + gfx.program->bindAttributeLocation("vertexCoordEntry", 0); + gfx.program->bindAttributeLocation("textureCoordEntry", 1); + gfx.program->link(); - m_textureEntry = m_program->uniformLocation("texture"); - m_matEntry = m_program->uniformLocation("mat"); + gfx.textureEntry = gfx.program->uniformLocation("texture"); + gfx.matEntry = gfx.program->uniformLocation("mat"); } void QEglFSCursor::createCursorTexture(uint *texture, const QImage &image) @@ -214,7 +213,7 @@ void QEglFSCursor::changeCursor(QCursor *cursor, QWindow *window) Q_UNUSED(window); const QRect oldCursorRect = cursorRect(); if (setCurrentCursor(cursor)) - update(oldCursorRect | cursorRect()); + update(oldCursorRect | cursorRect(), false); } bool QEglFSCursor::setCurrentCursor(QCursor *cursor) @@ -238,16 +237,17 @@ bool QEglFSCursor::setCurrentCursor(QCursor *cursor) hs * (m_cursor.shape / m_cursorAtlas.cursorsPerRow), ws, hs); m_cursor.hotSpot = m_cursorAtlas.hotSpots[m_cursor.shape]; - m_cursor.texture = m_cursorAtlas.texture; + m_cursor.useCustomCursor = false; m_cursor.size = QSize(m_cursorAtlas.cursorWidth, m_cursorAtlas.cursorHeight); } else { QImage image = cursor->pixmap().toImage(); m_cursor.textureRect = QRectF(0, 0, 1, 1); m_cursor.hotSpot = cursor->hotSpot(); - m_cursor.texture = 0; // will get updated in the next render() + m_cursor.useCustomCursor = false; // will get updated in the next render() m_cursor.size = image.size(); m_cursor.customCursorImage = image; m_cursor.customCursorPending = true; + m_cursor.customCursorKey = m_cursor.customCursorImage.cacheKey(); } return true; @@ -257,17 +257,20 @@ bool QEglFSCursor::setCurrentCursor(QCursor *cursor) class CursorUpdateEvent : public QEvent { public: - CursorUpdateEvent(const QPoint &pos, const QRegion &rgn) + CursorUpdateEvent(const QPoint &pos, const QRect &rect, bool allScreens) : QEvent(QEvent::Type(QEvent::User + 1)), m_pos(pos), - m_region(rgn) + m_rect(rect), + m_allScreens(allScreens) { } QPoint pos() const { return m_pos; } - QRegion region() const { return m_region; } + QRegion rect() const { return m_rect; } + bool allScreens() const { return m_allScreens; } private: QPoint m_pos; - QRegion m_region; + QRect m_rect; + bool m_allScreens; }; bool QEglFSCursor::event(QEvent *e) @@ -275,21 +278,30 @@ bool QEglFSCursor::event(QEvent *e) if (e->type() == QEvent::User + 1) { CursorUpdateEvent *ev = static_cast(e); m_updateRequested = false; - QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(ev->pos()), ev->region()); - QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + if (!ev->allScreens()) { + QWindow *w = m_screen->topLevelAt(ev->pos()); // works for the entire virtual desktop, no need to loop + if (w) { + QWindowSystemInterface::handleExposeEvent(w, ev->rect()); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + } + } else { + for (QWindow *w : qGuiApp->topLevelWindows()) + QWindowSystemInterface::handleExposeEvent(w, w->geometry()); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + } return true; } return QPlatformCursor::event(e); } -void QEglFSCursor::update(const QRegion &rgn) +void QEglFSCursor::update(const QRect &rect, bool allScreens) { if (!m_updateRequested) { // Must not flush the window system events directly from here since we are likely to // be a called directly from QGuiApplication's processMouseEvents. Flushing events // could cause reentering by dispatching more queued mouse events. m_updateRequested = true; - QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rgn)); + QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rect, allScreens)); } } @@ -308,8 +320,9 @@ void QEglFSCursor::setPos(const QPoint &pos) QGuiApplicationPrivate::inputDeviceManager()->setCursorPos(pos); const QRect oldCursorRect = cursorRect(); m_cursor.pos = pos; - update(oldCursorRect | cursorRect()); - m_screen->handleCursorMove(m_cursor.pos); + update(oldCursorRect | cursorRect(), false); + for (QPlatformScreen *screen : m_screen->virtualSiblings()) + static_cast(screen)->handleCursorMove(m_cursor.pos); } void QEglFSCursor::pointerEvent(const QMouseEvent &event) @@ -318,8 +331,9 @@ void QEglFSCursor::pointerEvent(const QMouseEvent &event) return; const QRect oldCursorRect = cursorRect(); m_cursor.pos = event.screenPos().toPoint(); - update(oldCursorRect | cursorRect()); - m_screen->handleCursorMove(m_cursor.pos); + update(oldCursorRect | cursorRect(), false); + for (QPlatformScreen *screen : m_screen->virtualSiblings()) + static_cast(screen)->handleCursorMove(m_cursor.pos); } void QEglFSCursor::paintOnScreen() @@ -327,15 +341,35 @@ void QEglFSCursor::paintOnScreen() if (!m_visible) return; - const QRectF cr = cursorRect(); - const QRect screenRect(m_screen->geometry()); - const GLfloat x1 = 2 * (cr.left() / screenRect.width()) - 1; - const GLfloat x2 = 2 * (cr.right() / screenRect.width()) - 1; - const GLfloat y1 = 1 - (cr.top() / screenRect.height()) * 2; - const GLfloat y2 = 1 - (cr.bottom() / screenRect.height()) * 2; - QRectF r(QPointF(x1, y1), QPointF(x2, y2)); + QRect cr = cursorRect(); // hotspot included + + // Support virtual desktop too. Backends with multi-screen support (e.g. all + // variants of KMS/DRM) will enable this by default. In this case all + // screens are siblings of each other. When not enabled, the sibling list + // only contains m_screen itself. + for (QPlatformScreen *screen : m_screen->virtualSiblings()) { + if (screen->geometry().contains(cr.topLeft() + m_cursor.hotSpot) + && QOpenGLContext::currentContext()->screen() == screen->screen()) + { + cr.translate(-screen->geometry().topLeft()); + const QSize screenSize = screen->geometry().size(); + const GLfloat x1 = 2 * (cr.left() / GLfloat(screenSize.width())) - 1; + const GLfloat x2 = 2 * (cr.right() / GLfloat(screenSize.width())) - 1; + const GLfloat y1 = 1 - (cr.top() / GLfloat(screenSize.height())) * 2; + const GLfloat y2 = 1 - (cr.bottom() / GLfloat(screenSize.height())) * 2; + QRectF r(QPointF(x1, y1), QPointF(x2, y2)); + + draw(r); + + if (screen != m_activeScreen) { + m_activeScreen = screen; + // Do not want a leftover cursor on the screen the cursor just left. + update(cursorRect(), true); + } - draw(r); + break; + } + } } // In order to prevent breaking code doing custom OpenGL rendering while @@ -437,30 +471,33 @@ void QEglFSCursor::draw(const QRectF &r) { StateSaver stateSaver; - if (!m_program) { + GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]); + if (!gfx.program) { // one time initialization initializeOpenGLFunctions(); createShaderPrograms(); - if (!m_cursorAtlas.texture) { - createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image); + if (!gfx.atlasTexture) { + createCursorTexture(&gfx.atlasTexture, m_cursorAtlas.image); if (m_cursor.shape != Qt::BitmapCursor) - m_cursor.texture = m_cursorAtlas.texture; + m_cursor.useCustomCursor = false; } } - if (m_cursor.shape == Qt::BitmapCursor && m_cursor.customCursorPending) { + if (m_cursor.shape == Qt::BitmapCursor && (m_cursor.customCursorPending || m_cursor.customCursorKey != gfx.customCursorKey)) { // upload the custom cursor - createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage); - m_cursor.texture = m_cursor.customCursorTexture; + createCursorTexture(&gfx.customCursorTexture, m_cursor.customCursorImage); + m_cursor.useCustomCursor = true; m_cursor.customCursorPending = false; + gfx.customCursorKey = m_cursor.customCursorKey; } - Q_ASSERT(m_cursor.texture); + GLuint cursorTexture = !m_cursor.useCustomCursor ? gfx.atlasTexture : gfx.customCursorTexture; + Q_ASSERT(cursorTexture); - m_program->bind(); + gfx.program->bind(); const GLfloat x1 = r.left(); const GLfloat x2 = r.right(); @@ -485,20 +522,20 @@ void QEglFSCursor::draw(const QRectF &r) }; glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_cursor.texture); + glBindTexture(GL_TEXTURE_2D, cursorTexture); if (stateSaver.vaoHelper->isValid()) stateSaver.vaoHelper->glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); - m_program->enableAttributeArray(0); - m_program->enableAttributeArray(1); - m_program->setAttributeArray(0, cursorCoordinates, 2); - m_program->setAttributeArray(1, textureCoordinates, 2); + gfx.program->enableAttributeArray(0); + gfx.program->enableAttributeArray(1); + gfx.program->setAttributeArray(0, cursorCoordinates, 2); + gfx.program->setAttributeArray(1, textureCoordinates, 2); - m_program->setUniformValue(m_textureEntry, 0); - m_program->setUniformValue(m_matEntry, m_rotationMatrix); + gfx.program->setUniformValue(gfx.textureEntry, 0); + gfx.program->setUniformValue(gfx.matEntry, m_rotationMatrix); glDisable(GL_CULL_FACE); glFrontFace(GL_CCW); @@ -508,9 +545,9 @@ void QEglFSCursor::draw(const QRectF &r) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - m_program->disableAttributeArray(0); - m_program->disableAttributeArray(1); - m_program->release(); + gfx.program->disableAttributeArray(0); + gfx.program->disableAttributeArray(1); + gfx.program->release(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h index f72e4c0374..8ccbe4493c 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h @@ -105,30 +105,29 @@ private: bool setCurrentCursor(QCursor *cursor); #endif void draw(const QRectF &rect); - void update(const QRegion ®ion); + void update(const QRect &rect, bool allScreens); void createShaderPrograms(); void createCursorTexture(uint *texture, const QImage &image); void initCursorAtlas(); // current cursor information struct Cursor { - Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0), customCursorPending(false) { } - uint texture; // a texture from 'image' or the atlas + Cursor() : shape(Qt::BlankCursor), customCursorPending(false), customCursorKey(0), useCustomCursor(false) { } Qt::CursorShape shape; QRectF textureRect; // normalized rect inside texture QSize size; // size of the cursor QPoint hotSpot; QImage customCursorImage; QPoint pos; // current cursor position - uint customCursorTexture; bool customCursorPending; + qint64 customCursorKey; + bool useCustomCursor; } m_cursor; // cursor atlas information struct CursorAtlas { - CursorAtlas() : cursorsPerRow(0), texture(0), cursorWidth(0), cursorHeight(0) { } + CursorAtlas() : cursorsPerRow(0), cursorWidth(0), cursorHeight(0) { } int cursorsPerRow; - uint texture; int width, height; // width and height of the atlas int cursorWidth, cursorHeight; // width and height of cursors inside the atlas QList hotSpots; @@ -137,12 +136,22 @@ private: bool m_visible; QEglFSScreen *m_screen; - QOpenGLShaderProgram *m_program; - int m_textureEntry; - int m_matEntry; + QPlatformScreen *m_activeScreen; QEglFSCursorDeviceListener *m_deviceListener; bool m_updateRequested; QMatrix4x4 m_rotationMatrix; + + struct GraphicsContextData { + GraphicsContextData() : program(nullptr), textureEntry(0), matEntry(0), + customCursorTexture(0), atlasTexture(0), customCursorKey(0) { } + QOpenGLShaderProgram *program; + int textureEntry; + int matEntry; + uint customCursorTexture; + uint atlasTexture; + qint64 customCursorKey; + }; + QHash m_gfx; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp index 3848e99221..6f65929913 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp @@ -41,6 +41,7 @@ #include "qeglfsintegration.h" #include "qeglfscursor_p.h" #include "qeglfswindow_p.h" +#include "qeglfsscreen_p.h" #include "qeglfshooks_p.h" #include @@ -311,7 +312,7 @@ bool QEglFSDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap QPlatformCursor *QEglFSDeviceIntegration::createCursor(QPlatformScreen *screen) const { - return new QEglFSCursor(screen); + return new QEglFSCursor(static_cast(screen)); } void QEglFSDeviceIntegration::waitForVSync(QPlatformSurface *surface) const diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp index 743f714cf0..f45b947fa6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp @@ -40,11 +40,15 @@ #include "qeglfskmsegldevice.h" #include "qeglfskmsegldevicescreen.h" #include "qeglfskmsegldeviceintegration.h" +#include "private/qeglfscursor_p.h" #include +QT_BEGIN_NAMESPACE + QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path) - : QEglFSKmsDevice(integration, path) + : QEglFSKmsDevice(integration, path), + m_globalCursor(nullptr) { } @@ -52,6 +56,8 @@ bool QEglFSKmsEglDevice::open() { Q_ASSERT(fd() == -1); + qCDebug(qLcEglfsKmsDebug, "Opening DRM device %s", qPrintable(devicePath())); + int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR); if (Q_UNLIKELY(fd < 0)) qFatal("Could not open DRM device"); @@ -63,6 +69,8 @@ bool QEglFSKmsEglDevice::open() void QEglFSKmsEglDevice::close() { + qCDebug(qLcEglfsKmsDebug, "Closing DRM device"); + if (qt_safe_close(fd()) == -1) qErrnoWarning("Could not close DRM device"); @@ -74,7 +82,26 @@ EGLNativeDisplayType QEglFSKmsEglDevice::nativeDisplay() const return static_cast(m_integration)->eglDevice(); } -QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, + QEglFSKmsOutput output, QPoint position) { - return new QEglFSKmsEglDeviceScreen(integration, device, output, position); + QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(integration, device, output, position); + + if (!m_globalCursor && !integration->separateScreens()) { + qCDebug(qLcEglfsKmsDebug, "Creating new global mouse cursor"); + m_globalCursor = new QEglFSCursor(screen); + } + + return screen; } + +void QEglFSKmsEglDevice::destroyGlobalCursor() +{ + if (m_globalCursor) { + qCDebug(qLcEglfsKmsDebug, "Destroying global mouse cursor"); + delete m_globalCursor; + m_globalCursor = nullptr; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h index b1c98f3fe6..a27112fb4f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h @@ -42,6 +42,10 @@ #include +QT_BEGIN_NAMESPACE + +class QPlatformCursor; + class QEglFSKmsEglDevice: public QEglFSKmsDevice { public: @@ -56,6 +60,14 @@ public: QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) Q_DECL_OVERRIDE; + + QPlatformCursor *globalCursor() { return m_globalCursor; } + void destroyGlobalCursor(); + +private: + QPlatformCursor *m_globalCursor; }; +QT_END_NAMESPACE + #endif // QEGLFSKMSEGLDEVICE_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index cbf7cfe7d0..0120c0726d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -41,6 +41,7 @@ #include "qeglfskmsegldeviceintegration.h" #include #include "private/qeglfswindow_p.h" +#include "private/qeglfscursor_p.h" #include "qeglfskmsegldevice.h" #include "qeglfskmsscreen.h" #include @@ -258,4 +259,9 @@ bool QEglFSKmsEglDeviceIntegration::query_egl_device() return true; } +QPlatformCursor *QEglFSKmsEglDeviceIntegration::createCursor(QPlatformScreen *screen) const +{ + return separateScreens() ? new QEglFSCursor(screen) : nullptr; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h index af6b3f81ce..375c388548 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h @@ -65,6 +65,7 @@ public: protected: QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE; + QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE; private: bool setup_kms(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp index da1b577801..b0deabe834 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -39,12 +39,32 @@ #include "qeglfskmsegldevicescreen.h" #include "qeglfskmsegldevice.h" +#include + +QT_BEGIN_NAMESPACE QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) : QEglFSKmsScreen(integration, device, output, position) { } +QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen() +{ + const int remainingScreenCount = qGuiApp->screens().count(); + qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount); + if (!remainingScreenCount && !m_integration->separateScreens()) + static_cast(device())->destroyGlobalCursor(); +} + +QPlatformCursor *QEglFSKmsEglDeviceScreen::cursor() const +{ + // The base class creates a cursor via integration->createCursor() + // in its ctor. With separateScreens just use that. Otherwise + // there's a virtual desktop and the device has a global cursor + // and the base class has no dedicated cursor at all. + return m_integration->separateScreens() ? QEglFSScreen::cursor() : static_cast(device())->globalCursor(); +} + void QEglFSKmsEglDeviceScreen::waitForFlip() { if (!output().mode_set) { @@ -76,3 +96,5 @@ void QEglFSKmsEglDeviceScreen::waitForFlip() } } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h index 0cd46e9f9d..7fceae4978 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h @@ -42,6 +42,8 @@ #include +QT_BEGIN_NAMESPACE + class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen { public: @@ -49,8 +51,13 @@ public: QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position); + ~QEglFSKmsEglDeviceScreen(); + + QPlatformCursor *cursor() const Q_DECL_OVERRIDE; void waitForFlip() Q_DECL_OVERRIDE; }; +QT_END_NAMESPACE + #endif // QEGLFSKMSEGLDEVICESCREEN_H -- cgit v1.2.3