From 6d6b013720ca987cd617cdb3d7543ded5ad6d9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 26 Mar 2013 07:45:08 +0100 Subject: [PATCH] Introduce a proper screen property in Toplevel Instead of calculating the screen number each time screen() is invoked, the screen number gets stored in a private member variable and evaluated whenever either the screen count changes or the Toplevel's geometry changes. During move/resize the screen property doesn't get updated. The update is delayed till the end of the move/resize operation. REVIEW: 109715 --- client.cpp | 2 ++ geometry.cpp | 1 + toplevel.cpp | 43 +++++++++++++++++++++++++++++++++++++------ toplevel.h | 18 +++++++++++++++++- unmanaged.cpp | 1 + 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/client.cpp b/client.cpp index 2bd6832259..3aad8cd5db 100644 --- a/client.cpp +++ b/client.cpp @@ -219,6 +219,8 @@ Client::Client(Workspace* ws) connect(this, SIGNAL(clientStepUserMovedResized(KWin::Client*,QRect)), SIGNAL(geometryChanged())); connect(this, SIGNAL(clientStartUserMovedResized(KWin::Client*)), SIGNAL(moveResizedChanged())); connect(this, SIGNAL(clientFinishUserMovedResized(KWin::Client*)), SIGNAL(moveResizedChanged())); + connect(this, SIGNAL(clientStartUserMovedResized(KWin::Client*)), SLOT(removeCheckScreenConnection())); + connect(this, SIGNAL(clientFinishUserMovedResized(KWin::Client*)), SLOT(setupCheckScreenConnection())); connect(clientMachine(), SIGNAL(localhostChanged()), SLOT(updateCaption())); connect(options, SIGNAL(condensedTitleChanged()), SLOT(updateCaption())); diff --git a/geometry.cpp b/geometry.cpp index fdb112bdc9..9f99d485f5 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2064,6 +2064,7 @@ void Client::move(int x, int y, ForceGeometry_t force) // Update states of all other windows in this group if (tabGroup()) tabGroup()->updateStates(this, TabGroup::Geometry); + emit geometryChanged(); } void Client::blockGeometryUpdates(bool block) diff --git a/toplevel.cpp b/toplevel.cpp index 1d4406c36f..9bb9802bd3 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -29,6 +29,8 @@ along with this program. If not, see . #include "shadow.h" #include "xcbutils.h" +#include + namespace KWin { @@ -49,8 +51,12 @@ Toplevel::Toplevel(Workspace* ws) , unredirect(false) , unredirectSuspend(false) , m_damageReplyPending(false) + , m_screen(0) { connect(this, SIGNAL(damaged(KWin::Toplevel*,QRect)), SIGNAL(needsRepaint())); + connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), SLOT(checkScreen())); + connect(QApplication::desktop(), SIGNAL(resized(int)), SLOT(checkScreen())); + setupCheckScreenConnection(); } Toplevel::~Toplevel() @@ -140,6 +146,7 @@ void Toplevel::copyToDeleted(Toplevel* c) wmClientLeaderWin = c->wmClientLeader(); window_role = c->windowRole(); opaque_region = c->opaqueRegion(); + m_screen = c->m_screen; // this needs to be done already here, otherwise 'c' could very likely // call discardWindowPixmap() in something called during cleanup c->window_pix = None; @@ -324,14 +331,38 @@ void Toplevel::deleteEffectWindow() effect_window = NULL; } +void Toplevel::checkScreen() +{ + if (Workspace::self()->numScreens() == 1) { + if (m_screen != 0) { + m_screen = 0; + emit screenChanged(); + } + return; + } + const int s = Workspace::self()->screenNumber(geometry().center()); + if (s != m_screen) { + m_screen = s; + emit screenChanged(); + } +} + +void Toplevel::setupCheckScreenConnection() +{ + connect(this, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), SLOT(checkScreen())); + connect(this, SIGNAL(geometryChanged()), SLOT(checkScreen())); + checkScreen(); +} + +void Toplevel::removeCheckScreenConnection() +{ + disconnect(this, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), this, SLOT(checkScreen())); + disconnect(this, SIGNAL(geometryChanged()), this, SLOT(checkScreen())); +} + int Toplevel::screen() const { - int s = workspace()->screenNumber(geometry().center()); - if (s < 0) { - kDebug(1212) << "Invalid screen: Center" << geometry().center() << ", screen" << s; - return 0; - } - return s; + return m_screen; } bool Toplevel::isOnScreen(int screen) const diff --git a/toplevel.h b/toplevel.h index 96e65f6865..dfc48f141b 100644 --- a/toplevel.h +++ b/toplevel.h @@ -57,7 +57,7 @@ class Toplevel Q_PROPERTY(int height READ height) Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) Q_PROPERTY(QPoint pos READ pos) - Q_PROPERTY(int screen READ screen) + Q_PROPERTY(int screen READ screen NOTIFY screenChanged) Q_PROPERTY(QSize size READ size) Q_PROPERTY(int width READ width) Q_PROPERTY(qulonglong windowId READ window CONSTANT) @@ -326,6 +326,21 @@ signals: **/ void needsRepaint(); void activitiesChanged(KWin::Toplevel* toplevel); + /** + * Emitted whenever the Toplevel's screen changes. This can happen either in consequence to + * a screen being removed/added or if the Toplevel's geometry changes. + * @since 4.11 + **/ + void screenChanged(); + +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(); protected: virtual ~Toplevel(); @@ -394,6 +409,7 @@ private: bool m_damageReplyPending; QRegion opaque_region; xcb_xfixes_fetch_region_cookie_t m_regionCookie; + int m_screen; // when adding new data members, check also copyToDeleted() }; diff --git a/unmanaged.cpp b/unmanaged.cpp index 8ae58ab2c2..39b1638e0c 100644 --- a/unmanaged.cpp +++ b/unmanaged.cpp @@ -55,6 +55,7 @@ bool Unmanaged::track(Window w) setWindowHandles(w, w); // the window is also the frame XSelectInput(display(), w, attr.your_event_mask | StructureNotifyMask | PropertyChangeMask); geom = QRect(attr.x, attr.y, attr.width, attr.height); + checkScreen(); vis = attr.visual; bit_depth = attr.depth; unsigned long properties[ 2 ];