KWin
Loading...
Searching...
No Matches
decorationitem.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
9#include "compositor.h"
10#include "core/output.h"
13#include "window.h"
14
15#include <cmath>
16
17#include <KDecoration2/DecoratedClient>
18#include <KDecoration2/Decoration>
19
20namespace KWin
21{
22
24 : m_client(client)
25 , m_imageSizesDirty(true)
26{
27 connect(client->decoration(), &KDecoration2::Decoration::damaged,
29
30 connect(client->decoration(), &KDecoration2::Decoration::bordersChanged,
32 connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged,
34
35 invalidate();
36}
37
42
44{
45 if (m_client) {
46 addDamage(m_client->window()->rect().toAlignedRect());
47 }
48 m_imageSizesDirty = true;
49}
50
52{
53 return m_damage;
54}
55
56void DecorationRenderer::addDamage(const QRegion &region)
57{
58 m_damage += region;
59 Q_EMIT damaged(region);
60}
61
63{
64 m_damage = QRegion();
65}
66
68{
69 // QPainter won't let paint with a device pixel ratio less than 1.
70 return std::max(qreal(1.0), devicePixelRatio());
71}
72
74{
75 return m_devicePixelRatio;
76}
77
79{
80 if (m_devicePixelRatio != dpr) {
81 m_devicePixelRatio = dpr;
82 invalidate();
83 }
84}
85
86void DecorationRenderer::renderToPainter(QPainter *painter, const QRect &rect)
87{
88 client()->decoration()->paint(painter, rect);
89}
90
91DecorationItem::DecorationItem(KDecoration2::Decoration *decoration, Window *window, Scene *scene, Item *parent)
92 : Item(scene, parent)
93 , m_window(window)
94 , m_decoration(decoration)
95{
97
99 this, &DecorationItem::handleOutputChanged);
100
101 connect(decoration->client(), &KDecoration2::DecoratedClient::sizeChanged,
102 this, &DecorationItem::handleDecorationGeometryChanged);
103 connect(decoration, &KDecoration2::Decoration::bordersChanged,
104 this, &DecorationItem::handleDecorationGeometryChanged);
105
107 this, qOverload<const QRegion &>(&Item::scheduleRepaint));
108
109 setSize(decoration->size());
110 handleOutputChanged();
111}
112
113QList<QRectF> DecorationItem::shape() const
114{
115 QRectF left, top, right, bottom;
116 m_window->layoutDecorationRects(left, top, right, bottom);
117 return {left, top, right, bottom};
118}
119
121{
122 if (m_window->decorationHasAlpha()) {
123 return QRegion();
124 }
125 QRectF left, top, right, bottom;
126 m_window->layoutDecorationRects(left, top, right, bottom);
127
128 // We have to map to integers which has rounding issues
129 // it's safer for a region to be considered transparent than opaque
130 // so always align inwards
131 const QMargins roundingPad = QMargins(1, 1, 1, 1);
132 QRegion roundedLeft = left.toAlignedRect().marginsRemoved(roundingPad);
133 QRegion roundedTop = top.toAlignedRect().marginsRemoved(roundingPad);
134 QRegion roundedRight = right.toAlignedRect().marginsRemoved(roundingPad);
135 QRegion roundedBottom = bottom.toAlignedRect().marginsRemoved(roundingPad);
136
137 return roundedLeft | roundedTop | roundedRight | roundedBottom;
138}
139
141{
142 const QRegion damage = m_renderer->damage();
143 if (!damage.isEmpty()) {
144 m_renderer->render(damage);
145 m_renderer->resetDamage();
146 }
147}
148
149void DecorationItem::handleOutputChanged()
150{
151 if (m_output) {
152 disconnect(m_output, &Output::scaleChanged, this, &DecorationItem::handleOutputScaleChanged);
153 }
154
155 m_output = m_window->output();
156
157 if (m_output) {
158 handleOutputScaleChanged();
159 connect(m_output, &Output::scaleChanged, this, &DecorationItem::handleOutputScaleChanged);
160 }
161}
162
163void DecorationItem::handleOutputScaleChanged()
164{
165 const qreal dpr = m_output->scale();
166 if (m_renderer->devicePixelRatio() != dpr) {
167 m_renderer->setDevicePixelRatio(dpr);
168 discardQuads();
169 }
170}
171
172void DecorationItem::handleDecorationGeometryChanged()
173{
174 setSize(m_decoration->size());
175 discardQuads();
176}
177
179{
180 return m_renderer.get();
181}
182
184{
185 return m_window;
186}
187
188WindowQuad buildQuad(const QRectF &partRect, const QPoint &textureOffset,
189 const qreal devicePixelRatio, bool rotated)
190{
191 const QRectF &r = partRect;
192 const int p = DecorationRenderer::TexturePad;
193
194 const int x0 = r.x();
195 const int y0 = r.y();
196 const int x1 = r.x() + r.width();
197 const int y1 = r.y() + r.height();
198
199 WindowQuad quad;
200 if (rotated) {
201 const int u0 = textureOffset.y() + p;
202 const int v0 = textureOffset.x() + p;
203 const int u1 = textureOffset.y() + p + std::round(r.width() * devicePixelRatio);
204 const int v1 = textureOffset.x() + p + std::round(r.height() * devicePixelRatio);
205
206 quad[0] = WindowVertex(x0, y0, v0, u1); // Top-left
207 quad[1] = WindowVertex(x1, y0, v0, u0); // Top-right
208 quad[2] = WindowVertex(x1, y1, v1, u0); // Bottom-right
209 quad[3] = WindowVertex(x0, y1, v1, u1); // Bottom-left
210 } else {
211 const int u0 = textureOffset.x() + p;
212 const int v0 = textureOffset.y() + p;
213 const int u1 = textureOffset.x() + p + std::round(r.width() * devicePixelRatio);
214 const int v1 = textureOffset.y() + p + std::round(r.height() * devicePixelRatio);
215
216 quad[0] = WindowVertex(x0, y0, u0, v0); // Top-left
217 quad[1] = WindowVertex(x1, y0, u1, v0); // Top-right
218 quad[2] = WindowVertex(x1, y1, u1, v1); // Bottom-right
219 quad[3] = WindowVertex(x0, y1, u0, v1); // Bottom-left
220 }
221 return quad;
222}
223
225{
226 if (m_window->frameMargins().isNull()) {
227 return WindowQuadList();
228 }
229
230 QRectF left, top, right, bottom;
231 const qreal devicePixelRatio = m_renderer->effectiveDevicePixelRatio();
232 const int texturePad = DecorationRenderer::TexturePad;
233
234 m_window->layoutDecorationRects(left, top, right, bottom);
235
236 const int topHeight = std::round(top.height() * devicePixelRatio);
237 const int bottomHeight = std::round(bottom.height() * devicePixelRatio);
238 const int leftWidth = std::round(left.width() * devicePixelRatio);
239
240 const QPoint topPosition(0, 0);
241 const QPoint bottomPosition(0, topPosition.y() + topHeight + (2 * texturePad));
242 const QPoint leftPosition(0, bottomPosition.y() + bottomHeight + (2 * texturePad));
243 const QPoint rightPosition(0, leftPosition.y() + leftWidth + (2 * texturePad));
244
245 WindowQuadList list;
246 if (left.isValid()) {
247 list.append(buildQuad(left, leftPosition, devicePixelRatio, true));
248 }
249 if (top.isValid()) {
250 list.append(buildQuad(top, topPosition, devicePixelRatio, false));
251 }
252 if (right.isValid()) {
253 list.append(buildQuad(right, rightPosition, devicePixelRatio, true));
254 }
255 if (bottom.isValid()) {
256 list.append(buildQuad(bottom, bottomPosition, devicePixelRatio, false));
257 }
258 return list;
259}
260
261} // namespace KWin
262
263#include "moc_decorationitem.cpp"
WorkspaceScene * scene() const
Definition compositor.h:60
static Compositor * self()
KDecoration2::DecoratedClient * decoratedClient()
void preprocess() override
WindowQuadList buildQuads() const override
DecorationRenderer * renderer() const
Window * window() const
QList< QRectF > shape() const override final
DecorationItem(KDecoration2::Decoration *decoration, Window *window, Scene *scene, Item *parent=nullptr)
QRegion opaque() const override final
static const int TexturePad
void renderToPainter(QPainter *painter, const QRect &rect)
void damaged(const QRegion &region)
DecorationRenderer(Decoration::DecoratedClientImpl *client)
Decoration::DecoratedClientImpl * client() const
void addDamage(const QRegion &region)
qreal effectiveDevicePixelRatio() const
void setDevicePixelRatio(qreal dpr)
void setSize(const QSizeF &size)
Definition item.cpp:140
void discardQuads()
Definition item.cpp:350
void scheduleRepaint(const QRectF &region)
Definition item.cpp:396
void scaleChanged()
bool decorationHasAlpha
Definition window.h:448
Decoration::DecoratedClientImpl * decoratedClient() const
Definition window.cpp:2811
void outputChanged()
QMargins frameMargins() const
Definition window.cpp:417
void layoutDecorationRects(QRectF &left, QRectF &top, QRectF &right, QRectF &bottom) const
Definition window.cpp:2690
KWin::Output * output
Definition window.h:111
Class representing one area of a window.
Vertex class.
virtual std::unique_ptr< DecorationRenderer > createDecorationRenderer(Decoration::DecoratedClientImpl *)=0
WindowQuad buildQuad(const QRectF &partRect, const QPoint &textureOffset, const qreal devicePixelRatio, bool rotated)