From 6b1f0b1fcac2892de5b6670bc28407a9eb05273d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 27 Feb 2014 09:55:45 +0100 Subject: [PATCH] [kwin] Introduce Screens::size and Screens::geometry Screens provides a size which is constructed from the size of the bounding geometry of all screens and provides an overload taking an int to return the size of a specified screen. For geometry() a new ovload is added without an argument, which is just a convenient wrapper for QRect(QPoint(0, 0), size()). Both new methods are exported to effects and scripting as new properties there called virtualScreenSize and virtualScreenGeometry. The (virtual) size gets cached in screens and is updated whenever the count or geometry changes. Construction of Screens is slightly changed by moving the init code from ctor into a virtual method init(). Reason is that we ended in a loop with accessing the singleton pointer before it was set. REVIEW: 116114 --- effects.cpp | 12 +++++++ effects.h | 2 ++ libkwineffects/kwineffects.h | 33 ++++++++++++++++++ screens.cpp | 60 ++++++++++++++++++++++++++------- screens.h | 59 ++++++++++++++++++++++++++++++++ scripting/workspace_wrapper.cpp | 12 +++++++ scripting/workspace_wrapper.h | 29 ++++++++++++++++ 7 files changed, 195 insertions(+), 12 deletions(-) diff --git a/effects.cpp b/effects.cpp index 05ce0c6955..8266d2417e 100644 --- a/effects.cpp +++ b/effects.cpp @@ -266,6 +266,8 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene) SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers))); connect(ws, SIGNAL(propertyNotify(long)), this, SLOT(slotPropertyNotify(long))); connect(screens(), &Screens::countChanged, this, &EffectsHandler::numberScreensChanged); + connect(screens(), &Screens::sizeChanged, this, &EffectsHandler::virtualScreenSizeChanged); + connect(screens(), &Screens::geometryChanged, this, &EffectsHandler::virtualScreenGeometryChanged); #ifdef KWIN_BUILD_ACTIVITIES Activities *activities = Activities::self(); connect(activities, SIGNAL(added(QString)), SIGNAL(activityAdded(QString))); @@ -1236,6 +1238,16 @@ QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, const QPoint& p, int return Workspace::self()->clientArea(opt, p, desktop); } +QRect EffectsHandlerImpl::virtualScreenGeometry() const +{ + return screens()->geometry(); +} + +QSize EffectsHandlerImpl::virtualScreenSize() const +{ + return screens()->size(); +} + void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape) { if (!m_mouseInterceptionWindow.isValid()) { diff --git a/effects.h b/effects.h index 04d2fe6ea0..89849f5a1b 100644 --- a/effects.h +++ b/effects.h @@ -147,6 +147,8 @@ public: QRect clientArea(clientAreaOption, int screen, int desktop) const override; QRect clientArea(clientAreaOption, const EffectWindow* c) const override; QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const override; + QSize virtualScreenSize() const override; + QRect virtualScreenGeometry() const override; double animationTimeFactor() const override; WindowQuadType newWindowQuadType() override; diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index df3bd3fdc7..4da48cc55e 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -690,6 +690,8 @@ class KWINEFFECTS_EXPORT EffectsHandler : public QObject Q_PROPERTY(bool decorationSupportsBlurBehind READ decorationSupportsBlurBehind) Q_PROPERTY(CompositingType compositingType READ compositingType CONSTANT) Q_PROPERTY(QPoint cursorPos READ cursorPos) + Q_PROPERTY(QSize virtualScreenSize READ virtualScreenSize NOTIFY virtualScreenSizeChanged) + Q_PROPERTY(QRect virtualScreenGeometry READ virtualScreenGeometry NOTIFY virtualScreenGeometryChanged) friend class Effect; public: explicit EffectsHandler(CompositingType type); @@ -841,6 +843,25 @@ public: virtual QRect clientArea(clientAreaOption, int screen, int desktop) const = 0; virtual QRect clientArea(clientAreaOption, const EffectWindow* c) const = 0; virtual QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const = 0; + + /** + * The bounding size of all screens combined. Overlapping areas + * are not counted multiple times. + * + * @see virtualScreenGeometry() + * @see virtualScreenSizeChanged() + * @since 5.0 + **/ + virtual QSize virtualScreenSize() const = 0; + /** + * The bounding geometry of all outputs combined. Always starts at (0,0) and has + * virtualScreenSize as it's size. + * + * @see virtualScreenSize() + * @see virtualScreenGeometryChanged() + * @since 5.0 + **/ + virtual QRect virtualScreenGeometry() const = 0; /** * Factor by which animation speed in the effect should be modified (multiplied). * If configurable in the effect itself, the option should have also 'default' @@ -1316,6 +1337,18 @@ Q_SIGNALS: * @since 4.11 **/ void screenEdgeApproaching(ElectricBorder border, qreal factor, const QRect &geometry); + /** + * Emitted whenever the virtualScreenSize changes. + * @see virtualScreenSize() + * @since 5.0 + **/ + void virtualScreenSizeChanged(); + /** + * Emitted whenever the virtualScreenGeometry changes. + * @see virtualScreenGeometry() + * @since 5.0 + **/ + void virtualScreenGeometryChanged(); protected: QVector< EffectPair > loaded_effects; diff --git a/screens.cpp b/screens.cpp index 42d4304080..2ad69d1e9d 100644 --- a/screens.cpp +++ b/screens.cpp @@ -30,7 +30,14 @@ along with this program. If not, see . namespace KWin { -KWIN_SINGLETON_FACTORY_FACTORED(Screens, DesktopWidgetScreens) +Screens *Screens::s_self = nullptr; +Screens *Screens::create(QObject *parent) +{ + Q_ASSERT(!s_self); + s_self = new DesktopWidgetScreens(parent); + s_self->init(); + return s_self; +} Screens::Screens(QObject *parent) : QObject(parent) @@ -39,14 +46,6 @@ Screens::Screens(QObject *parent) , m_currentFollowsMouse(false) , m_changedTimer(new QTimer(this)) { - m_changedTimer->setSingleShot(true); - m_changedTimer->setInterval(100); - connect(m_changedTimer, SIGNAL(timeout()), SLOT(updateCount())); - connect(m_changedTimer, SIGNAL(timeout()), SIGNAL(changed())); - - Settings settings; - settings.setDefaults(); - m_currentFollowsMouse = settings.activeMouseScreen(); } Screens::~Screens() @@ -54,6 +53,21 @@ Screens::~Screens() s_self = NULL; } +void Screens::init() +{ + m_changedTimer->setSingleShot(true); + m_changedTimer->setInterval(100); + connect(m_changedTimer, SIGNAL(timeout()), SLOT(updateCount())); + connect(m_changedTimer, SIGNAL(timeout()), SIGNAL(changed())); + connect(this, &Screens::countChanged, this, &Screens::changed); + connect(this, &Screens::changed, this, &Screens::updateSize); + connect(this, &Screens::sizeChanged, this, &Screens::geometryChanged); + + Settings settings; + settings.setDefaults(); + m_currentFollowsMouse = settings.activeMouseScreen(); +} + void Screens::reconfigure() { if (!m_config) { @@ -64,6 +78,18 @@ void Screens::reconfigure() setCurrentFollowsMouse(settings.activeMouseScreen()); } +void Screens::updateSize() +{ + QRect bounding; + for (int i = 0; i < count(); ++i) { + bounding = bounding.united(geometry(i)); + } + if (m_boundingSize != bounding.size()) { + m_boundingSize = bounding.size(); + emit sizeChanged(); + } +} + void Screens::setCount(int count) { if (m_count == count) { @@ -133,15 +159,20 @@ DesktopWidgetScreens::DesktopWidgetScreens(QObject *parent) : Screens(parent) , m_desktop(QApplication::desktop()) { - connect(m_desktop, SIGNAL(screenCountChanged(int)), SLOT(startChangedTimer())); - connect(m_desktop, SIGNAL(resized(int)), SLOT(startChangedTimer())); - updateCount(); } DesktopWidgetScreens::~DesktopWidgetScreens() { } +void DesktopWidgetScreens::init() +{ + Screens::init(); + connect(m_desktop, SIGNAL(screenCountChanged(int)), SLOT(startChangedTimer())); + connect(m_desktop, SIGNAL(resized(int)), SLOT(startChangedTimer())); + updateCount(); +} + QRect DesktopWidgetScreens::geometry(int screen) const { if (Screens::self()->isChanging()) @@ -149,6 +180,11 @@ QRect DesktopWidgetScreens::geometry(int screen) const return m_desktop->screenGeometry(screen); } +QSize DesktopWidgetScreens::size(int screen) const +{ + return geometry(screen).size(); +} + int DesktopWidgetScreens::number(const QPoint &pos) const { if (Screens::self()->isChanging()) diff --git a/screens.h b/screens.h index 13659e1a6a..e4df1fa45d 100644 --- a/screens.h +++ b/screens.h @@ -64,6 +64,27 @@ public: bool isCurrentFollowsMouse() const; void setCurrentFollowsMouse(bool follows); virtual QRect geometry(int screen) const = 0; + /** + * The bounding geometry of all screens combined. Overlapping areas + * are not counted multiple times. + * @see geometryChanged() + **/ + QRect geometry() const; + /** + * @returns size of the @p screen. + * + * To get the size of all screens combined use size(). + * @see size() + **/ + virtual QSize size(int screen) const = 0; + /** + * The bounding size of all screens combined. Overlapping areas + * are not counted multiple times. + * + * @see geometry() + * @see sizeChanged() + **/ + QSize size() const; virtual int number(const QPoint &pos) const = 0; inline bool isChanging() { return m_changedTimer->isActive(); } @@ -80,18 +101,42 @@ Q_SIGNALS: **/ void changed(); void currentChanged(); + /** + * Emitted when the geometry of all screens combined changes. + * Not emitted when the geometry of an individual screen changes. + * @see geometry() + **/ + void geometryChanged(); + /** + * Emitted when the size of all screens combined changes. + * Not emitted when the size of an individual screen changes. + * @see size() + **/ + void sizeChanged(); protected Q_SLOTS: void setCount(int count); void startChangedTimer(); virtual void updateCount() = 0; +protected: + /** + * Called once the singleton instance has been created. + * Any initialization code should go into this method. Overriding classes have to call + * the base implementation first. + **/ + virtual void init(); + +private Q_SLOTS: + void updateSize(); + private: int m_count; int m_current; bool m_currentFollowsMouse; QTimer *m_changedTimer; KSharedConfig::Ptr m_config; + QSize m_boundingSize; KWIN_SINGLETON(Screens) }; @@ -102,8 +147,10 @@ class DesktopWidgetScreens : public Screens public: DesktopWidgetScreens(QObject *parent); virtual ~DesktopWidgetScreens(); + void init() override; virtual QRect geometry(int screen) const; virtual int number(const QPoint &pos) const; + QSize size(int screen) const override; protected Q_SLOTS: void updateCount(); @@ -135,6 +182,18 @@ void Screens::startChangedTimer() m_changedTimer->start(); } +inline +QSize Screens::size() const +{ + return m_boundingSize; +} + +inline +QRect Screens::geometry() const +{ + return QRect(QPoint(0,0), size()); +} + inline Screens *screens() { diff --git a/scripting/workspace_wrapper.cpp b/scripting/workspace_wrapper.cpp index b452249fbd..d42222543f 100644 --- a/scripting/workspace_wrapper.cpp +++ b/scripting/workspace_wrapper.cpp @@ -55,6 +55,8 @@ WorkspaceWrapper::WorkspaceWrapper(QObject* parent) : QObject(parent) connect(activities, SIGNAL(removed(QString)), SIGNAL(activitiesChanged(QString))); connect(activities, SIGNAL(removed(QString)), SIGNAL(activityRemoved(QString))); #endif + connect(screens(), &Screens::sizeChanged, this, &WorkspaceWrapper::virtualScreenSizeChanged); + connect(screens(), &Screens::geometryChanged, this, &WorkspaceWrapper::virtualScreenGeometryChanged); connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), SIGNAL(numberScreensChanged(int))); connect(QApplication::desktop(), SIGNAL(resized(int)), SIGNAL(screenResized(int))); foreach (KWin::Client *client, ws->clientList()) { @@ -297,4 +299,14 @@ int WorkspaceWrapper::activeScreen() const return screens()->current(); } +QRect WorkspaceWrapper::virtualScreenGeometry() const +{ + return screens()->geometry(); +} + +QSize WorkspaceWrapper::virtualScreenSize() const +{ + return screens()->size(); +} + } // KWin diff --git a/scripting/workspace_wrapper.h b/scripting/workspace_wrapper.h index 5f3d3d6f35..0d742ea298 100644 --- a/scripting/workspace_wrapper.h +++ b/scripting/workspace_wrapper.h @@ -53,20 +53,35 @@ class WorkspaceWrapper : public QObject Q_PROPERTY(int desktops READ numberOfDesktops WRITE setNumberOfDesktops NOTIFY numberDesktopsChanged) /** * The same of the display, that is all screens. + * @deprecated since 5.0 use virtualScreenSize **/ Q_PROPERTY(QSize displaySize READ displaySize) /** * The width of the display, that is width of all combined screens. + * @deprecated since 5.0 use virtualScreenSize **/ Q_PROPERTY(int displayWidth READ displayWidth) /** * The height of the display, that is height of all combined screens. + * @deprecated since 5.0 use virtualScreenSize **/ Q_PROPERTY(int displayHeight READ displayHeight) Q_PROPERTY(int activeScreen READ activeScreen) Q_PROPERTY(int numScreens READ numScreens NOTIFY numberScreensChanged) Q_PROPERTY(QString currentActivity READ currentActivity NOTIFY currentActivityChanged) Q_PROPERTY(QStringList activities READ activityList NOTIFY activitiesChanged) + /** + * The bounding size of all screens combined. Overlapping areas + * are not counted multiple times. + * @see virtualScreenGeometry + **/ + Q_PROPERTY(QSize virtualScreenSize READ virtualScreenSize NOTIFY virtualScreenSizeChanged) + /** + * The bounding geometry of all outputs combined. Always starts at (0,0) and has + * virtualScreenSize as it's size. + * @see virtualScreenSize + **/ + Q_PROPERTY(QRect virtualScreenGeometry READ virtualScreenGeometry NOTIFY virtualScreenGeometryChanged) private: Q_DISABLE_COPY(WorkspaceWrapper) @@ -134,6 +149,18 @@ Q_SIGNALS: * @param id id of the removed activity */ void activityRemoved(const QString &id); + /** + * Emitted whenever the virtualScreenSize changes. + * @see virtualScreenSize() + * @since 5.0 + **/ + void virtualScreenSizeChanged(); + /** + * Emitted whenever the virtualScreenGeometry changes. + * @see virtualScreenGeometry() + * @since 5.0 + **/ + void virtualScreenGeometryChanged(); public: //------------------------------------------------------------------ @@ -191,6 +218,8 @@ void setter( rettype val ); int numScreens() const; QString currentActivity() const; QStringList activityList() const; + QSize virtualScreenSize() const; + QRect virtualScreenGeometry() const; /** * List of Clients currently managed by KWin.