[scene] Introduce helpers for mapping between different coordinate spaces
We currently deal with three distinct coordinate spaces - the window pixmap coordinate space, the window coordinate space, and the buffer pixel coordinate space. This change introduces a couple of helper methods to make it easier to map points from the window pixmap space to the other two spaces. The main motivation behind the new helpers is to break the direct relationship between the surface-local coordinates and buffer pixel coordinates for wayland surfaces.
This commit is contained in:
parent
fe83cbf034
commit
9e797cf943
4 changed files with 72 additions and 83 deletions
|
@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*********************************************************************/
|
||||
#include "scene_qpainter.h"
|
||||
// KWin
|
||||
#include "x11client.h"
|
||||
#include "abstract_client.h"
|
||||
#include "composite.h"
|
||||
#include "cursor.h"
|
||||
#include "deleted.h"
|
||||
|
@ -228,37 +228,6 @@ SceneQPainter::Window::~Window()
|
|||
{
|
||||
}
|
||||
|
||||
static void paintSubSurface(QPainter *painter, const QPoint &pos, QPainterWindowPixmap *pixmap)
|
||||
{
|
||||
QPoint p = pos;
|
||||
if (!pixmap->subSurface().isNull()) {
|
||||
p += pixmap->subSurface()->position();
|
||||
}
|
||||
|
||||
painter->drawImage(QRect(pos, pixmap->size()), pixmap->image());
|
||||
const auto &children = pixmap->children();
|
||||
for (auto it = children.begin(); it != children.end(); ++it) {
|
||||
auto pixmap = static_cast<QPainterWindowPixmap*>(*it);
|
||||
if (pixmap->subSurface().isNull() || pixmap->subSurface()->surface().isNull() || !pixmap->subSurface()->surface()->isMapped()) {
|
||||
continue;
|
||||
}
|
||||
paintSubSurface(painter, p, pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isXwaylandClient(Toplevel *toplevel)
|
||||
{
|
||||
X11Client *client = qobject_cast<X11Client *>(toplevel);
|
||||
if (client) {
|
||||
return true;
|
||||
}
|
||||
Deleted *deleted = qobject_cast<Deleted *>(toplevel);
|
||||
if (deleted) {
|
||||
return deleted->wasX11Client();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const WindowPaintData &data)
|
||||
{
|
||||
QRegion region = _region;
|
||||
|
@ -299,28 +268,7 @@ void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const
|
|||
}
|
||||
renderShadow(painter);
|
||||
renderWindowDecorations(painter);
|
||||
|
||||
// render content
|
||||
QRect source;
|
||||
QRect target;
|
||||
if (isXwaylandClient(toplevel)) {
|
||||
// special case for XWayland windows
|
||||
source = QRect(toplevel->clientPos(), toplevel->clientSize());
|
||||
target = source;
|
||||
} else {
|
||||
source = pixmap->image().rect();
|
||||
target = toplevel->bufferGeometry().translated(-pos());
|
||||
}
|
||||
painter->drawImage(target, pixmap->image(), source);
|
||||
|
||||
// render subsurfaces
|
||||
const auto &children = pixmap->children();
|
||||
for (auto pixmap : children) {
|
||||
if (pixmap->subSurface().isNull() || pixmap->subSurface()->surface().isNull() || !pixmap->subSurface()->surface()->isMapped()) {
|
||||
continue;
|
||||
}
|
||||
paintSubSurface(painter, bufferOffset(), static_cast<QPainterWindowPixmap*>(pixmap));
|
||||
}
|
||||
renderWindowPixmap(painter, pixmap);
|
||||
|
||||
if (!opaque) {
|
||||
tempPainter.restore();
|
||||
|
@ -336,6 +284,30 @@ void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const
|
|||
painter->restore();
|
||||
}
|
||||
|
||||
void SceneQPainter::Window::renderWindowPixmap(QPainter *painter, QPainterWindowPixmap *windowPixmap)
|
||||
{
|
||||
const QRegion shape = windowPixmap->shape();
|
||||
for (const QRectF &rect : shape) {
|
||||
const QPointF windowTopLeft = windowPixmap->mapToWindow(rect.topLeft());
|
||||
const QPointF windowBottomRight = windowPixmap->mapToWindow(rect.bottomRight());
|
||||
|
||||
const QPointF bufferTopLeft = windowPixmap->mapToBuffer(rect.topLeft());
|
||||
const QPointF bufferBottomRight = windowPixmap->mapToBuffer(rect.bottomRight());
|
||||
|
||||
painter->drawImage(QRectF(windowTopLeft, windowBottomRight),
|
||||
windowPixmap->image(),
|
||||
QRectF(bufferTopLeft, bufferBottomRight));
|
||||
}
|
||||
|
||||
const QVector<WindowPixmap *> children = windowPixmap->children();
|
||||
for (WindowPixmap *child : children) {
|
||||
QPainterWindowPixmap *scenePixmap = static_cast<QPainterWindowPixmap *>(child);
|
||||
if (scenePixmap->isValid()) {
|
||||
renderWindowPixmap(painter, scenePixmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneQPainter::Window::renderShadow(QPainter* painter)
|
||||
{
|
||||
if (!toplevel->shadow()) {
|
||||
|
|
|
@ -71,20 +71,6 @@ private:
|
|||
class Window;
|
||||
};
|
||||
|
||||
class SceneQPainter::Window : public Scene::Window
|
||||
{
|
||||
public:
|
||||
Window(SceneQPainter *scene, Toplevel *c);
|
||||
~Window() override;
|
||||
void performPaint(int mask, const QRegion ®ion, const WindowPaintData &data) override;
|
||||
protected:
|
||||
WindowPixmap *createWindowPixmap() override;
|
||||
private:
|
||||
void renderShadow(QPainter *painter);
|
||||
void renderWindowDecorations(QPainter *painter);
|
||||
SceneQPainter *m_scene;
|
||||
};
|
||||
|
||||
class QPainterWindowPixmap : public WindowPixmap
|
||||
{
|
||||
public:
|
||||
|
@ -103,6 +89,21 @@ private:
|
|||
QImage m_image;
|
||||
};
|
||||
|
||||
class SceneQPainter::Window : public Scene::Window
|
||||
{
|
||||
public:
|
||||
Window(SceneQPainter *scene, Toplevel *c);
|
||||
~Window() override;
|
||||
void performPaint(int mask, const QRegion ®ion, const WindowPaintData &data) override;
|
||||
protected:
|
||||
WindowPixmap *createWindowPixmap() override;
|
||||
private:
|
||||
void renderWindowPixmap(QPainter *painter, QPainterWindowPixmap *windowPixmap);
|
||||
void renderShadow(QPainter *painter);
|
||||
void renderWindowDecorations(QPainter *painter);
|
||||
SceneQPainter *m_scene;
|
||||
};
|
||||
|
||||
class QPainterEffectFrame : public Scene::EffectFrame
|
||||
{
|
||||
public:
|
||||
|
|
38
scene.cpp
38
scene.cpp
|
@ -1028,30 +1028,28 @@ WindowQuadList Scene::Window::makeContentsQuads() const
|
|||
continue;
|
||||
|
||||
const QRegion region = windowPixmap->shape();
|
||||
const QPoint position = windowPixmap->framePosition();
|
||||
const qreal scale = windowPixmap->scale();
|
||||
const int quadId = id++;
|
||||
|
||||
for (const QRect &rect : region) {
|
||||
for (const QRectF &rect : region) {
|
||||
// Note that the window quad id is not unique if the window is shaped, i.e. the
|
||||
// region contains more than just one rectangle. We assume that the "source" quad
|
||||
// had been subdivided.
|
||||
WindowQuad quad(WindowQuadContents, quadId);
|
||||
|
||||
const qreal x0 = rect.x() + position.x();
|
||||
const qreal y0 = rect.y() + position.y();
|
||||
const qreal x1 = rect.x() + rect.width() + position.x();
|
||||
const qreal y1 = rect.y() + rect.height() + position.y();
|
||||
const QPointF windowTopLeft = windowPixmap->mapToWindow(rect.topLeft());
|
||||
const QPointF windowTopRight = windowPixmap->mapToWindow(rect.topRight());
|
||||
const QPointF windowBottomRight = windowPixmap->mapToWindow(rect.bottomRight());
|
||||
const QPointF windowBottomLeft = windowPixmap->mapToWindow(rect.bottomLeft());
|
||||
|
||||
const qreal u0 = rect.x() * scale;
|
||||
const qreal v0 = rect.y() * scale;
|
||||
const qreal u1 = (rect.x() + rect.width()) * scale;
|
||||
const qreal v1 = (rect.y() + rect.height()) * scale;
|
||||
const QPointF bufferTopLeft = windowPixmap->mapToBuffer(rect.topLeft());
|
||||
const QPointF bufferTopRight = windowPixmap->mapToBuffer(rect.topRight());
|
||||
const QPointF bufferBottomRight = windowPixmap->mapToBuffer(rect.bottomRight());
|
||||
const QPointF bufferBottomLeft = windowPixmap->mapToBuffer(rect.bottomLeft());
|
||||
|
||||
quad[0] = WindowVertex(QPointF(x0, y0), QPointF(u0, v0));
|
||||
quad[1] = WindowVertex(QPointF(x1, y0), QPointF(u1, v0));
|
||||
quad[2] = WindowVertex(QPointF(x1, y1), QPointF(u1, v1));
|
||||
quad[3] = WindowVertex(QPointF(x0, y1), QPointF(u0, v1));
|
||||
quad[0] = WindowVertex(windowTopLeft, bufferTopLeft);
|
||||
quad[1] = WindowVertex(windowTopRight, bufferTopRight);
|
||||
quad[2] = WindowVertex(windowBottomRight, bufferBottomRight);
|
||||
quad[3] = WindowVertex(windowBottomLeft, bufferBottomLeft);
|
||||
|
||||
quads << quad;
|
||||
}
|
||||
|
@ -1288,6 +1286,16 @@ bool WindowPixmap::hasAlphaChannel() const
|
|||
return toplevel()->hasAlpha();
|
||||
}
|
||||
|
||||
QPointF WindowPixmap::mapToWindow(const QPointF &point) const
|
||||
{
|
||||
return point + framePosition();
|
||||
}
|
||||
|
||||
QPointF WindowPixmap::mapToBuffer(const QPointF &point) const
|
||||
{
|
||||
return point * scale();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Scene::EffectFrame
|
||||
//****************************************
|
||||
|
|
8
scene.h
8
scene.h
|
@ -502,6 +502,14 @@ public:
|
|||
* Returns @c true if the attached buffer has an alpha channel; otherwise returns @c false.
|
||||
*/
|
||||
bool hasAlphaChannel() const;
|
||||
/**
|
||||
* Maps the specified @a point from the window pixmap coordinates to the window local coordinates.
|
||||
*/
|
||||
QPointF mapToWindow(const QPointF &point) const;
|
||||
/**
|
||||
* Maps the specified @a point from the window pixmap coordinates to the buffer pixel coordinates.
|
||||
*/
|
||||
QPointF mapToBuffer(const QPointF &point) const;
|
||||
|
||||
/**
|
||||
* @returns the parent WindowPixmap in the sub-surface tree
|
||||
|
|
Loading…
Reference in a new issue