libkwineffects: Introduce EffectScreen

This provides the compositor a way to indicate what output is being
rendered. The effects such as the screenshot can check the provided
screen object in order to function as expected.
This commit is contained in:
Vlad Zahorodnii 2021-03-01 11:45:52 +02:00
parent b3e7031893
commit 38996d9725
14 changed files with 212 additions and 69 deletions

View file

@ -273,6 +273,21 @@ public:
KWin::SessionState sessionState() const override { KWin::SessionState sessionState() const override {
return KWin::SessionState::Normal; return KWin::SessionState::Normal;
} }
QList<KWin::EffectScreen *> screens() const override {
return {};
}
KWin::EffectScreen *screenAt(const QPoint &point) const override {
Q_UNUSED(point)
return nullptr;
}
KWin::EffectScreen *findScreen(const QString &name) const override {
Q_UNUSED(name)
return nullptr;
}
KWin::EffectScreen *findScreen(int screenId) const override {
Q_UNUSED(screenId)
return nullptr;
}
private: private:
bool m_animationsSuported = true; bool m_animationsSuported = true;

View file

@ -47,12 +47,12 @@ void TestScreenPaintData::testCtor()
QCOMPARE(data.rotationAngle(), 0.0); QCOMPARE(data.rotationAngle(), 0.0);
QCOMPARE(data.rotationOrigin(), QVector3D()); QCOMPARE(data.rotationOrigin(), QVector3D());
QCOMPARE(data.rotationAxis(), QVector3D(0.0, 0.0, 1.0)); QCOMPARE(data.rotationAxis(), QVector3D(0.0, 0.0, 1.0));
QCOMPARE(data.outputGeometry(), QRect()); QCOMPARE(data.screen(), nullptr);
} }
void TestScreenPaintData::testCopyCtor() void TestScreenPaintData::testCopyCtor()
{ {
ScreenPaintData data(QMatrix4x4(), QRect(10, 20, 30, 40)); ScreenPaintData data;
ScreenPaintData data2(data); ScreenPaintData data2(data);
// no value had been changed // no value had been changed
QCOMPARE(data2.xScale(), 1.0); QCOMPARE(data2.xScale(), 1.0);
@ -65,7 +65,6 @@ void TestScreenPaintData::testCopyCtor()
QCOMPARE(data2.rotationAngle(), 0.0); QCOMPARE(data2.rotationAngle(), 0.0);
QCOMPARE(data2.rotationOrigin(), QVector3D()); QCOMPARE(data2.rotationOrigin(), QVector3D());
QCOMPARE(data2.rotationAxis(), QVector3D(0.0, 0.0, 1.0)); QCOMPARE(data2.rotationAxis(), QVector3D(0.0, 0.0, 1.0));
QCOMPARE(data2.outputGeometry(), QRect(10, 20, 30, 40));
data2.setScale(QVector3D(0.5, 2.0, 3.0)); data2.setScale(QVector3D(0.5, 2.0, 3.0));
data2.translate(0.5, 2.0, 3.0); data2.translate(0.5, 2.0, 3.0);
@ -89,14 +88,13 @@ void TestScreenPaintData::testCopyCtor()
void TestScreenPaintData::testAssignmentOperator() void TestScreenPaintData::testAssignmentOperator()
{ {
ScreenPaintData data; ScreenPaintData data;
ScreenPaintData data2(QMatrix4x4(), QRect(10, 20, 30, 40)); ScreenPaintData data2;
data2.setScale(QVector3D(0.5, 2.0, 3.0)); data2.setScale(QVector3D(0.5, 2.0, 3.0));
data2.translate(0.5, 2.0, 3.0); data2.translate(0.5, 2.0, 3.0);
data2.setRotationAngle(45.0); data2.setRotationAngle(45.0);
data2.setRotationOrigin(QVector3D(1.0, 2.0, 3.0)); data2.setRotationOrigin(QVector3D(1.0, 2.0, 3.0));
data2.setRotationAxis(QVector3D(1.0, 1.0, 0.0)); data2.setRotationAxis(QVector3D(1.0, 1.0, 0.0));
QCOMPARE(data2.outputGeometry(), QRect(10, 20, 30, 40));
data = data2; data = data2;
// data and data2 should be the same // data and data2 should be the same
@ -110,7 +108,6 @@ void TestScreenPaintData::testAssignmentOperator()
QCOMPARE(data.rotationAngle(), 45.0); QCOMPARE(data.rotationAngle(), 45.0);
QCOMPARE(data.rotationOrigin(), QVector3D(1.0, 2.0, 3.0)); QCOMPARE(data.rotationOrigin(), QVector3D(1.0, 2.0, 3.0));
QCOMPARE(data.rotationAxis(), QVector3D(1.0, 1.0, 0.0)); QCOMPARE(data.rotationAxis(), QVector3D(1.0, 1.0, 0.0));
QCOMPARE(data.outputGeometry(), QRect(10, 20, 30, 40));
// data 2 // data 2
QCOMPARE(data2.xScale(), 0.5); QCOMPARE(data2.xScale(), 0.5);
QCOMPARE(data2.yScale(), 2.0); QCOMPARE(data2.yScale(), 2.0);

View file

@ -10,6 +10,7 @@
#include "effects.h" #include "effects.h"
#include "abstract_output.h"
#include "effectsadaptor.h" #include "effectsadaptor.h"
#include "effectloader.h" #include "effectloader.h"
#ifdef KWIN_BUILD_ACTIVITIES #ifdef KWIN_BUILD_ACTIVITIES
@ -189,9 +190,9 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
&KWin::EffectsHandler::sessionStateChanged); &KWin::EffectsHandler::sessionStateChanged);
connect(vds, &VirtualDesktopManager::countChanged, this, &EffectsHandler::numberDesktopsChanged); connect(vds, &VirtualDesktopManager::countChanged, this, &EffectsHandler::numberDesktopsChanged);
connect(Cursors::self()->mouse(), &Cursor::mouseChanged, this, &EffectsHandler::mouseChanged); connect(Cursors::self()->mouse(), &Cursor::mouseChanged, this, &EffectsHandler::mouseChanged);
connect(screens(), &Screens::countChanged, this, &EffectsHandler::numberScreensChanged); connect(Screens::self(), &Screens::countChanged, this, &EffectsHandler::numberScreensChanged);
connect(screens(), &Screens::sizeChanged, this, &EffectsHandler::virtualScreenSizeChanged); connect(Screens::self(), &Screens::sizeChanged, this, &EffectsHandler::virtualScreenSizeChanged);
connect(screens(), &Screens::geometryChanged, this, &EffectsHandler::virtualScreenGeometryChanged); connect(Screens::self(), &Screens::geometryChanged, this, &EffectsHandler::virtualScreenGeometryChanged);
#ifdef KWIN_BUILD_ACTIVITIES #ifdef KWIN_BUILD_ACTIVITIES
if (Activities *activities = Activities::self()) { if (Activities *activities = Activities::self()) {
connect(activities, &Activities::added, this, &EffectsHandler::activityAdded); connect(activities, &Activities::added, this, &EffectsHandler::activityAdded);
@ -251,6 +252,14 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
setupClientConnections(client); setupClientConnections(client);
} }
connect(kwinApp()->platform(), &Platform::outputEnabled, this, &EffectsHandlerImpl::slotOutputEnabled);
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &EffectsHandlerImpl::slotOutputDisabled);
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
for (AbstractOutput *output : outputs) {
slotOutputEnabled(output);
}
reconfigure(); reconfigure();
} }
@ -977,12 +986,12 @@ int EffectsHandlerImpl::desktopGridHeight() const
int EffectsHandlerImpl::workspaceWidth() const int EffectsHandlerImpl::workspaceWidth() const
{ {
return desktopGridWidth() * screens()->size().width(); return desktopGridWidth() * Screens::self()->size().width();
} }
int EffectsHandlerImpl::workspaceHeight() const int EffectsHandlerImpl::workspaceHeight() const
{ {
return desktopGridHeight() * screens()->size().height(); return desktopGridHeight() * Screens::self()->size().height();
} }
int EffectsHandlerImpl::desktopAtCoords(QPoint coords) const int EffectsHandlerImpl::desktopAtCoords(QPoint coords) const
@ -1003,7 +1012,7 @@ QPoint EffectsHandlerImpl::desktopCoords(int id) const
QPoint coords = VirtualDesktopManager::self()->grid().gridCoords(id); QPoint coords = VirtualDesktopManager::self()->grid().gridCoords(id);
if (coords.x() == -1) if (coords.x() == -1)
return QPoint(-1, -1); return QPoint(-1, -1);
const QSize displaySize = screens()->size(); const QSize displaySize = Screens::self()->size();
return QPoint(coords.x() * displaySize.width(), coords.y() * displaySize.height()); return QPoint(coords.x() * displaySize.width(), coords.y() * displaySize.height());
} }
@ -1208,17 +1217,17 @@ void EffectsHandlerImpl::addRepaint(int x, int y, int w, int h)
int EffectsHandlerImpl::activeScreen() const int EffectsHandlerImpl::activeScreen() const
{ {
return screens()->current(); return Screens::self()->current();
} }
int EffectsHandlerImpl::numScreens() const int EffectsHandlerImpl::numScreens() const
{ {
return screens()->count(); return Screens::self()->count();
} }
int EffectsHandlerImpl::screenNumber(const QPoint& pos) const int EffectsHandlerImpl::screenNumber(const QPoint& pos) const
{ {
return screens()->number(pos); return Screens::self()->number(pos);
} }
QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, int screen, int desktop) const QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, int screen, int desktop) const
@ -1243,12 +1252,12 @@ QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, const QPoint& p, int
QRect EffectsHandlerImpl::virtualScreenGeometry() const QRect EffectsHandlerImpl::virtualScreenGeometry() const
{ {
return screens()->geometry(); return Screens::self()->geometry();
} }
QSize EffectsHandlerImpl::virtualScreenSize() const QSize EffectsHandlerImpl::virtualScreenSize() const
{ {
return screens()->size(); return Screens::self()->size();
} }
void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape) void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape)
@ -1697,6 +1706,81 @@ SessionState EffectsHandlerImpl::sessionState() const
return Workspace::self()->sessionManager()->state(); return Workspace::self()->sessionManager()->state();
} }
QList<EffectScreen *> EffectsHandlerImpl::screens() const
{
return m_effectScreens;
}
EffectScreen *EffectsHandlerImpl::screenAt(const QPoint &point) const
{
return m_effectScreens.value(screenNumber(point));
}
EffectScreen *EffectsHandlerImpl::findScreen(const QString &name) const
{
for (EffectScreen *screen : qAsConst(m_effectScreens)) {
if (screen->name() == name) {
return screen;
}
}
return nullptr;
}
EffectScreen *EffectsHandlerImpl::findScreen(int screenId) const
{
return m_effectScreens.value(screenId);
}
void EffectsHandlerImpl::slotOutputEnabled(AbstractOutput *output)
{
EffectScreen *screen = new EffectScreenImpl(output, this);
m_effectScreens.append(screen);
emit screenAdded(screen);
}
void EffectsHandlerImpl::slotOutputDisabled(AbstractOutput *output)
{
auto it = std::find_if(m_effectScreens.begin(), m_effectScreens.end(), [&output](EffectScreen *screen) {
return static_cast<EffectScreenImpl *>(screen)->platformOutput() == output;
});
if (it != m_effectScreens.end()) {
EffectScreen *screen = *it;
m_effectScreens.erase(it);
emit screenRemoved(screen);
delete screen;
}
}
//****************************************
// EffectScreenImpl
//****************************************
EffectScreenImpl::EffectScreenImpl(AbstractOutput *output, QObject *parent)
: EffectScreen(parent)
, m_platformOutput(output)
{
}
AbstractOutput *EffectScreenImpl::platformOutput() const
{
return m_platformOutput;
}
QString EffectScreenImpl::name() const
{
return m_platformOutput->name();
}
qreal EffectScreenImpl::devicePixelRatio() const
{
return m_platformOutput->scale();
}
QRect EffectScreenImpl::geometry() const
{
return m_platformOutput->geometry();
}
//**************************************** //****************************************
// EffectWindowImpl // EffectWindowImpl
//**************************************** //****************************************

