Drop Screens::geometry() and Screens::size()

Currently, the main user of these two functions is the X11 standalone
platform.

This change ports that code to Workspace::geometry(), which is not great
but the X11 backend already depends on the Workspace indirectly via the
Screens. Not sure if it's worth making the standalone X11 backend track
the xinerama rect internally.
This commit is contained in:
Vlad Zahorodnii 2022-08-26 10:04:21 +03:00
parent 1baa267127
commit 070f63c451
9 changed files with 27 additions and 113 deletions

View file

@ -32,8 +32,6 @@ private Q_SLOTS:
void initTestCase();
void init();
void cleanup();
void testSize_data();
void testSize();
void testCurrent_data();
void testCurrent();
void testCurrentWithFollowsMouse_data();
@ -92,31 +90,6 @@ void ScreensTest::cleanup()
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
}
void ScreensTest::testSize_data()
{
QTest::addColumn<QVector<QRect>>("geometries");
QTest::addColumn<QSize>("expectedSize");
QTest::newRow("empty") << QVector<QRect>{{QRect()}} << QSize(0, 0);
QTest::newRow("cloned") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QSize(200, 100);
QTest::newRow("adjacent") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QSize(600, 400);
QTest::newRow("overlapping") << QVector<QRect>{{QRect{-10, -20, 50, 100}, QRect{0, 0, 100, 200}}} << QSize(110, 220);
QTest::newRow("gap") << QVector<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QSize(30, 60);
}
void ScreensTest::testSize()
{
QSignalSpy sizeChangedSpy(workspace()->screens(), &Screens::sizeChanged);
QVERIFY(sizeChangedSpy.isValid());
QFETCH(QVector<QRect>, geometries);
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection,
Q_ARG(int, geometries.count()), Q_ARG(QVector<QRect>, geometries));
QVERIFY(sizeChangedSpy.wait());
QTEST(workspace()->screens()->size(), "expectedSize");
}
void ScreensTest::testCurrent_data()
{
QTest::addColumn<int>("currentId");

View file

@ -10,7 +10,6 @@
#include "x11_standalone_effects.h"
#include "cursor.h"
#include "screenedge.h"
#include "screens.h"
#include "utils/common.h"
#include "workspace.h"
#include "x11_standalone_effects_mouse_interception_filter.h"
@ -66,7 +65,7 @@ void EffectsHandlerImplX11::doStartMouseInterception(Qt::CursorShape shape)
// NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h
// The mouse grab is implemented by using a full screen input only window
if (!m_mouseInterceptionWindow.isValid()) {
const QSize &s = workspace()->screens()->size();
const QSize &s = workspace()->geometry().size();
const QRect geo(0, 0, s.width(), s.height());
const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
const uint32_t values[] = {

View file

@ -12,7 +12,6 @@
#include "platform.h"
#include "renderloop_p.h"
#include "scene.h"
#include "screens.h"
#include "softwarevsyncmonitor.h"
#include "surfaceitem_x11.h"
#include "workspace.h"
@ -58,7 +57,7 @@ EglBackend::EglBackend(Display *display, X11StandalonePlatform *backend)
m_vsyncMonitor->setRefreshRate(backend->renderLoop()->refreshRate());
connect(m_vsyncMonitor.get(), &VsyncMonitor::vblankOccurred, this, &EglBackend::vblank);
connect(workspace()->screens(), &Screens::sizeChanged, this, &EglBackend::screenGeometryChanged);
connect(workspace(), &Workspace::geometryChanged, this, &EglBackend::screenGeometryChanged);
}
EglBackend::~EglBackend()
@ -107,7 +106,7 @@ void EglBackend::init()
return;
}
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->screens()->size());
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->geometry().size());
kwinApp()->platform()->setSceneEglDisplay(shareDisplay);
kwinApp()->platform()->setSceneEglGlobalShareContext(shareContext);
@ -116,11 +115,11 @@ void EglBackend::init()
void EglBackend::screenGeometryChanged()
{
overlayWindow()->resize(workspace()->screens()->size());
overlayWindow()->resize(workspace()->geometry().size());
// The back buffer contents are now undefined
m_bufferAge = 0;
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->screens()->size());
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->geometry().size());
}
OutputLayerBeginFrameInfo EglBackend::beginFrame()
@ -160,19 +159,19 @@ void EglBackend::present(Output *output)
QRegion effectiveRenderedRegion = m_lastRenderedRegion;
if (!GLPlatform::instance()->isGLES()) {
const QRegion displayRegion(workspace()->screens()->geometry());
if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRegion) {
const QRect displayRect = workspace()->geometry();
if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRect) {
glReadBuffer(GL_FRONT);
copyPixels(displayRegion - m_lastRenderedRegion);
copyPixels(QRegion(displayRect) - m_lastRenderedRegion, displayRect.size());
glReadBuffer(GL_BACK);
effectiveRenderedRegion = displayRegion;
effectiveRenderedRegion = displayRect;
}
}
// Pop the default render target from the render target stack.
GLFramebuffer::popFramebuffer();
presentSurface(surface(), effectiveRenderedRegion, workspace()->screens()->geometry());
presentSurface(surface(), effectiveRenderedRegion, workspace()->geometry());
if (overlayWindow() && overlayWindow()->window()) { // show the window only after the first pass,
overlayWindow()->show(); // since that pass may take long

View file

@ -28,7 +28,6 @@
#include "platform.h"
#include "renderloop_p.h"
#include "scene.h"
#include "screens.h"
#include "surfaceitem_x11.h"
#include "utils/xcbutils.h"
#include "workspace.h"
@ -137,7 +136,7 @@ GlxBackend::GlxBackend(Display *display, X11StandalonePlatform *backend)
// by Mesa when using DRI2.
QOpenGLContext::supportsThreadedOpenGL();
connect(workspace()->screens(), &Screens::sizeChanged, this, &GlxBackend::screenGeometryChanged);
connect(workspace(), &Workspace::geometryChanged, this, &GlxBackend::screenGeometryChanged);
}
GlxBackend::~GlxBackend()
@ -227,7 +226,7 @@ void GlxBackend::init()
glPlatform->printResults();
initGL(&getProcAddress);
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->screens()->size());
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->geometry().size());
bool supportsSwapEvent = false;
@ -456,7 +455,7 @@ bool GlxBackend::initBuffer()
xcb_colormap_t colormap = xcb_generate_id(c);
xcb_create_colormap(c, false, colormap, rootWindow(), visual);
const QSize size = workspace()->screens()->size();
const QSize size = workspace()->geometry().size();
window = xcb_generate_id(c);
xcb_create_window(c, visualDepth(visual), window, overlayWindow()->window(),
@ -732,7 +731,7 @@ void GlxBackend::setSwapInterval(int interval)
void GlxBackend::present(const QRegion &damage)
{
const QSize &screenSize = workspace()->screens()->size();
const QSize &screenSize = workspace()->geometry().size();
const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height());
const bool fullRepaint = supportsBufferAge() || (damage == displayRegion);
@ -749,7 +748,7 @@ void GlxBackend::present(const QRegion &damage)
}
} else { // Copy Pixels (horribly slow on Mesa)
glDrawBuffer(GL_FRONT);
copyPixels(damage);
copyPixels(damage, screenSize);
glDrawBuffer(GL_BACK);
}
@ -761,7 +760,7 @@ void GlxBackend::present(const QRegion &damage)
void GlxBackend::screenGeometryChanged()
{
const QSize size = workspace()->screens()->size();
const QSize size = workspace()->geometry().size();
doneCurrent();
XMoveResizeWindow(display(), window, 0, 0, size.width(), size.height());
@ -815,14 +814,14 @@ void GlxBackend::present(Output *output)
m_vsyncMonitor->arm();
}
const QRegion displayRegion(workspace()->screens()->geometry());
const QRect displayRect = workspace()->geometry();
QRegion effectiveRenderedRegion = m_lastRenderedRegion;
if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRegion) {
if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRect) {
glReadBuffer(GL_FRONT);
copyPixels(displayRegion - m_lastRenderedRegion);
copyPixels(QRegion(displayRect) - m_lastRenderedRegion, displayRect.size());
glReadBuffer(GL_BACK);
effectiveRenderedRegion = displayRegion;
effectiveRenderedRegion = displayRect;
}
GLFramebuffer::popFramebuffer();

