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 static WId id = 1;
64 mWindowId = id++;
65 initializeWlSurface();
66
68 &QNativeInterface::Private::QWaylandWindow::surfaceCreated);
70 &QNativeInterface::Private::QWaylandWindow::surfaceDestroyed);
71}
72
74{
75 delete mWindowDecoration;
76
77 if (mSurface)
78 reset();
79
80 const QWindow *parent = window();
81 const auto tlw = QGuiApplication::topLevelWindows();
82 for (QWindow *w : tlw) {
83 if (w->transientParent() == parent)
85 }
86
87 if (mMouseGrab == this) {
88 mMouseGrab = nullptr;
89 }
90}
91
99
100void QWaylandWindow::initWindow()
101{
102 if (window()->type() == Qt::Desktop)
103 return;
104
105 if (!mSurface) {
106 initializeWlSurface();
107 }
108
109 if (mDisplay->fractionalScaleManager() && qApp->highDpiScaleFactorRoundingPolicy() == Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) {
110 mFractionalScale.reset(new QWaylandFractionalScale(mDisplay->fractionalScaleManager()->get_fractional_scale(mSurface->object())));
111
113 this, &QWaylandWindow::updateScale);
114 }
115
116 if (shouldCreateSubSurface()) {
118
119 auto *parent = static_cast<QWaylandWindow *>(QPlatformWindow::parent());
120 if (!parent->mSurface)
121 parent->initializeWlSurface();
122 if (parent->wlSurface()) {
123 if (::wl_subsurface *subsurface = mDisplay->createSubSurface(this, parent))
124 mSubSurfaceWindow = new QWaylandSubSurface(this, parent, subsurface);
125 }
126 } else if (shouldCreateShellSurface()) {
129 mTransientParent = guessTransientParent();
130 if (mTransientParent) {
131 if (window()->type() == Qt::Popup) {
132 if (mTopPopup && mTopPopup != mTransientParent) {
133 qCWarning(lcQpaWayland) << "Creating a popup with a parent," << mTransientParent->window()
134 << "which does not match the current topmost grabbing popup,"
135 << mTopPopup->window() << "With some shell surface protocols, this"
136 << "is not allowed. The wayland QPA plugin is currently handling"
137 << "it by setting the parent to the topmost grabbing popup."
138 << "Note, however, that this may cause positioning errors and"
139 << "popups closing unxpectedly. Please fix the transient parent of the popup.";
140 mTransientParent = mTopPopup;
141 }
142 mTopPopup = this;
143 }
144 }
145
147 if (mShellSurface) {
148 if (mTransientParent) {
149 if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup)
150 mTransientParent->addChildPopup(this);
151 }
152
153 // Set initial surface title
155
156 // The appId is the desktop entry identifier that should follow the
157 // reverse DNS convention (see
158 // http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html). According
159 // to xdg-shell the appId is only the name, without the .desktop suffix.
160 //
161 // If the application specifies the desktop file name use that,
162 // otherwise fall back to the executable name and prepend the
163 // reversed organization domain when available.
164 if (!QGuiApplication::desktopFileName().isEmpty()) {
166 } else {
167 QFileInfo fi = QFileInfo(QCoreApplication::instance()->applicationFilePath());
168 QStringList domainName =
169 QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'),
171
172 if (domainName.isEmpty()) {
173 mShellSurface->setAppId(fi.baseName());
174 } else {
175 QString appId;
176 for (int i = 0; i < domainName.size(); ++i)
177 appId.prepend(QLatin1Char('.')).prepend(domainName.at(i));
178 appId.append(fi.baseName());
179 mShellSurface->setAppId(appId);
180 }
181 }
182 // the user may have already set some window properties, so make sure to send them out
183 for (auto it = m_properties.cbegin(); it != m_properties.cend(); ++it)
184 mShellSurface->sendProperty(it.key(), it.value());
185
186 emit surfaceRoleCreated();
187 } else {
188 qWarning("Could not create a shell surface object.");
189 }
190 }
191
192 // The fractional scale manager check is needed to work around Gnome < 36 where viewports don't work
193 // Right now viewports are only necessary when a fractional scale manager is used
194 if (display()->viewporter() && display()->fractionalScaleManager()) {
195 mViewport.reset(new QWaylandViewport(display()->createViewport(this)));
196 }
197
198 // Enable high-dpi rendering. Scale() returns the screen scale factor and will
199 // typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
200 // to inform the compositor that high-resolution buffers will be provided.
201 if (mViewport)
202 updateViewport();
203 else if (mSurface->version() >= 3)
204 mSurface->set_buffer_scale(std::ceil(scale()));
205
209 if (geometry.width() <= 0)
210 geometry.setWidth(defaultGeometry.width());
211 if (geometry.height() <= 0)
212 geometry.setHeight(defaultGeometry.height());
213
214 setGeometry_helper(geometry);
215 setMask(window()->mask());
216 if (mShellSurface)
218 handleContentOrientationChange(window()->contentOrientation());
219 mFlags = window()->flags();
220
221 mSurface->commit();
222}
223
224void QWaylandWindow::initializeWlSurface()
225{
227 {
231 this, &QWaylandWindow::handleScreensChanged);
233 this, &QWaylandWindow::updateScale);
236 mSurface->m_window = this;
237 }
239}
240
242{
244 if (mShellSurface) {
245 qCWarning(lcQpaWayland) << "Cannot set shell integration while there's already a shell surface created";
246 return;
247 }
249}
250
251bool QWaylandWindow::shouldCreateShellSurface() const
252{
253 if (!shellIntegration())
254 return false;
255
256 if (shouldCreateSubSurface())
257 return false;
258
259 if (window()->inherits("QShapedPixmapWindow"))
260 return false;
261
262 if (qEnvironmentVariableIsSet("QT_WAYLAND_USE_BYPASSWINDOWMANAGERHINT"))
264
265 return true;
266}
267
268bool QWaylandWindow::shouldCreateSubSurface() const
269{
270 return QPlatformWindow::parent() != nullptr;
271}
272
274{
275 mSurfaceLock.lockForRead();
276}
277
279{
280 mSurfaceLock.unlock();
281}
282
284{
286
287 if (mTopPopup == this)
288 mTopPopup = mTransientParent && (mTransientParent->window()->type() == Qt::Popup) ? mTransientParent : nullptr;
289
290 if (mSurface) {
291 {
295 mTransientParent->removeChildPopup(this);
296 delete mShellSurface;
297 mShellSurface = nullptr;
298 emit surfaceRoleDestroyed();
299 delete mSubSurfaceWindow;
300 mSubSurfaceWindow = nullptr;
301 mTransientParent = nullptr;
302 mSurface.reset();
303 mViewport.reset();
304 mFractionalScale.reset();
305 }
307 }
308
309 {
311 if (mFrameCallback) {
312 wl_callback_destroy(mFrameCallback);
313 mFrameCallback = nullptr;
314 }
315
318 }
322 }
323
326 mCanResize = true;
327 mResizeDirty = false;
328 mScale = std::nullopt;
329
331 mMask = QRegion();
332
335
336 if (mQueuedBuffer) {
337 mQueuedBuffer->setBusy(false);
338 }
339 mQueuedBuffer = nullptr;
341
343}
344
346{
348 return s->m_window;
349 return nullptr;
350}
351
353{
354 return mWindowId;
355}
356
358{
359 if (!window()->isVisible())
360 return;
361
362 QWaylandWindow *oldparent = mSubSurfaceWindow ? mSubSurfaceWindow->parent() : nullptr;
363 if (oldparent == parent)
364 return;
365
366 if (mSubSurfaceWindow && parent) { // new parent, but we were a subsurface already
367 delete mSubSurfaceWindow;
368 QWaylandWindow *p = const_cast<QWaylandWindow *>(static_cast<const QWaylandWindow *>(parent));
370 } else { // we're changing role, need to make a new wl_surface
371 reset();
372 initWindow();
373 }
374}
375
380
382{
383 const QString separator = QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH
384 const QString formatted = formatWindowTitle(title, separator);
385
386 const int libwaylandMaxBufferSize = 4096;
387 // Some parts of the buffer is used for metadata, so subtract 100 to be on the safe side.
388 // Also, QString is in utf-16, which means that in the worst case each character will be
389 // three bytes when converted to utf-8 (which is what libwayland uses), so divide by three.
390 const int maxLength = libwaylandMaxBufferSize / 3 - 100;
391
392 auto truncated = QStringView{formatted}.left(maxLength);
393 if (truncated.size() < formatted.size()) {
394 qCWarning(lcQpaWayland) << "Window titles longer than" << maxLength << "characters are not supported."
395 << "Truncating window title (from" << formatted.size() << "chars)";
396 }
397
398 mWindowTitle = truncated.toString();
399
400 if (mShellSurface)
402
405}
406
414
416{
417 return QRect(QPoint(), QSize(500,500));
418}
419
420void QWaylandWindow::setGeometry_helper(const QRect &rect)
421{
423 if (mViewport)
424 updateViewport();
425
426 if (mSubSurfaceWindow) {
428 mSubSurfaceWindow->set_position(rect.x() + m.left(), rect.y() + m.top());
429
430 QWaylandWindow *parentWindow = mSubSurfaceWindow->parent();
431 if (parentWindow && parentWindow->isExposed()) {
432 QRect parentExposeGeometry(QPoint(), parentWindow->geometry().size());
433 parentWindow->sendExposeEvent(parentExposeGeometry);
434 }
435 }
436}
437
439{
440 auto rect = r;
442 && window()->type() != Qt::ToolTip) {
443 rect.moveTo(screen()->geometry().topLeft());
444 }
445 setGeometry_helper(rect);
446
447 if (window()->isVisible() && rect.isValid()) {
450
453 mResizeDirty = true;
454 } else {
456 }
457 mSentInitialResize = true;
458 }
459 QRect exposeGeometry(QPoint(), geometry().size());
460 if (isExposed() && !mInResizeFromApplyConfigure && exposeGeometry != mLastExposeGeometry)
461 sendExposeEvent(exposeGeometry);
462
463 if (mShellSurface) {
465 if (!qt_window_private(window())->positionAutomatic && !mInResizeFromApplyConfigure)
467 }
468
469 if (isOpaque() && mMask.isEmpty())
470 setOpaqueArea(QRect(QPoint(0, 0), rect.size()));
471}
472
473void QWaylandWindow::updateInputRegion()
474{
475 if (!mSurface)
476 return;
477
478 const bool transparentInputRegion = mFlags.testFlag(Qt::WindowTransparentForInput);
479
480 QRegion inputRegion;
481 if (!transparentInputRegion)
482 inputRegion = mMask;
483
484 if (mInputRegion == inputRegion && mTransparentInputRegion == transparentInputRegion)
485 return;
486
487 mInputRegion = inputRegion;
488 mTransparentInputRegion = transparentInputRegion;
489
491 mSurface->set_input_region(nullptr);
492 } else {
493 struct ::wl_region *region = mDisplay->createRegion(mInputRegion);
494 mSurface->set_input_region(region);
495 wl_region_destroy(region);
496 }
497}
498
499void QWaylandWindow::updateViewport()
500{
501 if (!surfaceSize().isEmpty())
502 mViewport->setDestination(surfaceSize());
503}
504
505void QWaylandWindow::setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins)
506{
507 QMargins margins = clientSideMargins();
508
509 QPoint positionWithoutMargins = globalPosition + QPoint(margins.left(), margins.top());
510 int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
511 int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
512
513 QRect geometry(positionWithoutMargins, QSize(widthWithoutMargins, heightWithoutMargins));
514
515 mInResizeFromApplyConfigure = true;
517 mInResizeFromApplyConfigure = false;
518}
519
521{
522 QMargins margins = clientSideMargins();
523 QPoint positionWithoutMargins = globalPosition + QPoint(margins.left(), margins.top());
524
525 QRect geometry(positionWithoutMargins, windowGeometry().size());
526 mInResizeFromApplyConfigure = true;
528 mInResizeFromApplyConfigure = false;
529}
530
532{
533 QMargins margins = clientSideMargins();
534 int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
535 int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1);
536 QRect geometry(windowGeometry().topLeft(), QSize(widthWithoutMargins, heightWithoutMargins));
537
538 mOffset += offset;
539 mInResizeFromApplyConfigure = true;
541 mInResizeFromApplyConfigure = false;
542}
543
545{
548 else
549 qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
550 mLastExposeGeometry = rect;
551}
552
553QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
554{
556 if (mSurface) {
557 if (auto *screen = mSurface->oldestEnteredScreen())
558 return screen;
559 }
561}
562
564{
565 // Workaround for issue where setVisible may be called with the same value twice
566 if (lastVisible == visible)
567 return;
568 lastVisible = visible;
569
570 if (visible) {
571 initWindow();
572
574 // Don't flush the events here, or else the newly visible window may start drawing, but since
575 // there was no frame before it will be stuck at the waitForFrameSync() in
576 // QWaylandShmBackingStore::beginPaint().
577
578 if (mShellSurface)
580 } else {
582 reset();
583 }
584}
585
586
588{
589 if (mShellSurface)
591}
592
593
595{
596 if (mShellSurface)
598}
599
601{
602 QReadLocker locker(&mSurfaceLock);
603 if (!mSurface)
604 return;
605
606 if (mMask == mask)
607 return;
608
609 mMask = mask;
610
611 updateInputRegion();
612
613 if (isOpaque()) {
614 if (mMask.isEmpty())
615 setOpaqueArea(QRect(QPoint(0, 0), geometry().size()));
616 else
617 setOpaqueArea(mMask);
618 }
619}
620
626
628{
629 if (mShellSurface)
630 return mShellSurface->isAlertState();
631
632 return false;
633}
634
643
645{
647 return;
648
649 Q_ASSERT_X(QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed(),
650 "QWaylandWindow::doApplyConfigure", "not called from main thread");
651
652 if (mShellSurface)
654
656}
657
658void QWaylandWindow::doApplyConfigureFromOtherThread()
659{
662 return;
665}
666
668{
670 mCanResize = canResize;
671
672 if (canResize) {
673 if (mResizeDirty) {
675 }
677 bool inGuiThread = QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed();
678 if (inGuiThread) {
681 } else {
682 QMetaObject::invokeMethod(this, &QWaylandWindow::doApplyConfigureFromOtherThread, Qt::QueuedConnection);
683 }
684 } else if (mResizeDirty) {
685 mResizeDirty = false;
687 }
688 }
689}
690
702
704{
705 if (!isExposed())
707 else
709
710 for (QWaylandSubSurface *subSurface : std::as_const(mChildren)) {
711 auto subWindow = subSurface->window();
712 subWindow->sendRecursiveExposeEvent();
713 }
714}
715
717{
718 QReadLocker locker(&mSurfaceLock);
719 if (mSurface == nullptr)
720 return;
721
722 if (buffer) {
723 Q_ASSERT(!buffer->committed());
724 handleUpdate();
725 buffer->setBusy(true);
726 if (mSurface->version() >= WL_SURFACE_OFFSET_SINCE_VERSION) {
727 mSurface->offset(x, y);
728 mSurface->attach(buffer->buffer(), 0, 0);
729 } else {
730 mSurface->attach(buffer->buffer(), x, y);
731 }
732 } else {
733 mSurface->attach(nullptr, 0, 0);
734 }
735}
736
742
744{
745 QReadLocker locker(&mSurfaceLock);
746 if (mSurface == nullptr)
747 return;
748
749 const qreal s = scale();
750 if (mSurface->version() >= 4) {
751 const QRect bufferRect =
752 QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
753 .toAlignedRect();
754 mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
755 bufferRect.height());
756 } else {
757 mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
758 }
759}
760
762{
763 if (isExposed()) {
765 } else {
766 if (mQueuedBuffer) {
767 mQueuedBuffer->setBusy(false);
768 }
770 mQueuedBuffer->setBusy(true);
772 }
773}
774
776{
778 if (buffer->committed()) {
779 qCDebug(lcWaylandBackingstore) << "Buffer already committed, ignoring.";
780 return;
781 }
782
783 QReadLocker locker(&mSurfaceLock);
784 if (!mSurface)
785 return;
786
788 if (mSurface->version() >= 4) {
789 const qreal s = scale();
790 for (const QRect &rect : damage) {
791 const QRect bufferRect =
792 QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
793 .toAlignedRect();
794 mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
795 bufferRect.height());
796 }
797 } else {
798 for (const QRect &rect: damage)
799 mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
800 }
801 Q_ASSERT(!buffer->committed());
802 buffer->setCommitted();
803 mSurface->commit();
804}
805
807{
808 QReadLocker locker(&mSurfaceLock);
809 if (mSurface != nullptr)
810 mSurface->commit();
811}
812
813const wl_callback_listener QWaylandWindow::callbackListener = {
814 [](void *data, wl_callback *callback, uint32_t time) {
815 Q_UNUSED(time);
816 auto *window = static_cast<QWaylandWindow*>(data);
817 window->handleFrameCallback(callback);
818 }
819};
820
821void QWaylandWindow::handleFrameCallback(wl_callback* callback)
822{
824 if (!mFrameCallback) {
825 // This means the callback is already unset by QWaylandWindow::reset.
826 // The wl_callback object will be destroyed there too.
827 return;
828 }
829 Q_ASSERT(callback == mFrameCallback);
830 wl_callback_destroy(callback);
831 mFrameCallback = nullptr;
832
835
836 // The rest can wait until we can run it on the correct thread
838 // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync()
839 // in the single-threaded case.
841 }
843}
844
846{
848 bool wasExposed = isExposed();
850 if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
852 if (wasExposed && hasPendingUpdateRequest())
854
855}
856
858{
860
863
865 qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
867 mWaitingForUpdate = false;
869 }
870
872}
873
883
888
890 const QMargins oldMargins = mCustomMargins;
891 mCustomMargins = margins;
893 setGeometry(geometry().marginsRemoved(oldMargins).marginsAdded(margins));
894}
895
900{
901 return geometry().marginsAdded(clientSideMargins()).size();
902}
903
905{
906 QMargins shadowMargins;
907
910
911 if (!mCustomMargins.isNull())
912 shadowMargins += mCustomMargins;
913
914 return shadowMargins;
915}
916
922{
923 const QMargins margins = windowContentMargins();
924 return QRect(QPoint(margins.left(), margins.top()), surfaceSize().shrunkBy(margins));
925}
926
935{
936 const QMargins margins = clientSideMargins();
937 return QPointF(surfacePosition.x() - margins.left(), surfacePosition.y() - margins.top());
938}
939
940wl_surface *QWaylandWindow::wlSurface() const
941{
942 QReadLocker locker(&mSurfaceLock);
943 return mSurface ? mSurface->object() : nullptr;
944}
945
950
952{
954 return mSubSurfaceWindow->object();
955 if (mShellSurface)
956 return mShellSurface->surfaceRole();
957 return {};
958}
959
964
966{
967 auto *platformScreen = QPlatformWindow::screen();
968 Q_ASSERT(platformScreen);
969 if (platformScreen->isPlaceholder())
970 return nullptr;
971 return static_cast<QWaylandScreen *>(platformScreen);
972}
973
979
981{
982 QReadLocker locker(&mSurfaceLock);
983 if (mSurface == nullptr || mSurface->version() < 2)
984 return;
985
986 wl_output_transform transform;
988
989 if (mSurface->version() >= 6) {
990 const auto transform = mSurface->preferredBufferTransform().value_or(WL_OUTPUT_TRANSFORM_NORMAL);
991 if (auto screen = waylandScreen())
992 screenOrientation = screen->toScreenOrientation(transform, Qt::PrimaryOrientation);
993 } else {
994 if (auto screen = window()->screen())
995 screenOrientation = screen->primaryOrientation();
996 }
997
998 const bool isPortrait = (screenOrientation == Qt::PortraitOrientation);
999
1002 transform = WL_OUTPUT_TRANSFORM_NORMAL;
1003 break;
1005 transform = isPortrait ? WL_OUTPUT_TRANSFORM_270 : WL_OUTPUT_TRANSFORM_NORMAL;
1006 break;
1008 transform = isPortrait ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_90;
1009 break;
1011 transform = isPortrait ? WL_OUTPUT_TRANSFORM_90 : WL_OUTPUT_TRANSFORM_180;
1012 break;
1014 transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
1015 break;
1016 default:
1017 Q_UNREACHABLE();
1018 }
1019 mSurface->set_buffer_transform(transform);
1020}
1021
1027
1033
1035{
1036 if (mShellSurface)
1038
1039 mFlags = flags;
1041
1042 QReadLocker locker(&mSurfaceLock);
1043 updateInputRegion();
1044}
1045
1047{
1048 Q_ASSERT_X(QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed(),
1049 "QWaylandWindow::createDecoration", "not called from main thread");
1050 // TODO: client side decorations do not work with Vulkan backend.
1051 if (window()->surfaceType() == QSurface::VulkanSurface)
1052 return false;
1054 return false;
1055
1056 static bool decorationPluginFailed = false;
1057 bool decoration = false;
1058 switch (window()->type()) {
1059 case Qt::Window:
1060 case Qt::Widget:
1061 case Qt::Dialog:
1062 case Qt::Tool:
1063 case Qt::Drawer:
1064 decoration = true;
1065 break;
1066 default:
1067 break;
1068 }
1070 decoration = false;
1072 decoration = false;
1074 decoration = false;
1076 decoration = false;
1077
1078 bool hadDecoration = mWindowDecorationEnabled;
1079 if (decoration && !decorationPluginFailed) {
1081 if (mWindowDecoration) {
1082 delete mWindowDecoration;
1083 mWindowDecoration = nullptr;
1084 }
1085
1087 if (decorations.empty()) {
1088 qWarning() << "No decoration plugins available. Running with no decorations.";
1089 decorationPluginFailed = true;
1090 return false;
1091 }
1092
1093 QString targetKey;
1094 QByteArray decorationPluginName = qgetenv("QT_WAYLAND_DECORATION");
1095 if (!decorationPluginName.isEmpty()) {
1096 targetKey = QString::fromLocal8Bit(decorationPluginName);
1097 if (!decorations.contains(targetKey)) {
1098 qWarning() << "Requested decoration " << targetKey << " not found, falling back to default";
1099 targetKey = QString(); // fallthrough
1100 }
1101 }
1102
1103 if (targetKey.isEmpty()) {
1104 auto unixServices = dynamic_cast<QGenericUnixServices *>(
1106 const QByteArray currentDesktop = unixServices->desktopEnvironment();
1107 if (currentDesktop == "GNOME") {
1108 if (decorations.contains("adwaita"_L1))
1109 targetKey = "adwaita"_L1;
1110 else if (decorations.contains("gnome"_L1))
1111 targetKey = "gnome"_L1;
1112 } else {
1113 // Do not use Adwaita/GNOME decorations on other DEs
1114 decorations.removeAll("adwaita"_L1);
1115 decorations.removeAll("gnome"_L1);
1116 }
1117 }
1118
1119 if (targetKey.isEmpty())
1120 targetKey = decorations.first(); // first come, first served.
1121
1122
1124 if (!mWindowDecoration) {
1125 qWarning() << "Could not create decoration from factory! Running with no decorations.";
1126 decorationPluginFailed = true;
1127 return false;
1128 }
1131 }
1132 } else {
1134 }
1135
1136 if (hadDecoration != mWindowDecorationEnabled) {
1137 for (QWaylandSubSurface *subsurf : std::as_const(mChildren)) {
1138 QPoint pos = subsurf->window()->geometry().topLeft();
1140 subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
1141 }
1143
1144 // creating a decoration changes our margins which in turn change size hints
1146
1147 // This is a special case where the buffer is recreated, but since
1148 // the content rect remains the same, the widgets remain the same
1149 // size and are not redrawn, leaving the new buffer empty. As a simple
1150 // work-around, we trigger a full extra update whenever the client-side
1151 // window decorations are toggled while the window is showing.
1152 window()->requestUpdate();
1153 }
1154
1155 return mWindowDecoration;
1156}
1157
1162
1164{
1165 while (window) {
1166 auto w = static_cast<QWaylandWindow *>(window->handle());
1167 if (w && w->shellSurface())
1168 return w;
1169 window = window->transientParent() ? window->transientParent() : window->parent();
1170 }
1171 return nullptr;
1172}
1173
1178
1179QWaylandWindow *QWaylandWindow::guessTransientParent() const
1180{
1181 // Take the closest window with a shell surface, since the transient parent may be a
1182 // QWidgetWindow or some other window without a shell surface, which is then not able to
1183 // get mouse events.
1185 return transientParent;
1186
1187 if (window()->type() == Qt::Popup) {
1188 if (mTopPopup)
1189 return mTopPopup;
1190 }
1191
1192 if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup) {
1193 if (auto lastInputWindow = display()->lastInputWindow())
1194 return closestShellSurfaceWindow(lastInputWindow->window());
1195 }
1196
1197 return nullptr;
1198}
1199
1201{
1202 if (e.type == QEvent::Leave) {
1206 } else {
1208 }
1209#if QT_CONFIG(cursor)
1210 restoreMouseCursor(inputDevice);
1211#endif
1212 return;
1213 }
1214
1216 handleMouseEventWithDecoration(inputDevice, e);
1217 } else {
1218 switch (e.type) {
1219 case QEvent::Enter:
1221 break;
1224 case QEvent::MouseMove:
1226 break;
1227 case QEvent::Wheel:
1230 e.phase, e.source, e.inverted);
1231 break;
1232 default:
1233 Q_UNREACHABLE();
1234 }
1235 }
1236
1237#if QT_CONFIG(cursor)
1238 if (e.type == QEvent::Enter) {
1239 QRect contentGeometry = QRect(QPoint(), surfaceSize()).marginsRemoved(clientSideMargins());
1240 if (contentGeometry.contains(e.local.toPoint()))
1241 restoreMouseCursor(inputDevice);
1242 }
1243#endif
1244}
1245
1246#ifndef QT_NO_GESTURES
1249{
1250 switch (e.state) {
1251 case Qt::GestureStarted:
1253 qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
1254
1256 // whole gesture sequence will be ignored
1258 return;
1259 }
1260
1263 inputDevice->mTouchPadDevice,
1265 e.local, e.global, e.fingers);
1266 break;
1267 case Qt::GestureUpdated:
1269 return;
1270
1271 if (!e.delta.isNull()) {
1273 window(), e.timestamp, inputDevice->mTouchPadDevice,
1275 0, e.delta, e.local, e.global, e.fingers);
1276 }
1277 break;
1282 return;
1283 }
1284
1286 qCWarning(lcQpaWaylandInput) << "Unexpected" << (e.state == Qt::GestureFinished ? "GestureFinished" : "GestureCanceled");
1287
1289
1290 // There's currently no way to expose cancelled gestures to the rest of Qt, so
1291 // this part of information is lost.
1293 inputDevice->mTouchPadDevice,
1295 e.local, e.global, e.fingers);
1296 break;
1297 default:
1298 break;
1299 }
1300}
1301
1304{
1305 switch (e.state) {
1306 case Qt::GestureStarted:
1308 qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
1309
1311 // whole gesture sequence will be ignored
1313 return;
1314 }
1315
1318 inputDevice->mTouchPadDevice,
1320 e.local, e.global, e.fingers);
1321 break;
1322 case Qt::GestureUpdated:
1324 return;
1325
1326 if (!e.delta.isNull()) {
1328 window(), e.timestamp, inputDevice->mTouchPadDevice,
1330 0, e.delta, e.local, e.global, e.fingers);
1331 }
1332 if (e.rotation_delta != 0) {
1334 inputDevice->mTouchPadDevice,
1337 e.local, e.global, e.fingers);
1338 }
1339 if (e.scale_delta != 0) {
1341 inputDevice->mTouchPadDevice,
1343 e.scale_delta,
1344 e.local, e.global, e.fingers);
1345 }
1346 break;
1351 return;
1352 }
1353
1355 qCWarning(lcQpaWaylandInput) << "Unexpected" << (e.state == Qt::GestureFinished ? "GestureFinished" : "GestureCanceled");
1356
1358
1359 // There's currently no way to expose cancelled gestures to the rest of Qt, so
1360 // this part of information is lost.
1362 inputDevice->mTouchPadDevice,
1364 e.local, e.global, e.fingers);
1365 break;
1366 default:
1367 break;
1368 }
1369}
1370#endif // #ifndef QT_NO_GESTURES
1371
1372
1373bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods)
1374{
1376 return false;
1377 return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods);
1378}
1379
1380void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
1381{
1383 mWindowDecoration->handleMouse(inputDevice, e.local, e.global, e.buttons, e.modifiers)) {
1387 }
1388 return;
1389 }
1390
1391 QMargins marg = clientSideMargins();
1392 QRect windowRect(0 + marg.left(),
1393 0 + marg.top(),
1394 geometry().size().width(),
1395 geometry().size().height());
1396 if (windowRect.contains(e.local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
1397 const QPointF localTranslated = mapFromWlSurface(e.local);
1398 QPointF globalTranslated = e.global;
1399 globalTranslated.setX(globalTranslated.x() - marg.left());
1400 globalTranslated.setY(globalTranslated.y() - marg.top());
1402#if QT_CONFIG(cursor)
1403 restoreMouseCursor(inputDevice);
1404#endif
1406 }
1407
1408 switch (e.type) {
1409 case QEvent::Enter:
1410 QWindowSystemInterface::handleEnterEvent(window(), localTranslated, globalTranslated);
1411 break;
1414 case QEvent::MouseMove:
1415 QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.button, e.type, e.modifiers);
1416 break;
1417 case QEvent::Wheel: {
1419 localTranslated, globalTranslated,
1421 e.phase, e.source, e.inverted);
1422 break;
1423 }
1424 default:
1425 Q_UNREACHABLE();
1426 }
1427
1430 } else {
1434 }
1435 }
1436}
1437
1438void QWaylandWindow::handleScreensChanged()
1439{
1440 QPlatformScreen *newScreen = calculateScreenFromSurfaceEvents();
1441
1442 if (newScreen->screen() == window()->screen())
1443 return;
1444
1445 QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
1446
1448 && window()->type() != Qt::ToolTip
1449 && geometry().topLeft() != newScreen->geometry().topLeft()) {
1450 auto geometry = this->geometry();
1451 geometry.moveTo(newScreen->geometry().topLeft());
1453 }
1454
1455 updateScale();
1457}
1458
1459void QWaylandWindow::updateScale()
1460{
1461 if (mFractionalScale) {
1462 auto preferredScale = mFractionalScale->preferredScale().value_or(1.0);
1463 preferredScale = std::max(1.0, preferredScale);
1465 setScale(preferredScale);
1466 return;
1467 }
1468
1469 if (mSurface && mSurface->version() >= 6) {
1470 auto preferredScale = mSurface->preferredBufferScale().value_or(1);
1471 preferredScale = std::max(1, preferredScale);
1472 setScale(preferredScale);
1473 return;
1474 }
1475
1476 int scale = screen()->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(screen())->scale();
1477 setScale(scale);
1478}
1479
1480void QWaylandWindow::setScale(qreal newScale)
1481{
1482 if (mScale.has_value() && qFuzzyCompare(mScale.value(), newScale))
1483 return;
1484 mScale = newScale;
1485
1487 if (mSurface) {
1488 if (mViewport)
1489 updateViewport();
1490 else if (mSurface->version() >= 3)
1491 mSurface->set_buffer_scale(std::ceil(newScale));
1492 }
1493 ensureSize();
1494
1495 if (isExposed()) {
1496 // redraw at the new DPR
1497 window()->requestUpdate();
1499 }
1500}
1501
1502#if QT_CONFIG(cursor)
1503void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor)
1504{
1505 int fallbackBufferScale = int(devicePixelRatio());
1506 device->setCursor(&cursor, {}, fallbackBufferScale);
1507}
1508
1509void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
1510{
1511 if (const QCursor *overrideCursor = QGuiApplication::overrideCursor())
1512 setMouseCursor(device, *overrideCursor);
1513 else
1514 setMouseCursor(device, window()->cursor());
1515}
1516#endif
1517
1523
1525{
1526 if (!window()->isVisible())
1527 return false;
1528
1530 return false;
1531
1532 if (mShellSurface)
1533 return mShellSurface->isExposed();
1534
1536 return mSubSurfaceWindow->parent()->isExposed();
1537
1538 return !(shouldCreateShellSurface() || shouldCreateSubSurface());
1539}
1540
1542{
1543 return mDisplay->isWindowActivated(this);
1544}
1545
1547{
1548 return devicePixelRatio();
1549}
1550
1552{
1553 return mScale.value_or(waylandScreen() ? waylandScreen()->scale() : 1);
1554}
1555
1557{
1558 if (window()->type() != Qt::Popup) {
1559 qWarning("This plugin supports grabbing the mouse only for popup windows");
1560 return false;
1561 }
1562
1563 mMouseGrab = grab ? this : nullptr;
1564 return true;
1565}
1566
1567QWaylandWindow::ToplevelWindowTilingStates QWaylandWindow::toplevelWindowTilingStates() const
1568{
1570}
1571
1576
1577Qt::WindowStates QWaylandWindow::windowStates() const
1578{
1580}
1581
1583{
1585 Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
1586 Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
1588 lastStatesWithoutActive);
1590}
1591
1601
1603{
1605 QWaylandNativeInterface *nativeInterface = static_cast<QWaylandNativeInterface *>(
1607 nativeInterface->emitWindowPropertyChanged(this, name);
1608}
1609
1611{
1612 return m_properties;
1613}
1614
1619
1621{
1622 return m_properties.value(name, defaultValue);
1623}
1624
1625#ifdef QT_PLATFORM_WINDOW_HAS_VIRTUAL_SET_BACKING_STORE
1627{
1628 mBackingStore = dynamic_cast<QWaylandShmBackingStore *>(store);
1629}
1630#endif
1631
1633{
1634 if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
1635 return;
1636
1637 {
1639
1640 bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
1641 if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
1644 }
1645 if (!mFrameCallbackElapsedTimer.isValid() || !callbackTimerExpired) {
1646 return;
1647 }
1649 }
1650
1651 qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
1653 mWaitingForUpdate = false;
1655}
1656
1658{
1659 qCDebug(lcWaylandBackingstore) << "requestUpdate";
1660 Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
1661
1662 // If we have a frame callback all is good and will be taken care of there
1663 {
1666 return;
1667 }
1668
1669 // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
1670 // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
1671 // here so we can get this information when debugging update/frame callback issues.
1672 // Continue as nothing happened, though.
1674 qCDebug(lcWaylandBackingstore) << "requestUpdate called twice without committing anything";
1675
1676 // Some applications (such as Qt Quick) depend on updates being delivered asynchronously,
1677 // so use invokeMethod to delay the delivery a bit.
1678 QMetaObject::invokeMethod(this, [this] {
1679 // Things might have changed in the meantime
1680 {
1683 return;
1684 }
1688}
1689
1690// Should be called whenever we commit a buffer (directly through wl_surface.commit or indirectly
1691// with eglSwapBuffers) to know when it's time to commit the next one.
1692// Can be called from the render thread (without locking anything) so make sure to not make races in this method.
1694{
1695 qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
1696
1697 // TODO: Should sync subsurfaces avoid requesting frame callbacks?
1699 if (!mSurface)
1700 return;
1701
1704 return;
1705
1706 struct ::wl_surface *wrappedSurface = reinterpret_cast<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object()));
1707 wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mDisplay->frameEventQueue());
1708 mFrameCallback = wl_surface_frame(wrappedSurface);
1709 wl_proxy_wrapper_destroy(wrappedSurface);
1710 wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
1712 mWaitingForUpdate = false;
1713
1714 // Start a timer for handling the case when the compositor stops sending frame callbacks.
1715 if (mFrameCallbackTimeout > 0) {
1716 QMetaObject::invokeMethod(this, [this] {
1718
1723 }
1725 }
1726}
1727
1729{
1730 qCDebug(lcWaylandBackingstore) << "deliverUpdateRequest";
1731 mWaitingForUpdate = true;
1733}
1734
1736{
1737 mOffset += point;
1738}
1739
1745
1747{
1748 if (auto *seat = display()->lastInputDevice()) {
1749 bool rc = mShellSurface && mShellSurface->resize(seat, edges);
1750 seat->handleEndDrag();
1751 return rc;
1752 }
1753 return false;
1754}
1755
1757{
1758 if (auto seat = display()->lastInputDevice()) {
1759 bool rc = mShellSurface && mShellSurface->move(seat);
1760 seat->handleEndDrag();
1761 return rc;
1762 }
1763 return false;
1764}
1765
1766bool QWaylandWindow::isOpaque() const
1767{
1768 return window()->requestedFormat().alphaBufferSize() <= 0;
1769}
1770
1771void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
1772{
1773 const QRegion translatedOpaqueArea = opaqueArea.translated(clientSideMargins().left(), clientSideMargins().top());
1774
1775 if (translatedOpaqueArea == mOpaqueArea || !mSurface)
1776 return;
1777
1778 mOpaqueArea = translatedOpaqueArea;
1779
1780 struct ::wl_region *region = mDisplay->createRegion(translatedOpaqueArea);
1781 mSurface->set_opaque_region(region);
1782 wl_region_destroy(region);
1783}
1784
1789
1794
1795void QWaylandWindow::addChildPopup(QWaylandWindow *child)
1796{
1797 if (mShellSurface)
1798 mShellSurface->attachPopup(child->shellSurface());
1799 mChildPopups.append(child);
1800}
1801
1802void QWaylandWindow::removeChildPopup(QWaylandWindow *child)
1803{
1804 if (mShellSurface)
1805 mShellSurface->detachPopup(child->shellSurface());
1806 mChildPopups.removeAll(child);
1807}
1808
1810 while (!mChildPopups.isEmpty()) {
1811 auto popup = mChildPopups.takeLast();
1812 popup->reset();
1813 }
1814}
1815
1817{
1818 if (window()->isVisible()) {
1819 initWindow();
1822 }
1823}
1824
1835
1836}
1837
1839
1840#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.
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:689
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:358
const_iterator cend() const
Definition qmap.h:606
const_iterator cbegin() const
Definition qmap.h:602
\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:5959
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6028
QString & append(QChar c)
Definition qstring.cpp:3254
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:167
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:21
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:3011
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...