View file

@ -267,6 +267,10 @@ public:
void renderEffectQuickView(EffectQuickView *effectQuickView) const override; void renderEffectQuickView(EffectQuickView *effectQuickView) const override;
SessionState sessionState() const override; SessionState sessionState() const override;
QList<EffectScreen *> screens() const override;
EffectScreen *screenAt(const QPoint &point) const override;
EffectScreen *findScreen(const QString &name) const override;
EffectScreen *findScreen(int screenId) const override;
public Q_SLOTS: public Q_SLOTS:
void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to); void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
@ -295,6 +299,8 @@ protected Q_SLOTS:
void slotFrameGeometryChanged(Toplevel *toplevel, const QRect &oldGeometry); void slotFrameGeometryChanged(Toplevel *toplevel, const QRect &oldGeometry);
void slotPaddingChanged(KWin::Toplevel *t, const QRect &old); void slotPaddingChanged(KWin::Toplevel *t, const QRect &old);
void slotWindowDamaged(KWin::Toplevel *t, const QRegion& r); void slotWindowDamaged(KWin::Toplevel *t, const QRegion& r);
void slotOutputEnabled(AbstractOutput *output);
void slotOutputDisabled(AbstractOutput *output);
protected: protected:
void connectNotify(const QMetaMethod &signal) override; void connectNotify(const QMetaMethod &signal) override;
@ -357,6 +363,24 @@ private:
EffectLoader *m_effectLoader; EffectLoader *m_effectLoader;
int m_trackingCursorChanges; int m_trackingCursorChanges;
std::unique_ptr<WindowPropertyNotifyX11Filter> m_x11WindowPropertyNotify; std::unique_ptr<WindowPropertyNotifyX11Filter> m_x11WindowPropertyNotify;
QList<EffectScreen *> m_effectScreens;
};
class EffectScreenImpl : public EffectScreen
{
Q_OBJECT
public:
explicit EffectScreenImpl(AbstractOutput *output, QObject *parent = nullptr);
AbstractOutput *platformOutput() const;
QString name() const override;
qreal devicePixelRatio() const override;
QRect geometry() const override;
private:
AbstractOutput *m_platformOutput;
}; };
class EffectWindowImpl : public EffectWindow class EffectWindowImpl : public EffectWindow

