1 | // Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net> |
2 | // Copyright (C) 2016 The Qt Company Ltd. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include "qwaylandabstractdecoration_p.h" |
6 | |
7 | #include <private/qobject_p.h> |
8 | #include "qwaylandwindow_p.h" |
9 | #include "qwaylandshellsurface_p.h" |
10 | #include "qwaylandinputdevice_p.h" |
11 | #include "qwaylandscreen_p.h" |
12 | |
13 | #include <QtGui/QImage> |
14 | |
15 | QT_BEGIN_NAMESPACE |
16 | |
17 | namespace QtWaylandClient { |
18 | |
19 | class QWaylandAbstractDecorationPrivate : public QObjectPrivate |
20 | { |
21 | Q_DECLARE_PUBLIC(QWaylandAbstractDecoration) |
22 | |
23 | public: |
24 | QWaylandAbstractDecorationPrivate(); |
25 | ~QWaylandAbstractDecorationPrivate() override; |
26 | |
27 | QWindow *m_window = nullptr; |
28 | QWaylandWindow *m_wayland_window = nullptr; |
29 | |
30 | bool m_isDirty = true; |
31 | QImage m_decorationContentImage; |
32 | |
33 | Qt::MouseButtons m_mouseButtons = Qt::NoButton; |
34 | }; |
35 | |
36 | QWaylandAbstractDecorationPrivate::QWaylandAbstractDecorationPrivate() |
37 | : m_decorationContentImage(nullptr) |
38 | { |
39 | } |
40 | |
41 | QWaylandAbstractDecorationPrivate::~QWaylandAbstractDecorationPrivate() |
42 | { |
43 | } |
44 | |
45 | QWaylandAbstractDecoration::QWaylandAbstractDecoration() |
46 | : QObject(*new QWaylandAbstractDecorationPrivate) |
47 | { |
48 | } |
49 | |
50 | QWaylandAbstractDecoration::~QWaylandAbstractDecoration() |
51 | { |
52 | } |
53 | |
54 | // we do this as a setter to get around plugin factory creates not really |
55 | // being a great way to pass arguments |
56 | void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window) |
57 | { |
58 | Q_D(QWaylandAbstractDecoration); |
59 | |
60 | // double initialization is probably not great |
61 | Q_ASSERT(!d->m_window && !d->m_wayland_window); |
62 | |
63 | d->m_window = window->window(); |
64 | d->m_wayland_window = window; |
65 | } |
66 | |
67 | // Creates regions like this on the outside of a rectangle with inner size \a size |
68 | // ----- |
69 | // | | |
70 | // ----- |
71 | // I.e. the top and bottom extends into the corners |
72 | static QRegion marginsRegion(const QSize &size, const QMargins &margins) |
73 | { |
74 | QRegion r; |
75 | |
76 | r += QRect(0, 0, size.width(), margins.top()); // top |
77 | r += QRect(0, size.height()-margins.bottom(), size.width(), margins.bottom()); //bottom |
78 | r += QRect(0, margins.top(), margins.left(), size.height()); //left |
79 | r += QRect(size.width()-margins.left(), margins.top(), margins.right(), size.height()-margins.top()); // right |
80 | return r; |
81 | } |
82 | |
83 | const QImage &QWaylandAbstractDecoration::contentImage() |
84 | { |
85 | Q_D(QWaylandAbstractDecoration); |
86 | if (d->m_isDirty) { |
87 | // Update the decoration backingstore |
88 | |
89 | const qreal bufferScale = waylandWindow()->scale(); |
90 | const QSize imageSize = waylandWindow()->surfaceSize() * bufferScale; |
91 | d->m_decorationContentImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied); |
92 | // Only scale by buffer scale, not QT_SCALE_FACTOR etc. |
93 | d->m_decorationContentImage.setDevicePixelRatio(bufferScale); |
94 | d->m_decorationContentImage.fill(color: Qt::transparent); |
95 | this->paint(device: &d->m_decorationContentImage); |
96 | |
97 | QRegion damage = marginsRegion(size: waylandWindow()->surfaceSize(), margins: waylandWindow()->frameMargins()); |
98 | for (QRect r : damage) |
99 | waylandWindow()->damage(rect: r); |
100 | |
101 | d->m_isDirty = false; |
102 | } |
103 | |
104 | return d->m_decorationContentImage; |
105 | } |
106 | |
107 | void QWaylandAbstractDecoration::update() |
108 | { |
109 | Q_D(QWaylandAbstractDecoration); |
110 | d->m_isDirty = true; |
111 | } |
112 | |
113 | void QWaylandAbstractDecoration::setMouseButtons(Qt::MouseButtons mb) |
114 | { |
115 | Q_D(QWaylandAbstractDecoration); |
116 | d->m_mouseButtons = mb; |
117 | } |
118 | |
119 | void QWaylandAbstractDecoration::startResize(QWaylandInputDevice *inputDevice, Qt::Edges edges, Qt::MouseButtons buttons) |
120 | { |
121 | Q_D(QWaylandAbstractDecoration); |
122 | if (isLeftClicked(newMouseButtonState: buttons) && d->m_wayland_window->shellSurface()) { |
123 | d->m_wayland_window->shellSurface()->resize(inputDevice, edges); |
124 | inputDevice->removeMouseButtonFromState(button: Qt::LeftButton); |
125 | } |
126 | } |
127 | |
128 | void QWaylandAbstractDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) |
129 | { |
130 | Q_D(QWaylandAbstractDecoration); |
131 | if (isLeftClicked(newMouseButtonState: buttons) && d->m_wayland_window->shellSurface()) { |
132 | d->m_wayland_window->shellSurface()->move(inputDevice); |
133 | inputDevice->removeMouseButtonFromState(button: Qt::LeftButton); |
134 | } |
135 | } |
136 | |
137 | void QWaylandAbstractDecoration::showWindowMenu(QWaylandInputDevice *inputDevice) |
138 | { |
139 | Q_D(QWaylandAbstractDecoration); |
140 | if (auto *s = d->m_wayland_window->shellSurface()) |
141 | s->showWindowMenu(seat: inputDevice); |
142 | } |
143 | |
144 | bool QWaylandAbstractDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) |
145 | { |
146 | Q_D(QWaylandAbstractDecoration); |
147 | return !(d->m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton); |
148 | } |
149 | |
150 | bool QWaylandAbstractDecoration::isRightClicked(Qt::MouseButtons newMouseButtonState) |
151 | { |
152 | Q_D(QWaylandAbstractDecoration); |
153 | return !(d->m_mouseButtons & Qt::RightButton) && (newMouseButtonState & Qt::RightButton); |
154 | } |
155 | |
156 | bool QWaylandAbstractDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) |
157 | { |
158 | Q_D(QWaylandAbstractDecoration); |
159 | return (d->m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton); |
160 | } |
161 | |
162 | bool QWaylandAbstractDecoration::isDirty() const |
163 | { |
164 | Q_D(const QWaylandAbstractDecoration); |
165 | return d->m_isDirty; |
166 | } |
167 | |
168 | QWindow *QWaylandAbstractDecoration::window() const |
169 | { |
170 | Q_D(const QWaylandAbstractDecoration); |
171 | return d->m_window; |
172 | } |
173 | |
174 | QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const |
175 | { |
176 | Q_D(const QWaylandAbstractDecoration); |
177 | return d->m_wayland_window; |
178 | } |
179 | |
180 | } |
181 | |
182 | QT_END_NAMESPACE |
183 | |
184 | #include "moc_qwaylandabstractdecoration_p.cpp" |
185 | |