Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qwaylanddecorationhandler.cpp
Go to the documentation of this file.
1
// Copyright (C) 2025
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
#
include
"qwaylandabstractdecoration_p.h"
5
#
include
"qwaylanddecorationhandler_p.h"
6
7
#
include
"qwaylandviewport_p.h"
8
#
include
"qwaylandwindow_p.h"
9
#
include
"qwaylandshmbackingstore_p.h"
10
#
include
"qwaylanddisplay_p.h"
11
#
include
"qwaylandinputdevice_p.h"
12
#
include
"qwaylanddecorationfactory_p.h"
13
#
include
"qwaylandplatformservices_p.h"
14
15
#
include
<
QtGui
/
QImage
>
16
#
include
<
QtGui
/
QPainter
>
17
#
include
<
QtCore
/
QThread
>
18
#
include
<
QtGui
/
private
/
qguiapplication_p
.
h
>
19
#
include
<
QGuiApplication
>
20
21
QT_BEGIN_NAMESPACE
22
23
using
namespace
Qt::StringLiterals;
24
25
namespace
QtWaylandClient
{
26
27
void
QWaylandDecorationSurface
::
SubsurfaceDeleter
::
operator
()(
QtWayland
::
wl_subsurface
*
subsurface
)
const
28
{
29
if
(!
subsurface
)
30
return
;
31
32
subsurface
->
destroy
();
33
delete
subsurface
;
34
}
35
36
QWaylandDecorationHandler
::
QWaylandDecorationHandler
(
QWaylandWindow
*
window
)
37
:
mWindow
(
window
)
38
{
39
}
40
41
QWaylandDecorationHandler
::~
QWaylandDecorationHandler
()
42
{
43
}
44
45
void
QWaylandDecorationHandler
::
reset
()
46
{
47
mWindowDecorationEnabled
=
false
;
48
mWindowDecoration
.
reset
();
49
mTopDecorationSurface
.
reset
();
50
mLeftDecorationSurface
.
reset
();
51
mRightDecorationSurface
.
reset
();
52
mBottomDecorationSurface
.
reset
();
53
mWindowDecorationEnabled
=
false
;
54
}
55
56
QWaylandAbstractDecoration
*
QWaylandDecorationHandler
::
decoration
()
const
57
{
58
return
mWindowDecorationEnabled
?
mWindowDecoration
.
get
() :
nullptr
;
59
}
60
61
void
QWaylandDecorationHandler
::
updateNeedsDecoration
()
62
{
63
Q_ASSERT_X
(
QThread
::
isMainThread
(),
64
"QWaylandDecorationHandler::createDecoration"
,
"not called from main thread"
);
65
if
(!
mWindow
->
display
()->
supportsWindowDecoration
())
66
return
;
67
68
static
bool
decorationPluginFailed
=
false
;
69
bool
decoration
=
false
;
70
switch
(
mWindow
->
window
()->
type
()) {
71
case
Qt
::
Window
:
72
case
Qt
::
Widget
:
73
case
Qt
::
Dialog
:
74
case
Qt
::
Tool
:
75
case
Qt
::
Drawer
:
76
decoration
=
true
;
77
break
;
78
default
:
79
break
;
80
}
81
if
(
mWindow
->
windowFlags
() &
Qt
::
FramelessWindowHint
)
82
decoration
=
false
;
83
if
(
mWindow
->
windowFlags
() &
Qt
::
BypassWindowManagerHint
)
84
decoration
=
false
;
85
if
(
mWindow
->
subSurfaceWindow
())
86
decoration
=
false
;
87
if
(!
mWindow
->
shellSurface
() || !
mWindow
->
shellSurface
()->
wantsDecorations
())
88
decoration
=
false
;
89
90
if
(
decoration
&& !
decorationPluginFailed
) {
91
if
(!
mWindowDecorationEnabled
) {
92
if
(
mWindowDecoration
) {
93
mWindowDecoration
.
reset
();
94
}
95
96
QStringList
decorations
=
QWaylandDecorationFactory
::
keys
();
97
if
(
decorations
.
empty
()) {
98
qWarning
() <<
"No decoration plugins available. Running with no decorations."
;
99
decorationPluginFailed
=
true
;
100
return
;
101
}
102
103
QString
targetKey
;
104
105
QByteArray
decorationPluginName
=
qgetenv
(
"QT_WAYLAND_DECORATION"
);
106
if
(!
decorationPluginName
.
isEmpty
()) {
107
targetKey
=
QString
::
fromLocal8Bit
(
decorationPluginName
);
108
if
(!
decorations
.
contains
(
targetKey
)) {
109
qWarning
() <<
"Requested decoration "
<<
targetKey
<<
" not found, falling back to default"
;
110
targetKey
=
QString
();
// fallthrough
111
}
112
}
113
114
if
(
targetKey
.
isEmpty
()) {
115
auto
unixServices
=
dynamic_cast
<
QDesktopUnixServices
*>(
116
QGuiApplicationPrivate
::
platformIntegration
()->
services
());
117
const
QList
<
QByteArray
>
desktopNames
=
unixServices
->
desktopEnvironment
().
split
(
':'
);
118
if
(
desktopNames
.
contains
(
"GNOME"
)) {
119
if
(
decorations
.
contains
(
"adwaita"_L1
))
120
targetKey
=
"adwaita"_L1
;
121
else
if
(
decorations
.
contains
(
"gnome"_L1
))
122
targetKey
=
"gnome"_L1
;
123
}
else
{
124
// Do not use Adwaita/GNOME decorations on other DEs
125
decorations
.
removeAll
(
"adwaita"_L1
);
126
decorations
.
removeAll
(
"gnome"_L1
);
127
}
128
}
129
130
if
(
targetKey
.
isEmpty
())
131
targetKey
=
decorations
.
first
();
// first come, first served.
132
133
mWindowDecoration
.
reset
(
QWaylandDecorationFactory
::
create
(
targetKey
,
QStringList
()));
134
if
(!
mWindowDecoration
) {
135
qWarning
() <<
"Could not create decoration from factory! Running with no decorations."
;
136
decorationPluginFailed
=
true
;
137
return
;
138
}
139
140
mWindowDecoration
->
setWaylandWindow
(
mWindow
);
141
mWindowDecorationEnabled
=
true
;
142
}
143
}
else
{
144
reset
();
145
}
146
147
return
;
148
}
149
150
151
void
QWaylandDecorationHandler
::
update
()
152
{
153
Q_ASSERT
(
mWindowDecorationEnabled
&&
mWindowDecoration
);
154
auto
decoration
=
mWindowDecoration
.
get
();
155
if
(!
decoration
->
isDirty
())
156
return
;
157
158
auto
margins
=
decoration
->
margins
();
159
const
QSize
imageSize
=
mWindow
->
geometry
().
marginsAdded
(
margins
).
size
();
160
const
int
top
=
margins
.
top
();
161
const
int
bottom
=
margins
.
bottom
();
162
const
int
left
=
margins
.
left
();
163
const
int
right
=
margins
.
right
();
164
const
int
sideHeight
=
mWindow
->
geometry
().
height
();
165
166
updateTile
(
mTopDecorationSurface
,
167
QRect
(-
left
, -
top
,
imageSize
.
width
(),
top
),
168
QRect
(0, 0,
imageSize
.
width
(),
top
),
169
QWaylandDecorationSurface
::
Part
::
Top
);
170
updateTile
(
mLeftDecorationSurface
,
171
QRect
(-
left
, 0,
left
,
sideHeight
),
172
QRect
(0,
top
,
left
,
sideHeight
),
173
QWaylandDecorationSurface
::
Part
::
Left
);
174
updateTile
(
mRightDecorationSurface
,
175
QRect
(
mWindow
->
geometry
().
width
(), 0,
right
,
sideHeight
),
176
QRect
(
imageSize
.
width
() -
right
,
top
,
right
,
sideHeight
),
177
QWaylandDecorationSurface
::
Part
::
Right
);
178
updateTile
(
mBottomDecorationSurface
,
179
QRect
(-
left
,
mWindow
->
geometry
().
height
(),
imageSize
.
width
(),
bottom
),
180
QRect
(0,
imageSize
.
height
() -
bottom
,
imageSize
.
width
(),
bottom
),
181
QWaylandDecorationSurface
::
Part
::
Bottom
);
182
183
const
auto
paintTile
= [](
const
std
::
unique_ptr
<
QWaylandDecorationSurface
> &
surface
) {
184
return
!
surface
||
surface
->
paint
();
185
};
186
187
// if any buffer is busy, try again later
188
if
(!
paintTile
(
mTopDecorationSurface
)
189
|| !
paintTile
(
mLeftDecorationSurface
)
190
|| !
paintTile
(
mRightDecorationSurface
)
191
|| !
paintTile
(
mBottomDecorationSurface
)) {
192
mWindow
->
requestForcedUpdate
();
193
return
;
194
}
195
196
decoration
->
resetDirty
();
197
}
198
199
200
void
QWaylandDecorationHandler
::
updateTile
(
std
::
unique_ptr
<
QWaylandDecorationSurface
> &
surface
,
201
const
QRect
&
windowGeometry
,
202
const
QRect
&
paintGeometry
,
203
QWaylandDecorationSurface
::
Part
part
)
204
{
205
if
(
paintGeometry
.
isEmpty
()) {
206
surface
.
reset
();
207
return
;
208
}
209
210
if
(!
surface
)
211
surface
.
reset
(
new
QWaylandDecorationSurface
(
mWindow
,
mWindowDecoration
.
get
(),
part
));
212
213
surface
->
setGeometry
(
windowGeometry
,
paintGeometry
);
214
}
215
216
QWaylandDecorationSurface
::
QWaylandDecorationSurface
(
QWaylandWindow
*
parentWindow
,
217
QWaylandAbstractDecoration
*
decoration
,
218
Part
part
)
219
:
mParentWindow
(
parentWindow
)
220
,
mWindowDecoration
(
decoration
)
221
,
mPart
(
part
)
222
{
223
auto
display
=
parentWindow
->
display
();
224
225
mSurface
=
std
::
make_unique
<
QWaylandSurface
>(
parentWindow
->
display
());
226
mViewport
=
std
::
make_unique
<
QWaylandViewport
>(
display
->
createViewport
(
mSurface
.
get
()));
227
mSurface
->
m_container
=
this
;
228
// avoiding the wrapper, as that assumes it's a window, we could split QWaylandSubsurface
229
mSubsurface
.
reset
(
new
QtWayland
::
wl_subsurface
(
display
->
createSubSurface
(
mSurface
.
get
(),
230
parentWindow
->
waylandSurface
())));
231
mSubsurface
->
place_below
(
parentWindow
->
surface
());
232
}
233
234
QWaylandDecorationSurface
::~
QWaylandDecorationSurface
()
235
{
236
}
237
238
void
QWaylandDecorationSurface
::
setGeometry
(
const
QRect
&
windowGeometry
,
const
QRect
&
paintGeometry
)
239
{
240
createBuffer
(
paintGeometry
.
size
());
241
mWindowGeometry
=
windowGeometry
;
242
mPaintGeometry
=
paintGeometry
;
243
mSubsurface
->
set_position
(
windowGeometry
.
x
(),
windowGeometry
.
y
());
244
if
(
mViewport
)
245
mViewport
->
setDestination
(
paintGeometry
.
size
());
246
}
247
248
bool
QWaylandDecorationSurface
::
paint
()
249
{
250
auto
*
buffer
=
mBackBuffer
.
get
();
251
if
(!
buffer
) {
252
return
true
;
253
}
254
if
(
buffer
->
busy
())
255
return
false
;
256
257
QPainter
painter
(
buffer
->
image
());
258
painter
.
translate
(-
mPaintGeometry
.
topLeft
());
259
switch
(
mPart
) {
260
case
Part
::
Top
:
261
mWindowDecoration
->
paintTop
(&
painter
);
262
break
;
263
case
Part
::
Left
:
264
mWindowDecoration
->
paintLeft
(&
painter
);
265
break
;
266
case
Part
::
Right
:
267
mWindowDecoration
->
paintRight
(&
painter
);
268
break
;
269
case
Part
::
Bottom
:
270
mWindowDecoration
->
paintBottom
(&
painter
);
271
break
;
272
}
273
painter
.
end
();
274
275
mSurface
->
attach
(
mBackBuffer
->
buffer
(), 0, 0);
276
mSurface
->
damage
(0, 0,
mBackBuffer
->
size
().
width
(),
mBackBuffer
->
size
().
height
());
277
mSurface
->
commit
();
278
std
::
swap
(
mFrontBuffer
,
mBackBuffer
);
279
return
true
;
280
}
281
282
void
QWaylandDecorationSurface
::
createBuffer
(
const
QSize
&
size
)
283
{
284
QImage
::
Format
format
=
QImage
::
Format_ARGB32_Premultiplied
;
285
qreal
scale
= 1.0;
286
if
(
mViewport
)
287
scale
=
mParentWindow
->
scale
();
288
289
const
QSize
bufferSize
=
size
*
scale
;
290
if
(
mFrontBuffer
&&
mFrontBuffer
->
size
() ==
bufferSize
) {
291
return
;
292
}
293
mFrontBuffer
=
std
::
make_unique
<
QWaylandShmBuffer
>(
mParentWindow
->
display
(),
bufferSize
,
format
,
scale
);
294
mBackBuffer
=
std
::
make_unique
<
QWaylandShmBuffer
>(
mParentWindow
->
display
(),
bufferSize
,
format
,
scale
);
295
}
296
297
void
QWaylandDecorationSurface
::
handleMouse
(
QWaylandInputDevice
*
inputDevice
,
const
QWaylandPointerEvent
&
e
)
298
{
299
mWindowDecoration
->
handleMouse
(
inputDevice
,
300
e
.
local
+
mPaintGeometry
.
topLeft
(),
301
e
.
global
,
302
e
.
buttons
,
303
e
.
modifiers
);
304
}
305
306
QPointF
QWaylandDecorationSurface
::
mapToGlobal
(
const
QPointF
&
pointIn
)
307
{
308
return
mParentWindow
->
mapInputToGlobal
(
pointIn
+
mWindowGeometry
.
topLeft
());
309
}
310
311
312
313
}
// namespace QtWaylandClient
314
315
QT_END_NAMESPACE
QtWaylandClient
Definition
qwaylandclientextension.h:16
qtbase
src
plugins
platforms
wayland
qwaylanddecorationhandler.cpp
Generated on
for Qt by
1.18.0