diff --git a/shell/desktopview.h b/shell/desktopview.h --- a/shell/desktopview.h +++ b/shell/desktopview.h @@ -88,12 +88,14 @@ Q_SIGNALS: void stayBehindChanged(); void windowTypeChanged(); + void screenRenamed(); private: void coronaPackageChanged(const KPackage::Package &package); void ensureWindowType(); void setupWaylandIntegration(); + QString m_screenName; QPointer m_configView; QPointer m_oldScreen; QPointer m_screenToFollow; diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp --- a/shell/desktopview.cpp +++ b/shell/desktopview.cpp @@ -85,12 +85,7 @@ return; } - /*connect(screen, &QObject::destroyed, this, [this]() { - if (DesktopView::screen()) { - m_screenToFollow = DesktopView::screen(); - adaptToScreen(); - } - });*/ + m_screenName = screen->name(); m_screenToFollow = screen; setScreen(screen); adaptToScreen(); @@ -204,7 +199,17 @@ bool DesktopView::event(QEvent *e) { - if (e->type() == QEvent::KeyRelease) { + //NOTE: we need this heuristic for the case when there is an + //internal laptop screen that gets disabled upon connection of an external one. the only QCreen * pointer gets recycled and there is no dedicated signal to discover this at all + //after being moved, the view will get an expose event, so we can check there if the screen has been renamed + //see https://bugs.kde.org/show_bug.cgi?id=373880 + //https://bugreports.qt.io/browse/QTBUG-57785 + if (e->type() == QEvent::Expose) { + if (m_screenToFollow && m_screenToFollow->name() != m_screenName) { + m_screenName = m_screenToFollow->name(); + emit screenRenamed(); + } + } else if (e->type() == QEvent::KeyRelease) { QKeyEvent *ke = static_cast(e); if (KWindowSystem::showingDesktop() && ke->key() == Qt::Key_Escape) { ShellCorona *c = qobject_cast(corona()); diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -1144,6 +1144,20 @@ DesktopView *view = new DesktopView(this, screen); connect(view, &QQuickWindow::sceneGraphError, this, &ShellCorona::showOpenGLNotCompatibleWarning); + // a particular edge case: when we switch the only enabled screen + // we don't have any signal about it, the primary screen changes but we have the same old QScreen* getting recycled + // see https://bugs.kde.org/show_bug.cgi?id=373880 + // if this slot will be invoked many times, their//second time on will do nothing as name and primaryconnector will be the same by then + connect(view, &DesktopView::screenRenamed, this, [=](){ + if (qGuiApp->primaryScreen()->name() != m_screenPool->primaryConnector()) { + //new screen? + if (m_screenPool->id(qGuiApp->primaryScreen()->name()) < 0) { + m_screenPool->insertScreenMapping(m_screenPool->firstAvailableId(), qGuiApp->primaryScreen()->name()); + } + //switch the primary screen in the pool + m_screenPool->setPrimaryConnector(qGuiApp->primaryScreen()->name()); + } + }); Plasma::Containment *containment = createContainmentForActivity(m_activityController->currentActivity(), insertPosition); Q_ASSERT(containment);