diff --git a/CMakeLists.txt b/CMakeLists.txt index edfdf66..5cf725e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,8 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS # WARNING PlasmaQuick provides unversioned CMake config find_package(KF5 REQUIRED COMPONENTS PlasmaQuick) find_package(KF5 REQUIRED COMPONENTS SysGuard) -find_package(KF5 REQUIRED COMPONENTS Screen) +# Require KScreen >= 5.0.93 due to large API change +find_package(KF5 5.0.93 REQUIRED COMPONENTS Screen) find_package(KF5TextEditor) find_package(KWinDBusInterface CONFIG REQUIRED) diff --git a/shell/panelview.cpp b/shell/panelview.cpp index 997f8d0..cf6357b 100644 --- a/shell/panelview.cpp +++ b/shell/panelview.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #if HAVE_X11 #include @@ -100,10 +101,14 @@ PanelView::PanelView(ShellCorona *corona, QScreen *targetScreen, QWindow *parent m_strutsTimer.setSingleShot(true); connect(&m_strutsTimer, &QTimer::timeout, this, &PanelView::updateStruts); - connect(m_corona->screensConfiguration(), &KScreen::Config::outputAdded, - this, &PanelView::updateStruts); - connect(m_corona->screensConfiguration(), &KScreen::Config::outputRemoved, - this, &PanelView::updateStruts); + connect(m_corona->screensConfiguration().data(), &KScreen::Config::outputAdded, + this, [=] (const KScreen::OutputPtr &) { + updateStruts(); + }); + connect(m_corona->screensConfiguration().data(), &KScreen::Config::outputRemoved, + this, [=] (int) { + updateStruts(); + }); qmlRegisterType(); engine()->rootContext()->setContextProperty("panel", this); diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp index 37a1cfd..00e0441 100644 --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -44,7 +44,9 @@ #include #include -#include +#include +#include +#include #include "config-ktexteditor.h" // HAVE_KTEXTEDITOR @@ -160,7 +162,6 @@ ShellCorona::ShellCorona(QObject *parent) connect(m_activityConsumer, SIGNAL(activityRemoved(QString)), this, SLOT(activityRemoved(QString))); new Osd(this); - m_screenConfiguration = KScreen::Config::current(); #if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) connect(qGuiApp, &QGuiApplication::screenRemoved, this, &ShellCorona::screenRemoved); @@ -227,9 +228,12 @@ void ShellCorona::setShell(const QString &shell) if (m_activityConsumer->serviceStatus() == KActivities::Consumer::Unknown) { connect(m_activityConsumer, SIGNAL(serviceStatusChanged(Consumer::ServiceStatus)), SLOT(load()), Qt::UniqueConnection); - } else { - load(); } + connect(new KScreen::GetConfigOperation(KScreen::GetConfigOperation::NoEDID), &KScreen::GetConfigOperation::finished, + this, [=](KScreen::ConfigOperation *op) { + m_screenConfiguration = qobject_cast(op)->config(); + load(); + }); } QString ShellCorona::shell() const @@ -237,7 +241,7 @@ QString ShellCorona::shell() const return m_shell; } -bool outputLess(KScreen::Output *a, KScreen::Output *b) +bool outputLess(const KScreen::OutputPtr &a, const KScreen::OutputPtr &b) { return ((a->isEnabled() && !b->isEnabled()) || (a->isEnabled() == b->isEnabled() && (a->isPrimary() && !b->isPrimary())) @@ -245,9 +249,9 @@ bool outputLess(KScreen::Output *a, KScreen::Output *b) || (a->pos().x() == b->pos().x() && a->pos().y() < b->pos().y())))); } -static QList sortOutputs(const QHash &outputs) +static QList sortOutputs(const KScreen::OutputList &outputs) { - QList ret = outputs.values(); + QList ret = outputs.values(); std::sort(ret.begin(), ret.end(), outputLess); return ret; } @@ -255,7 +259,8 @@ static QList sortOutputs(const QHash &o void ShellCorona::load() { if (m_shell.isEmpty() || - m_activityConsumer->serviceStatus() == KActivities::Consumer::Unknown) { + m_activityConsumer->serviceStatus() == KActivities::Consumer::Unknown || + !m_screenConfiguration) { return; } @@ -292,10 +297,11 @@ void ShellCorona::load() KScreen::ConfigMonitor::instance()->addConfig(m_screenConfiguration); //we're not going through the connectedOutputs because we need to connect to all outputs - for (KScreen::Output *output : sortOutputs(m_screenConfiguration->outputs())) { + for (const KScreen::OutputPtr &output : sortOutputs(m_screenConfiguration->outputs())) { addOutput(output); } - connect(m_screenConfiguration, &KScreen::Config::outputAdded, this, &ShellCorona::addOutput); + connect(m_screenConfiguration.data(), &KScreen::Config::outputAdded, this, &ShellCorona::addOutput); + connect(m_screenConfiguration.data(), &KScreen::Config::primaryOutputChanged, this, &ShellCorona::primaryOutputChanged); if (!m_waitingPanels.isEmpty()) { m_waitingPanelsTimer.start(); @@ -321,7 +327,7 @@ void ShellCorona::primaryOutputChanged() return; } - KScreen::Output *output = findPrimaryOutput(); + const KScreen::OutputPtr output = m_screenConfiguration->primaryOutput(); if (!output) { return; } @@ -367,7 +373,7 @@ void ShellCorona::screenInvariants() const Q_ASSERT(!m_loading); Q_ASSERT(m_views.count() <= QGuiApplication::screens().count()); QScreen *s = m_views.isEmpty() ? nullptr : m_views[0]->screen(); - KScreen::Output *primaryOutput = findPrimaryOutput(); + const KScreen::OutputPtr primaryOutput = m_screenConfiguration->primaryOutput(); if (!s) { qWarning() << "error: couldn't find primary output" << primaryOutput; return; @@ -400,7 +406,7 @@ void ShellCorona::screenInvariants() const ++i; } - foreach (KScreen::Output* out, m_redundantOutputs) { + foreach (const KScreen::OutputPtr &out, m_redundantOutputs) { Q_ASSERT(isOutputRedundant(out)); } @@ -520,7 +526,7 @@ QRect ShellCorona::screenGeometry(int id) const { if (id >= m_views.count() || id < 0) { qWarning() << "requesting unexisting screen" << id; - QScreen *s = outputToScreen(findPrimaryOutput()); + QScreen *s = outputToScreen(m_screenConfiguration->primaryOutput()); return s ? s->geometry() : QRect(); } return m_views[id]->geometry(); @@ -531,7 +537,7 @@ QRegion ShellCorona::availableScreenRegion(int id) const if (id >= m_views.count() || id < 0) { //each screen should have a view qWarning() << "requesting unexisting screen" << id; - QScreen *s = outputToScreen(findPrimaryOutput()); + QScreen *s = outputToScreen(m_screenConfiguration->primaryOutput()); return s ? s->availableGeometry() : QRegion(); } DesktopView *view = m_views[id]; @@ -552,7 +558,7 @@ QRect ShellCorona::availableScreenRect(int id) const if (id >= m_views.count() || id < 0) { //each screen should have a view qWarning() << "requesting unexisting screen" << id; - QScreen *s = outputToScreen(findPrimaryOutput()); + QScreen *s = outputToScreen(m_screenConfiguration->primaryOutput()); return s ? s->availableGeometry() : QRect(); } @@ -678,17 +684,17 @@ void ShellCorona::screenRemoved(QScreen* screen) void ShellCorona::outputEnabledChanged() { - addOutput(qobject_cast(sender())); + addOutput(KScreen::OutputPtr(qobject_cast(sender()), [](void*){})); } -bool ShellCorona::isOutputRedundant(KScreen::Output *screen) const +bool ShellCorona::isOutputRedundant(const KScreen::OutputPtr &screen) const { Q_ASSERT(screen->currentMode()); const QRect geometry = screen->geometry(); //FIXME: QScreen doesn't have any idea of "this qscreen is clone of this other one //so this ultra inefficient heuristic has to stay until we have a slightly better api - foreach (const KScreen::Output *s, m_screenConfiguration->connectedOutputs()) { + foreach (const KScreen::OutputPtr &s, m_screenConfiguration->connectedOutputs()) { if (screen == s || !s->isEnabled() || !s->currentMode()) { continue; } @@ -711,7 +717,7 @@ void ShellCorona::reconsiderOutputs() return; } - foreach (KScreen::Output *out, m_screenConfiguration->connectedOutputs()) { + foreach (const KScreen::OutputPtr &out, m_screenConfiguration->connectedOutputs()) { if (!out->isEnabled() || !out->currentMode()) { // qDebug() << "skip screen" << out << desktopForScreen(outputToScreen(out)); continue; @@ -737,16 +743,21 @@ void ShellCorona::reconsiderOutputs() CHECK_SCREEN_INVARIANTS } -void ShellCorona::addOutput(KScreen::Output *output) +void ShellCorona::addOutput(const KScreen::OutputPtr &output) { if (!output) { return; } - connect(output, &KScreen::Output::isEnabledChanged, this, &ShellCorona::outputEnabledChanged, Qt::UniqueConnection); - connect(output, &KScreen::Output::posChanged, &m_reconsiderOutputsTimer, static_cast(&QTimer::start), Qt::UniqueConnection); - connect(output, &KScreen::Output::currentModeIdChanged, &m_reconsiderOutputsTimer, static_cast(&QTimer::start), Qt::UniqueConnection); - connect(output, &KScreen::Output::isPrimaryChanged, this, &ShellCorona::primaryOutputChanged, Qt::UniqueConnection); + connect(output.data(), &KScreen::Output::isEnabledChanged, + this, &ShellCorona::outputEnabledChanged, + Qt::UniqueConnection); + connect(output.data(), &KScreen::Output::posChanged, + &m_reconsiderOutputsTimer, static_cast(&QTimer::start), + Qt::UniqueConnection); + connect(output.data(), &KScreen::Output::currentModeIdChanged, + &m_reconsiderOutputsTimer, static_cast(&QTimer::start), + Qt::UniqueConnection); if (!output->isEnabled()) { m_redundantOutputs.remove(output); @@ -766,7 +777,7 @@ void ShellCorona::addOutput(KScreen::Output *output) int insertPosition = 0; foreach (DesktopView *view, m_views) { - KScreen::Output *out = screenToOutput(view->screen()); + const KScreen::OutputPtr out = screenToOutput(view->screen()); if (outputLess(output, out)) { break; } @@ -807,7 +818,7 @@ void ShellCorona::addOutput(KScreen::Output *output) CHECK_SCREEN_INVARIANTS } -QScreen *ShellCorona::outputToScreen(KScreen::Output *output) const +QScreen *ShellCorona::outputToScreen(const KScreen::OutputPtr &output) const { if (!output) { return nullptr; @@ -822,25 +833,15 @@ QScreen *ShellCorona::outputToScreen(KScreen::Output *output) const return nullptr; } -KScreen::Output *ShellCorona::screenToOutput(QScreen *screen) const +KScreen::OutputPtr ShellCorona::screenToOutput(QScreen *screen) const { - foreach (KScreen::Output *output, m_screenConfiguration->connectedOutputs()) { + foreach (const KScreen::OutputPtr &output, m_screenConfiguration->connectedOutputs()) { if (screen->name() == output->name()) { return output; } } - return nullptr; -} - -KScreen::Output *ShellCorona::findPrimaryOutput() const -{ - foreach (KScreen::Output *output, m_screenConfiguration->connectedOutputs()) { - if (output->isPrimary()) - return output; - } - - return nullptr; + return KScreen::OutputPtr(); } QScreen* ShellCorona::insertScreen(QScreen *screen, int idx) @@ -1506,7 +1507,7 @@ void ShellCorona::desktopContainmentDestroyed(QObject *obj) } } -KScreen::Config* ShellCorona::screensConfiguration() const +KScreen::ConfigPtr ShellCorona::screensConfiguration() const { return m_screenConfiguration; } diff --git a/shell/shellcorona.h b/shell/shellcorona.h index 5e97e02..37f8b0e 100644 --- a/shell/shellcorona.h +++ b/shell/shellcorona.h @@ -30,6 +30,8 @@ #include +#include + class Activity; class DesktopView; class PanelView; @@ -49,7 +51,6 @@ namespace KDeclarative namespace KScreen { class Output; - class Config; } // namespace KScreen namespace Plasma @@ -90,7 +91,7 @@ public: Plasma::Containment *setContainmentTypeForScreen(int screen, const QString &plugin); - KScreen::Config *screensConfiguration() const; + KScreen::ConfigPtr screensConfiguration() const; QScreen *screenForId(int screenId) const; void remove(DesktopView *desktopView); @@ -166,7 +167,7 @@ private Q_SLOTS: void populateAddPanelsMenu(); void outputEnabledChanged(); - void addOutput(KScreen::Output *output); + void addOutput(const KScreen::OutputPtr &output); void primaryOutputChanged(); void activityOpened(); @@ -179,12 +180,11 @@ private Q_SLOTS: void screenRemoved(QScreen* screen); private: - QScreen *outputToScreen(KScreen::Output *output) const; - KScreen::Output *screenToOutput(QScreen *screen) const; - KScreen::Output *findPrimaryOutput() const; + QScreen *outputToScreen(const KScreen::OutputPtr &output) const; + KScreen::OutputPtr screenToOutput(QScreen *screen) const; QScreen *insertScreen(QScreen *screen, int idx); void removeView(int idx); - bool isOutputRedundant(KScreen::Output *output) const; + bool isOutputRedundant(const KScreen::OutputPtr &output) const; void reconsiderOutputs(); QList panelsForScreen(QScreen *screen) const; DesktopView* desktopForScreen(QScreen *screen) const; @@ -207,11 +207,11 @@ private: QAction *m_addPanelAction; QMenu *m_addPanelsMenu; Plasma::Package m_lookAndFeelPackage; - QSet m_redundantOutputs; + QSet m_redundantOutputs; QList m_alternativesObjects; KDeclarative::QmlObject *m_interactiveConsole; - KScreen::Config *m_screenConfiguration; + KScreen::ConfigPtr m_screenConfiguration; QTimer m_waitingPanelsTimer; QTimer m_appConfigSyncTimer; QTimer m_reconsiderOutputsTimer;