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.