View file

@ -52,7 +52,7 @@ ColorPickerEffect::~ColorPickerEffect() = default;
void ColorPickerEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData &data) void ColorPickerEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData &data)
{ {
m_cachedOutputGeometry = data.outputGeometry(); m_paintedScreen = data.screen();
effects->paintScreen(mask, region, data); effects->paintScreen(mask, region, data);
} }
@ -60,7 +60,7 @@ void ColorPickerEffect::postPaintScreen()
{ {
effects->postPaintScreen(); effects->postPaintScreen();
if (m_scheduledPosition != QPoint(-1, -1) && (m_cachedOutputGeometry.isEmpty() || m_cachedOutputGeometry.contains(m_scheduledPosition))) { if (m_scheduledPosition != QPoint(-1, -1) && (!m_paintedScreen || m_paintedScreen->geometry().contains(m_scheduledPosition))) {
uint8_t data[3]; uint8_t data[3];
const QRect geo = GLRenderTarget::virtualScreenGeometry(); const QRect geo = GLRenderTarget::virtualScreenGeometry();
const QPoint screenPosition(m_scheduledPosition.x() - geo.x(), m_scheduledPosition.y() - geo.y()); const QPoint screenPosition(m_scheduledPosition.x() - geo.x(), m_scheduledPosition.y() - geo.y());

View file

@ -44,7 +44,7 @@ private:
void hideInfoMessage(); void hideInfoMessage();
QDBusMessage m_replyMessage; QDBusMessage m_replyMessage;
QRect m_cachedOutputGeometry; EffectScreen *m_paintedScreen = nullptr;
QPoint m_scheduledPosition; QPoint m_scheduledPosition;
bool m_picking = false; bool m_picking = false;
}; };

View file

@ -179,10 +179,7 @@ static xcb_pixmap_t xpixmapFromImage(const QImage &image)
void ScreenShotEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData &data) void ScreenShotEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData &data)
{ {
m_cachedOutputGeometry = data.outputGeometry(); m_paintedScreen = data.screen();
// When taking a non-nativeSize fullscreenshot, pretend we have a uniform 1.0 ratio
// so the screenshot size will match the virtualGeometry
m_cachedScale = m_nativeSize ? data.screenScale() : 1.0;
effects->paintScreen(mask, region, data); effects->paintScreen(mask, region, data);
} }
@ -340,22 +337,23 @@ void ScreenShotEffect::postPaintScreen()
} }
if (!m_scheduledGeometry.isNull()) { if (!m_scheduledGeometry.isNull()) {
if (!m_cachedOutputGeometry.isNull()) { if (m_paintedScreen) {
// special handling for per-output geometry rendering // special handling for per-output geometry rendering
const QRect intersection = m_scheduledGeometry.intersected(m_cachedOutputGeometry); const QRect intersection = m_scheduledGeometry.intersected(m_paintedScreen->geometry());
if (intersection.isEmpty()) { if (intersection.isEmpty()) {
// doesn't intersect, not going onto this screenshot // doesn't intersect, not going onto this screenshot
return; return;
} }
QImage img = blitScreenshot(intersection, m_cachedScale); const qreal devicePixelRatio = m_nativeSize ? m_paintedScreen->devicePixelRatio() : 1.0;
if (img.size() == (m_scheduledGeometry.size() * m_cachedScale)) { QImage img = blitScreenshot(intersection, devicePixelRatio);
if (img.size() == (m_scheduledGeometry.size() * devicePixelRatio)) {
// we are done // we are done
sendReplyImage(img); sendReplyImage(img);
return; return;
} }
img.setDevicePixelRatio(m_cachedScale); img.setDevicePixelRatio(devicePixelRatio);
m_cacheOutputsImages.insert(ComparableQPoint(m_cachedOutputGeometry.topLeft()), img); m_cacheOutputsImages.insert(ComparableQPoint(m_paintedScreen->geometry().topLeft()), img);
m_multipleOutputsRendered = m_multipleOutputsRendered.united(intersection); m_multipleOutputsRendered = m_multipleOutputsRendered.united(intersection);
if (m_multipleOutputsRendered.boundingRect() == m_scheduledGeometry) { if (m_multipleOutputsRendered.boundingRect() == m_scheduledGeometry) {
@ -460,7 +458,6 @@ void ScreenShotEffect::clearState()
m_captureCursor = false; m_captureCursor = false;
m_windowMode = WindowMode::NoCapture; m_windowMode = WindowMode::NoCapture;
m_cacheOutputsImages.clear(); m_cacheOutputsImages.clear();
m_cachedOutputGeometry = QRect();
m_nativeSize = false; m_nativeSize = false;
m_orderImg.clear(); m_orderImg.clear();
} }

View file

@ -164,7 +164,6 @@ private:
ScreenShotType m_type; ScreenShotType m_type;
QRect m_scheduledGeometry; QRect m_scheduledGeometry;
QDBusMessage m_replyMessage; QDBusMessage m_replyMessage;
QRect m_cachedOutputGeometry;
QRegion m_multipleOutputsRendered; QRegion m_multipleOutputsRendered;
QMap<ComparableQPoint, QImage> m_cacheOutputsImages; QMap<ComparableQPoint, QImage> m_cacheOutputsImages;
QList<QPoint> m_orderImg; QList<QPoint> m_orderImg;
@ -178,7 +177,7 @@ private:
}; };
WindowMode m_windowMode = WindowMode::NoCapture; WindowMode m_windowMode = WindowMode::NoCapture;
int m_fd = -1; int m_fd = -1;
qreal m_cachedScale; EffectScreen *m_paintedScreen = nullptr;
}; };
} // namespace } // namespace