View file

@ -12,7 +12,6 @@
#include "composite.h"
#include "kwinglobals.h"
#include "scene.h"
#include "screens.h"
#include "utils/common.h"
#include "utils/xcbutils.h"
#include "workspace.h"
@ -58,7 +57,7 @@ bool OverlayWindowX11::create()
if (m_window == XCB_WINDOW_NONE) {
return false;
}
resize(workspace()->screens()->size());
resize(workspace()->geometry().size());
return true;
#else
return false;
@ -71,7 +70,7 @@ void OverlayWindowX11::setup(xcb_window_t window)
Q_ASSERT(Xcb::Extensions::self()->isShapeInputAvailable());
setNoneBackgroundPixmap(m_window);
m_shape = QRegion();
const QSize &s = workspace()->screens()->size();
const QSize &s = workspace()->geometry().size();
setShape(QRect(0, 0, s.width(), s.height()));
if (window != XCB_WINDOW_NONE) {
setNoneBackgroundPixmap(window);
@ -108,7 +107,7 @@ void OverlayWindowX11::hide()
Q_ASSERT(m_window != XCB_WINDOW_NONE);
xcb_unmap_window(connection(), m_window);
m_shown = false;
const QSize &s = workspace()->screens()->size();
const QSize &s = workspace()->geometry().size();
setShape(QRect(0, 0, s.width(), s.height()));
}
@ -152,7 +151,7 @@ void OverlayWindowX11::destroy()
return;
}
// reset the overlay shape
const QSize &s = workspace()->screens()->size();
const QSize &s = workspace()->geometry().size();
xcb_rectangle_t rec = {0, 0, static_cast<uint16_t>(s.width()), static_cast<uint16_t>(s.height())};
xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec);
xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec);

