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#ifndef QWAYLANDWINDOW_H
5#define QWAYLANDWINDOW_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/QWaitCondition>
19#include <QtCore/QMutex>
20#include <QtCore/QReadWriteLock>
21
22#include <QtGui/QIcon>
23#include <QtGui/QEventPoint>
24#include <QtCore/QVariant>
25#include <QtCore/QLoggingCategory>
26#include <QtCore/QElapsedTimer>
27#include <QtCore/QList>
28#include <QtCore/QMap> // for QVariantMap
29
30#include <qpa/qplatformwindow.h>
31#include <qpa/qplatformwindow_p.h>
32
33#include <QtWaylandClient/private/qwayland-wayland.h>
34#include <QtWaylandClient/private/qwaylanddisplay_p.h>
35#include <QtWaylandClient/qtwaylandclientglobal.h>
36#include <QtWaylandClient/private/qwaylandshellsurface_p.h>
37
38#include <QtCore/qpointer.h>
39
40struct wl_egl_window;
41
42QT_BEGIN_NAMESPACE
43
44namespace QtWaylandClient {
45
46Q_DECLARE_LOGGING_CATEGORY(lcWaylandBackingstore)
47
48class QWaylandDisplay;
49class QWaylandBuffer;
50class QWaylandShellSurface;
51class QWaylandSubSurface;
52class QWaylandAbstractDecoration;
53class QWaylandInputDevice;
54class QWaylandScreen;
55class QWaylandShellIntegration;
56class QWaylandShmBackingStore;
57class QWaylandPointerEvent;
58class QWaylandPointerGestureSwipeEvent;
59class QWaylandPointerGesturePinchEvent;
60class QWaylandSurface;
61class QWaylandFractionalScale;
62class QWaylandViewport;
63
64class Q_WAYLANDCLIENT_EXPORT QWaylandWindow : public QNativeInterface::Private::QWaylandWindow,
65 public QPlatformWindow
66{
67 Q_OBJECT
68public:
69 enum WindowType {
70 Shm,
71 Egl,
72 Vulkan
73 };
74
75 enum ToplevelWindowTilingState {
76 WindowNoState = 0,
77 WindowTiledLeft = 1,
78 WindowTiledRight = 2,
79 WindowTiledTop = 4,
80 WindowTiledBottom = 8
81 };
82 Q_DECLARE_FLAGS(ToplevelWindowTilingStates, ToplevelWindowTilingState)
83
84 QWaylandWindow(QWindow *window, QWaylandDisplay *display);
85 ~QWaylandWindow() override;
86
87 // Keep Toplevels position on the top left corner of their screen
88 static inline bool fixedToplevelPositions = true;
89
90 virtual WindowType windowType() const = 0;
91 virtual void ensureSize();
92 WId winId() const override;
93 void setVisible(bool visible) override;
94 void setParent(const QPlatformWindow *parent) override;
95
96 QString windowTitle() const;
97 void setWindowTitle(const QString &title) override;
98
99 inline QIcon windowIcon() const;
100 void setWindowIcon(const QIcon &icon) override;
101
102 void setGeometry(const QRect &rect) override;
103 void resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset = {0, 0});
104 void repositionFromApplyConfigure(const QPoint &position);
105 void setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins);
106
107 void applyConfigureWhenPossible(); //rename to possible?
108
109 void attach(QWaylandBuffer *buffer, int x, int y);
110 void attachOffset(QWaylandBuffer *buffer);
111 QPoint attachOffset() const;
112
113 void damage(const QRect &rect);
114
115 void safeCommit(QWaylandBuffer *buffer, const QRegion &damage);
116 void commit(QWaylandBuffer *buffer, const QRegion &damage);
117
118 void commit();
119
120 bool waitForFrameSync(int timeout);
121
122 QMargins frameMargins() const override;
123 QMargins clientSideMargins() const;
124 void setCustomMargins(const QMargins &margins) override;
125 QSize surfaceSize() const;
126 QMargins windowContentMargins() const;
127 QRect windowContentGeometry() const;
128 QPointF mapFromWlSurface(const QPointF &surfacePosition) const;
129
130 QWaylandSurface *waylandSurface() const { return mSurface.data(); }
131 ::wl_surface *wlSurface() const;
132 ::wl_surface *surface() const override
133 {
134 return wlSurface();
135 }
136 static QWaylandWindow *fromWlSurface(::wl_surface *surface);
137
138 QWaylandDisplay *display() const { return mDisplay; }
139 QWaylandShellSurface *shellSurface() const;
140 std::any _surfaceRole() const override;
141 QWaylandSubSurface *subSurfaceWindow() const;
142 QWaylandScreen *waylandScreen() const;
143
144 void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
145 void updateBufferTransform();
146 void setOrientationMask(Qt::ScreenOrientations mask);
147
148 ToplevelWindowTilingStates toplevelWindowTilingStates() const;
149 void handleToplevelWindowTilingStatesChanged(ToplevelWindowTilingStates states);
150
151 Qt::WindowStates windowStates() const;
152 void setWindowState(Qt::WindowStates states) override;
153 void setWindowFlags(Qt::WindowFlags flags) override;
154 void handleWindowStatesChanged(Qt::WindowStates states);
155
156 void raise() override;
157 void lower() override;
158
159 void setMask(const QRegion &region) override;
160
161 void setAlertState(bool enabled) override;
162 bool isAlertState() const override;
163
164 qreal scale() const;
165 qreal devicePixelRatio() const override;
166
167 void requestActivateWindow() override;
168 bool isExposed() const override;
169 bool isActive() const override;
170
171 QWaylandAbstractDecoration *decoration() const;
172
173 void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
174#ifndef QT_NO_GESTURES
175 void handleSwipeGesture(QWaylandInputDevice *inputDevice,
176 const QWaylandPointerGestureSwipeEvent &e);
177 void handlePinchGesture(QWaylandInputDevice *inputDevice,
178 const QWaylandPointerGesturePinchEvent &e);
179#endif
180
181 bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
182 QEventPoint::State state, Qt::KeyboardModifiers mods);
183 bool handleTabletEventDecoration(QWaylandInputDevice *inputDevice, const QPointF &local,
184 const QPointF &global, Qt::MouseButtons buttons,
185 Qt::KeyboardModifiers modifiers);
186
187 bool createDecoration();
188
189#if QT_CONFIG(cursor)
190 void setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor);
191 void restoreMouseCursor(QWaylandInputDevice *device);
192#endif
193
194 QWaylandWindow *transientParent() const;
195
196 void doApplyConfigure();
197 void setCanResize(bool canResize);
198
199 bool setMouseGrabEnabled(bool grab) override;
200 static QWaylandWindow *mouseGrab() { return mMouseGrab; }
201
202 void sendProperty(const QString &name, const QVariant &value);
203 void setProperty(const QString &name, const QVariant &value);
204
205 QVariantMap properties() const;
206 QVariant property(const QString &name);
207 QVariant property(const QString &name, const QVariant &defaultValue);
208
209#ifdef QT_PLATFORM_WINDOW_HAS_VIRTUAL_SET_BACKING_STORE
210 void setBackingStore(QPlatformBackingStore *store) override;
211#else
212 void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; }
213#endif
214 QWaylandShmBackingStore *backingStore() const { return mBackingStore; }
215
216 void setShellIntegration(QWaylandShellIntegration *shellIntegration);
217 QWaylandShellIntegration *shellIntegration() const { return mShellIntegration; }
218
219 bool setKeyboardGrabEnabled(bool) override { return false; }
220 void propagateSizeHints() override;
221 void addAttachOffset(const QPoint point);
222
223 bool startSystemResize(Qt::Edges edges) override;
224 bool startSystemMove() override;
225
226 void timerEvent(QTimerEvent *event) override;
227 void requestUpdate() override;
228 void handleUpdate();
229 void deliverUpdateRequest() override;
230
231 void setXdgActivationToken(const QString &token);
232 void requestXdgActivationToken(uint serial) override;
233
234 void beginFrame();
235 void endFrame();
236
237 void closeChildPopups();
238 void sendRecursiveExposeEvent();
239
240 virtual void reinit();
241 void reset();
242
243 bool windowEvent(QEvent *event) override;
244
245public Q_SLOTS:
246 void applyConfigure();
247
248Q_SIGNALS:
249 void wlSurfaceCreated();
250 void wlSurfaceDestroyed();
251
252protected:
253 virtual void doHandleFrameCallback();
254 virtual QRect defaultGeometry() const;
255 void sendExposeEvent(const QRect &rect);
256
257 QWaylandDisplay *mDisplay = nullptr;
258
259 // mSurface can be written by the main thread. Other threads should claim a read lock for access
260 mutable QReadWriteLock mSurfaceLock;
261 QScopedPointer<QWaylandSurface> mSurface;
262 QScopedPointer<QWaylandFractionalScale> mFractionalScale;
263 QScopedPointer<QWaylandViewport> mViewport;
264
265 QWaylandShellIntegration *mShellIntegration = nullptr;
266 QWaylandShellSurface *mShellSurface = nullptr;
267 QWaylandSubSurface *mSubSurfaceWindow = nullptr;
268 QList<QWaylandSubSurface *> mChildren;
269
270 QWaylandAbstractDecoration *mWindowDecoration = nullptr;
271 bool mWindowDecorationEnabled = false;
272 bool mMouseEventsInContentArea = false;
273 Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
274
275#ifndef QT_NO_GESTURES
276 enum GestureState {
277 GestureNotActive,
278 GestureActiveInContentArea,
279 GestureActiveInDecoration
280 };
281
282 // We want gestures started in the decoration area to be completely ignored even if the mouse
283 // pointer is later moved to content area. Likewise, gestures started in the content area should
284 // keep sending events even if the mouse pointer is moved over the decoration (consider that
285 // the events for that gesture will be sent to us even if it's moved outside the window).
286 // So we track the gesture state and accept or ignore events based on that. Note that
287 // concurrent gestures of different types are not allowed in the protocol, so single state is
288 // enough
289 GestureState mGestureState = GestureNotActive;
290#endif
291
292 WId mWindowId;
293 bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
294 int mFrameCallbackCheckIntervalTimerId = -1;
295 QAtomicInt mWaitingForUpdateDelivery = false;
296
297 bool mWaitingForFrameCallback = false; // Protected by mFrameSyncMutex
298 QElapsedTimer mFrameCallbackElapsedTimer; // Protected by mFrameSyncMutex
299 struct ::wl_callback *mFrameCallback = nullptr; // Protected by mFrameSyncMutex
300 QMutex mFrameSyncMutex;
301 QWaitCondition mFrameSyncWait;
302
303 // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
304 bool mWaitingForUpdate = false;
305
306 QRecursiveMutex mResizeLock;
307 bool mWaitingToApplyConfigure = false;
308 bool mCanResize = true;
309 bool mResizeDirty = false;
310 bool mResizeAfterSwap;
311 int mFrameCallbackTimeout = 100;
312 QVariantMap m_properties;
313
314 bool mSentInitialResize = false;
315 QPoint mOffset;
316 std::optional<qreal> mScale = std::nullopt;
317
318 QString mWindowTitle;
319 QIcon mWindowIcon;
320
321 Qt::WindowFlags mFlags;
322 QRegion mMask;
323
324 // Empty QRegion maps to "infinite" input region, needs a dedicated "deliberately empty" state.
325 QRegion mInputRegion;
326 bool mTransparentInputRegion = false;
327
328 QRegion mOpaqueArea;
329 Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
330 ToplevelWindowTilingStates mLastReportedToplevelWindowTilingStates = WindowNoState;
331
332 QWaylandShmBackingStore *mBackingStore = nullptr;
333
334 QMargins mCustomMargins;
335
336 QPointer<QWaylandWindow> mTransientParent;
337 QList<QPointer<QWaylandWindow>> mChildPopups;
338
339 Qt::ScreenOrientation mLastReportedContentOrientation = Qt::PrimaryOrientation;
340
341private Q_SLOTS:
342 void doApplyConfigureFromOtherThread();
343
344private:
345 void setGeometry_helper(const QRect &rect);
346 void initWindow();
347 void initializeWlSurface();
348 bool shouldCreateShellSurface() const;
349 bool shouldCreateSubSurface() const;
350 QPlatformScreen *calculateScreenFromSurfaceEvents() const;
351 void setOpaqueArea(const QRegion &opaqueArea);
352 bool isOpaque() const;
353 void updateInputRegion();
354 void updateViewport();
355
356 void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
357 void handleScreensChanged();
358 void updateScale();
359 void setScale(qreal newScale);
360
361 QWaylandWindow *guessTransientParent() const;
362 void addChildPopup(QWaylandWindow *child);
363 void removeChildPopup(QWaylandWindow *child);
364
365 bool mInResizeFromApplyConfigure = false;
366 bool lastVisible = false;
367 QRect mLastExposeGeometry;
368
369 static const wl_callback_listener callbackListener;
370 void handleFrameCallback(struct ::wl_callback* callback);
371
372 static QWaylandWindow *mMouseGrab;
373 static QWaylandWindow *mTopPopup;
374
375 friend class QWaylandSubSurface;
376};
377
378Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandWindow::ToplevelWindowTilingStates)
379
380inline QIcon QWaylandWindow::windowIcon() const
381{
382 return mWindowIcon;
383}
384
385inline QPoint QWaylandWindow::attachOffset() const
386{
387 return mOffset;
388}
389
390}
391
392QT_END_NAMESPACE
393
394#endif // QWAYLANDWINDOW_H
395

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtwayland/src/client/qwaylandwindow_p.h