From a1f1039b58d4fdd57757e08bcff44b59f298b1a2 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 28 Aug 2021 18:34:58 +0300 Subject: [PATCH] Store AbstractOutput in Toplevel Since AbstractOutput is used more than int screen ids in kwin, it's worth storing AbstractOutput for better performance. --- src/abstract_client.cpp | 6 ++--- src/toplevel.cpp | 56 +++++++++++++++++++---------------------- src/toplevel.h | 9 ++++--- src/unmanaged.cpp | 2 +- src/workspace.cpp | 8 +++++- 5 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/abstract_client.cpp b/src/abstract_client.cpp index 7f6e3f49d4..d717ada508 100644 --- a/src/abstract_client.cpp +++ b/src/abstract_client.cpp @@ -61,8 +61,8 @@ AbstractClient::AbstractClient() { connect(this, &AbstractClient::clientStartUserMovedResized, this, &AbstractClient::moveResizedChanged); connect(this, &AbstractClient::clientFinishUserMovedResized, this, &AbstractClient::moveResizedChanged); - connect(this, &AbstractClient::clientStartUserMovedResized, this, &AbstractClient::removeCheckScreenConnection); - connect(this, &AbstractClient::clientFinishUserMovedResized, this, &AbstractClient::setupCheckScreenConnection); + connect(this, &AbstractClient::clientStartUserMovedResized, this, &AbstractClient::removeCheckOutputConnection); + connect(this, &AbstractClient::clientFinishUserMovedResized, this, &AbstractClient::setupCheckOutputConnection); connect(this, &AbstractClient::paletteChanged, this, &AbstractClient::triggerDecorationRepaint); @@ -981,7 +981,7 @@ void AbstractClient::finishInteractiveMoveResize(bool cancel) } moveResize(moveResizeGeom); } - checkScreen(); // needs to be done because clientFinishUserMovedResized has not yet re-activated online alignment + checkOutput(); // needs to be done because clientFinishUserMovedResized has not yet re-activated online alignment if (output() != interactiveMoveResizeStartOutput()) { if (isFullScreen() || isElectricBorderMaximizing()) { updateGeometryRestoresForFullscreen(output()); diff --git a/src/toplevel.cpp b/src/toplevel.cpp index c81c1afadc..650cc71c1a 100644 --- a/src/toplevel.cpp +++ b/src/toplevel.cpp @@ -44,12 +44,10 @@ Toplevel::Toplevel() , effect_window(nullptr) , m_clientMachine(new ClientMachine(this)) , m_wmClientLeader(XCB_WINDOW_NONE) - , m_screen(0) , m_skipCloseAnimation(false) { - connect(screens(), &Screens::changed, this, &Toplevel::checkScreen); - connect(screens(), &Screens::countChanged, this, &Toplevel::checkScreen); - setupCheckScreenConnection(); + connect(screens(), &Screens::changed, this, &Toplevel::screenChanged); + setupCheckOutputConnection(); connect(this, &Toplevel::bufferGeometryChanged, this, &Toplevel::inputTransformationChanged); // Only for compatibility reasons, drop in the next major release. @@ -126,7 +124,7 @@ void Toplevel::copyToDeleted(Toplevel* c) m_clientMachine->setParent(this); m_wmClientLeader = c->wmClientLeader(); opaque_region = c->opaqueRegion(); - m_screen = c->m_screen; + m_output = c->m_output; m_skipCloseAnimation = c->m_skipCloseAnimation; m_internalFBO = c->m_internalFBO; m_internalImage = c->m_internalImage; @@ -367,46 +365,44 @@ void Toplevel::deleteEffectWindow() effect_window = nullptr; } -void Toplevel::checkScreen() +void Toplevel::checkOutput() { - if (screens()->count() == 1) { - if (m_screen != 0) { - m_screen = 0; - Q_EMIT screenChanged(); - } - } else { - const int s = screens()->number(frameGeometry().center()); - if (s != m_screen) { - m_screen = s; - Q_EMIT screenChanged(); - } - } - qreal newScale = screens()->scale(m_screen); - if (newScale != m_screenScale) { - m_screenScale = newScale; - Q_EMIT screenScaleChanged(); - } + setOutput(kwinApp()->platform()->outputAt(frameGeometry().center())); } -void Toplevel::setupCheckScreenConnection() +void Toplevel::setupCheckOutputConnection() { - connect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::checkScreen); - checkScreen(); + connect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::checkOutput); + checkOutput(); } -void Toplevel::removeCheckScreenConnection() +void Toplevel::removeCheckOutputConnection() { - disconnect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::checkScreen); + disconnect(this, &Toplevel::frameGeometryChanged, this, &Toplevel::checkOutput); } int Toplevel::screen() const { - return m_screen; + return kwinApp()->platform()->enabledOutputs().indexOf(m_output); } AbstractOutput *Toplevel::output() const { - return kwinApp()->platform()->findOutput(screen()); + return m_output; +} + +void Toplevel::setOutput(AbstractOutput *output) +{ + if (m_output != output) { + m_output = output; + Q_EMIT screenChanged(); + } + + qreal newScale = m_output->scale(); + if (newScale != m_screenScale) { + m_screenScale = newScale; + Q_EMIT screenScaleChanged(); + } } qreal Toplevel::screenScale() const diff --git a/src/toplevel.h b/src/toplevel.h index 60ee92abf9..2a957accf1 100644 --- a/src/toplevel.h +++ b/src/toplevel.h @@ -346,6 +346,7 @@ public: bool isOnActiveOutput() const; int screen() const; // the screen where the center is AbstractOutput *output() const; + void setOutput(AbstractOutput *output); /** * The scale of the screen this window is currently on * @note The buffer scale can be different. @@ -662,9 +663,9 @@ protected Q_SLOTS: * Checks whether the screen number for this Toplevel changed and updates if needed. * Any method changing the geometry of the Toplevel should call this method. */ - void checkScreen(); - void setupCheckScreenConnection(); - void removeCheckScreenConnection(); + void checkOutput(); + void setupCheckOutputConnection(); + void removeCheckOutputConnection(); void setReadyForPainting(); protected: @@ -720,7 +721,7 @@ private: QRegion opaque_region; mutable QRegion m_shapeRegion; mutable bool m_shapeRegionIsValid = false; - int m_screen; + AbstractOutput *m_output = nullptr; bool m_skipCloseAnimation; quint32 m_surfaceId = 0; KWaylandServer::SurfaceInterface *m_surface = nullptr; diff --git a/src/unmanaged.cpp b/src/unmanaged.cpp index cede479f7e..5d83230186 100644 --- a/src/unmanaged.cpp +++ b/src/unmanaged.cpp @@ -102,7 +102,7 @@ bool Unmanaged::track(xcb_window_t w) m_bufferGeometry = geo.rect(); m_frameGeometry = geo.rect(); m_clientGeometry = geo.rect(); - checkScreen(); + checkOutput(); m_visual = attr->visual; bit_depth = geo->depth; info = new NETWinInfo(connection(), w, rootWindow(), diff --git a/src/workspace.cpp b/src/workspace.cpp index 518f7e59c3..73a2119ef3 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -1213,7 +1213,13 @@ void Workspace::slotOutputEnabled(AbstractOutput *output) void Workspace::slotOutputDisabled(AbstractOutput *output) { - // TODO: Send clients on the given output to other outputs. + const auto stack = xStackingOrder(); + for (Toplevel *toplevel : stack) { + if (toplevel->output() == output) { + toplevel->setOutput(kwinApp()->platform()->outputAt(toplevel->frameGeometry().center())); + } + } + disconnect(output, &AbstractOutput::geometryChanged, this, &Workspace::desktopResized); desktopResized(); }