View file

@ -11,7 +11,6 @@
#include <kwineffects.h>
#include <kwinglutils_funcs.h>
#include "screens.h"
#include "surfaceitem.h"
#include "utils/common.h"
#include "workspace.h"
@ -45,9 +44,9 @@ void OpenGLBackend::setFailed(const QString &reason)
m_failed = true;
}
void OpenGLBackend::copyPixels(const QRegion &region)
void OpenGLBackend::copyPixels(const QRegion &region, const QSize &screenSize)
{
const int height = workspace()->screens()->size().height();
const int height = screenSize.height();
for (const QRect &r : region) {
const int x0 = r.x();
const int y0 = height - r.y() - r.height();

View file

@ -124,7 +124,7 @@ public:
/**
* Copy a region of pixels from the current read to the current draw buffer
*/
void copyPixels(const QRegion &region);
void copyPixels(const QRegion &region, const QSize &screenSize);
virtual std::shared_ptr<GLTexture> textureForOutput(Output *output) const;

View file

@ -30,19 +30,10 @@ Screens::Screens()
void Screens::init()
{
connect(this, &Screens::changed, this, &Screens::updateSize);
connect(this, &Screens::sizeChanged, this, &Screens::geometryChanged);
Q_EMIT changed();
}
QRect Screens::geometry(int screen) const
{
if (Output *output = findOutput(screen)) {
return output->geometry();
}
return QRect();
}
qreal Screens::scale(int screen) const
{
if (Output *output = findOutput(screen)) {
@ -58,16 +49,10 @@ qreal Screens::maxScale() const
void Screens::updateSize()
{
QRect bounding;
qreal maxScale = 1.0;
for (int i = 0; i < workspace()->outputs().count(); ++i) {
bounding = bounding.united(geometry(i));
maxScale = qMax(maxScale, scale(i));
}
if (m_boundingSize != bounding.size()) {
m_boundingSize = bounding.size();
Q_EMIT sizeChanged();
}
if (!qFuzzyCompare(m_maxScale, maxScale)) {
m_maxScale = maxScale;
Q_EMIT maxScaleChanged();
@ -79,14 +64,4 @@ Output *Screens::findOutput(int screen) const
return workspace()->outputs().value(screen);
}
QSize Screens::size() const
{
return m_boundingSize;
}
QRect Screens::geometry() const
{
return QRect(QPoint(0, 0), size());
}
} // namespace

View file

@ -35,14 +35,6 @@ public:
void init();
QRect geometry(int screen) const;
/**
* The bounding geometry of all screens combined. Overlapping areas
* are not counted multiple times.
* @see geometryChanged()
*/
QRect geometry() const;
/**
* The highest scale() of all connected screens
* for use when deciding what scale to load global assets at
@ -55,32 +47,12 @@ public:
* The output scale for this display, for use by high DPI displays
*/
qreal scale(int screen) const;
/**
* The bounding size of all screens combined. Overlapping areas
* are not counted multiple times.
*
* @see geometry()
* @see sizeChanged()
*/
QSize size() const;
Q_SIGNALS:
/**
* Emitted whenever the screens are changed either count or geometry.
*/
void changed();
/**
* 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();
/**
* Emitted when the maximum scale of all attached screens changes
* @see maxScale
@ -93,7 +65,6 @@ private Q_SLOTS:
private:
Output *findOutput(int screenId) const;
QSize m_boundingSize;
qreal m_maxScale;
};
}