[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
This commit is contained in:
Martin Gräßlin 2014-02-27 09:55:45 +01:00
parent aee20b4a5a
commit 6b1f0b1fca
7 changed files with 195 additions and 12 deletions

View file

@ -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()) {

View file

@ -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;

View file

@ -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;

View file

@ -30,7 +30,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
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())

View file

@ -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()
{

View file

@ -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

View file

@ -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.