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