Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwaylandwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qwaylandwindow_p.h"
5
6#include "qwaylandbuffer_p.h"
7#include "qwaylanddisplay_p.h"
8#include "qwaylandsurface_p.h"
11#include "qwaylandscreen_p.h"
20#include "qwaylandviewport_p.h"
21
22#include <QtCore/QFileInfo>
23#include <QtCore/QPointer>
24#include <QtCore/QRegularExpression>
25#include <QtGui/QWindow>
26
27#include <QGuiApplication>
28#include <qpa/qwindowsysteminterface.h>
29#include <QtGui/private/qguiapplication_p.h>
30#include <QtGui/private/qwindow_p.h>
31
32#include <QtCore/QDebug>
33#include <QtCore/QThread>
34#include <QtCore/private/qthread_p.h>
35
36#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h>
37
39
40using namespace Qt::StringLiterals;
41
42namespace QtWaylandClient {
43
44Q_LOGGING_CATEGORY(lcWaylandBackingstore, "qt.qpa.wayland.backingstore")
45
46QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
47QWaylandWindow *QWaylandWindow::mTopPopup = nullptr;
48
51 , mDisplay(display)
52 , mSurfaceLock(QReadWriteLock::Recursive)
53 , mShellIntegration(display->shellIntegration())
54 , mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
55{
56 {
57 bool ok;
58 int frameCallbackTimeout = qEnvironmentVariableIntValue("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", &ok);
59 if (ok)
60 mFrameCallbackTimeout = frameCallbackTimeout;
61 }
62
63 mScale = waylandScreen() ? waylandScreen()->scale() : 1; // fallback to 1 if we don't have a real screen
64
65 static WId id = 1;
66 mWindowId = id++;
67 initializeWlSurface();
68
70 &QNativeInterface::Private::QWaylandWindow::surfaceCreated);
72 &QNativeInterface::Private::QWaylandWindow::surfaceDestroyed);
73}
74
76{
77 delete mWindowDecoration;
78
79 if (mSurface)
80 reset();
81
82 const QWindow *parent = window();
83 const auto tlw = QGuiApplication::topLevelWindows();
84 for (QWindow *w : tlw) {
85 if (w->transientParent() == parent)
87 }
88
89 if (mMouseGrab == this) {
90 mMouseGrab = nullptr;
91 }
92}
93
101
102void QWaylandWindow::initWindow()
103{
104 if (window()->type() == Qt::Desktop)
105 return;
106
107 if (!mSurface) {
108 initializeWlSurface();
109 }
110
111 if (mDisplay->fractionalScaleManager() && qApp->highDpiScaleFactorRoundingPolicy() == Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) {
112 mFractionalScale.reset(new QWaylandFractionalScale(mDisplay->fractionalScaleManager()->get_fractional_scale(mSurface->object())));
113
115 this, &QWaylandWindow::updateScale);
116 }
117
118 if (shouldCreateSubSurface()) {
120
121 auto *parent = static_cast<QWaylandWindow *>(QPlatformWindow::parent());
122 if (!parent->mSurface)
123 parent->initializeWlSurface();
124 if (parent->wlSurface()) {
125 if (::wl_subsurface *subsurface = mDisplay->createSubSurface(this, parent))
126 mSubSurfaceWindow = new QWaylandSubSurface(this, parent, subsurface);
127 }
128 } else if (shouldCreateShellSurface()) {
131 mTransientParent = guessTransientParent();
132 if (mTransientParent) {
133 if (window()->type() == Qt::Popup) {
134 if (mTopPopup && mTopPopup != mTransientParent) {
135 qCWarning(lcQpaWayland) << "Creating a popup with a parent," << mTransientParent->window()
136 << "which does not match the current topmost grabbing popup,"
137 << mTopPopup->window() << "With some shell surface protocols, this"
138 << "is not allowed. The wayland QPA plugin is currently handling"
139 << "it by setting the parent to the topmost grabbing popup."
140 << "Note, however, that this may cause positioning errors and"
141 << "popups closing unxpectedly. Please fix the transient parent of the popup.";
142 mTransientParent = mTopPopup;
143 }
144 mTopPopup = this;
145 }
146 }
147
149 if (mShellSurface) {
150 if (mTransientParent) {
151 if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup)
152 mTransientParent->addChildPopup(this);
153 }
154
155 // Set initial surface title
157
158 // The appId is the desktop entry identifier that should follow the
159 // reverse DNS convention (see
160 // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html). According
161 // to xdg-shell the appId is only the name, without the .desktop suffix.
162 //
163 // If the application specifies the desktop file name use that,
164 // otherwise fall back to the executable name and prepend the
165 // reversed organization domain when available.
166 if (!QGuiApplication::desktopFileName().isEmpty()) {
168 } else {
169 QFileInfo fi = QFileInfo(QCoreApplication::instance()->applicationFilePath());
170 QStringList domainName =
171 QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'),
173
174 if (domainName.isEmpty()) {
175 mShellSurface->setAppId(fi.baseName());
176 } else {
177 QString appId;
178 for (int i = 0; i < domainName.size(); ++i)
179 appId.prepend(QLatin1Char('.')).prepend(domainName.at(i));
180 appId.append(fi.baseName());
181 mShellSurface->setAppId(appId);
182 }
183 }
184 // the user may have already set some window properties, so make sure to send them out
185 for (auto it = m_properties.cbegin(); it != m_properties.cend(); ++it)
186 mShellSurface->sendProperty(it.key(), it.value());
187
188 emit surfaceRoleCreated();
189 } else {
190 qWarning("Could not create a shell surface object.");
191 }
192 }
193
194 // The fractional scale manager check is needed to work around Gnome < 36 where viewports don't work
195 // Right now viewports are only necessary when a fractional scale manager is used
196 if (display()->viewporter() && display()->fractionalScaleManager()) {
197 mViewport.reset(new QWaylandViewport(display()->createViewport(this)));
198 }
199
200 // Enable high-dpi rendering. Scale() returns the screen scale factor and will
201 // typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
202 // to inform the compositor that high-resolution buffers will be provided.
203 if (mViewport)
204 updateViewport();
205 else if (mSurface->version() >= 3)
206 mSurface->set_buffer_scale(std::ceil(scale()));
207
211 if (geometry.width() <= 0)
212 geometry.setWidth(defaultGeometry.width());
213 if (geometry.height() <= 0)
214 geometry.setHeight(defaultGeometry.height());
215
216 setGeometry_helper(geometry);
217 setMask(window()->mask());
218 if (mShellSurface)
220 handleContentOrientationChange(window()->contentOrientation());
221 mFlags = window()->flags();
222
223 mSurface->commit();
224}
225
226void QWaylandWindow::initializeWlSurface()
227{
229 {
233 this, &QWaylandWindow::handleScreensChanged);
235 this, &QWaylandWindow::updateScale);
238 mSurface->m_window = this;
239 }
241}
242
244{
246 if (mShellSurface) {
247 qCWarning(lcQpaWayland) << "Cannot set shell integration while there's already a shell surface created";
248 return;
249 }
251}
252
253bool QWaylandWindow::shouldCreateShellSurface() const
254{
255 if (!shellIntegration())
256 return false;
257
258 if (shouldCreateSubSurface())
259 return false;
260
261 if (window()->inherits("QShapedPixmapWindow"))
262 return false;
263
264 if (qEnvironmentVariableIsSet("QT_WAYLAND_USE_BYPASSWINDOWMANAGERHINT"))
266
267 return true;
268}
269
270bool QWaylandWindow::shouldCreateSubSurface() const
271{
272 return QPlatformWindow::parent() != nullptr;
273}
274
276{
277 mSurfaceLock.lockForRead();
278}
279
281{
282 mSurfaceLock.unlock();
283}
284
286{
288
289 if (mTopPopup == this)
290 mTopPopup = mTransientParent && (mTransientParent->window()->type() == Qt::Popup) ? mTransientParent : nullptr;
291
292 if (mSurface) {
293 {
297 mTransientParent->removeChildPopup(this);
298 delete mShellSurface;
299 mShellSurface = nullptr;
300 emit surfaceRoleDestroyed();
301 delete mSubSurfaceWindow;
302 mSubSurfaceWindow = nullptr;
303 mTransientParent = nullptr;
304 mSurface.reset();
305 mViewport.reset();
306 mFractionalScale.reset();
307 }
309 }
310
311 {
313 if (mFrameCallback) {
314 wl_callback_destroy(mFrameCallback);
315 mFrameCallback = nullptr;
316 }
317
320 }
324 }
325
328 mCanResize = true;
329 mResizeDirty = false;
330
332 mMask = QRegion();
333
336
337 if (mQueuedBuffer) {
338 mQueuedBuffer->setBusy(false);
339 }
340 mQueuedBuffer = nullptr;
342
344}
345
347{
349 return s->m_window;
350 return nullptr;
351}
352
354{
355 return mWindowId;
356}
357
359{
360 if (!window()->isVisible())
361 return;
362
363 QWaylandWindow *oldparent = mSubSurfaceWindow ? mSubSurfaceWindow->parent() : nullptr;
364 if (oldparent == parent)
365 return;
366
367 if (mSubSurfaceWindow && parent) { // new parent, but we were a subsurface already
368 delete mSubSurfaceWindow;
369 QWaylandWindow *p = const_cast<QWaylandWindow *>(static_cast<const QWaylandWindow *>(parent));
371 } else { // we're changing role, need to make a new wl_surface
372 reset();
373 initWindow();
374 }
375}
376
381
383{
384 const QString separator = QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH
385 const QString formatted = formatWindowTitle(title, separator);
386
387 const int libwaylandMaxBufferSize = 4096;
388 // Some parts of the buffer is used for metadata, so subtract 100 to be on the safe side.
389 // Also, QString is in utf-16, which means that in the worst case each character will be
390 // three bytes when converted to utf-8 (which is what libwayland uses), so divide by three.
391 const int maxLength = libwaylandMaxBufferSize / 3 - 100;
392
393 auto truncated = QStringView{formatted}.left(maxLength);
394 if (truncated.size() < formatted.size()) {
395 qCWarning(lcQpaWayland) << "Window titles longer than" << maxLength << "characters are not supported."
396 << "Truncating window title (from" << formatted.size() << "chars)";
397 }
398
399 mWindowTitle = truncated.toString();
400
401 if (mShellSurface)
403
406}
407
415
417{
418 return QRect(QPoint(), QSize(500,500));
419}
420
421void QWaylandWindow::setGeometry_helper(const QRect &rect)
422{
424 if (mViewport)
425 updateViewport();
426
427 if (mSubSurfaceWindow) {
429 mSubSurfaceWindow->set_position(rect.x() + m.left(), rect.y() + m.top());
430
431 QWaylandWindow *parentWindow = mSubSurfaceWindow->parent();
432 if (parentWindow && parentWindow->isExposed()) {
433 QRect parentExposeGeometry(QPoint(), parentWindow->geometry().size());
434 parentWindow->sendExposeEvent(parentExposeGeometry);
435 }
436 }
437}
438
440{
441 auto rect = r;
443 && window()->type() != Qt::ToolTip) {
444 rect.moveTo(screen()->geometry().topLeft());
445 }
446 setGeometry_helper(rect);
447
448 if (window()->isVisible() && rect.isValid()) {
451
454 mResizeDirty = true;
455 } else {
457 }
458 mSentInitialResize = true;
459 }
460 QRect exposeGeometry(QPoint(), geometry().size());
461 if (isExposed() && !mInResizeFromApplyConfigure && exposeGeometry != mLastExposeGeometry)
462 sendExposeEvent(exposeGeometry);
463
464 if (mShellSurface) {
466 if (!qt_window_private(window())->positionAutomatic)
468 }
469
470 if (isOpaque() && mMask.isEmpty())
471 setOpaqueArea(QRect(QPoint(0, 0), rect.size()));
472}
473
474void QWaylandWindow::updateInputRegion()
475{
476 if (!mSurface)
477 return;
478
479 const bool transparentInputRegion = mFlags.testFlag(Qt::WindowTransparentForInput);
480
481 QRegion inputRegion;
482 if (!transparentInputRegion)
483 inputRegion = mMask;
484
485 if (mInputRegion == inputRegion && mTransparentInputRegion == transparentInputRegion)
486 return;
487
488 mInputRegion = inputRegion;
489 mTransparentInputRegion = transparentInputRegion;
490
492 mSurface->set_input_region(nullptr);
493 } else {
494 struct ::wl_region *region = mDisplay->createRegion(mInputRegion);
495 mSurface->set_input_region(region);
496 wl_region_destroy(region);
497 }
498}
499
500void QWaylandWindow::updateViewport()
501{
502 if (!surfaceSize().isEmpty())
503 mViewport->setDestination(surfaceSize());
504}
505
506void QWaylandWindow::setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins)
507{
508 QMargins margins = clientSideMargins();
509
510 QPoint positionWithoutMargins = globalPosition + QPoint(margins.left(), margins.top());
511 int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
512 int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
513
514 QRect geometry(positionWithoutMargins, QSize(widthWithoutMargins, heightWithoutMargins));
515
516 mInResizeFromApplyConfigure = true;
518 mInResizeFromApplyConfigure = false;
519}
520
522{
523 QMargins margins = clientSideMargins();
524 QPoint positionWithoutMargins = globalPosition + QPoint(margins.left(), margins.top());
525
526 QRect geometry(positionWithoutMargins, windowGeometry().size());
527 mInResizeFromApplyConfigure = true;
529 mInResizeFromApplyConfigure = false;
530}
531
533{
534 QMargins margins = clientSideMargins();
535 int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
536 int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
537 QRect geometry(windowGeometry().topLeft(), QSize(widthWithoutMargins, heightWithoutMargins));
538
539 mOffset += offset;
540 mInResizeFromApplyConfigure = true;
542 mInResizeFromApplyConfigure = false;
543}
544
546{
549 else
550 qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
551 mLastExposeGeometry = rect;
552}
553
554QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
555{
557 if (mSurface) {
558 if (auto *screen = mSurface->oldestEnteredScreen())
559 return screen;
560 }
561
563}
564
566{
567 // Workaround for issue where setVisible may be called with the same value twice
568 if (lastVisible == visible)
569 return;
570 lastVisible = visible;
571
572 if (visible) {
573 initWindow();
574
576 // Don't flush the events here, or else the newly visible window may start drawing, but since
577 // there was no frame before it will be stuck at the waitForFrameSync() in
578 // QWaylandShmBackingStore::beginPaint().
579
580 if (mShellSurface)
582 } else {
584 reset();
585 }
586}
587
588
590{
591 if (mShellSurface)
593}
594
595
597{
598 if (mShellSurface)
600}
601
603{
604 QReadLocker locker(&mSurfaceLock);
605 if (!mSurface)
606 return;
607
608 if (mMask == mask)
609 return;
610
611 mMask = mask;
612
613 updateInputRegion();
614
615 if (isOpaque()) {
616 if (mMask.isEmpty())
617 setOpaqueArea(QRect(QPoint(0, 0), geometry().size()));
618 else
619 setOpaqueArea(mMask);
620 }
621}
622
628
630{
631 if (mShellSurface)
632 return mShellSurface->isAlertState();
633
634 return false;
635}
636
645
647{
649 return;
650
651 Q_ASSERT_X(QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed(),
652 "QWaylandWindow::doApplyConfigure", "not called from main thread");
653
654 if (mShellSurface)
656
658}
659
660void QWaylandWindow::doApplyConfigureFromOtherThread()
661{
664 return;
667}
668
670{
672 mCanResize = canResize;
673
674 if (canResize) {
675 if (mResizeDirty) {
677 }
679 bool inGuiThread = QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed();
680 if (inGuiThread) {
683 } else {
684 QMetaObject::invokeMethod(this, &QWaylandWindow::doApplyConfigureFromOtherThread, Qt::QueuedConnection);
685 }
686 } else if (mResizeDirty) {
687 mResizeDirty = false;
689 }
690 }
691}
692
704
706{
707 if (!isExposed())
709 else
711
712 for (QWaylandSubSurface *subSurface : std::as_const(mChildren)) {
713 auto subWindow = subSurface->window();
714 subWindow->sendRecursiveExposeEvent();
715 }
716}
717
719{
720 QReadLocker locker(&mSurfaceLock);
721 if (mSurface == nullptr)
722 return;
723
724 if (buffer) {
725 Q_ASSERT(!buffer->committed());
726 handleUpdate();
727 buffer->setBusy(true);
728 if (mSurface->version() >= WL_SURFACE_OFFSET_SINCE_VERSION) {
729 mSurface->offset(x, y);
730 mSurface->attach(buffer->buffer(), 0, 0);
731 } else {
732 mSurface->attach(buffer->buffer(), x, y);
733 }
734 } else {
735 mSurface->attach(nullptr, 0, 0);
736 }
737}
738
744
746{
747 QReadLocker locker(&mSurfaceLock);
748 if (mSurface == nullptr)
749 return;
750
751 const qreal s = scale();
752 if (mSurface->version() >= 4) {
753 const QRect bufferRect =
754 QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
755 .toAlignedRect();
756 mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
757 bufferRect.height());
758 } else {
759 mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
760 }
761}
762
764{
765 if (isExposed()) {
767 } else {
768 if (mQueuedBuffer) {
769 mQueuedBuffer->setBusy(false);
770 }
772 mQueuedBuffer->setBusy(true);
774 }
775}
776
778{
780 if (buffer->committed()) {
781 qCDebug(lcWaylandBackingstore) << "Buffer already committed, ignoring.";
782 return;
783 }
784
785 QReadLocker locker(&mSurfaceLock);
786 if (!mSurface)
787 return;
788
790 if (mSurface->version() >= 4) {
791 const qreal s = scale();
792 for (const QRect &rect : damage) {
793 const QRect bufferRect =
794 QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
795 .toAlignedRect();
796 mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
797 bufferRect.height());
798 }
799 } else {
800 for (const QRect &rect: damage)
801 mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
802 }
803 Q_ASSERT(!buffer->committed());
804 buffer->setCommitted();
805 mSurface->commit();
806}
807
809{
810 QReadLocker locker(&mSurfaceLock);
811 if (mSurface != nullptr)
812 mSurface->commit();
813}
814
815const wl_callback_listener QWaylandWindow::callbackListener = {
816 [](void *data, wl_callback *callback, uint32_t time) {
817 Q_UNUSED(time);
818 auto *window = static_cast<QWaylandWindow*>(data);
819 window->handleFrameCallback(callback);
820 }
821};
822
823void QWaylandWindow::handleFrameCallback(wl_callback* callback)
824{
826 if (!mFrameCallback) {
827 // This means the callback is already unset by QWaylandWindow::reset.
828 // The wl_callback object will be destroyed there too.
829 return;
830 }
831 Q_ASSERT(callback == mFrameCallback);
832 wl_callback_destroy(callback);
833 mFrameCallback = nullptr;
834
837
838 // The rest can wait until we can run it on the correct thread
840 // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync()
841 // in the single-threaded case.
843 }
845}
846
848{
850 bool wasExposed = isExposed();
852 if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
854 if (wasExposed && hasPendingUpdateRequest())
856
857}
858
860{
862
865
867 qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
869 mWaitingForUpdate = false;
871 }
872
874}
875
885
890
892 const QMargins oldMargins = mCustomMargins;
893 mCustomMargins = margins;
894 setGeometry(geometry().marginsRemoved(oldMargins).marginsAdded(margins));
895}
896
901{
902 return geometry().marginsAdded(clientSideMargins()).size();
903}
904
906{
907 QMargins shadowMargins;
908
911
912 if (!mCustomMargins.isNull())
913 shadowMargins += mCustomMargins;
914
915 return shadowMargins;
916}
917
923{
924 const QMargins margins = windowContentMargins();
925 return QRect(QPoint(margins.left(), margins.top()), surfaceSize().shrunkBy(margins));
926}
927
936{
937 const QMargins margins = clientSideMargins();
938 return QPointF(surfacePosition.x() - margins.left(), surfacePosition.y() - margins.top());
939}
940
941wl_surface *QWaylandWindow::wlSurface() const
942{
943 QReadLocker locker(&mSurfaceLock);
944 return mSurface ? mSurface->object() : nullptr;
945}
946
951
953{
955 return mSubSurfaceWindow->object();
956 if (mShellSurface)
957 return mShellSurface->surfaceRole();
958 return {};
959}
960
965
967{
968 auto *platformScreen = QPlatformWindow::screen();
969 Q_ASSERT(platformScreen);
970 if (platformScreen->isPlaceholder())
971 return nullptr;
972 return static_cast<QWaylandScreen *>(platformScreen);
973}
974
980
982{
983 QReadLocker locker(&mSurfaceLock);
984 if (mSurface == nullptr || mSurface->version() < 2)
985 return;
986
987 wl_output_transform transform;
989
990 if (mSurface->version() >= 6) {
991 const auto transform = mSurface->preferredBufferTransform().value_or(WL_OUTPUT_TRANSFORM_NORMAL);
992 if (auto screen = waylandScreen())
993 screenOrientation = screen->toScreenOrientation(transform, Qt::PrimaryOrientation);
994 } else {
995 if (auto screen = window()->screen())
996 screenOrientation = screen->primaryOrientation();
997 }
998
999 const bool isPortrait = (screenOrientation == Qt::PortraitOrientation);
1000
1003 transform = WL_OUTPUT_TRANSFORM_NORMAL;
1004 break;
1006 transform = isPortrait ? WL_OUTPUT_TRANSFORM_270 : WL_OUTPUT_TRANSFORM_NORMAL;
1007 break;
1009 transform = isPortrait ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_90;
1010 break;
1012 transform = isPortrait ? WL_OUTPUT_TRANSFORM_90 : WL_OUTPUT_TRANSFORM_180;
1013 break;
1015 transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
1016 break;
1017 default:
1018 Q_UNREACHABLE();
1019 }
1020 mSurface->set_buffer_transform(transform);
1021}
1022
1028
1034
1036{
1037 if (mShellSurface)
1039
1040 mFlags = flags;
1042
1043 QReadLocker locker(&mSurfaceLock);
1044 updateInputRegion();
1045}
1046
1048{
1049 Q_ASSERT_X(QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed(),
1050 "QWaylandWindow::createDecoration", "not called from main thread");
1051 // TODO: client side decorations do not work with Vulkan backend.
1052 if (window()->surfaceType() == QSurface::VulkanSurface)
1053 return false;
1055 return false;
1056
1057 static bool decorationPluginFailed = false;
1058 bool decoration = false;
1059 switch (window()->type()) {
1060 case Qt::Window:
1061 case Qt::Widget:
1062 case Qt::Dialog:
1063 case Qt::Tool:
1064 case Qt::Drawer:
1065 decoration = true;
1066 break;
1067 default:
1068 break;
1069 }
1071 decoration = false;
1073 decoration = false;
1075 decoration = false;
1077 decoration = false;
1078
1079 bool hadDecoration = mWindowDecorationEnabled;
1080 if (decoration && !decorationPluginFailed) {
1082 if (mWindowDecoration) {
1083 delete mWindowDecoration;
1084 mWindowDecoration = nullptr;
1085 }
1086
1088 if (decorations.empty()) {
1089 qWarning() << "No decoration plugins available. Running with no decorations.";
1090 decorationPluginFailed = true;
1091 return false;
1092 }
1093
1094 QString targetKey;
1095 QByteArray decorationPluginName = qgetenv("QT_WAYLAND_DECORATION");
1096 if (!decorationPluginName.isEmpty()) {
1097 targetKey = QString::fromLocal8Bit(decorationPluginName);
1098 if (!decorations.contains(targetKey)) {
1099 qWarning() << "Requested decoration " << targetKey << " not found, falling back to default";
1100 targetKey = QString(); // fallthrough
1101 }
1102 }
1103
1104 if (targetKey.isEmpty()) {
1105 auto unixServices = dynamic_cast<QGenericUnixServices *>(
1107 const QByteArray currentDesktop = unixServices->desktopEnvironment();
1108 if (currentDesktop == "GNOME") {
1109 if (decorations.contains("adwaita"_L1))
1110 targetKey = "adwaita"_L1;
1111 else if (decorations.contains("gnome"_L1))
1112 targetKey = "gnome"_L1;
1113 } else {
1114 // Do not use Adwaita/GNOME decorations on other DEs
1115 decorations.removeAll("adwaita"_L1);
1116 decorations.removeAll("gnome"_L1);
1117 }
1118 }
1119
1120 if (targetKey.isEmpty())
1121 targetKey = decorations.first(); // first come, first served.
1122
1123
1125 if (!mWindowDecoration) {
1126 qWarning() << "Could not create decoration from factory! Running with no decorations.";
1127 decorationPluginFailed = true;
1128 return false;
1129 }
1132 }
1133 } else {
1135 }
1136
1137 if (hadDecoration != mWindowDecorationEnabled) {
1138 for (QWaylandSubSurface *subsurf : std::as_const(mChildren)) {
1139 QPoint pos = subsurf->window()->geometry().topLeft();
1141 subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
1142 }
1144
1145 // creating a decoration changes our margins which in turn change size hints
1147
1148 // This is a special case where the buffer is recreated, but since
1149 // the content rect remains the same, the widgets remain the same
1150 // size and are not redrawn, leaving the new buffer empty. As a simple
1151 // work-around, we trigger a full extra update whenever the client-side
1152 // window decorations are toggled while the window is showing.
1153 window()->requestUpdate();
1154 }
1155
1156 return mWindowDecoration;
1157}
1158
1163
1165{
1166 while (window) {
1167 auto w = static_cast<QWaylandWindow *>(window->handle());
1168 if (w && w->shellSurface())
1169 return w;
1170 window = window->transientParent() ? window->transientParent() : window->parent();
1171 }
1172 return nullptr;
1173}
1174
1179
1180QWaylandWindow *QWaylandWindow::guessTransientParent() const
1181{
1182 // Take the closest window with a shell surface, since the transient parent may be a
1183 // QWidgetWindow or some other window without a shell surface, which is then not able to
1184 // get mouse events.
1186 return transientParent;
1187
1190
1191 return nullptr;
1192}
1193
1195{
1196 if (e.type == QEvent::Leave) {
1200 } else {
1202 }
1203#if QT_CONFIG(cursor)
1204 restoreMouseCursor(inputDevice);
1205#endif
1206 return;
1207 }
1208
1210 handleMouseEventWithDecoration(inputDevice, e);
1211 } else {
1212 switch (e.type) {
1213 case QEvent::Enter:
1215 break;
1218 case QEvent::MouseMove:
1220 break;
1221 case QEvent::Wheel:
1224 e.phase, e.source, e.inverted);
1225 break;
1226 default:
1227 Q_UNREACHABLE();
1228 }
1229 }
1230
1231#if QT_CONFIG(cursor)
1232 if (e.type == QEvent::Enter) {
1233 QRect contentGeometry = QRect(QPoint(), surfaceSize()).marginsRemoved(clientSideMargins());
1234 if (contentGeometry.contains(e.local.toPoint()))
1235 restoreMouseCursor(inputDevice);
1236 }
1237#endif
1238}
1239
1240#ifndef QT_NO_GESTURES
1243{
1244 switch (e.state) {
1245 case Qt::GestureStarted:
1247 qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
1248
1250 // whole gesture sequence will be ignored
1252 return;
1253 }
1254
1257 inputDevice->mTouchPadDevice,
1259 e.local, e.global, e.fingers);
1260 break;
1261 case Qt::GestureUpdated:
1263 return;
1264
1265 if (!e.delta.isNull()) {
1267 window(), e.timestamp, inputDevice->mTouchPadDevice,
1269 0, e.delta, e.local, e.global, e.fingers);
1270 }
1271 break;
1276 return;
1277 }
1278
1280 qCWarning(lcQpaWaylandInput) << "Unexpected" << (e.state == Qt::GestureFinished ? "GestureFinished" : "GestureCanceled");
1281
1283
1284 // There's currently no way to expose cancelled gestures to the rest of Qt, so
1285 // this part of information is lost.
1287 inputDevice->mTouchPadDevice,
1289 e.local, e.global, e.fingers);
1290 break;
1291 default:
1292 break;
1293 }
1294}
1295
1298{
1299 switch (e.state) {
1300 case Qt::GestureStarted:
1302 qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
1303
1305 // whole gesture sequence will be ignored
1307 return;
1308 }
1309
1312 inputDevice->mTouchPadDevice,
1314 e.local, e.global, e.fingers);
1315 break;
1316 case Qt::GestureUpdated:
1318 return;
1319
1320 if (!e.delta.isNull()) {
1322 window(), e.timestamp, inputDevice->mTouchPadDevice,
1324 0, e.delta, e.local, e.global, e.fingers);
1325 }
1326 if (e.rotation_delta != 0) {
1328 inputDevice->mTouchPadDevice,
1331 e.local, e.global, e.fingers);
1332 }
1333 if (e.scale_delta != 0) {
1335 inputDevice->mTouchPadDevice,
1337 e.scale_delta,
1338 e.local, e.global, e.fingers);
1339 }
1340 break;
1345 return;
1346 }
1347
1349 qCWarning(lcQpaWaylandInput) << "Unexpected" << (e.state == Qt::GestureFinished ? "GestureFinished" : "GestureCanceled");
1350
1352
1353 // There's currently no way to expose cancelled gestures to the rest of Qt, so
1354 // this part of information is lost.
1356 inputDevice->mTouchPadDevice,
1358 e.local, e.global, e.fingers);
1359 break;
1360 default:
1361 break;
1362 }
1363}
1364#endif // #ifndef QT_NO_GESTURES
1365
1366
1367bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods)
1368{
1370 return false;
1371 return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods);
1372}
1373
1374void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
1375{
1377 mWindowDecoration->handleMouse(inputDevice, e.local, e.global, e.buttons, e.modifiers)) {
1381 }
1382 return;
1383 }
1384
1385 QMargins marg = clientSideMargins();
1386 QRect windowRect(0 + marg.left(),
1387 0 + marg.top(),
1388 geometry().size().width(),
1389 geometry().size().height());
1390 if (windowRect.contains(e.local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
1391 const QPointF localTranslated = mapFromWlSurface(e.local);
1392 QPointF globalTranslated = e.global;
1393 globalTranslated.setX(globalTranslated.x() - marg.left());
1394 globalTranslated.setY(globalTranslated.y() - marg.top());
1396#if QT_CONFIG(cursor)
1397 restoreMouseCursor(inputDevice);
1398#endif
1400 }
1401
1402 switch (e.type) {
1403 case QEvent::Enter:
1404 QWindowSystemInterface::handleEnterEvent(window(), localTranslated, globalTranslated);
1405 break;
1408 case QEvent::MouseMove:
1409 QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.button, e.type, e.modifiers);
1410 break;
1411 case QEvent::Wheel: {
1413 localTranslated, globalTranslated,
1415 e.phase, e.source, e.inverted);
1416 break;
1417 }
1418 default:
1419 Q_UNREACHABLE();
1420 }
1421
1424 } else {
1428 }
1429 }
1430}
1431
1432void QWaylandWindow::handleScreensChanged()
1433{
1434 QPlatformScreen *newScreen = calculateScreenFromSurfaceEvents();
1435
1436 if (newScreen == mLastReportedScreen)
1437 return;
1438
1439 if (!newScreen->isPlaceholder() && !newScreen->QPlatformScreen::screen())
1441 QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
1442
1443 mLastReportedScreen = newScreen;
1445 && window()->type() != Qt::ToolTip
1446 && geometry().topLeft() != newScreen->geometry().topLeft()) {
1447 auto geometry = this->geometry();
1448 geometry.moveTo(newScreen->geometry().topLeft());
1450 }
1451
1452 updateScale();
1454}
1455
1456void QWaylandWindow::updateScale()
1457{
1458 if (mFractionalScale) {
1459 auto preferredScale = mFractionalScale->preferredScale().value_or(1.0);
1460 preferredScale = std::max(1.0, preferredScale);
1462 setScale(preferredScale);
1463 return;
1464 }
1465
1466 if (mSurface && mSurface->version() >= 6) {
1467 auto preferredScale = mSurface->preferredBufferScale().value_or(1);
1468 preferredScale = std::max(1, preferredScale);
1469 setScale(preferredScale);
1470 return;
1471 }
1472
1473 int scale = mLastReportedScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(mLastReportedScreen)->scale();
1474 setScale(scale);
1475}
1476
1477void QWaylandWindow::setScale(qreal newScale)
1478{
1479 if (qFuzzyCompare(mScale, newScale))
1480 return;
1481 mScale = newScale;
1482
1484 if (mSurface) {
1485 if (mViewport)
1486 updateViewport();
1487 else if (mSurface->version() >= 3)
1488 mSurface->set_buffer_scale(std::ceil(mScale));
1489 }
1490 ensureSize();
1491
1492 if (isExposed()) {
1493 // redraw at the new DPR
1494 window()->requestUpdate();
1496 }
1497}
1498
1499#if QT_CONFIG(cursor)
1500void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor)
1501{
1502 int fallbackBufferScale = int(devicePixelRatio());
1503 device->setCursor(&cursor, {}, fallbackBufferScale);
1504}
1505
1506void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
1507{
1508 if (const QCursor *overrideCursor = QGuiApplication::overrideCursor())
1509 setMouseCursor(device, *overrideCursor);
1510 else
1511 setMouseCursor(device, window()->cursor());
1512}
1513#endif
1514
1520
1522{
1523 if (!window()->isVisible())
1524 return false;
1525
1527 return false;
1528
1529 if (mShellSurface)
1530 return mShellSurface->isExposed();
1531
1533 return mSubSurfaceWindow->parent()->isExposed();
1534
1535 return !(shouldCreateShellSurface() || shouldCreateSubSurface());
1536}
1537
1539{
1540 return mDisplay->isWindowActivated(this);
1541}
1542
1544{
1545 return devicePixelRatio();
1546}
1547
1549{
1550 return qreal(mScale);
1551}
1552
1554{
1555 if (window()->type() != Qt::Popup) {
1556 qWarning("This plugin supports grabbing the mouse only for popup windows");
1557 return false;
1558 }
1559
1560 mMouseGrab = grab ? this : nullptr;
1561 return true;
1562}
1563
1564QWaylandWindow::ToplevelWindowTilingStates QWaylandWindow::toplevelWindowTilingStates() const
1565{
1567}
1568
1573
1574Qt::WindowStates QWaylandWindow::windowStates() const
1575{
1577}
1578
1580{
1582 Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
1583 Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
1585 lastStatesWithoutActive);
1587}
1588
1598
1600{
1602 QWaylandNativeInterface *nativeInterface = static_cast<QWaylandNativeInterface *>(
1604 nativeInterface->emitWindowPropertyChanged(this, name);
1605}
1606
1608{
1609 return m_properties;
1610}
1611
1616
1618{
1619 return m_properties.value(name, defaultValue);
1620}
1621
1622#ifdef QT_PLATFORM_WINDOW_HAS_VIRTUAL_SET_BACKING_STORE
1624{
1625 mBackingStore = dynamic_cast<QWaylandShmBackingStore *>(store);
1626}
1627#endif
1628
1630{
1631 if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
1632 return;
1633
1634 {
1636
1637 bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
1638 if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
1641 }
1642 if (!mFrameCallbackElapsedTimer.isValid() || !callbackTimerExpired) {
1643 return;
1644 }
1646 }
1647
1648 qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
1650 mWaitingForUpdate = false;
1652}
1653
1655{
1656 qCDebug(lcWaylandBackingstore) << "requestUpdate";
1657 Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
1658
1659 // If we have a frame callback all is good and will be taken care of there
1660 {
1663 return;
1664 }
1665
1666 // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
1667 // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
1668 // here so we can get this information when debugging update/frame callback issues.
1669 // Continue as nothing happened, though.
1671 qCDebug(lcWaylandBackingstore) << "requestUpdate called twice without committing anything";
1672
1673 // Some applications (such as Qt Quick) depend on updates being delivered asynchronously,
1674 // so use invokeMethod to delay the delivery a bit.
1675 QMetaObject::invokeMethod(this, [this] {
1676 // Things might have changed in the meantime
1677 {
1680 return;
1681 }
1685}
1686
1687// Should be called whenever we commit a buffer (directly through wl_surface.commit or indirectly
1688// with eglSwapBuffers) to know when it's time to commit the next one.
1689// Can be called from the render thread (without locking anything) so make sure to not make races in this method.
1691{
1692 qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
1693
1694 // TODO: Should sync subsurfaces avoid requesting frame callbacks?
1696 if (!mSurface)
1697 return;
1698
1701 return;
1702
1703 struct ::wl_surface *wrappedSurface = reinterpret_cast<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object()));
1704 wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mDisplay->frameEventQueue());
1705 mFrameCallback = wl_surface_frame(wrappedSurface);
1706 wl_proxy_wrapper_destroy(wrappedSurface);
1707 wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
1709 mWaitingForUpdate = false;
1710
1711 // Start a timer for handling the case when the compositor stops sending frame callbacks.
1712 if (mFrameCallbackTimeout > 0) {
1713 QMetaObject::invokeMethod(this, [this] {
1715
1720 }
1722 }
1723}
1724
1726{
1727 qCDebug(lcWaylandBackingstore) << "deliverUpdateRequest";
1728 mWaitingForUpdate = true;
1730}
1731
1733{
1734 mOffset += point;
1735}
1736
1742
1744{
1745 if (auto *seat = display()->lastInputDevice()) {
1746 bool rc = mShellSurface && mShellSurface->resize(seat, edges);
1747 seat->handleEndDrag();
1748 return rc;
1749 }
1750 return false;
1751}
1752
1754{
1755 if (auto seat = display()->lastInputDevice()) {
1756 bool rc = mShellSurface && mShellSurface->move(seat);
1757 seat->handleEndDrag();
1758 return rc;
1759 }
1760 return false;
1761}
1762
1763bool QWaylandWindow::isOpaque() const
1764{
1765 return window()->requestedFormat().alphaBufferSize() <= 0;
1766}
1767
1768void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
1769{
1770 const QRegion translatedOpaqueArea = opaqueArea.translated(clientSideMargins().left(), clientSideMargins().top());
1771
1772 if (translatedOpaqueArea == mOpaqueArea || !mSurface)
1773 return;
1774
1775 mOpaqueArea = translatedOpaqueArea;
1776
1777 struct ::wl_region *region = mDisplay->createRegion(translatedOpaqueArea);
1778 mSurface->set_opaque_region(region);
1779 wl_region_destroy(region);
1780}
1781
1786
1791
1792void QWaylandWindow::addChildPopup(QWaylandWindow *child)
1793{
1794 if (mShellSurface)
1795 mShellSurface->attachPopup(child->shellSurface());
1796 mChildPopups.append(child);
1797}
1798
1799void QWaylandWindow::removeChildPopup(QWaylandWindow *child)
1800{
1801 if (mShellSurface)
1802 mShellSurface->detachPopup(child->shellSurface());
1803 mChildPopups.removeAll(child);
1804}
1805
1807 while (!mChildPopups.isEmpty()) {
1808 auto popup = mChildPopups.takeLast();
1809 popup->reset();
1810 }
1811}
1812
1814{
1815 if (window()->isVisible()) {
1816 initWindow();
1819 }
1820}
1821
1832
1833}
1834
1836
1837#include "moc_qwaylandwindow_p.cpp"
IOBluetoothDevice * device
bool testAndSetAcquire(T expectedValue, T newValue) noexcept
void storeRelease(T newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
The QCursor class provides a mouse cursor with an arbitrary shape.
Definition qcursor.h:45
\inmodule QtCore
void invalidate() noexcept
Marks this QElapsedTimer object as invalid.
bool hasExpired(qint64 timeout) const noexcept
Returns true if elapsed() exceeds the given timeout, otherwise false.
void start() noexcept
\typealias QElapsedTimer::Duration Synonym for std::chrono::nanoseconds.
bool isValid() const noexcept
Returns false if the timer has never been started or invalidated by a call to invalidate().
State
Specifies the state of this event point.
Definition qeventpoint.h:48
\inmodule QtCore
Definition qcoreevent.h:45
@ ApplicationPaletteChange
Definition qcoreevent.h:93
@ MouseMove
Definition qcoreevent.h:63
@ MouseButtonPress
Definition qcoreevent.h:60
@ ApplicationFontChange
Definition qcoreevent.h:91
@ MouseButtonRelease
Definition qcoreevent.h:61
static QPlatformIntegration * platformIntegration()
static QPlatformNativeInterface * platformNativeInterface()
static QWindowList topLevelWindows()
Returns a list of the top-level windows in the application.
static QCursor * overrideCursor()
Returns the active application override cursor.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
QString desktopFileName
the base name of the desktop entry for this application
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
const_iterator cend() const
Definition qmap.h:605
const_iterator cbegin() const
Definition qmap.h:601
\inmodule QtCore
Definition qmargins.h:24
constexpr int bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:115
constexpr bool isNull() const noexcept
Returns true if all margins are is 0; otherwise returns false.
Definition qmargins.h:103
constexpr int left() const noexcept
Returns the left margin.
Definition qmargins.h:106
constexpr int right() const noexcept
Returns the right margin.
Definition qmargins.h:112
constexpr int top() const noexcept
Returns the top margin.
Definition qmargins.h:109
\inmodule QtCore
Definition qmutex.h:313
The QPlatformBackingStore class provides the drawing area for top-level windows.
The QPlatformScreen class provides an abstraction for visual displays.
virtual bool isPlaceholder() const
The QPlatformWindow class provides an abstraction for top-level windows.
static QString formatWindowTitle(const QString &title, const QString &separator)
Call this method to put together a window title composed of title separator the application display n...
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
QPlatformScreen * screen() const override
Returns the platform screen handle corresponding to this platform window, or null if the window is no...
virtual bool windowEvent(QEvent *event)
Reimplement this method to be able to do any platform specific event handling.
QPlatformWindow * parent() const
Returns the parent platform window (or \nullptr if orphan).
virtual void setGeometry(const QRect &rect)
This function is called by Qt whenever a window is moved or resized using the QWindow API.
bool hasPendingUpdateRequest() const
Returns true if the window has a pending update request.
virtual QRect geometry() const
Returns the current geometry of a window.
virtual void deliverUpdateRequest()
Delivers an QEvent::UpdateRequest event to the window.
virtual void invalidateSurface()
Invalidates the window's surface by releasing its surface buffers.
virtual QMargins frameMargins() const
QRect windowGeometry() const
Returns the QWindow geometry.
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
constexpr void setX(qreal x) noexcept
Sets the x coordinate of this point to the given finite x coordinate.
Definition qpoint.h:353
bool isNull() const noexcept
Returns true if both the x and y coordinates are set to 0.0 (ignoring the sign); otherwise returns fa...
Definition qpoint.h:338
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qrect.h:484
QRect toAlignedRect() const noexcept
Definition qrect.cpp:2338
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr QRect marginsRemoved(const QMargins &margins) const noexcept
Removes the margins from the rectangle, shrinking it.
Definition qrect.h:454
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr void moveTo(int x, int t) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:270
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
QRegion translated(int dx, int dy) const
Definition qregion.cpp:593
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
constexpr QStringView left(qsizetype n) const noexcept
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString & append(QChar c)
Definition qstring.cpp:3252
QString & prepend(QChar c)
Definition qstring.h:478
int alphaBufferSize() const
Get the size in bits of the alpha channel of the color buffer.
@ VulkanSurface
Definition qsurface.h:35
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:291
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
Definition qthread.h:149
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
\inmodule QtCore
Definition qvariant.h:65
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
\qmltype WaylandSurface \instantiates QWaylandSurface \inqmlmodule QtWayland.Compositor
static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Make Qt Gui process all events on the event queue immediately.
static bool handleGestureEventWithValueAndDelta(QWindow *window, ulong timestamp, const QPointingDevice *device, Qt::NativeGestureType type, qreal value, const QPointF &delta, const QPointF &local, const QPointF &global, int fingerCount=2)
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen)
static void handleLeaveEvent(QWindow *window)
static bool handleGestureEventWithRealValue(QWindow *window, ulong timestamp, const QPointingDevice *device, Qt::NativeGestureType type, qreal value, const QPointF &local, const QPointF &global, int fingerCount=2)
static bool handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons state, Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods=Qt::NoModifier, Qt::MouseEventSource source=Qt::MouseEventNotSynthesized)
static bool handleCloseEvent(QWindow *window)
static void handleGeometryChange(QWindow *window, const QRect &newRect)
static void handleWindowDevicePixelRatioChanged(QWindow *window)
static bool handleExposeEvent(QWindow *window, const QRegion &region)
static bool handleGestureEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, Qt::NativeGestureType type, const QPointF &local, const QPointF &global, int fingerCount=0)
static void handleEnterEvent(QWindow *window, const QPointF &local=QPointF(), const QPointF &global=QPointF())
static bool handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods=Qt::NoModifier, Qt::ScrollPhase phase=Qt::NoScrollPhase, Qt::MouseEventSource source=Qt::MouseEventNotSynthesized)
static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState=-1)
\inmodule QtGui
Definition qwindow.h:63
Qt::WindowFlags flags
the window flags of the window
Definition qwindow.h:79
\inmodule QtCore
virtual bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods)=0
virtual QMargins margins(MarginsType marginsType=Full) const =0
virtual bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)=0
static QWaylandAbstractDecoration * create(const QString &name, const QStringList &args)
struct::wl_region * createRegion(const QRegion &qregion)
struct::wl_subsurface * createSubSurface(QWaylandWindow *window, QWaylandWindow *parent)
void handleWindowDestroyed(QWaylandWindow *window)
bool isWindowActivated(const QWaylandWindow *window)
QtWayland::wp_fractional_scale_manager_v1 * fractionalScaleManager() const
void emitWindowPropertyChanged(QPlatformWindow *window, const QString &name)
virtual QWaylandShellSurface * createShellSurface(QWaylandWindow *window)=0
virtual void setWindowFlags(Qt::WindowFlags flags)
virtual void requestWindowStates(Qt::WindowStates states)
virtual void requestXdgActivationToken(quint32 serial)
virtual void sendProperty(const QString &name, const QVariant &value)
virtual void detachPopup(QWaylandShellSurface *popup)
virtual bool resize(QWaylandInputDevice *, Qt::Edges)
virtual void attachPopup(QWaylandShellSurface *popup)
virtual void setContentOrientationMask(Qt::ScreenOrientations orientation)
virtual void setXdgActivationToken(const QString &token)
virtual bool handleExpose(const QRegion &)
virtual void setWindowPosition(const QPoint &position)
virtual void setWindowGeometry(const QRect &rect)
static QWaylandSurface * fromWlSurface(::wl_surface *surface)
std::any _surfaceRole() const override
void setProperty(const QString &name, const QVariant &value)
void setBackingStore(QWaylandShmBackingStore *backingStore)
QWaylandShellIntegration * mShellIntegration
QWaylandAbstractDecoration * mWindowDecoration
void handleWindowStatesChanged(Qt::WindowStates states)
QPointF mapFromWlSurface(const QPointF &surfacePosition) const
Converts from wl_surface coordinates to Qt window coordinates.
void lower() override
Reimplement to be able to let Qt lower windows to the bottom of the desktop.
void setWindowTitle(const QString &title) override
Reimplement to set the window title to title.
QScopedPointer< QWaylandViewport > mViewport
QWaylandAbstractDecoration * decoration() const
QWaylandWindow(QWindow *window, QWaylandDisplay *display)
void attach(QWaylandBuffer *buffer, int x, int y)
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
Qt::WindowStates windowStates() const
bool isAlertState() const override
Reimplement this method return whether the window is in an alert state.
qreal devicePixelRatio() const override
Reimplement this function in subclass to return the device pixel ratio for the window.
QWaylandShellSurface * shellSurface() const
bool setMouseGrabEnabled(bool grab) override
bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods)
bool windowEvent(QEvent *event) override
Reimplement this method to be able to do any platform specific event handling.
void setShellIntegration(QWaylandShellIntegration *shellIntegration)
void sendProperty(const QString &name, const QVariant &value)
QWaylandSubSurface * mSubSurfaceWindow
virtual QRect defaultGeometry() const
QWaylandWindow * transientParent() const
QWaylandShmBackingStore * mBackingStore
void setAlertState(bool enabled) override
Reimplement this method to set whether the window demands attention (for example, by flashing the tas...
void setXdgActivationToken(const QString &token)
QList< QPointer< QWaylandWindow > > mChildPopups
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
QVariant property(const QString &name)
QScopedPointer< QWaylandSurface > mSurface
QWaylandScreen * waylandScreen() const
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override
Handle changes to the orientation of the platform window's contents.
QWaylandDisplay * display() const
struct::wl_callback * mFrameCallback
void safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
void setOrientationMask(Qt::ScreenOrientations mask)
void handleSwipeGesture(QWaylandInputDevice *inputDevice, const QWaylandPointerGestureSwipeEvent &e)
Qt::ScreenOrientation mLastReportedContentOrientation
QSize surfaceSize() const
Size, with decorations (including including eventual shadows) in wl_surface coordinates.
void setWindowState(Qt::WindowStates states) override
Requests setting the window state of this surface to type.
QWaylandSubSurface * subSurfaceWindow() const
void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states)
void handlePinchGesture(QWaylandInputDevice *inputDevice, const QWaylandPointerGesturePinchEvent &e)
void raise() override
Reimplement to be able to let Qt raise windows to the top of the desktop.
void requestUpdate() override
Requests an QEvent::UpdateRequest event.
void requestXdgActivationToken(uint serial) override
QPointer< QWaylandWindow > mTransientParent
QScopedPointer< QWaylandFractionalScale > mFractionalScale
void addAttachOffset(const QPoint point)
virtual WindowType windowType() const =0
bool isExposed() const override
Returns if this window is exposed in the windowing system.
static QWaylandWindow * fromWlSurface(::wl_surface *surface)
void repositionFromApplyConfigure(const QPoint &position)
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
void deliverUpdateRequest() override
Delivers an QEvent::UpdateRequest event to the window.
bool isActive() const override
Returns true if the window should appear active from a style perspective.
bool startSystemResize(Qt::Edges edges) override
Reimplement this method to start a system resize operation if the system supports it and return true ...
QList< QWaylandSubSurface * > mChildren
void setMask(const QRegion &region) override
Reimplement to be able to let Qt set the mask of a window.
ToplevelWindowTilingStates toplevelWindowTilingStates() const
void setWindowFlags(Qt::WindowFlags flags) override
Requests setting the window flags of this surface to flags.
::wl_surface * wlSurface() const
void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
Qt::MouseButtons mMousePressedInContentArea
void setParent(const QPlatformWindow *parent) override
This function is called to enable native child window in QPA.
QRect windowContentGeometry() const
Window geometry as defined by the xdg-shell spec (in wl_surface coordinates) topLeft is where the sha...
void damage(const QRect &rect)
QWaylandShellIntegration * shellIntegration() const
WId winId() const override
Reimplement in subclasses to return a handle to the native window.
void timerEvent(QTimerEvent *event) override
void propagateSizeHints() override
Reimplement to propagate the size hints of the QWindow.
ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates
::wl_surface * surface() const override
void resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset={0, 0})
void setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins)
void setWindowIcon(const QIcon &icon) override
Reimplement to set the window icon to icon.
QMargins frameMargins() const override
void sendExposeEvent(const QRect &rect)
QWaylandShellSurface * mShellSurface
void setCustomMargins(const QMargins &margins) override
bool startSystemMove() override
Reimplement this method to start a system move operation if the system supports it and return true to...
#define this
Definition dialogs.cpp:9
QCursor cursor
QSet< QString >::iterator it
rect
[4]
else opt state
[0]
Token token
Definition keywords.cpp:444
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
static QWaylandWindow * closestShellSurfaceWindow(QWindow *window)
Definition qcompare.h:63
@ NoButton
Definition qnamespace.h:57
@ GestureCanceled
@ GestureStarted
@ GestureUpdated
@ GestureFinished
ScreenOrientation
Definition qnamespace.h:271
@ InvertedLandscapeOrientation
Definition qnamespace.h:276
@ InvertedPortraitOrientation
Definition qnamespace.h:275
@ LandscapeOrientation
Definition qnamespace.h:274
@ PortraitOrientation
Definition qnamespace.h:273
@ PrimaryOrientation
Definition qnamespace.h:272
@ QueuedConnection
@ RotateNativeGesture
@ ZoomNativeGesture
@ BeginNativeGesture
@ EndNativeGesture
@ PanNativeGesture
@ SkipEmptyParts
Definition qnamespace.h:128
@ BypassWindowManagerHint
Definition qnamespace.h:223
@ Desktop
Definition qnamespace.h:215
@ Widget
Definition qnamespace.h:206
@ FramelessWindowHint
Definition qnamespace.h:225
@ ToolTip
Definition qnamespace.h:213
@ Drawer
Definition qnamespace.h:210
@ Popup
Definition qnamespace.h:211
@ Window
Definition qnamespace.h:207
@ Dialog
Definition qnamespace.h:208
@ WindowTransparentForInput
Definition qnamespace.h:234
@ Tool
Definition qnamespace.h:212
QList< QString > QStringList
Constructs a string list that contains the given string, str.
#define qApp
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLdouble GLdouble GLdouble GLdouble top
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint buffer
GLint GLsizei width
GLint left
GLenum type
GLbitfield flags
GLenum GLuint GLintptr offset
GLuint name
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint y
struct _cl_event * event
GLuint GLenum GLenum transform
GLdouble s
[6]
Definition qopenglext.h:235
GLsizei maxLength
GLfloat GLfloat p
[1]
GLenum GLenum GLenum GLenum GLenum scale
GLuint * states
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define emit
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
Q_GUI_EXPORT QWindowPrivate * qt_window_private(QWindow *window)
Definition qwindow.cpp:2950
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QDeadlineTimer deadline(30s)
QString title
[35]
timer inherits("QTimer")
QReadWriteLock lock
[0]
edit isVisible()
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QJSValue global
\inmodule QtCore \reentrant
Definition qchar.h:18
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...