View file

@ -422,8 +422,7 @@ class ScreenPaintData::Private
{ {
public: public:
QMatrix4x4 projectionMatrix; QMatrix4x4 projectionMatrix;
QRect outputGeometry; EffectScreen *screen = nullptr;
qreal screenScale;
}; };
ScreenPaintData::ScreenPaintData() ScreenPaintData::ScreenPaintData()
@ -432,13 +431,12 @@ ScreenPaintData::ScreenPaintData()
{ {
} }
ScreenPaintData::ScreenPaintData(const QMatrix4x4 &projectionMatrix, const QRect &outputGeometry, const qreal screenScale) ScreenPaintData::ScreenPaintData(const QMatrix4x4 &projectionMatrix, EffectScreen *screen)
: PaintData() : PaintData()
, d(new Private()) , d(new Private())
{ {
d->projectionMatrix = projectionMatrix; d->projectionMatrix = projectionMatrix;
d->outputGeometry = outputGeometry; d->screen = screen;
d->screenScale = screenScale;
} }
ScreenPaintData::~ScreenPaintData() = default; ScreenPaintData::~ScreenPaintData() = default;
@ -455,7 +453,7 @@ ScreenPaintData::ScreenPaintData(const ScreenPaintData &other)
setRotationAxis(other.rotationAxis()); setRotationAxis(other.rotationAxis());
setRotationAngle(other.rotationAngle()); setRotationAngle(other.rotationAngle());
d->projectionMatrix = other.d->projectionMatrix; d->projectionMatrix = other.d->projectionMatrix;
d->outputGeometry = other.d->outputGeometry; d->screen = other.d->screen;
} }
ScreenPaintData &ScreenPaintData::operator=(const ScreenPaintData &rhs) ScreenPaintData &ScreenPaintData::operator=(const ScreenPaintData &rhs)
@ -470,7 +468,7 @@ ScreenPaintData &ScreenPaintData::operator=(const ScreenPaintData &rhs)
setRotationAxis(rhs.rotationAxis()); setRotationAxis(rhs.rotationAxis());
setRotationAngle(rhs.rotationAngle()); setRotationAngle(rhs.rotationAngle());
d->projectionMatrix = rhs.d->projectionMatrix; d->projectionMatrix = rhs.d->projectionMatrix;
d->outputGeometry = rhs.d->outputGeometry; d->screen = rhs.d->screen;
return *this; return *this;
} }
@ -523,14 +521,9 @@ QMatrix4x4 ScreenPaintData::projectionMatrix() const
return d->projectionMatrix; return d->projectionMatrix;
} }
QRect ScreenPaintData::outputGeometry() const EffectScreen *ScreenPaintData::screen() const
{ {
return d->outputGeometry; return d->screen;
}
qreal ScreenPaintData::screenScale() const
{
return d->screenScale;
} }
//**************************************** //****************************************
@ -763,6 +756,10 @@ bool EffectsHandler::isOpenGLCompositing() const
EffectsHandler* effects = nullptr; EffectsHandler* effects = nullptr;
EffectScreen::EffectScreen(QObject *parent)
: QObject(parent)
{
}
//**************************************** //****************************************
// EffectWindow // EffectWindow

