diff options
Diffstat (limited to 'src/plugins')
18 files changed, 228 insertions, 32 deletions
diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext.cpp b/src/plugins/platforms/eglfs/api/qeglfscontext.cpp index 9c10c1a998c..0b9db8039f1 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscontext.cpp @@ -79,8 +79,10 @@ void QEglFSContext::swapBuffers(QPlatformSurface *surface) // draw the cursor if (surface->surface()->surfaceClass() == QSurface::Window) { QPlatformWindow *window = static_cast<QPlatformWindow *>(surface); - if (QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(window->screen()->cursor())) - cursor->paintOnScreen(); + if (QPlatformScreen *screen = window->screen()) { + if (QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(screen->cursor())) + cursor->paintOnScreen(); + } } qt_egl_device_integration()->waitForVSync(surface); diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 4abe948117e..2f278a474e0 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -154,6 +154,7 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi if (!window->handle()) window->create(); static_cast<QEglFSWindow *>(window->handle())->setBackingStore(bs); + m_bs = bs; return bs; #else Q_UNUSED(window); @@ -175,6 +176,9 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen()) w->requestActivateWindow(); + if (window->isTopLevel()) + w->setBackingStore(static_cast<QOpenGLCompositorBackingStore *>(m_bs)); + return w; } diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h index 2359b7f29f1..3865b7130b7 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h @@ -112,6 +112,7 @@ private: QScopedPointer<QFbVtHandler> m_vtHandler; QPointer<QWindow> m_pointerWindow; bool m_disableInputHandlers; + mutable QPlatformBackingStore *m_bs = nullptr; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor_p.h index a0f78bb3103..cca9097e2f0 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor_p.h @@ -62,6 +62,8 @@ public: void reevaluateVisibilityForScreens() { setPos(pos()); } + QEglFSKmsGbmScreen *screen() const { return m_screen; } + private: void initCursorAtlas(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index a7592ed55e4..9f19e649f85 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -113,13 +113,27 @@ QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output) { QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output, false); - createGlobalCursor(screen); + + // On some platforms (e.g. rpi4), you'll get a kernel warning/error + // if the cursor is created 'at the same time' as the screen is created. + // (drmModeMoveCursor is the specific call that causes the issue) + // When this issue is triggered, the screen's connector is unusable until reboot + // + // Below is a work-around (without negative implications for other platforms). + // + // interval of 0 and QMetaObject::invokeMethod (w/o Qt::QueuedConnection) + // do no help / will still trigger issue + QTimer::singleShot(1, [screen, this](){ + createGlobalCursor(screen); + }); return screen; } QPlatformScreen *QEglFSKmsGbmDevice::createHeadlessScreen() { + destroyGlobalCursor(); + return new QEglFSKmsGbmScreen(this, QKmsOutput(), true); } @@ -127,9 +141,6 @@ void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen, QPlatformScreen *screenThisScreenClones, const QList<QPlatformScreen *> &screensCloningThisScreen) { - if (!screenThisScreenClones && screensCloningThisScreen.isEmpty()) - return; - QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen); gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen); } @@ -144,6 +155,32 @@ void QEglFSKmsGbmDevice::registerScreen(QPlatformScreen *screen, m_globalCursor->reevaluateVisibilityForScreens(); } +void QEglFSKmsGbmDevice::unregisterScreen(QPlatformScreen *screen) +{ + // The global cursor holds a pointer to a QEglFSKmsGbmScreen. + // If that screen is being unregistered, + // this will recreate the global cursor with the first sibling screen. + if (m_globalCursor && screen == m_globalCursor->screen()) { + qCDebug(qLcEglfsKmsDebug) << "Destroying global GBM mouse cursor due to unregistering" + << "it's screen - will probably be recreated right away"; + delete m_globalCursor; + m_globalCursor = nullptr; + + QList<QPlatformScreen *> siblings = screen->virtualSiblings(); + siblings.removeOne(screen); + if (siblings.count() > 0) { + QEglFSKmsGbmScreen *kmsScreen = static_cast<QEglFSKmsGbmScreen *>(siblings.first()); + m_globalCursor = new QEglFSKmsGbmCursor(kmsScreen); + qCDebug(qLcEglfsKmsDebug) << "Creating new global GBM mouse cursor on sibling screen"; + } else { + qCWarning(qLcEglfsKmsDebug) << "Couldn't find a sibling to recreate" + << "the GBM mouse cursor - it might vanish"; + } + } + + QEglFSKmsDevice::unregisterScreen(screen); +} + bool QEglFSKmsGbmDevice::usesEventReader() const { static const bool eventReaderThreadDisabled = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_NO_EVENT_READER_THREAD"); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h index e00992ed291..0ffed0ec4ef 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h @@ -51,6 +51,7 @@ public: bool isPrimary, const QPoint &virtualPos, const QList<QPlatformScreen *> &virtualSiblings) override; + void unregisterScreen(QPlatformScreen *screen) override; bool usesEventReader() const; QEglFSKmsEventReader *eventReader() { return &m_eventReader; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp index 05ffb3b212e..eb61de3c534 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp @@ -11,6 +11,7 @@ #include "private/qeglfscursor_p.h" #include <QtCore/QLoggingCategory> +#include <QtCore/QFileSystemWatcher> #include <QtGui/QScreen> #include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h> @@ -23,6 +24,10 @@ QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration() qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created"); } +QEglFSKmsGbmIntegration::~QEglFSKmsGbmIntegration() +{ +} + #ifndef EGL_EXT_platform_base typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); #endif @@ -94,14 +99,16 @@ void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface) QKmsDevice *QEglFSKmsGbmIntegration::createDevice() { + + m_deviceDiscovery = std::unique_ptr<QDeviceDiscovery>(QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask)); + m_kmsConfigWatcher = std::unique_ptr<QFileSystemWatcher>(new QFileSystemWatcher()); + QString path = screenConfig()->devicePath(); if (!path.isEmpty()) { qCDebug(qLcEglfsKmsDebug) << "GBM: Using DRM device" << path << "specified in config file"; } else { - QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask); - const QStringList devices = d->scanConnectedDevices(); + const QStringList devices = m_deviceDiscovery->scanConnectedDevices(); qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices; - d->deleteLater(); if (Q_UNLIKELY(devices.isEmpty())) qFatal("Could not find DRM device!"); @@ -110,6 +117,35 @@ QKmsDevice *QEglFSKmsGbmIntegration::createDevice() qCDebug(qLcEglfsKmsDebug) << "Using" << path; } + bool hotreload = !qEnvironmentVariable("QT_QPA_EGLFS_HOTPLUG_ENABLED").isEmpty(); + if (hotreload) { + qCWarning(qLcEglfsKmsDebug) << "EGLFS/KMS: Hot-Reload on KMS-events enabled, be aware that" + << "this requires actions in UI code for proper functionallity" + << "(e.g. close/open windows on screen's disconnect/connect)"; + QObject::connect(m_deviceDiscovery.get(), &QDeviceDiscovery::deviceChanged, + m_deviceDiscovery.get(), [this](const QString &deviceNode) { + qCDebug(qLcEglfsKmsDebug) << "KMS device changed:" << deviceNode; + m_device->checkConnectedScreens(); + }); + } + + QString json = qEnvironmentVariable("QT_QPA_EGLFS_KMS_CONFIG"); + if (json.isEmpty()) + json = qEnvironmentVariable("QT_QPA_KMS_CONFIG"); + + if (!json.isEmpty()) { + m_kmsConfigWatcher->addPath(json); + QObject::connect(m_kmsConfigWatcher.get(), &QFileSystemWatcher::fileChanged, + m_kmsConfigWatcher.get(), [this, json]() { + qCDebug(qLcEglfsKmsDebug) << "KMS config-file has changed! path:" + << json; + m_screenConfig->refreshConfig(); + m_device->updateScreens(); + m_kmsConfigWatcher->addPath(json); // as per QFileSystemWatcher doc we have to re-add + // the path in case it's a new file + }); + } + return new QEglFSKmsGbmDevice(screenConfig(), path); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration_p.h index fb118438d25..7c2c2a474d7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration_p.h @@ -24,11 +24,14 @@ QT_BEGIN_NAMESPACE class QEglFSKmsDevice; +class QDeviceDiscovery; +class QFileSystemWatcher; class Q_EGLFS_EXPORT QEglFSKmsGbmIntegration : public QEglFSKmsIntegration { public: QEglFSKmsGbmIntegration(); + ~QEglFSKmsGbmIntegration() override; EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) override; EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) override; @@ -42,6 +45,8 @@ protected: QKmsDevice *createDevice() override; private: + std::unique_ptr<QDeviceDiscovery> m_deviceDiscovery; + std::unique_ptr<QFileSystemWatcher> m_kmsConfigWatcher; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 00fecb87f1f..332030f03f2 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -20,7 +20,7 @@ QT_BEGIN_NAMESPACE -QMutex QEglFSKmsGbmScreen::m_nonThreadedFlipMutex; +QMutex QEglFSKmsGbmScreen::s_nonThreadedFlipMutex; static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat) { @@ -92,9 +92,26 @@ QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsDevice *device, const QKmsOutput QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen() { const int remainingScreenCount = qGuiApp->screens().count(); - qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount); + qCDebug(qLcEglfsKmsDebug, "Screen dtor. %p Remaining screens: %d", this, remainingScreenCount); if (!remainingScreenCount && !device()->screenConfig()->separateScreens()) static_cast<QEglFSKmsGbmDevice *>(device())->destroyGlobalCursor(); + + if (m_cloneSource) { + // Remove this screen from the screen that has it as a clone destination + QList<CloneDestination> &dests = m_cloneSource->m_cloneDests; + auto newEnd = std::remove_if(dests.begin(), dests.end(), + [this](CloneDestination &dest) { + return dest.screen == this; + }); + dests.erase(newEnd, dests.end()); + } + + // Other screens can no longer have this screen as a clone source + for (CloneDestination &dest : m_cloneDests) { + dest.screen->m_cloneSource = nullptr; + // Mode must be set again before flipping + dest.screen->m_output.mode_set = false; + } } QPlatformCursor *QEglFSKmsGbmScreen::cursor() const @@ -206,9 +223,12 @@ void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones, if (clonesAnother) { m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones); qCDebug(qLcEglfsKmsDebug, "Screen %s clones %s", qPrintable(name()), qPrintable(m_cloneSource->name())); + } else { + m_cloneSource = nullptr; } // clone sources need to know their additional destinations + m_cloneDests.clear(); for (QPlatformScreen *s : screensCloningThisScreen) { CloneDestination d; d.screen = static_cast<QEglFSKmsGbmScreen *>(s); @@ -271,8 +291,11 @@ void QEglFSKmsGbmScreen::nonThreadedPageFlipHandler(int fd, // note that with cloning involved this callback is called also for screens that clone another one Q_UNUSED(fd); QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data); - screen->flipFinished(); - screen->pageFlipped(sequence, tv_sec, tv_usec); + // The screen might have been deleted when DRM calls this handler + if (QEglFSKmsScreen::isScreenKnown(screen)) { + screen->flipFinished(); + screen->pageFlipped(sequence, tv_sec, tv_usec); + } } void QEglFSKmsGbmScreen::waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen) @@ -280,7 +303,21 @@ void QEglFSKmsGbmScreen::waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen) m_flipMutex.lock(); QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device()); dev->eventReader()->startWaitFlip(screen, &m_flipMutex, &m_flipCond); - m_flipCond.wait(&m_flipMutex); + + // We should only wait forever on this screen, clones should have a timeout + // (e.g. I clone might have been created just before the flip, + // we might wait for it but it might not know about waking us up) + bool succ = false; + if (screen == this) + succ = m_flipCond.wait(&m_flipMutex); + else + succ = m_flipCond.wait(&m_flipMutex, 300); + + if (!succ) + qCWarning(qLcEglfsKmsDebug) << "timeout on waitForFlipWithEventReader, screen to wait for:" + << screen << ", screen waiting (shouldn't be the same screen):" + << this; + m_flipMutex.unlock(); screen->flipFinished(); } @@ -306,7 +343,7 @@ void QEglFSKmsGbmScreen::waitForFlip() waitForFlipWithEventReader(d.screen); } } else { - QMutexLocker lock(&m_nonThreadedFlipMutex); + QMutexLocker lock(&s_nonThreadedFlipMutex); while (m_gbm_bo_next) { drmEventContext drmEvent; memset(&drmEvent, 0, sizeof(drmEvent)); @@ -359,15 +396,10 @@ static void addAtomicFlip(drmModeAtomicReq *request, const QKmsOutput &output, u void QEglFSKmsGbmScreen::flip() { - // For headless screen just return silently. It is not necessarily an error + // For headless or cloned screen just return silently. It is not necessarily an error // to end up here, so show no warnings. - if (m_headless) - return; - - if (m_cloneSource) { - qWarning("Screen %s clones another screen. swapBuffers() not allowed.", qPrintable(name())); + if (m_headless || m_cloneSource) return; - } if (!m_gbm_surface) { qWarning("Cannot sync before platform init!"); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h index aca34fcae21..65625a3c1cd 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h @@ -67,7 +67,7 @@ protected: QMutex m_flipMutex; QWaitCondition m_flipCond; - static QMutex m_nonThreadedFlipMutex; + static QMutex s_nonThreadedFlipMutex; QScopedPointer<QEglFSKmsGbmCursor> m_cursor; 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 ece19f46a49..ff4921c2b15 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -213,9 +213,13 @@ QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this); m_funcs->initialize(eglWindow->screen()->display()); - if (Q_UNLIKELY(!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm && m_funcs->has_egl_stream && - m_funcs->has_egl_stream_producer_eglsurface && m_funcs->has_egl_stream_consumer_egloutput))) + if (Q_UNLIKELY(!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm + && m_funcs->has_egl_stream && m_funcs->has_egl_stream_producer_eglsurface + && m_funcs->has_egl_stream_consumer_egloutput))) { + qCDebug(qLcEglfsKmsDebug, "EGL_EXTENSIONS %s", + eglQueryString(eglWindow->screen()->display(), EGL_EXTENSIONS)); qFatal("Required extensions missing!"); + } return eglWindow; } 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 5af45e63a2f..5775ac3607a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -71,7 +71,7 @@ QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen() } const int remainingScreenCount = qGuiApp->screens().size(); - qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount); + qCDebug(qLcEglfsKmsDebug, "Screen dtor. %p Remaining screens: %d", this, remainingScreenCount); if (!remainingScreenCount && !device()->screenConfig()->separateScreens()) static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor(); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp index 037b26f023e..59ca53355d6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp @@ -25,4 +25,39 @@ void QEglFSKmsDevice::registerScreen(QPlatformScreen *screen, QWindowSystemInterface::handleScreenAdded(s, isPrimary); } +void QEglFSKmsDevice::unregisterScreen(QPlatformScreen *screen) +{ + QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen); + for (QPlatformScreen *sibling : s->virtualSiblings()) + static_cast<QEglFSKmsScreen *>(sibling)->removeSibling(s); + + QWindowSystemInterface::handleScreenRemoved(screen); +} + +void QEglFSKmsDevice::updateScreen(QPlatformScreen *screen, const QPoint &virtualPos, + const QList<QPlatformScreen *> &virtualSiblings) +{ + QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen); + QRect before = s->geometry(); + s->setVirtualPosition(virtualPos); + s->setVirtualSiblings(virtualSiblings); + QRect after = s->geometry(); + + if (before != after) + QWindowSystemInterface::handleScreenGeometryChange(s->screen(), after, + s->availableGeometry()); +} + +void QEglFSKmsDevice::updateScreenOutput(QPlatformScreen *screen, const QKmsOutput &output) +{ + QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen); + QRect before = s->geometry(); + s->updateOutput(output); + QRect after = s->geometry(); + + if (before != after) + QWindowSystemInterface::handleScreenGeometryChange(s->screen(), after, + s->availableGeometry()); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h index 6e11953a699..49b82d8baad 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h @@ -30,6 +30,13 @@ public: bool isPrimary, const QPoint &virtualPos, const QList<QPlatformScreen *> &virtualSiblings) override; + + void unregisterScreen(QPlatformScreen *screen) override; + + void updateScreen(QPlatformScreen *screen, const QPoint &virtualPos, + const QList<QPlatformScreen *> &virtualSiblings) override; + + void updateScreenOutput(QPlatformScreen *screen, const QKmsOutput &output) override; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp index c0c96554962..fa735388bc0 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp @@ -20,7 +20,10 @@ static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, t->eventHost()->handlePageFlipCompleted(user_data); QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data); - screen->pageFlipped(sequence, tv_sec, tv_usec); + if (QEglFSKmsScreen::isScreenKnown(screen)) + screen->pageFlipped(sequence, tv_sec, tv_usec); + else + qWarning("Deleted screen got it's pageFlipHandler called; Dead pointer: %p", user_data); } class RegisterWaitFlipEvent : public QEvent diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp index cc7381fb701..a40287bdfed 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -16,6 +16,8 @@ QT_BEGIN_NAMESPACE +QSet<QEglFSKmsScreen *> QEglFSKmsScreen::s_screens; + class QEglFSKmsInterruptHandler : public QObject { public: @@ -59,10 +61,14 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsDevice *device, const QKmsOutput &outp } else { qCDebug(qLcEglfsKmsDebug) << "No EDID data for output" << name(); } + + s_screens.insert(this); } QEglFSKmsScreen::~QEglFSKmsScreen() { + s_screens.remove(this); + m_output.cleanup(m_device); delete m_interruptHandler; } @@ -166,6 +172,11 @@ void QEglFSKmsScreen::waitForFlip() { } +void QEglFSKmsScreen::updateOutput(QKmsOutput output) +{ + m_output = output; +} + void QEglFSKmsScreen::restoreMode() { m_output.restoreMode(m_device); @@ -180,6 +191,11 @@ qreal QEglFSKmsScreen::refreshRate() const return refresh > 0 ? refresh : 60; } +void QEglFSKmsScreen::removeSibling(QPlatformScreen *screen) +{ + m_siblings.removeAll(screen); +} + QList<QPlatformScreen::Mode> QEglFSKmsScreen::modes() const { QList<QPlatformScreen::Mode> list; @@ -227,4 +243,9 @@ void QEglFSKmsScreen::pageFlipped(unsigned int sequence, unsigned int tv_sec, un Q_UNUSED(tv_usec); } +bool QEglFSKmsScreen::isScreenKnown(QEglFSKmsScreen *s) +{ + return s_screens.contains(s); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen_p.h index 6fb1f9a1348..2dc49152a97 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen_p.h @@ -58,6 +58,7 @@ public: QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; } void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; } + void removeSibling(QPlatformScreen *screen); QList<QPlatformScreen::Mode> modes() const override; @@ -68,6 +69,7 @@ public: virtual void waitForFlip(); + void updateOutput(QKmsOutput output); QKmsOutput &output() { return m_output; } void restoreMode(); @@ -80,6 +82,8 @@ public: void setCursorOutOfRange(bool b) { m_cursorOutOfRange = b; } virtual void pageFlipped(unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec); + static bool isScreenKnown(QEglFSKmsScreen *s); + protected: QEglFSKmsDevice *m_device; @@ -95,6 +99,8 @@ protected: QEglFSKmsInterruptHandler *m_interruptHandler; bool m_headless; + + static QSet<QEglFSKmsScreen *> s_screens; }; QT_END_NAMESPACE diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 7179109505b..3f40dea5eb9 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -1662,7 +1662,7 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op } case CE_ItemViewItem: { if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) { - if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget)) { + if (qobject_cast<const QAbstractItemView *>(widget)) { QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget); QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); @@ -1764,10 +1764,10 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state); - if (!view || !view->isPersistentEditorOpen(vopt->index)) { - painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color() : option->palette.text().color()); - d->viewItemDrawText(painter, vopt, textRect); - } + painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color() + : vopt->palette.text().color()); + d->viewItemDrawText(painter, vopt, textRect); + // paint a vertical marker for QListView if (vopt->state & State_Selected) { if (const QListView *lv = qobject_cast<const QListView *>(widget); |