notice when the only screen changes

Summary:
in a corner case that is used a lot, the internal laptop screen
gets automatically disabled when an external screen is connected.
the only QScreen* available from the QGuiApp gets recycled for the
new screen and there is no signal this switch occurred.

To work around this, as all the view get an expose event when this happen,
monitor the rename of the desktopview's qscreen and manage this separatedly
in the shell.

BUG:373880

Test Plan:
connection and disconnecting an external screen to the laptop
both in the case of internal screen enabled or disabled

Reviewers: davidedmundson, #plasma

Reviewed By: davidedmundson, #plasma

Subscribers: davidedmundson, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D3777
wilder-5.14
Marco Martin 9 years ago
parent d8402baf46
commit 20b439a4f4
  1. 19
      shell/desktopview.cpp
  2. 2
      shell/desktopview.h
  3. 14
      shell/shellcorona.cpp

@ -85,12 +85,7 @@ void DesktopView::setScreenToFollow(QScreen *screen)
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 @@ DesktopView::SessionType DesktopView::sessionType() const
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<QKeyEvent *>(e);
if (KWindowSystem::showingDesktop() && ke->key() == Qt::Key_Escape) {
ShellCorona *c = qobject_cast<ShellCorona *>(corona());

@ -88,12 +88,14 @@ private Q_SLOTS:
Q_SIGNALS:
void stayBehindChanged();
void windowTypeChanged();
void screenRenamed();
private:
void coronaPackageChanged(const KPackage::Package &package);
void ensureWindowType();
void setupWaylandIntegration();
QString m_screenName;
QPointer<PlasmaQuick::ConfigView> m_configView;
QPointer<QScreen> m_oldScreen;
QPointer<QScreen> m_screenToFollow;

@ -1144,6 +1144,20 @@ void ShellCorona::addOutput(QScreen* screen)
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);

Loading…
Cancel
Save