View file

@ -69,6 +69,7 @@ class EffectWindowGroup;
class EffectFrame; class EffectFrame;
class EffectFramePrivate; class EffectFramePrivate;
class EffectQuickView; class EffectQuickView;
class EffectScreen;
class Effect; class Effect;
class WindowQuad; class WindowQuad;
class GLShader; class GLShader;
@ -174,7 +175,7 @@ X-KDE-Library=kwin4_effect_cooleffect
#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0 #define KWIN_EFFECT_API_VERSION_MAJOR 0
#define KWIN_EFFECT_API_VERSION_MINOR 232 #define KWIN_EFFECT_API_VERSION_MINOR 233
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
@ -1378,7 +1379,24 @@ public:
* @since 5.18 * @since 5.18
*/ */
virtual SessionState sessionState() const = 0; virtual SessionState sessionState() const = 0;
/**
* Returns the list of all the screens connected to the system.
*/
virtual QList<EffectScreen *> screens() const = 0;
virtual EffectScreen *screenAt(const QPoint &point) const = 0;
virtual EffectScreen *findScreen(const QString &name) const = 0;
virtual EffectScreen *findScreen(int screenId) const = 0;
Q_SIGNALS: Q_SIGNALS:
/**
* This signal is emitted whenever a new @a screen is added to the system.
*/
void screenAdded(KWin::EffectScreen *screen);
/**
* This signal is emitted whenever a @a screen is removed from the system.
*/
void screenRemoved(KWin::EffectScreen *screen);
/** /**
* Signal emitted when the current desktop changed. * Signal emitted when the current desktop changed.
* @param oldDesktop The previously current desktop * @param oldDesktop The previously current desktop
@ -1833,6 +1851,31 @@ protected:
CompositingType compositing_type; CompositingType compositing_type;
}; };
/**
* The EffectScreen class represents a screen used by/for Effect classes.
*/
class KWINEFFECTS_EXPORT EffectScreen : public QObject
{
Q_OBJECT
public:
explicit EffectScreen(QObject *parent = nullptr);
/**
* Returns the name of the screen, e.g. "DP-1".
*/
virtual QString name() const = 0;
/**
* Returns the screen's ratio between physical pixels and device-independent pixels.
*/
virtual qreal devicePixelRatio() const = 0;
/**
* Returns the screen's geometry in the device-independent pixels.
*/
virtual QRect geometry() const = 0;
};
/** /**
* @short Representation of a window used by/for Effect classes. * @short Representation of a window used by/for Effect classes.
@ -3000,7 +3043,7 @@ class KWINEFFECTS_EXPORT ScreenPaintData : public PaintData
{ {
public: public:
ScreenPaintData(); ScreenPaintData();
ScreenPaintData(const QMatrix4x4 &projectionMatrix, const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0); ScreenPaintData(const QMatrix4x4 &projectionMatrix, EffectScreen *screen = nullptr);
ScreenPaintData(const ScreenPaintData &other); ScreenPaintData(const ScreenPaintData &other);
~ScreenPaintData() override; ~ScreenPaintData() override;
/** /**
@ -3054,21 +3097,10 @@ public:
QMatrix4x4 projectionMatrix() const; QMatrix4x4 projectionMatrix() const;
/** /**
* The geometry of the currently rendered output. * Returns the currently rendered screen. Only set for per-screen rendering, e.g. Wayland.
* Only set for per-output rendering (e.g. Wayland).
*
* This geometry can be used as a hint about the native window the OpenGL context
* is bound. OpenGL calls need to be translated to this geometry.
* @since 5.9
*/ */
QRect outputGeometry() const; EffectScreen *screen() const;
/**
* The scale factor for the output
*
* @since 5.19
*/
qreal screenScale() const;
private: private:
class Private; class Private;
QScopedPointer<Private> d; QScopedPointer<Private> d;

