Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandqtshellchrome.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
7
8#include <QtWaylandCompositor/qwaylandquickshellsurfaceitem.h>
9
11
12QPointF QWaylandQtShellChromePrivate::constrainPoint(const QPointF &point) const
13{
14 float x0 = maximizedRect.left();
15 float y0 = maximizedRect.top();
16 float x1 = maximizedRect.right();
17 float y1 = maximizedRect.bottom();
18 return QPoint(qBound(x0, point.x(), x1),
19 qBound(y0, point.y(), y1));
20}
21
23 const QQuickHandlerPoint &centroid)
24{
25 if (shellSurface == nullptr)
26 return;
27
28 if (decorationInteraction == quint8(DecorationInteraction::None)) {
29 decorationInteraction = flags;
30 decorationInteractionPosition = centroid.scenePressPosition();
31 decorationInteractionGeometry = shellSurface->windowGeometry();
32 }
33
34 if (decorationInteraction != flags)
35 return;
36
37 QPointF position = constrainPoint(centroid.scenePosition());
38 float dx = position.x() - decorationInteractionPosition.x();
39 float dy = position.y() - decorationInteractionPosition.y();
40
41 float minWidth = qMax(0, shellSurface->minimumSize().width());
42 float minHeight = qMax(0, shellSurface->minimumSize().height());
43
44 float maxWidth = shellSurface->maximumSize().width();
45 float maxHeight = shellSurface->maximumSize().height();
46
47 float minX = maxWidth >= 0.0f
48 ? decorationInteractionGeometry.right() - maxWidth
49 : -FLT_MAX;
50 float minY = maxHeight >= 0.0f
51 ? decorationInteractionGeometry.bottom() - maxHeight
52 : -FLT_MAX;
53 float maxX = maxWidth >= 0
54 ? decorationInteractionGeometry.left() + maxWidth
55 : FLT_MAX;
56 float maxY = maxHeight >= 0.0f
57 ? decorationInteractionGeometry.top() + maxHeight
58 : FLT_MAX;
59
60 float newLeft = decorationInteractionGeometry.left();
61 if (flags & quint8(DecorationInteraction::WestBound)) {
62 newLeft = qBound(minX,
63 newLeft + dx,
64 float(decorationInteractionGeometry.right() - minWidth));
65 }
66
67 float newTop = decorationInteractionGeometry.top();
68 if (flags & quint8(DecorationInteraction::NorthBound)) {
69 newTop = qBound(minY,
70 newTop + dy,
71 decorationInteractionGeometry.bottom() + minHeight);
72 }
73
74 float newRight = decorationInteractionGeometry.right();
75 if (flags & quint8(DecorationInteraction::EastBound)) {
76 newRight = qBound(decorationInteractionGeometry.left() + minWidth,
77 newRight + dx,
78 maxX);
79 }
80
81 float newBottom = decorationInteractionGeometry.bottom();
82 if (flags & quint8(DecorationInteraction::SouthBound)) {
83 newBottom = qBound(decorationInteractionGeometry.top() + minHeight,
84 newBottom + dy,
85 maxY);
86 }
87
88 shellSurface->requestWindowGeometry(shellSurface->windowState(),
89 QRect(int(newLeft), int(newTop),
90 int(newRight - newLeft), int(newBottom - newTop)));
91}
92
93/*!
94 * \qmltype QtShellChrome
95 * \nativetype QWaylandQtShellChrome
96 * \inqmlmodule QtWayland.Compositor.QtShell
97 * \since 6.3
98 * \brief Provides default window manager functionality for use with the \c qt-shell extension.
99 *
100 * The QtShellChrome is a convenience type that can be used to provide window manager functionality
101 * to the interaction with clients over the \c qt-shell
102 * \l{Shell Extensions - Qt Wayland Compositor}{shell extension protocol}.
103 *
104 * Given a ShellSurfaceItem with an associated QtShellSurface, the item will automatically adapt
105 * its size to match the surface. It will also provide automatic handling of:
106 * \list
107 * \li Window states, such as maximized, minimized and fullscreen.
108 * \li Window activation.
109 * \li Window resizing using with resize handles (if the appropriate properties are set.)
110 * \li Window repositioning using title bar interaction (if the \l titleBar property is set.)
111 * \endlist
112 *
113 * The QtShellChrome is intended to be used together with QtShell and QtShellSurface.
114 *
115 * \sa {QtShell Compositor}
116 */
117QWaylandQtShellChrome::QWaylandQtShellChrome(QQuickItem *parent)
118 : QQuickItem(*new QWaylandQtShellChromePrivate{}, parent)
119{
120 init();
121}
122
123QWaylandQtShellChrome::QWaylandQtShellChrome(QWaylandQtShellChromePrivate &dd,
124 QQuickItem *parent)
125 : QQuickItem(dd, parent)
126{
127 init();
128}
129
130QWaylandQtShellChrome::~QWaylandQtShellChrome()
131{
132 Q_D(QWaylandQtShellChrome);
133 if (d->shell != nullptr)
134 d->shell->unregisterChrome(this);
135}
136
137void QWaylandQtShellChrome::init()
138{
139 connect(this, &QWaylandQtShellChrome::currentWindowStateChanged,
140 this, &QWaylandQtShellChrome::windowMetaInfoChanged);
141
142 connect(this, &QWaylandQtShellChrome::currentWindowFlagsChanged,
143 this, &QWaylandQtShellChrome::windowMetaInfoChanged);
144
145 connect(this, &QWaylandQtShellChrome::windowMetaInfoChanged,
146 this, &QWaylandQtShellChrome::updateDecorations);
147
148 connect(this, &QWaylandQtShellChrome::leftResizeHandleChanged,
149 this, &QWaylandQtShellChrome::updateDecorations);
150
151 connect(this, &QWaylandQtShellChrome::rightResizeHandleChanged,
152 this, &QWaylandQtShellChrome::updateDecorations);
153
154 connect(this, &QWaylandQtShellChrome::topResizeHandleChanged,
155 this, &QWaylandQtShellChrome::updateDecorations);
156
157 connect(this, &QWaylandQtShellChrome::bottomResizeHandleChanged,
158 this, &QWaylandQtShellChrome::updateDecorations);
159
160 connect(this, &QWaylandQtShellChrome::topLeftResizeHandleChanged,
161 this, &QWaylandQtShellChrome::updateDecorations);
162
163 connect(this, &QWaylandQtShellChrome::bottomLeftResizeHandleChanged,
164 this, &QWaylandQtShellChrome::updateDecorations);
165
166 connect(this, &QWaylandQtShellChrome::topRightResizeHandleChanged,
167 this, &QWaylandQtShellChrome::updateDecorations);
168
169 connect(this, &QWaylandQtShellChrome::bottomRightResizeHandleChanged,
170 this, &QWaylandQtShellChrome::updateDecorations);
171}
172
173/*!
174 * \qmlmethod void QtShellChrome::toggleFullScreen()
175 *
176 * Toggles between fullscreen and normal window states. This method also clears the minimized
177 * or maximized window states if either is set.
178 */
179void QWaylandQtShellChrome::toggleFullScreen()
180{
181 Q_D(QWaylandQtShellChrome);
182 if (d->shellSurface == nullptr)
183 return;
184
185 uint newState;
186 if ((d->shellSurface->windowState() & Qt::WindowFullScreen) == Qt::WindowFullScreen)
187 newState = d->currentState & ~Qt::WindowFullScreen;
188 else
189 newState = d->currentState | Qt::WindowFullScreen;
190
191 if ((newState & (Qt::WindowMinimized | Qt::WindowMaximized)) != 0)
192 newState &= ~(Qt::WindowMinimized | Qt::WindowMaximized);
193
194 setWindowState(newState);
195}
196
197/*!
198 * \qmlmethod void QtShellChrome::toggleMaximized()
199 *
200 * Toggles between maximized and normal states. This method also clears the minimized
201 * window state if it is set.
202 */
203void QWaylandQtShellChrome::toggleMaximized()
204{
205 Q_D(QWaylandQtShellChrome);
206 if (d->shellSurface == nullptr)
207 return;
208
209 uint newState;
210 if ((d->shellSurface->windowState() & Qt::WindowMaximized) == Qt::WindowMaximized)
211 newState = d->currentState & ~Qt::WindowMaximized;
212 else
213 newState = d->currentState | Qt::WindowMaximized;
214
215 if ((newState & Qt::WindowMinimized) == Qt::WindowMinimized)
216 newState &= ~Qt::WindowMinimized;
217
218 setWindowState(newState);
219}
220
221/*!
222 * \qmlmethod void QtShellChrome::toggleMinimized()
223 *
224 * Toggles between minimized and normal states. This method also clears the maximized
225 * window state if it is set.
226 */
227void QWaylandQtShellChrome::toggleMinimized()
228{
229 Q_D(QWaylandQtShellChrome);
230 if (d->shellSurface == nullptr)
231 return;
232
233 uint newState;
234 if ((d->shellSurface->windowState() & Qt::WindowMinimized) == Qt::WindowMinimized)
235 newState = d->currentState & ~Qt::WindowMinimized;
236 else
237 newState = d->currentState | Qt::WindowMinimized;
238
239 if ((newState & Qt::WindowMaximized) == Qt::WindowMaximized)
240 newState &= ~Qt::WindowMaximized;
241
242 setWindowState(newState);
243}
244
245/*!
246 * \qmlproperty ShellSurfaceItem QtShellChrome::shellSurfaceItem
247 *
248 * This property holds the shell surface item associated with this QtShellChrome. It will
249 * in turn manage the \c shellSurface of this item. The \c shellSurface of the item is expected to
250 * be of the type QtShellSurface.
251 *
252 * \qml
253 * QtShellChrome {
254 * id: chrome
255 * ShellSurfaceItem {
256 * id: sfi
257 * anchors.fill: parent
258 * moveItem: chrome
259 * }
260 * shellSurfaceItem: sfi
261 * }
262 * \endqml
263 */
264
265/*!
266 * \property QWaylandQtShellChrome::shellSurfaceItem
267 *
268 * This property holds the shell surface item associated with this
269 * QWaylandQtShellChrome. It will in turn manage the shell surface of this item.
270 * The shell surface of the item is expected to be of the type
271 * QWaylandQtShellSurface.
272 */
273void QWaylandQtShellChrome::setShellSurfaceItem(QWaylandQuickShellSurfaceItem *shellSurfaceItem)
274{
275 Q_D(QWaylandQtShellChrome);
276 if (d->shellSurfaceItem == shellSurfaceItem)
277 return;
278
279 if (d->shellSurfaceItem != nullptr)
280 d->shellSurfaceItem->disconnect(this);
281
282 d->shellSurfaceItem = shellSurfaceItem;
283
284 if (d->shellSurfaceItem != nullptr) {
285 connect(d->shellSurfaceItem, &QWaylandQuickShellSurfaceItem::shellSurfaceChanged,
286 this, &QWaylandQtShellChrome::updateShellSurface);
287 connect(d->shellSurfaceItem, &QWaylandQuickShellSurfaceItem::surfaceDestroyed,
288 this, &QWaylandQtShellChrome::clientDestroyed);
289 }
290
291 updateShellSurface();
292 emit shellSurfaceItemChanged();
293}
294
295QWaylandQuickShellSurfaceItem *QWaylandQtShellChrome::shellSurfaceItem() const
296{
297 Q_D(const QWaylandQtShellChrome);
298 return d->shellSurfaceItem;
299}
300
301void QWaylandQtShellChrome::stopGrab()
302{
303 Q_D(QWaylandQtShellChrome);
304 d->decorationInteraction = quint8(QWaylandQtShellChromePrivate::DecorationInteraction::None);
305}
306
307void QWaylandQtShellChrome::leftResize()
308{
309 Q_D(QWaylandQtShellChrome);
310 if (!d->leftResizeHandleHandler->active())
311 return;
312
313 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::WestBound),
314 d->leftResizeHandleHandler->centroid());
315}
316
317void QWaylandQtShellChrome::rightResize()
318{
319 Q_D(QWaylandQtShellChrome);
320 if (!d->rightResizeHandleHandler->active())
321 return;
322
323 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::EastBound),
324 d->rightResizeHandleHandler->centroid());
325}
326
327void QWaylandQtShellChrome::topResize()
328{
329 Q_D(QWaylandQtShellChrome);
330 if (!d->topResizeHandleHandler->active())
331 return;
332
333 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::NorthBound),
334 d->topResizeHandleHandler->centroid());
335}
336
337void QWaylandQtShellChrome::bottomResize()
338{
339 Q_D(QWaylandQtShellChrome);
340 if (!d->bottomResizeHandleHandler->active())
341 return;
342
343 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::SouthBound),
344 d->bottomResizeHandleHandler->centroid());
345}
346
347void QWaylandQtShellChrome::topLeftResize()
348{
349 Q_D(QWaylandQtShellChrome);
350 if (!d->topLeftResizeHandleHandler->active())
351 return;
352
353 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::WestBound)
354 | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::NorthBound),
355 d->topLeftResizeHandleHandler->centroid());
356}
357
358void QWaylandQtShellChrome::topRightResize()
359{
360 Q_D(QWaylandQtShellChrome);
361 if (!d->topRightResizeHandleHandler->active())
362 return;
363
364 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::EastBound)
365 | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::NorthBound),
366 d->topRightResizeHandleHandler->centroid());
367}
368
369void QWaylandQtShellChrome::bottomLeftResize()
370{
371 Q_D(QWaylandQtShellChrome);
372 if (!d->bottomLeftResizeHandleHandler->active())
373 return;
374
375 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::WestBound)
376 | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::SouthBound),
377 d->bottomLeftResizeHandleHandler->centroid());
378}
379
380void QWaylandQtShellChrome::bottomRightResize()
381{
382 Q_D(QWaylandQtShellChrome);
383 if (!d->bottomRightResizeHandleHandler->active())
384 return;
385
386 d->updateDecorationInteraction(quint8(QWaylandQtShellChromePrivate::DecorationInteraction::EastBound)
387 | quint8(QWaylandQtShellChromePrivate::DecorationInteraction::SouthBound),
388 d->bottomRightResizeHandleHandler->centroid());
389}
390
391void QWaylandQtShellChrome::titleBarMove()
392{
393 Q_D(QWaylandQtShellChrome);
394 if (!d->titleBarHandler->active())
395 return;
396
397 quint8 flags = quint8(QWaylandQtShellChromePrivate::DecorationInteraction::TitleBar);
398 QQuickHandlerPoint centroid = d->titleBarHandler->centroid();
399 if (d->decorationInteraction == quint8(QWaylandQtShellChromePrivate::DecorationInteraction::None)) {
400 d->decorationInteraction = flags;
401 d->decorationInteractionPosition = d->shellSurface->windowPosition() - centroid.scenePressPosition();
402
403 activate();
404 }
405
406 if (d->decorationInteraction != flags)
407 return;
408
409 QPointF position = d->constrainPoint(centroid.scenePosition());
410 d->shellSurface->setWindowPosition((position + d->decorationInteractionPosition).toPoint());
411}
412
413/*!
414 * \qmlproperty Item QtShellChrome::titleBar
415 *
416 * This property holds the default title bar item of the QtShellChrome. If set, a \l DragHandler
417 * will be installed on the title bar which moves the window around on user interaction. In
418 * addition, the window will automatically be activated if the title bar is clicked.
419 *
420 * The title bar will automatically hide and show, depending on the window flags and the
421 * window's full screen state.
422 *
423 * \qml
424 * QtShellChrome {
425 * Rectangle {
426 * id: tb
427 * anchors.top: parent.top
428 * anchors.right: parent.right
429 * anchors.left: parent.left
430 * height: 50
431 * color: "black"
432 *
433 * Text {
434 * color: "white"
435 * anchors.centerIn: parent
436 * text: shellSurfaceItem.shellSurface.windowTitle
437 * font.pixelSize: 25
438 * }
439 * }
440 * titleBar: tb
441 * }
442 * \endqml
443 *
444 * \note Unless explicit frame margins are set, the title bar's height will be included in the
445 * window's top frame margin.
446 */
447
448/*!
449 * \property QWaylandQtShellChrome::titleBar
450 *
451 * This property holds the default title bar item of the QWaylandQtShellChrome.
452 * If set, a QQuickDragHandler will be installed on the title bar which moves
453 * the window around on user interaction.
454 *
455 * \note Unless explicit frame margins are set, the title bar's height will be
456 * included in the window's top frame margin.
457 */
458QQuickItem *QWaylandQtShellChrome::titleBar() const
459{
460 Q_D(const QWaylandQtShellChrome);
461 return d->titleBar;
462}
463
464void QWaylandQtShellChrome::setTitleBar(QQuickItem *item)
465{
466 Q_D(QWaylandQtShellChrome);
467 if (d->titleBar == item)
468 return;
469
470 if (d->titleBar != nullptr) {
471 d->titleBar->disconnect(this);
472
473 delete d->titleBarHandler;
474 d->titleBarHandler = nullptr;
475 }
476
477 d->titleBar = item;
478
479 if (d->titleBar != nullptr) {
480 connect(d->titleBar, &QQuickItem::heightChanged,
481 this, &QWaylandQtShellChrome::updateDecorations);
482
483 d->titleBarHandler = new QQuickDragHandler(d->titleBar);
484 d->titleBarHandler->setTarget(nullptr);
485
486 connect(d->titleBarHandler, &QQuickPointerHandler::grabChanged,
487 this, &QWaylandQtShellChrome::stopGrab);
488 connect(d->titleBarHandler, &QQuickPointerHandler::grabChanged,
489 this, &QWaylandQtShellChrome::activateOnGrab);
490 connect(d->titleBarHandler, &QQuickMultiPointHandler::centroidChanged,
491 this, &QWaylandQtShellChrome::titleBarMove);
492 }
493
494 emit titleBarChanged();
495}
496
497/*!
498 * \qmlproperty Item QtShellChrome::leftResizeHandle
499 *
500 * This property holds the default left resize handle of the QtShellChrome. If set, a \l DragHandler
501 * will be installed on the resize handle which resizes the window by moving its left edge.
502 *
503 * The handle will automatically hide and show, depending on the window flags and the window's full
504 * screen state.
505 *
506 * \qml
507 * QtShellChrome {
508 * Rectangle {
509 * id: lrh
510 * anchors.left: parent.left
511 * anchors.top: parent.top
512 * anchors.bottom: parent.bottom
513 * width: 5
514 * color: "white"
515 * }
516 * leftResizeHandle: lrh
517 * }
518 * \endqml
519 *
520 * \note Unless explicit frame margins are set, the handle's width will be included in the
521 * window's left frame margin.
522 */
523
524/*!
525 * \property QWaylandQtShellChrome::leftResizeHandle
526 *
527 * This property holds the default left resize handle of the
528 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
529 * resize handle which resizes the window by moving its left edge.
530 *
531 * The handle will automatically hide and show, depending on the window flags
532 * and the window's full screen state.
533 *
534 * \note Unless explicit frame margins are set, the handle's width will be
535 * included in the window's left frame margin.
536 */
537QQuickItem *QWaylandQtShellChrome::leftResizeHandle() const
538{
539 Q_D(const QWaylandQtShellChrome);
540 return d->leftResizeHandle;
541}
542
543void QWaylandQtShellChrome::setLeftResizeHandle(QQuickItem *item)
544{
545 Q_D(QWaylandQtShellChrome);
546 if (d->leftResizeHandle == item)
547 return;
548
549 if (d->leftResizeHandle != nullptr) {
550 d->leftResizeHandle->disconnect(this);
551
552 delete d->leftResizeHandleHandler;
553 d->leftResizeHandleHandler = nullptr;
554 }
555
556 d->leftResizeHandle = item;
557
558 if (d->leftResizeHandle != nullptr) {
559 connect(d->leftResizeHandle, &QQuickItem::widthChanged,
560 this, &QWaylandQtShellChrome::updateDecorations);
561
562 d->leftResizeHandleHandler = new QQuickDragHandler(d->leftResizeHandle);
563 d->leftResizeHandleHandler->setCursorShape(Qt::SizeHorCursor);
564 d->leftResizeHandleHandler->setTarget(nullptr);
565
566 connect(d->leftResizeHandleHandler, &QQuickPointerHandler::grabChanged,
567 this, &QWaylandQtShellChrome::stopGrab);
568 connect(d->leftResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
569 this, &QWaylandQtShellChrome::leftResize);
570 }
571
572 emit leftResizeHandleChanged();
573}
574
575/*!
576 * \qmlproperty Item QtShellChrome::rightResizeHandle
577 *
578 * This property holds the default right resize handle of the QtShellChrome. If set, a \l DragHandler
579 * will be installed on the resize handle which resizes the window by moving its right edge.
580 *
581 * The handle will automatically hide and show, depending on the window flags and the window's full
582 * screen state.
583 *
584 * \qml
585 * QtShellChrome {
586 * Rectangle {
587 * id: rrh
588 * anchors.right: parent.right
589 * anchors.top: parent.top
590 * anchors.bottom: parent.bottom
591 * width: 5
592 * color: "white"
593 * }
594 * rightResizeHandle: rrh
595 * }
596 * \endqml
597 *
598 * \note Unless explicit frame margins are set, the handle's width will be included in the
599 * window's right frame margin.
600 */
601
602/*!
603 * \property QWaylandQtShellChrome::rightResizeHandle
604 *
605 * This property holds the default right resize handle of the
606 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
607 * resize handle which resizes the window by moving its right edge.
608 *
609 * The handle will automatically hide and show, depending on the window flags
610 * and the window's full screen state.
611 *
612 * \note Unless explicit frame margins are set, the handle's width will be
613 * included in the window's right frame margin.
614 */
615QQuickItem *QWaylandQtShellChrome::rightResizeHandle() const
616{
617 Q_D(const QWaylandQtShellChrome);
618 return d->rightResizeHandle;
619}
620
621void QWaylandQtShellChrome::setRightResizeHandle(QQuickItem *item)
622{
623 Q_D(QWaylandQtShellChrome);
624 if (d->rightResizeHandle == item)
625 return;
626
627 if (d->rightResizeHandle != nullptr) {
628 d->rightResizeHandle->disconnect(this);
629
630 delete d->rightResizeHandleHandler;
631 d->rightResizeHandleHandler = nullptr;
632 }
633
634 d->rightResizeHandle = item;
635
636 if (d->rightResizeHandle != nullptr) {
637 connect(d->rightResizeHandle, &QQuickItem::widthChanged,
638 this, &QWaylandQtShellChrome::updateDecorations);
639
640 d->rightResizeHandleHandler = new QQuickDragHandler(d->rightResizeHandle);
641 d->rightResizeHandleHandler->setCursorShape(Qt::SizeHorCursor);
642 d->rightResizeHandleHandler->setTarget(nullptr);
643
644 connect(d->rightResizeHandleHandler, &QQuickPointerHandler::grabChanged,
645 this, &QWaylandQtShellChrome::stopGrab);
646 connect(d->rightResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
647 this, &QWaylandQtShellChrome::rightResize);
648 }
649
650 emit rightResizeHandleChanged();
651}
652
653/*!
654 * \qmlproperty Item QtShellChrome::topResizeHandle
655 *
656 * This property holds the default top resize handle of the QtShellChrome. If set, a \l DragHandler
657 * will be installed on the resize handle which resizes the window by moving its top edge.
658 *
659 * The handle will automatically hide and show, depending on the window flags and the window's full
660 * screen state.
661 *
662 * \qml
663 * QtShellChrome {
664 * Rectangle {
665 * id: trh
666 * anchors.top: parent.top
667 * anchors.left: parent.left
668 * anchors.right: parent.right
669 * height: 5
670 * color: "white"
671 * }
672 * topResizeHandle: trh
673 * }
674 * \endqml
675 *
676 * \note Unless explicit frame margins are set, the handle's height will be included in the
677 * window's top frame margin.
678 */
679
680/*!
681 * \property QWaylandQtShellChrome::topResizeHandle
682 *
683 * This property holds the default top resize handle of the
684 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
685 * resize handle which resizes the window by moving its top edge.
686 *
687 * The handle will automatically hide and show, depending on the window flags
688 * and the window's full screen state.
689 *
690 * \note Unless explicit frame margins are set, the handle's height will be
691 * included in the window's top frame margin.
692 */
693QQuickItem *QWaylandQtShellChrome::topResizeHandle() const
694{
695 Q_D(const QWaylandQtShellChrome);
696 return d->topResizeHandle;
697}
698
699void QWaylandQtShellChrome::setTopResizeHandle(QQuickItem *item)
700{
701 Q_D(QWaylandQtShellChrome);
702 if (d->topResizeHandle == item)
703 return;
704
705 if (d->topResizeHandle != nullptr) {
706 d->topResizeHandle->disconnect(this);
707
708 delete d->topResizeHandleHandler;
709 d->topResizeHandleHandler = nullptr;
710 }
711
712 d->topResizeHandle = item;
713
714 if (d->topResizeHandle != nullptr) {
715 connect(d->topResizeHandle, &QQuickItem::heightChanged,
716 this, &QWaylandQtShellChrome::updateDecorations);
717
718 d->topResizeHandleHandler = new QQuickDragHandler(d->topResizeHandle);
719 d->topResizeHandleHandler->setCursorShape(Qt::SizeVerCursor);
720 d->topResizeHandleHandler->setTarget(nullptr);
721
722 connect(d->topResizeHandleHandler, &QQuickPointerHandler::grabChanged,
723 this, &QWaylandQtShellChrome::stopGrab);
724 connect(d->topResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
725 this, &QWaylandQtShellChrome::topResize);
726 }
727
728 emit topResizeHandleChanged();
729}
730
731/*!
732 * \qmlproperty Item QtShellChrome::bottomResizeHandle
733 *
734 * This property holds the default bottom resize handle of the QtShellChrome. If set, a \l DragHandler
735 * will be installed on the resize handle which resizes the window by moving its bottom edge.
736 *
737 * The handle will automatically hide and show, depending on the window flags and the window's full
738 * screen state.
739 *
740 * \qml
741 * QtShellChrome {
742 * Rectangle {
743 * id: brh
744 * anchors.bottom: parent.bottom
745 * anchors.left: parent.left
746 * anchors.right: parent.right
747 * height: 5
748 * color: "white"
749 * }
750 * bottomResizeHandle: brh
751 * }
752 * \endqml
753 *
754 * \note Unless explicit frame margins are set, the handle's height will be included in the
755 * window's bottom frame margin.
756 */
757
758/*!
759 * \property QWaylandQtShellChrome::bottomResizeHandle
760 *
761 * This property holds the default bottom resize handle of the
762 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
763 * resize handle which resizes the window by moving its bottom edge.
764 *
765 * The handle will automatically hide and show, depending on the window flags
766 * and the window's full screen state.
767 *
768 * \note Unless explicit frame margins are set, the handle's height will be
769 * included in the window's bottom frame margin.
770 */
771QQuickItem *QWaylandQtShellChrome::bottomResizeHandle() const
772{
773 Q_D(const QWaylandQtShellChrome);
774 return d->bottomResizeHandle;
775}
776
777void QWaylandQtShellChrome::setBottomResizeHandle(QQuickItem *item)
778{
779 Q_D(QWaylandQtShellChrome);
780 if (d->bottomResizeHandle == item)
781 return;
782
783 if (d->bottomResizeHandle != nullptr) {
784 d->bottomResizeHandle->disconnect(this);
785
786 delete d->bottomResizeHandleHandler;
787 d->bottomResizeHandleHandler = nullptr;
788 }
789
790 d->bottomResizeHandle = item;
791
792 if (d->bottomResizeHandle != nullptr) {
793 connect(d->bottomResizeHandle, &QQuickItem::heightChanged,
794 this, &QWaylandQtShellChrome::updateDecorations);
795
796 d->bottomResizeHandleHandler = new QQuickDragHandler(d->bottomResizeHandle);
797 d->bottomResizeHandleHandler->setCursorShape(Qt::SizeVerCursor);
798 d->bottomResizeHandleHandler->setTarget(nullptr);
799
800 connect(d->bottomResizeHandleHandler, &QQuickPointerHandler::grabChanged,
801 this, &QWaylandQtShellChrome::stopGrab);
802 connect(d->bottomResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
803 this, &QWaylandQtShellChrome::bottomResize);
804
805 }
806
807 emit bottomResizeHandleChanged();
808}
809
810/*!
811 * \qmlproperty Item QtShellChrome::topLeftResizeHandle
812 *
813 * This property holds the default top-left resize handle of the QtShellChrome. If set, a \l DragHandler
814 * will be installed on the resize handle which resizes the window by moving its top and left edges
815 * in equal amounts.
816 *
817 * The handle will automatically hide and show, depending on the window flags and the window's full
818 * screen state.
819 *
820 * \qml
821 * QtShellChrome {
822 * Rectangle {
823 * id: tlrh
824 * anchors.top: parent.top
825 * anchors.left: parent.left
826 * height: 5
827 * width: 5
828 * color: "white"
829 * }
830 * topLeftResizeHandle: tlrh
831 * }
832 * \endqml
833 */
834
835/*!
836 * \property QWaylandQtShellChrome::topLeftResizeHandle
837 *
838 * This property holds the default top-left resize handle of the
839 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
840 * resize handle which resizes the window by moving its top and left edges in
841 * equal amounts.
842 *
843 * The handle will automatically hide and show, depending on the window flags
844 * and the window's full screen state.
845 */
846QQuickItem *QWaylandQtShellChrome::topLeftResizeHandle() const
847{
848 Q_D(const QWaylandQtShellChrome);
849 return d->topLeftResizeHandle;
850}
851
852void QWaylandQtShellChrome::setTopLeftResizeHandle(QQuickItem *item)
853{
854 Q_D(QWaylandQtShellChrome);
855 if (d->topLeftResizeHandle == item)
856 return;
857
858 if (d->topLeftResizeHandle != nullptr) {
859 delete d->topLeftResizeHandleHandler;
860 d->topLeftResizeHandleHandler = nullptr;
861 }
862
863 d->topLeftResizeHandle = item;
864
865 if (d->topLeftResizeHandle != nullptr) {
866 d->topLeftResizeHandleHandler = new QQuickDragHandler(d->topLeftResizeHandle);
867 d->topLeftResizeHandleHandler->setCursorShape(Qt::SizeFDiagCursor);
868 d->topLeftResizeHandleHandler->setTarget(nullptr);
869
870 connect(d->topLeftResizeHandleHandler, &QQuickPointerHandler::grabChanged,
871 this, &QWaylandQtShellChrome::stopGrab);
872 connect(d->topLeftResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
873 this, &QWaylandQtShellChrome::topLeftResize);
874 }
875
876 emit topLeftResizeHandleChanged();
877}
878
879/*!
880 * \qmlproperty Item QtShellChrome::bottomLeftResizeHandle
881 *
882 * This property holds the default bottom-left resize handle of the QtShellChrome. If set, a \l DragHandler
883 * will be installed on the resize handle which resizes the window by moving its bottom and left edges
884 * in equal amounts.
885 *
886 * The handle will automatically hide and show, depending on the window flags and the window's full
887 * screen state.
888 *
889 * \qml
890 * QtShellChrome {
891 * Rectangle {
892 * id: blrh
893 * anchors.bottom: parent.bottom
894 * anchors.left: parent.left
895 * height: 5
896 * width: 5
897 * color: "white"
898 * }
899 * bottomLeftResizeHandle: blrh
900 * }
901 * \endqml
902 */
903
904/*!
905 * \property QWaylandQtShellChrome::bottomLeftResizeHandle
906 *
907 * This property holds the default bottom-left resize handle of the
908 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
909 * resize handle which resizes the window by moving its bottom and left edges in
910 * equal amounts.
911 *
912 * The handle will automatically hide and show, depending on the window flags
913 * and the window's full screen state.
914 */
915QQuickItem *QWaylandQtShellChrome::bottomLeftResizeHandle() const
916{
917 Q_D(const QWaylandQtShellChrome);
918 return d->bottomLeftResizeHandle;
919}
920
921void QWaylandQtShellChrome::setBottomLeftResizeHandle(QQuickItem *item)
922{
923 Q_D(QWaylandQtShellChrome);
924 if (d->bottomLeftResizeHandle == item)
925 return;
926
927 if (d->bottomLeftResizeHandle != nullptr) {
928 delete d->bottomLeftResizeHandleHandler;
929 d->bottomLeftResizeHandleHandler = nullptr;
930 }
931
932 d->bottomLeftResizeHandle = item;
933
934 if (d->bottomLeftResizeHandle != nullptr) {
935 d->bottomLeftResizeHandleHandler = new QQuickDragHandler(d->bottomLeftResizeHandle);
936 d->bottomLeftResizeHandleHandler->setCursorShape(Qt::SizeBDiagCursor);
937 d->bottomLeftResizeHandleHandler->setTarget(nullptr);
938
939 connect(d->bottomLeftResizeHandleHandler, &QQuickPointerHandler::grabChanged,
940 this, &QWaylandQtShellChrome::stopGrab);
941 connect(d->bottomLeftResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
942 this, &QWaylandQtShellChrome::bottomLeftResize);
943 }
944
945 emit bottomLeftResizeHandleChanged();
946}
947
948/*!
949 * \qmlproperty Item QtShellChrome::topRightResizeHandle
950 *
951 * This property holds the default top-right resize handle of the QtShellChrome. If set, a \l DragHandler
952 * will be installed on the resize handle which resizes the window by moving its top and right edges
953 * in equal amounts.
954 *
955 * The handle will automatically hide and show, depending on the window flags and the window's full
956 * screen state.
957 *
958 * \qml
959 * QtShellChrome {
960 * Rectangle {
961 * id: trrh
962 * anchors.top: parent.top
963 * anchors.right: parent.right
964 * height: 5
965 * width: 5
966 * color: "white"
967 * }
968 * topRightResizeHandle: trrh
969 * }
970 * \endqml
971 */
972
973/*!
974 * \property QWaylandQtShellChrome::topRightResizeHandle
975 *
976 * This property holds the default top-right resize handle of the
977 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
978 * resize handle which resizes the window by moving its top and right edges in
979 * equal amounts.
980 *
981 * The handle will automatically hide and show, depending on the window flags
982 * and the window's full screen state.
983 */
984QQuickItem *QWaylandQtShellChrome::topRightResizeHandle() const
985{
986 Q_D(const QWaylandQtShellChrome);
987 return d->topRightResizeHandle;
988}
989
990void QWaylandQtShellChrome::setTopRightResizeHandle(QQuickItem *item)
991{
992 Q_D(QWaylandQtShellChrome);
993 if (d->topRightResizeHandle == item)
994 return;
995
996 if (d->topRightResizeHandle != nullptr) {
997 delete d->topRightResizeHandleHandler;
998 d->topRightResizeHandleHandler = nullptr;
999 }
1000
1001 d->topRightResizeHandle = item;
1002
1003 if (d->topRightResizeHandle != nullptr) {
1004 d->topRightResizeHandleHandler = new QQuickDragHandler(d->topRightResizeHandle);
1005 d->topRightResizeHandleHandler->setCursorShape(Qt::SizeBDiagCursor);
1006 d->topRightResizeHandleHandler->setTarget(nullptr);
1007
1008 connect(d->topRightResizeHandleHandler, &QQuickPointerHandler::grabChanged,
1009 this, &QWaylandQtShellChrome::stopGrab);
1010 connect(d->topRightResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
1011 this, &QWaylandQtShellChrome::topRightResize);
1012 }
1013
1014 emit topRightResizeHandleChanged();
1015}
1016
1017/*!
1018 * \qmlproperty Item QtShellChrome::bottomRightResizeHandle
1019 *
1020 * This property holds the default bottom-right resize handle of the QtShellChrome. If set, a \l DragHandler
1021 * will be installed on the resize handle which resizes the window by moving its bottom and right edges
1022 * in equal amounts.
1023 *
1024 * The handle will automatically hide and show, depending on the window flags and the window's full
1025 * screen state.
1026 *
1027 * \qml
1028 * QtShellChrome {
1029 * Rectangle {
1030 * id: brrh
1031 * anchors.bottom: parent.bottom
1032 * anchors.right: parent.right
1033 * height: 5
1034 * width: 5
1035 * color: "white"
1036 * }
1037 * bottomRightResizeHandle: brrh
1038 * }
1039 * \endqml
1040 */
1041
1042/*!
1043 * \property QWaylandQtShellChrome::bottomRightResizeHandle
1044 *
1045 * This property holds the default bottom-right resize handle of the
1046 * QWaylandQtShellChrome. If set, a QQuickDragHandler will be installed on the
1047 * resize handle which resizes the window by moving its bottom and right edges
1048 * in equal amounts.
1049 *
1050 * The handle will automatically hide and show, depending on the window flags
1051 * and the window's full screen state.
1052 */
1053QQuickItem *QWaylandQtShellChrome::bottomRightResizeHandle() const
1054{
1055 Q_D(const QWaylandQtShellChrome);
1056 return d->bottomRightResizeHandle;
1057}
1058
1059void QWaylandQtShellChrome::setBottomRightResizeHandle(QQuickItem *item)
1060{
1061 Q_D(QWaylandQtShellChrome);
1062 if (d->bottomRightResizeHandle == item)
1063 return;
1064
1065 if (d->bottomRightResizeHandle != nullptr) {
1066 delete d->bottomRightResizeHandleHandler;
1067 d->bottomRightResizeHandleHandler = nullptr;
1068 }
1069
1070 d->bottomRightResizeHandle = item;
1071
1072 if (d->bottomRightResizeHandle != nullptr) {
1073 d->bottomRightResizeHandleHandler = new QQuickDragHandler(d->bottomRightResizeHandle);
1074 d->bottomRightResizeHandleHandler->setCursorShape(Qt::SizeFDiagCursor);
1075 d->bottomRightResizeHandleHandler->setTarget(nullptr);
1076
1077 connect(d->bottomRightResizeHandleHandler, &QQuickPointerHandler::grabChanged,
1078 this, &QWaylandQtShellChrome::stopGrab);
1079 connect(d->bottomRightResizeHandleHandler, &QQuickMultiPointHandler::centroidChanged,
1080 this, &QWaylandQtShellChrome::bottomRightResize);
1081 }
1082
1083 emit bottomRightResizeHandleChanged();
1084}
1085
1086/*!
1087 * \qmlproperty rect QtShellChrome::maximizedRect
1088 *
1089 * This property holds the are of the WaylandOutput which is available to be filled by the
1090 * window when it is in maximized state. By default, the window will fill the entire geometry
1091 * of the WaylandOutput when it is maximized. Changing it can be useful for example when the
1092 * compositor has other system UI which should not be obscured by maximized applications, such as
1093 * a task bar.
1094 */
1095
1096/*!
1097 * \property QWaylandQtShellChrome::maximizedRect
1098 *
1099 * This property holds the area of the QWaylandOutput which is available to be
1100 * filled by the window when it is in maximized state. By default, the window
1101 * will fill the entire geometry of the QWaylandOutput when it is maximized.
1102 * Changing it can be useful such as when the compositor has other system UI
1103 * which should not be obscured by maximized applications, such as a task bar.
1104 */
1105void QWaylandQtShellChrome::setMaximizedRect(const QRect &rect)
1106{
1107 Q_D(QWaylandQtShellChrome);
1108 if (d->maximizedRect == rect)
1109 return;
1110
1111 d->maximizedRect = rect;
1112 emit maximizedRectChanged();
1113}
1114
1115QRect QWaylandQtShellChrome::maximizedRect() const
1116{
1117 Q_D(const QWaylandQtShellChrome);
1118 if (d->maximizedRect.isValid())
1119 return d->maximizedRect;
1120 else if (d->shellSurfaceItem != nullptr && d->shellSurfaceItem->output() != nullptr)
1121 return d->shellSurfaceItem->output()->geometry();
1122
1123 return QRect{};
1124}
1125
1126void QWaylandQtShellChrome::updateDecorations()
1127{
1128 Q_D(QWaylandQtShellChrome);
1129 if (d->shellSurface == nullptr)
1130 return;
1131
1132 bool decorations = hasDecorations();
1133 bool titleBarShowing = hasTitleBar();
1134
1135 QMargins margins;
1136 if (d->automaticFrameMargins) {
1137 if (d->leftResizeHandle != nullptr && decorations)
1138 margins.setLeft(d->leftResizeHandle->width());
1139 if (d->rightResizeHandle != nullptr && decorations)
1140 margins.setRight(d->rightResizeHandle->width());
1141 if (d->bottomResizeHandle != nullptr && decorations)
1142 margins.setBottom(d->bottomResizeHandle->height());
1143
1144 margins.setTop((decorations && d->topResizeHandle != nullptr ? d->topResizeHandle->height() : 0)
1145 + (titleBarShowing && d->titleBar != nullptr ? d->titleBar->height() : 0));
1146 } else {
1147 margins = d->explicitFrameMargins;
1148 }
1149 d->shellSurface->setFrameMargins(margins);
1150
1151 if (d->titleBar != nullptr)
1152 d->titleBar->setVisible(titleBarShowing);
1153 if (d->leftResizeHandle != nullptr)
1154 d->leftResizeHandle->setVisible(decorations);
1155 if (d->rightResizeHandle != nullptr)
1156 d->rightResizeHandle->setVisible(decorations);
1157 if (d->topResizeHandle != nullptr)
1158 d->topResizeHandle->setVisible(decorations);
1159 if (d->bottomResizeHandle != nullptr)
1160 d->bottomResizeHandle->setVisible(decorations);
1161 if (d->bottomLeftResizeHandle != nullptr)
1162 d->bottomLeftResizeHandle->setVisible(decorations);
1163 if (d->topLeftResizeHandle != nullptr)
1164 d->topLeftResizeHandle->setVisible(decorations);
1165 if (d->bottomRightResizeHandle != nullptr)
1166 d->bottomRightResizeHandle->setVisible(decorations);
1167 if (d->topRightResizeHandle != nullptr)
1168 d->topRightResizeHandle->setVisible(decorations);
1169
1170 bool minimizedOrMaximized = (d->currentState & (Qt::WindowMaximized|Qt::WindowMinimized)) != 0;
1171 if (d->leftResizeHandleHandler != nullptr)
1172 d->leftResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1173 if (d->rightResizeHandleHandler != nullptr)
1174 d->rightResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1175 if (d->bottomResizeHandleHandler != nullptr)
1176 d->bottomResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1177 if (d->topResizeHandleHandler != nullptr)
1178 d->topResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1179 if (d->bottomLeftResizeHandleHandler != nullptr)
1180 d->bottomLeftResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1181 if (d->bottomRightResizeHandleHandler != nullptr)
1182 d->bottomRightResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1183 if (d->topLeftResizeHandleHandler != nullptr)
1184 d->topLeftResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1185 if (d->topRightResizeHandleHandler != nullptr)
1186 d->topRightResizeHandleHandler->setEnabled(decorations && !minimizedOrMaximized);
1187 if (d->titleBarHandler != nullptr)
1188 d->titleBarHandler->setEnabled(titleBarShowing && !minimizedOrMaximized);
1189}
1190
1191void QWaylandQtShellChrome::updateGeometry()
1192{
1193 Q_D(QWaylandQtShellChrome);
1194 if (d->shellSurface == nullptr)
1195 return;
1196
1197 QRect windowGeometry = d->shellSurface->windowGeometry();
1198
1199 QPointF position = windowGeometry.topLeft();
1200 position.rx() -= d->shellSurface->frameMarginLeft();
1201 position.ry() -= d->shellSurface->frameMarginTop();
1202
1203 QSizeF size = windowGeometry.size();
1204 size.rwidth() += d->shellSurface->frameMarginLeft() + d->shellSurface->frameMarginRight();
1205 size.rheight() += d->shellSurface->frameMarginTop() + d->shellSurface->frameMarginBottom();
1206
1207 setPosition(position);
1208 setSize(size);
1209}
1210
1211void QWaylandQtShellChrome::updateSurface()
1212{
1213 Q_D(QWaylandQtShellChrome);
1214 QWaylandSurface *surface = d->shellSurface != nullptr ? d->shellSurface->surface() : nullptr;
1215 if (d->surface == surface)
1216 return;
1217
1218 if (d->surface != nullptr)
1219 d->surface->disconnect(this);
1220
1221 d->surface = surface;
1222
1223 if (d->surface != nullptr) {
1224 connect(d->surface, &QWaylandSurface::hasContentChanged,
1225 this, &QWaylandQtShellChrome::updateAutomaticPosition);
1226 }
1227}
1228
1229void QWaylandQtShellChrome::updateShellSurface()
1230{
1231 Q_D(QWaylandQtShellChrome);
1232 QWaylandQtShellSurface *sf = d->shellSurfaceItem != nullptr
1233 ? qobject_cast<QWaylandQtShellSurface *>(d->shellSurfaceItem->shellSurface())
1234 : nullptr;
1235 if (d->shellSurface == sf)
1236 return;
1237
1238 if (d->shellSurface != nullptr) {
1239 d->shellSurface->disconnect(this);
1240 if (d->shell != nullptr)
1241 d->shell->unregisterChrome(this);
1242 d->shell = nullptr;
1243 }
1244
1245 d->shellSurface = sf;
1246 if (d->shellSurface != nullptr) {
1247 d->shell = d->shellSurface->shell();
1248 if (d->shell != nullptr)
1249 d->shell->registerChrome(this);
1250
1251 updateWindowFlags();
1252 connect(d->shellSurface, &QWaylandQtShellSurface::windowFlagsChanged,
1253 this, &QWaylandQtShellChrome::updateWindowFlags);
1254 connect(d->shellSurface, &QWaylandQtShellSurface::windowStateChanged,
1255 this, &QWaylandQtShellChrome::updateWindowState);
1256 connect(d->shellSurface, &QWaylandQtShellSurface::frameMarginChanged,
1257 this, &QWaylandQtShellChrome::updateGeometry);
1258 connect(d->shellSurface, &QWaylandQtShellSurface::windowGeometryChanged,
1259 this, &QWaylandQtShellChrome::updateGeometry);
1260 connect(d->shellSurface, &QWaylandQtShellSurface::raiseRequested,
1261 this, &QWaylandQtShellChrome::raise);
1262 connect(d->shellSurface, &QWaylandQtShellSurface::lowerRequested,
1263 this, &QWaylandQtShellChrome::lower);
1264 connect(d->shellSurface, &QWaylandQtShellSurface::activeChanged,
1265 this, &QWaylandQtShellChrome::updateActiveState);
1266 connect(d->shellSurface, &QWaylandQtShellSurface::surfaceChanged,
1267 this, &QWaylandQtShellChrome::updateSurface);
1268 }
1269
1270 updateDecorations();
1271 updateSurface();
1272}
1273
1274void QWaylandQtShellChrome::updateWindowState()
1275{
1276 Q_D(QWaylandQtShellChrome);
1277 if (d->shellSurface == nullptr)
1278 return;
1279
1280 setWindowState(d->shellSurface->windowState());
1281}
1282
1283void QWaylandQtShellChrome::updateWindowFlags()
1284{
1285 Q_D(QWaylandQtShellChrome);
1286
1287 uint nextFlags = d->shellSurface == nullptr || d->shellSurface->windowFlags() == Qt::Window
1288 ? d->defaultFlags
1289 : d->shellSurface->windowFlags();
1290
1291 if (d->currentFlags != nextFlags) {
1292 d->currentFlags = nextFlags;
1293 emit currentWindowFlagsChanged();
1294 }
1295}
1296
1297/*!
1298 * \qmlproperty int QtShellChrome::windowFlags
1299 *
1300 * This property holds the window flags of the QtShellChrome. They will match the \c windowFlags
1301 * property of the associated QtShellSurface, except when this is equal to Qt.Window. In this case,
1302 * a set of default window flags will be used instead. The default window flags are Qt.Window,
1303 * Qt.WindowMaximizeButtonHint, Qt.WindowMinimizeButtonHint and Qt.WindowCloseButtonHint.
1304 */
1305
1306/*!
1307 * \property QWaylandQtShellChrome::windowFlags
1308 *
1309 * This property holds the window flags of the QWaylandQtShellChrome. They will
1310 * match the windowFlags property of the associated QWaylandQtShellSurface,
1311 * except when this is equal to Qt::Window. In this case, a set of default
1312 * window flags will be used instead. The default window flags are Qt::Window,
1313 * Qt::WindowMaximizeButtonHint, Qt::WindowMinimizeButtonHint and
1314 * Qt::WindowCloseButtonHint.
1315 */
1316uint QWaylandQtShellChrome::currentWindowFlags() const
1317{
1318 Q_D(const QWaylandQtShellChrome);
1319 return d->currentFlags;
1320}
1321
1322/*!
1323 * \qmlproperty int QtShellChrome::windowState
1324 *
1325 * This property holds the window state of the shell surface. It will be updated immediately when
1326 * the window state is requested on the compositor-side, before this has been acknowledged by the
1327 * client. Therefore, it may in brief periods differ from the shell surface's \c windowState
1328 * property, which will be updated when the client has acknowledged the request.
1329 */
1330
1331/*!
1332 * \property QWaylandQtShellChrome::windowState
1333 *
1334 * This property holds the window state of the shell surface. It will be updated
1335 * immediately when the window state is requested on the compositor-side, before
1336 * this has been acknowledged by the client. Therefore, it may in brief periods
1337 * differ from the shell surface's windowState property, which will be updated
1338 * when the client has acknowledged the request.
1339 */
1340uint QWaylandQtShellChrome::currentWindowState() const
1341{
1342 Q_D(const QWaylandQtShellChrome);
1343 return d->currentState;
1344}
1345
1346bool QWaylandQtShellChrome::hasTitleBar() const
1347{
1348 Q_D(const QWaylandQtShellChrome);
1349
1350 bool frameless = (d->currentFlags & Qt::FramelessWindowHint) == Qt::FramelessWindowHint
1351 || ((d->currentFlags & Qt::Popup) == Qt::Popup
1352 && (d->currentFlags & Qt::Tool) != Qt::Tool)
1353 || (d->currentState & Qt::WindowFullScreen) == Qt::WindowFullScreen;
1354 return !frameless;
1355}
1356
1357/*!
1358 * \qmlproperty bool QtShellChrome::hasDecorations
1359 *
1360 * This property is true if the QtShellChrome's decorations should be visible, based on its window
1361 * state and window flags.
1362 */
1363
1364/*!
1365 * \property QWaylandQtShellChrome::hasDecorations
1366 *
1367 * This property is \c true if the QWaylandQtShellChrome's decorations should be
1368 * visible, based on its window state and window flags.
1369 */
1370bool QWaylandQtShellChrome::hasDecorations() const
1371{
1372 Q_D(const QWaylandQtShellChrome);
1373
1374 return hasTitleBar() && (d->currentFlags & Qt::Window) == Qt::Window;
1375}
1376
1377QRect QWaylandQtShellChrome::maxContentRect() const
1378{
1379 Q_D(const QWaylandQtShellChrome);
1380 if (d->shellSurface == nullptr)
1381 return QRect{};
1382
1383 int x0 = d->maximizedRect.x() + d->shellSurface->frameMarginLeft();
1384 int x1 = d->maximizedRect.x() + d->maximizedRect.width() - d->shellSurface->frameMarginRight();
1385 int y0 = d->maximizedRect.y() + d->shellSurface->frameMarginTop();
1386 int y1 = d->maximizedRect.y() + d->maximizedRect.height() - d->shellSurface->frameMarginBottom();
1387
1388 return QRect(x0, y0, x1 - x0, y1 - y0);
1389}
1390
1391static int randomPos(int windowSize, int screenSize)
1392{
1393 return (windowSize >= screenSize) ? 0 : rand() % (screenSize - windowSize);
1394}
1395
1396void QWaylandQtShellChrome::setWindowState(uint nextState)
1397{
1398 Q_D(QWaylandQtShellChrome);
1399
1400 if (d->currentState == nextState)
1401 return;
1402
1403 if (d->shellSurface == nullptr || d->shellSurfaceItem == nullptr)
1404 return;
1405
1406 QWaylandOutput *output = d->shellSurfaceItem->output();
1407 if (output == nullptr)
1408 return;
1409
1410 if ((d->currentState & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)) == 0) {
1411 d->restoreGeometry = d->shellSurface->windowGeometry();
1412 }
1413
1414 d->currentState = nextState;
1415 emit currentWindowStateChanged();
1416
1417 if ((nextState & Qt::WindowMinimized) != 0) {
1418 d->shellSurface->requestWindowGeometry(nextState, QRect(0, 0, 1, 1));
1419 d->shellSurfaceItem->setVisible(false);
1420 deactivate();
1421 } else if ((nextState & Qt::WindowFullScreen) != 0) {
1422 d->shellSurfaceItem->setVisible(true);
1423 d->shellSurface->requestWindowGeometry(nextState, QRect(QPoint(0, 0), output->window()->size()));
1424 activate();
1425 } else if ((nextState & Qt::WindowMaximized) != 0) {
1426 d->shellSurfaceItem->setVisible(true);
1427 d->shellSurface->requestWindowGeometry(nextState, maxContentRect());
1428 activate();
1429 } else {
1430 d->shellSurfaceItem->setVisible(true);
1431 d->shellSurface->requestWindowGeometry(nextState, d->restoreGeometry);
1432 activate();
1433 }
1434}
1435
1436void QWaylandQtShellChrome::updateAutomaticPosition()
1437{
1438 Q_D(QWaylandQtShellChrome);
1439 if (!d->positionSet && d->shellSurface != nullptr) {
1440 bool randomize = d->shellSurface->positionAutomatic();
1441 QRect rect = d->shellSurface->windowGeometry();
1442 QRect space = maxContentRect();
1443
1444 int xpos = randomize ? randomPos(rect.width(), space.width()) + space.x()
1445 : qMax(rect.x(), space.x());
1446 int ypos = randomize ? randomPos(rect.height(), space.height()) + space.y()
1447 : qMax(rect.y(), space.y());
1448
1449 d->shellSurface->setWindowPosition(QPoint(xpos, ypos));
1450 d->positionSet = true;
1451 }
1452}
1453
1454/*!
1455 * \qmlmethod void QtShellChrome::deactivate()
1456 *
1457 * Manually deactivates this window. If the window was active, this will activate the next window in
1458 * the stack instead.
1459 */
1460void QWaylandQtShellChrome::deactivate()
1461{
1462 Q_D(QWaylandQtShellChrome);
1463 if (d->shellSurface != nullptr)
1464 d->shellSurface->setActive(false);
1465}
1466
1467void QWaylandQtShellChrome::activateOnGrab(QPointingDevice::GrabTransition transition)
1468{
1469 Q_D(QWaylandQtShellChrome);
1470 if (d->titleBarHandler != nullptr) {
1471 switch (transition) {
1472 case QPointingDevice::GrabPassive:
1473 case QPointingDevice::OverrideGrabPassive:
1474 case QPointingDevice::GrabExclusive:
1475 activate();
1476 break;
1477 default:
1478 break;
1479 }
1480 }
1481}
1482
1483/*!
1484 * \qmlmethod void QtShellChrome::activate()
1485 *
1486 * Manually activate this window. This will also raise the window.
1487 *
1488 * \sa raise()
1489 */
1490void QWaylandQtShellChrome::activate()
1491{
1492 Q_D(QWaylandQtShellChrome);
1493 if (d->shellSurface != nullptr)
1494 d->shellSurface->setActive(true);
1495 raise();
1496}
1497
1498/*!
1499 * \qmlmethod void QtShellChrome::raise()
1500 *
1501 * Raise this window, so that it stacks on top of other windows (except if the other window's
1502 * flags prohibit this.)
1503 */
1504void QWaylandQtShellChrome::raise()
1505{
1506 Q_D(QWaylandQtShellChrome);
1507 if (d->shellSurfaceItem != nullptr)
1508 d->shellSurfaceItem->raise();
1509}
1510
1511/*!
1512 * \qmlmethod void QtShellChrome::lower()
1513 *
1514 * Lower this window, so that it stacks underneath other windows (except if the other window's
1515 * window flags prohibit this.)
1516 */
1517void QWaylandQtShellChrome::lower()
1518{
1519 Q_D(QWaylandQtShellChrome);
1520 if (d->shellSurfaceItem != nullptr)
1521 d->shellSurfaceItem->lower();
1522}
1523
1524void QWaylandQtShellChrome::updateActiveState()
1525{
1526 Q_D(QWaylandQtShellChrome);
1527 if (d->shellSurface == nullptr)
1528 return;
1529
1530 if (d->shellSurface->active()) {
1531 raise();
1532 emit activated();
1533 } else {
1534 emit deactivated();
1535 }
1536}
1537
1538/*!
1539 * \qmlproperty int QtShellChrome::frameMarginLeft
1540 *
1541 * Sets the size of the left margin of the QtShellChrome which is reserved for window decorations.
1542 * By default, this will equal the width of the \l leftResizeHandle if it is set. Otherwise it will
1543 * be 0.
1544 *
1545 * \note By setting this property explicitly, all default frame margins will be overridden with
1546 * their corresponding properties.
1547 */
1548
1549/*!
1550 * \property QWaylandQtShellChrome::frameMarginLeft
1551 *
1552 * Sets the size of the left margin of the QWaylandQtShellChrome which is
1553 * reserved for window decorations. By default, this will equal the width of the
1554 * leftResizeHandle if it is set. Otherwise it will be 0.
1555 *
1556 * \note By setting this property explicitly, all default frame margins will be
1557 * overridden with their corresponding properties.
1558 */
1559void QWaylandQtShellChrome::setFrameMarginLeft(int left)
1560{
1561 Q_D(QWaylandQtShellChrome);
1562 if (d->explicitFrameMargins.left() == left)
1563 return;
1564
1565 d->explicitFrameMargins.setLeft(left);
1566 d->automaticFrameMargins = false;
1567 updateDecorations();
1568
1569 emit frameMarginChanged();
1570}
1571
1572int QWaylandQtShellChrome::frameMarginLeft() const
1573{
1574 Q_D(const QWaylandQtShellChrome);
1575 if (d->shellSurface == nullptr)
1576 return 0;
1577 return d->shellSurface->frameMarginLeft();
1578}
1579
1580/*!
1581 * \qmlproperty int QtShellChrome::frameMarginRight
1582 *
1583 * Sets the size of the right margin of the QtShellChrome which is reserved for window decorations.
1584 * By default, this will equal the width of the \l rightResizeHandle if it is set. Otherwise it will
1585 * be 0.
1586 *
1587 * \note By setting this property explicitly, all default frame margins will be overridden with
1588 * their corresponding properties.
1589 */
1590
1591/*!
1592 * \property QWaylandQtShellChrome::frameMarginRight
1593 *
1594 * Sets the size of the right margin of the QWaylandQtShellChrome which is
1595 * reserved for window decorations. By default, this will equal the width of the
1596 * rightResizeHandle if it is set. Otherwise it will be 0.
1597 *
1598 * \note By setting this property explicitly, all default frame margins will be
1599 * overridden with their corresponding properties.
1600 */
1601void QWaylandQtShellChrome::setFrameMarginRight(int right)
1602{
1603 Q_D(QWaylandQtShellChrome);
1604 if (d->explicitFrameMargins.right() == right)
1605 return;
1606
1607 d->explicitFrameMargins.setRight(right);
1608 d->automaticFrameMargins = false;
1609 updateDecorations();
1610
1611 emit frameMarginChanged();
1612}
1613
1614int QWaylandQtShellChrome::frameMarginRight() const
1615{
1616 Q_D(const QWaylandQtShellChrome);
1617 if (d->shellSurface == nullptr)
1618 return 0;
1619 return d->shellSurface->frameMarginRight();
1620}
1621
1622/*!
1623 * \qmlproperty int QtShellChrome::frameMarginTop
1624 *
1625 * Sets the size of the top margin of the QtShellChrome which is reserved for window decorations.
1626 * By default, this will equal the sum of the \l leftResizeHandle and the \l{titleBar}'s heights,
1627 * if they are set. Otherwise it will be 0.
1628 *
1629 * \note By setting this property explicitly, all default frame margins will be overridden with
1630 * their corresponding properties.
1631 */
1632
1633/*!
1634 * \property QWaylandQtShellChrome::frameMarginTop
1635 *
1636 * Sets the size of the top margin of the QWaylandQtShellChrome which is
1637 * reserved for window decorations. By default, this will equal the sum of the
1638 * topResizeHandle and the titleBar's heights, if they are set. Otherwise it
1639 * will be 0.
1640 *
1641 * \note By setting this property explicitly, all default frame margins will be
1642 * overridden with their corresponding properties.
1643 */
1644void QWaylandQtShellChrome::setFrameMarginTop(int top)
1645{
1646 Q_D(QWaylandQtShellChrome);
1647 if (d->explicitFrameMargins.top() == top)
1648 return;
1649 d->explicitFrameMargins.setTop(top);
1650 d->automaticFrameMargins = false;
1651 updateDecorations();
1652
1653 emit frameMarginChanged();
1654}
1655
1656int QWaylandQtShellChrome::frameMarginTop() const
1657{
1658 Q_D(const QWaylandQtShellChrome);
1659 if (d->shellSurface == nullptr)
1660 return 0;
1661 return d->shellSurface->frameMarginTop();
1662}
1663
1664/*!
1665 * \qmlproperty int QtShellChrome::frameMarginBottom
1666 *
1667 * Sets the size of the bottom margin of the QtShellChrome which is reserved for window decorations.
1668 * By default, this will equal the height of the \l bottomResizeHandle if it is set. Otherwise it will
1669 * be 0.
1670 *
1671 * \note By setting this property explicitly, all default frame margins will be overridden with
1672 * their corresponding properties.
1673 */
1674
1675/*!
1676 * \property QWaylandQtShellChrome::frameMarginBottom
1677 *
1678 * Sets the size of the bottom margin of the QWaylandQtShellChrome which is
1679 * reserved for window decorations. By default, this will equal the height of
1680 * the bottomResizeHandle if it is set. Otherwise it will be 0.
1681 *
1682 * \note By setting this property explicitly, all default frame margins will be
1683 * overridden with their corresponding properties.
1684 */
1685void QWaylandQtShellChrome::setFrameMarginBottom(int bottom)
1686{
1687 Q_D(QWaylandQtShellChrome);
1688 if (d->explicitFrameMargins.bottom() == bottom)
1689 return;
1690 d->explicitFrameMargins.setBottom(bottom);
1691 d->automaticFrameMargins = false;
1692 updateDecorations();
1693
1694 emit frameMarginChanged();
1695}
1696
1697int QWaylandQtShellChrome::frameMarginBottom() const
1698{
1699 Q_D(const QWaylandQtShellChrome);
1700 if (d->shellSurface == nullptr)
1701 return 0;
1702 return d->shellSurface->frameMarginBottom();
1703}
1704
1705QT_END_NAMESPACE
1706
1707#include "moc_qwaylandqtshellchrome.cpp"
void updateDecorationInteraction(quint8 flags, const QQuickHandlerPoint &centroid)
Combined button and popup list for selecting options.
static int randomPos(int windowSize, int screenSize)