Drop KScreen dependency from PlasmaShell

Uses QScreen to listen to updates on the different screen dispositions.

REVIEW: 125451
wilder-5.14
Aleix Pol 10 years ago
parent c003b80cc2
commit f8a381a54a
  1. 2
      CMakeLists.txt
  2. 1
      shell/CMakeLists.txt
  3. 30
      shell/panelview.cpp
  4. 5
      shell/panelview.h
  5. 193
      shell/shellcorona.cpp
  6. 15
      shell/shellcorona.h

@ -25,8 +25,6 @@ find_package(KF5XmlRpcClient REQUIRED)
# WARNING PlasmaQuick provides unversioned CMake config
find_package(KF5 REQUIRED COMPONENTS PlasmaQuick)
find_package(KF5 REQUIRED COMPONENTS SysGuard)
# Require KScreen >= 5.0.93 due to large API change
find_package(KF5 5.0.93 REQUIRED COMPONENTS Screen)
find_package(KF5 REQUIRED COMPONENTS Package)
# Baloo has a different version scheme than KF5 for now
find_package(KF5 5.1 REQUIRED COMPONENTS Baloo)

@ -89,7 +89,6 @@ target_link_libraries(plasmashell
KF5::GlobalAccel
KF5::CoreAddons
KF5::DBusAddons
KF5::Screen
KF5::Declarative
KF5::QuickAddons
KF5::XmlGui

@ -37,8 +37,6 @@
#include <Plasma/Containment>
#include <Plasma/Package>
#include <KScreen/Config>
#include <KScreen/Output>
#include <KWayland/Client/plasmashell.h>
#include <KWayland/Client/surface.h>
@ -88,6 +86,7 @@ PanelView::PanelView(ShellCorona *corona, QScreen *targetScreen, QWindow *parent
connect(&m_unhideTimer, &QTimer::timeout,
this, &PanelView::restoreAutoHide);
m_lastScreen = targetScreen;
connect(screen(), SIGNAL(geometryChanged(QRect)),
&m_positionPaneltimer, SLOT(start()));
connect(this, SIGNAL(locationChanged(Plasma::Types::Location)),
@ -103,9 +102,6 @@ PanelView::PanelView(ShellCorona *corona, QScreen *targetScreen, QWindow *parent
connect(&m_strutsTimer, &QTimer::timeout,
this, &PanelView::updateStruts);
connect(m_corona->screensConfiguration()->screen().data(), &KScreen::Screen::currentSizeChanged,
this, &PanelView::updateStruts);
qmlRegisterType<QScreen>();
rootContext()->setContextProperty(QStringLiteral("panel"), this);
setSource(QUrl::fromLocalFile(m_corona->kPackage().filePath("views", QStringLiteral("Panel.qml"))));
@ -658,19 +654,23 @@ void PanelView::showEvent(QShowEvent *event)
{
PanelShadows::self()->addWindow(this);
PlasmaQuick::ContainmentView::showEvent(event);
integrateScreen();
//When the screen is set, the screen is recreated internally, so we need to
//set anything that depends on the winId()
connect(this, &QWindow::screenChanged, this, [this](QScreen* screen) {
emit screenChangedProxy(screen);
connect(this, &QWindow::screenChanged, this, &PanelView::moveScreen, Qt::UniqueConnection);
integrateScreen();
}
if (!screen)
return;
integrateScreen();
showTemporarily();
m_positionPaneltimer.start();
});
void PanelView::moveScreen(QScreen* screen)
{
emit screenChangedProxy(screen);
m_lastScreen = screen;
if (!screen)
return;
integrateScreen();
showTemporarily();
m_positionPaneltimer.start();
}
bool PanelView::event(QEvent *e)
@ -881,7 +881,7 @@ void PanelView::updateStruts()
if (m_visibilityMode == NormalPanel) {
const QRect thisScreen = screen()->geometry();
// QScreen::virtualGeometry() is very unreliable (Qt 5.5)
const QRect wholeScreen = QRect(QPoint(0, 0), m_corona->screensConfiguration()->screen()->currentSize());
const QRect wholeScreen = QRect(QPoint(0, 0), screen()->geometry().size());
//Extended struts against a screen edge near to another screen are really harmful, so windows maximized under the panel is a lesser pain
//TODO: force "windows can cover" in those cases?

@ -136,6 +136,8 @@ public:
/* Shared with script/panel.cpp */
static KConfigGroup panelConfig(ShellCorona *corona, Plasma::Containment *containment, QScreen *screen);
void updateStruts();
protected:
void resizeEvent(QResizeEvent *ev) override;
void showEvent(QShowEvent *event) override;
@ -162,7 +164,6 @@ protected Q_SLOTS:
* It will be called when the configuration is requested
*/
void showConfigurationInterface(Plasma::Applet *applet) override;
void updateStruts();
private Q_SLOTS:
void themeChanged();
@ -176,6 +177,7 @@ private Q_SLOTS:
void screenDestroyed(QObject* screen);
private:
void moveScreen(QScreen* screen);
void resizePanel();
void integrateScreen();
bool containmentContainsPosition(const QPointF &point) const;
@ -200,6 +202,7 @@ private:
//only for the mask, not to actually paint
Plasma::FrameSvg *m_background;
KWayland::Client::PlasmaShellSurface *m_shellSurface;
QWeakPointer<QScreen> m_lastScreen;
static const int STRUTSTIMERDELAY = 200;
};

@ -44,11 +44,6 @@
#include <kdeclarative/qmlobject.h>
#include <KMessageBox>
#include <KScreen/Config>
#include <KScreen/ConfigMonitor>
#include <KScreen/GetConfigOperation>
#include <KScreen/Output>
#include <KPackage/PackageLoader>
#include <KWayland/Client/connection_thread.h>
@ -90,7 +85,6 @@ ShellCorona::ShellCorona(QObject *parent)
m_addPanelAction(nullptr),
m_addPanelsMenu(nullptr),
m_interactiveConsole(nullptr),
m_screenConfiguration(nullptr),
m_waylandPlasmaShell(nullptr)
{
setupWaylandIntegration();
@ -305,14 +299,7 @@ void ShellCorona::setShell(const QString &shell)
connect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &ShellCorona::load, Qt::UniqueConnection);
connect(new KScreen::GetConfigOperation(KScreen::GetConfigOperation::NoEDID), &KScreen::GetConfigOperation::finished,
this, [this](KScreen::ConfigOperation *op) {
if (op->hasError()) {
qWarning() << "Error found while setting up ShellCorona's KScreen: " << op->errorString();
}
m_screenConfiguration = qobject_cast<KScreen::GetConfigOperation*>(op)->config();
load();
});
load();
}
QString ShellCorona::shell() const
@ -320,17 +307,19 @@ QString ShellCorona::shell() const
return m_shell;
}
bool outputLess(const KScreen::OutputPtr &a, const KScreen::OutputPtr &b)
bool outputLess(QScreen* a, QScreen* b)
{
return ((a->isEnabled() && !b->isEnabled())
|| (a->isEnabled() == b->isEnabled() && (a->isPrimary() && !b->isPrimary()))
|| (a->isPrimary() == b->isPrimary() && (a->pos().x() < b->pos().x()
|| (a->pos().x() == b->pos().x() && a->pos().y() < b->pos().y()))));
const QPoint aPos = a->geometry().topLeft();
const QPoint bPos = b->geometry().topLeft();
return (qGuiApp->primaryScreen() == a
|| (qGuiApp->primaryScreen() != b && (aPos.x() < bPos.x()
|| (aPos.x() == bPos.x() && aPos.y() < bPos.y()))));
}
static QList<KScreen::OutputPtr> sortOutputs(const KScreen::OutputList &outputs)
static QList<QScreen*> sortOutputs(const QList<QScreen*> &outputs)
{
QList<KScreen::OutputPtr> ret = outputs.values();
QList<QScreen*> ret = outputs;
std::sort(ret.begin(), ret.end(), outputLess);
return ret;
}
@ -338,8 +327,7 @@ static QList<KScreen::OutputPtr> sortOutputs(const KScreen::OutputList &outputs)
void ShellCorona::load()
{
if (m_shell.isEmpty() ||
m_activityConsumer->serviceStatus() == KActivities::Consumer::Unknown ||
!m_screenConfiguration) {
m_activityConsumer->serviceStatus() == KActivities::Consumer::Unknown) {
return;
}
@ -373,13 +361,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 (const KScreen::OutputPtr &output : sortOutputs(m_screenConfiguration->outputs())) {
addOutput(output);
for (QScreen* screen : sortOutputs(qGuiApp->screens())) {
addOutput(screen);
}
connect(m_screenConfiguration.data(), &KScreen::Config::outputAdded, this, &ShellCorona::addOutput);
connect(m_screenConfiguration.data(), &KScreen::Config::primaryOutputChanged, this, &ShellCorona::primaryOutputChanged);
connect(qGuiApp, &QGuiApplication::screenAdded, this, &ShellCorona::addOutput);
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &ShellCorona::primaryOutputChanged);
connect(qGuiApp, &QGuiApplication::screenRemoved, this, &ShellCorona::screenRemoved);
if (!m_waitingPanels.isEmpty()) {
@ -401,13 +387,8 @@ void ShellCorona::primaryOutputChanged()
return;
}
const KScreen::OutputPtr output = m_screenConfiguration->primaryOutput();
if (!output) {
return;
}
QScreen *oldPrimary = m_views[0]->screen();
QScreen *newPrimary = outputToScreen(output);
QScreen *newPrimary = qGuiApp->primaryScreen();
if (!newPrimary || newPrimary == oldPrimary) {
return;
}
@ -433,7 +414,7 @@ void ShellCorona::primaryOutputChanged()
Q_ASSERT(oldPrimary != newPrimary);
Q_ASSERT(m_views[0]->screen() == oldPrimary);
Q_ASSERT(m_views[0]->screen() != newPrimary);
Q_ASSERT(m_views[0]->geometry() == oldPrimary->geometry());
// Q_ASSERT(m_views[0]->geometry() == oldPrimary->geometry());
qDebug() << "adapting" << newPrimary->geometry() << oldPrimary->geometry();
view->setScreen(oldPrimary);
@ -442,6 +423,7 @@ void ShellCorona::primaryOutputChanged()
}
m_views[0]->setScreen(newPrimary);
Q_ASSERT(m_views[0]->screen()==newPrimary);
foreach (PanelView *panel, m_panelViews) {
if (panel->screen() == oldPrimary) {
@ -459,21 +441,16 @@ void ShellCorona::screenInvariants() const
{
Q_ASSERT(m_views.count() <= QGuiApplication::screens().count());
QScreen *s = m_views.isEmpty() ? nullptr : m_views[0]->screen();
const KScreen::OutputPtr primaryOutput = m_screenConfiguration->primaryOutput();
if (!s) {
qWarning() << "error: couldn't find primary output" << primaryOutput;
return;
}
QScreen* ks = outputToScreen(primaryOutput);
Q_ASSERT(!ks || ks == s || !primaryOutput->isEnabled() || m_redundantOutputs.contains(primaryOutput));
QScreen* ks = qGuiApp->primaryScreen();
Q_ASSERT(ks == s);
QSet<QScreen*> screens;
int i = 0;
foreach (const DesktopView *view, m_views) {
QScreen *screen = view->screen();
Q_ASSERT(!screens.contains(screen));
Q_ASSERT(!m_redundantOutputs.contains(screenToOutput(screen)));
Q_ASSERT(!m_redundantOutputs.contains(screen));
// commented out because a different part of the code-base is responsible for this
// and sometimes is not yet called here.
// Q_ASSERT(!view->fillScreen() || view->geometry() == screen->geometry());
@ -492,7 +469,7 @@ void ShellCorona::screenInvariants() const
++i;
}
foreach (const KScreen::OutputPtr &out, m_redundantOutputs) {
foreach (QScreen* out, m_redundantOutputs) {
Q_ASSERT(isOutputRedundant(out));
}
@ -637,18 +614,14 @@ KActivities::Controller *ShellCorona::activityController()
int ShellCorona::numScreens() const
{
//don't start loading screens until kscreen has finished initialising.
if (!m_screenConfiguration) {
return 0;
}
return m_screenConfiguration->connectedOutputs().count();
return qGuiApp->screens().count();
}
QRect ShellCorona::screenGeometry(int id) const
{
if (id >= m_views.count() || id < 0) {
qWarning() << "requesting unexisting screen" << id;
QScreen *s = outputToScreen(m_screenConfiguration->primaryOutput());
QScreen *s = qGuiApp->primaryScreen();
return s ? s->geometry() : QRect();
}
return m_views[id]->geometry();
@ -659,7 +632,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(m_screenConfiguration->primaryOutput());
QScreen *s = qGuiApp->primaryScreen();
return s ? s->availableGeometry() : QRegion();
}
DesktopView *view = m_views[id];
@ -679,7 +652,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(m_screenConfiguration->primaryOutput());
QScreen *s = qGuiApp->primaryScreen();
return s ? s->availableGeometry() : QRect();
}
@ -798,24 +771,20 @@ void ShellCorona::screenRemoved(QScreen* screen)
{
if (DesktopView* v = desktopForScreen(screen))
remove(v);
// addOutput(screenToOutput(screen));
m_reconsiderOutputsTimer.start();
}
void ShellCorona::outputEnabledChanged()
{
addOutput(KScreen::OutputPtr(qobject_cast<KScreen::Output *>(sender()), [](void*){}));
m_reconsiderOutputsTimer.start();
m_redundantOutputs.remove(screen);
}
bool ShellCorona::isOutputRedundant(const KScreen::OutputPtr &screen) const
bool ShellCorona::isOutputRedundant(QScreen* screen) const
{
Q_ASSERT(screen->currentMode());
Q_ASSERT(screen);
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::OutputPtr &s, m_screenConfiguration->connectedOutputs()) {
if (screen == s || !s->isEnabled() || !s->currentMode()) {
foreach (QScreen* s, qGuiApp->screens()) {
if (screen == s) {
continue;
}
@ -832,71 +801,47 @@ bool ShellCorona::isOutputRedundant(const KScreen::OutputPtr &screen) const
void ShellCorona::reconsiderOutputs()
{
if (!m_screenConfiguration) {
return;
}
foreach (const KScreen::OutputPtr &out, m_screenConfiguration->connectedOutputs()) {
if (!out->isEnabled() || !out->currentMode()) {
// qDebug() << "skip screen" << out << desktopForScreen(outputToScreen(out));
continue;
}
if (m_redundantOutputs.contains(out)) {
if (!isOutputRedundant(out)) {
foreach (QScreen* screen, qGuiApp->screens()) {
if (m_redundantOutputs.contains(screen)) {
if (!isOutputRedundant(screen)) {
// qDebug() << "not redundant anymore" << out;
addOutput(out);
addOutput(screen);
}
} else if (isOutputRedundant(out)) {
// qDebug() << "new redundant screen" << out;
} else if (isOutputRedundant(screen)) {
qDebug() << "new redundant screen" << screen;
if (DesktopView* v = desktopForScreen(outputToScreen(out)))
if (DesktopView* v = desktopForScreen(screen))
remove(v);
m_redundantOutputs.insert(out);
m_redundantOutputs.insert(screen);
}
// else
// qDebug() << "fine screen" << out;
}
updateStruts();
CHECK_SCREEN_INVARIANTS
}
void ShellCorona::addOutput(const KScreen::OutputPtr &output)
void ShellCorona::addOutput(QScreen* screen)
{
if (!output) {
return;
}
Q_ASSERT(screen);
connect(output.data(), &KScreen::Output::isEnabledChanged,
this, &ShellCorona::outputEnabledChanged,
Qt::UniqueConnection);
connect(output.data(), &KScreen::Output::posChanged,
&m_reconsiderOutputsTimer, static_cast<void (QTimer::*)()>(&QTimer::start),
Qt::UniqueConnection);
connect(output.data(), &KScreen::Output::currentModeIdChanged,
connect(screen, &QScreen::geometryChanged,
&m_reconsiderOutputsTimer, static_cast<void (QTimer::*)()>(&QTimer::start),
Qt::UniqueConnection);
if (!output->isEnabled()) {
m_redundantOutputs.remove(output);
m_reconsiderOutputsTimer.start();
return;
}
QScreen *screen = outputToScreen(output);
Q_ASSERT(screen);
if (isOutputRedundant(output)) {
m_redundantOutputs.insert(output);
if (isOutputRedundant(screen)) {
m_redundantOutputs.insert(screen);
return;
} else {
m_redundantOutputs.remove(output);
m_redundantOutputs.remove(screen);
}
int insertPosition = 0;
foreach (DesktopView *view, m_views) {
const KScreen::OutputPtr out = screenToOutput(view->screen());
if (outputLess(output, out)) {
if (outputLess(screen, view->screen())) {
break;
}
@ -935,32 +880,6 @@ void ShellCorona::addOutput(const KScreen::OutputPtr &output)
CHECK_SCREEN_INVARIANTS
}
QScreen *ShellCorona::outputToScreen(const KScreen::OutputPtr &output) const
{
if (!output) {
return nullptr;
}
foreach (QScreen *screen, QGuiApplication::screens()) {
if (screen->name() == output->name()) {
return screen;
}
}
return nullptr;
}
KScreen::OutputPtr ShellCorona::screenToOutput(QScreen *screen) const
{
foreach (const KScreen::OutputPtr &output, m_screenConfiguration->connectedOutputs()) {
if (screen->name() == output->name()) {
return output;
}
}
return KScreen::OutputPtr();
}
QScreen* ShellCorona::insertScreen(QScreen *screen, int idx)
{
if (idx == m_views.count()) {
@ -1630,7 +1549,7 @@ int ShellCorona::screenForContainment(const Plasma::Containment *containment) co
//a containment with lastScreen() == 0 but another activity,
//won't be associated to a screen
// qDebug() << "ShellCorona screenForContainment: " << containment << " Last screen is " << containment->lastScreen();
for (int i = 0, count = m_screenConfiguration->outputs().count(); i<count; ++i) {
for (int i = 0, count = qGuiApp->screens().count(); i<count; ++i) {
if (containment->lastScreen() == i &&
(containment->activity() == m_activityConsumer->currentActivity() ||
containment->containmentType() == Plasma::Types::PanelContainment || containment->containmentType() == Plasma::Types::CustomPanelContainment)) {
@ -1750,11 +1669,6 @@ void ShellCorona::desktopContainmentDestroyed(QObject *obj)
}
}
KScreen::ConfigPtr ShellCorona::screensConfiguration() const
{
return m_screenConfiguration;
}
void ShellCorona::showOpenGLNotCompatibleWarning()
{
static bool s_multipleInvokations = false;
@ -1797,6 +1711,13 @@ KWayland::Client::PlasmaShell *ShellCorona::waylandPlasmaShellInterface() const
return m_waylandPlasmaShell;
}
void ShellCorona::updateStruts()
{
foreach(PanelView* view, m_panelViews) {
view->updateStruts();
}
}
// Desktop corona handler

@ -32,8 +32,6 @@
#include <KPackage/Package>
#include <KScreen/Types>
class Activity;
class DesktopView;
class PanelView;
@ -101,8 +99,6 @@ public:
Plasma::Containment *setContainmentTypeForScreen(int screen, const QString &plugin);
KScreen::ConfigPtr screensConfiguration() const;
QScreen *screenForId(int screenId) const;
void remove(DesktopView *desktopView);
@ -188,8 +184,7 @@ private Q_SLOTS:
void addPanel(QAction *action);
void populateAddPanelsMenu();
void outputEnabledChanged();
void addOutput(const KScreen::OutputPtr &output);
void addOutput(QScreen* screen);
void primaryOutputChanged();
void activityOpened();
@ -203,11 +198,10 @@ private Q_SLOTS:
void screenRemoved(QScreen* screen);
private:
QScreen *outputToScreen(const KScreen::OutputPtr &output) const;
KScreen::OutputPtr screenToOutput(QScreen *screen) const;
void updateStruts();
QScreen *insertScreen(QScreen *screen, int idx);
void removeView(int idx);
bool isOutputRedundant(const KScreen::OutputPtr &output) const;
bool isOutputRedundant(QScreen* screen) const;
void reconsiderOutputs();
QList<PanelView *> panelsForScreen(QScreen *screen) const;
DesktopView* desktopForScreen(QScreen *screen) const;
@ -232,11 +226,10 @@ private:
QAction *m_addPanelAction;
QMenu *m_addPanelsMenu;
KPackage::Package m_lookAndFeelPackage;
QSet<KScreen::OutputPtr> m_redundantOutputs;
QSet<QScreen*> m_redundantOutputs;
QList<KDeclarative::QmlObject *> m_alternativesObjects;
KDeclarative::QmlObject *m_interactiveConsole;
KScreen::ConfigPtr m_screenConfiguration;
QTimer m_waitingPanelsTimer;
QTimer m_appConfigSyncTimer;
QTimer m_reconsiderOutputsTimer;

Loading…
Cancel
Save