View file

@ -67,7 +67,7 @@ void EffectsHandlerImplX11::doStartMouseInterception(Qt::CursorShape shape)
// NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h // 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 // The mouse grab is implemented by using a full screen input only window
if (!m_mouseInterceptionWindow.isValid()) { if (!m_mouseInterceptionWindow.isValid()) {
const QSize &s = screens()->size(); const QSize &s = Screens::self()->size();
const QRect geo(0, 0, s.width(), s.height()); const QRect geo(0, 0, s.width(), s.height());
const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
const uint32_t values[] = { const uint32_t values[] = {

View file

@ -675,7 +675,7 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
updateProjectionMatrix(); updateProjectionMatrix();
paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid, paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid,
renderLoop, projectionMatrix(), geo, scaling); // call generic implementation renderLoop, projectionMatrix()); // call generic implementation
paintCursor(valid); paintCursor(valid);
if (!GLPlatform::instance()->isGLES() && screenId == -1) { if (!GLPlatform::instance()->isGLES() && screenId == -1) {

View file

@ -147,8 +147,7 @@ void Scene::reallocRepaints()
// returns mask and possibly modified region // returns mask and possibly modified region
void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint, void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop, QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop,
const QMatrix4x4 &projection, const QRect &outputGeometry, const QMatrix4x4 &projection)
qreal screenScale)
{ {
const QSize &screenSize = screens()->size(); const QSize &screenSize = screens()->size();
const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height());
@ -193,7 +192,7 @@ void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint
painted_region = region; painted_region = region;
repaint_region = repaint; repaint_region = repaint;
ScreenPaintData data(projection, outputGeometry, screenScale); ScreenPaintData data(projection, effects->findScreen(painted_screen));
effects->paintScreen(*mask, region, data); effects->paintScreen(*mask, region, data);
foreach (Window *w, stacking_order) { foreach (Window *w, stacking_order) {

View file

@ -210,8 +210,7 @@ protected:
// shared implementation, starts painting the screen // shared implementation, starts painting the screen
void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint, void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop, QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop,
const QMatrix4x4 &projection = QMatrix4x4(), const QMatrix4x4 &projection = QMatrix4x4());
const QRect &outputGeometry = QRect(), qreal screenScale = 1.0);
// Render cursor texture in case hardware cursor is disabled/non-applicable // Render cursor texture in case hardware cursor is disabled/non-applicable
virtual void paintCursor(const QRegion &region) = 0; virtual void paintCursor(const QRegion &region) = 0;
friend class EffectsHandlerImpl; friend class EffectsHandlerImpl;