1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the config.tests of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QWAYLANDWINDOW_H
41 #define QWAYLANDWINDOW_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtCore/QWaitCondition>
55 #include <QtCore/QMutex>
56 #include <QtCore/QReadWriteLock>
57 
58 #include <QtGui/QIcon>
59 #include <QtCore/QVariant>
60 #include <QtCore/QLoggingCategory>
61 #include <QtCore/QElapsedTimer>
62 
63 #include <qpa/qplatformwindow.h>
64 
65 #include <QtWaylandClient/private/qwayland-wayland.h>
66 #include <QtWaylandClient/private/qwaylanddisplay_p.h>
67 #include <QtWaylandClient/qtwaylandclientglobal.h>
68 
69 struct wl_egl_window;
70 
71 QT_BEGIN_NAMESPACE
72 
73 namespace QtWaylandClient {
74 
75 Q_DECLARE_LOGGING_CATEGORY(lcWaylandBackingstore)
76 
77 class QWaylandDisplay;
78 class QWaylandBuffer;
79 class QWaylandShellSurface;
80 class QWaylandSubSurface;
81 class QWaylandAbstractDecoration;
82 class QWaylandInputDevice;
83 class QWaylandScreen;
84 class QWaylandShmBackingStore;
85 class QWaylandPointerEvent;
86 class QWaylandSurface;
87 
88 class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow
89 {
90     Q_OBJECT
91 public:
92     enum WindowType {
93         Shm,
94         Egl,
95         Vulkan
96     };
97 
98     QWaylandWindow(QWindow *window, QWaylandDisplay *display);
99     ~QWaylandWindow() override;
100 
101     virtual WindowType windowType() const = 0;
102     virtual void ensureSize();
103     WId winId() const override;
104     void setVisible(bool visible) override;
105     void setParent(const QPlatformWindow *parent) override;
106 
107     void setWindowTitle(const QString &title) override;
108 
109     inline QIcon windowIcon() const;
110     void setWindowIcon(const QIcon &icon) override;
111 
112     void setGeometry(const QRect &rect) override;
113     void resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset = {0, 0});
114 
115     void applyConfigureWhenPossible(); //rename to possible?
116 
117     void attach(QWaylandBuffer *buffer, int x, int y);
118     void attachOffset(QWaylandBuffer *buffer);
119     QPoint attachOffset() const;
120 
121     void damage(const QRect &rect);
122 
123     void safeCommit(QWaylandBuffer *buffer, const QRegion &damage);
124     void handleExpose(const QRegion &region);
125     void commit(QWaylandBuffer *buffer, const QRegion &damage);
126 
127     void commit();
128 
129     bool waitForFrameSync(int timeout);
130 
131     QMargins frameMargins() const override;
132     QSize surfaceSize() const;
133     QRect windowContentGeometry() const;
134     QPointF mapFromWlSurface(const QPointF &surfacePosition) const;
135 
waylandSurface()136     QWaylandSurface *waylandSurface() const { return mSurface.data(); }
137     ::wl_surface *wlSurface();
138     static QWaylandWindow *fromWlSurface(::wl_surface *surface);
139 
display()140     QWaylandDisplay *display() const { return mDisplay; }
141     QWaylandShellSurface *shellSurface() const;
142     QWaylandSubSurface *subSurfaceWindow() const;
143     QWaylandScreen *waylandScreen() const;
144 
145     void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
146     void setOrientationMask(Qt::ScreenOrientations mask);
147 
148     void setWindowState(Qt::WindowStates states) override;
149     void setWindowFlags(Qt::WindowFlags flags) override;
150     void handleWindowStatesChanged(Qt::WindowStates states);
151     Qt::WindowStates windowStates() const;
152 
153     void raise() override;
154     void lower() override;
155 
156     void setMask(const QRegion &region) override;
157 
158     int scale() const;
159     qreal devicePixelRatio() const override;
160 
161     void requestActivateWindow() override;
162     bool isExposed() const override;
163     bool isActive() const override;
164 
165     QWaylandAbstractDecoration *decoration() const;
166 
167     void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
168 
169     bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
170                              Qt::TouchPointState state, Qt::KeyboardModifiers mods);
171 
172     bool createDecoration();
173 
174 #if QT_CONFIG(cursor)
175     void setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor);
176     void restoreMouseCursor(QWaylandInputDevice *device);
177 #endif
178 
179     QWaylandWindow *transientParent() const;
180 
resizeMutex()181     QMutex *resizeMutex() { return &mResizeLock; }
182     void doApplyConfigure();
183     void setCanResize(bool canResize);
184 
185     bool setMouseGrabEnabled(bool grab) override;
mouseGrab()186     static QWaylandWindow *mouseGrab() { return mMouseGrab; }
187 
188     void sendProperty(const QString &name, const QVariant &value);
189     void setProperty(const QString &name, const QVariant &value);
190 
191     QVariantMap properties() const;
192     QVariant property(const QString &name);
193     QVariant property(const QString &name, const QVariant &defaultValue);
194 
setBackingStore(QWaylandShmBackingStore * backingStore)195     void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; }
backingStore()196     QWaylandShmBackingStore *backingStore() const { return mBackingStore; }
197 
setKeyboardGrabEnabled(bool)198     bool setKeyboardGrabEnabled(bool) override { return false; }
199     void propagateSizeHints() override;
200     void addAttachOffset(const QPoint point);
201 
202     bool startSystemResize(Qt::Edges edges) override;
203     bool startSystemMove() override;
204 
205     void timerEvent(QTimerEvent *event) override;
206     void requestUpdate() override;
207     void handleUpdate();
208     void deliverUpdateRequest() override;
209 
210 public slots:
211     void applyConfigure();
212 
213 signals:
214     void wlSurfaceCreated();
215     void wlSurfaceDestroyed();
216 
217 protected:
218     QWaylandDisplay *mDisplay = nullptr;
219     QScopedPointer<QWaylandSurface> mSurface;
220     QWaylandShellSurface *mShellSurface = nullptr;
221     QWaylandSubSurface *mSubSurfaceWindow = nullptr;
222     QVector<QWaylandSubSurface *> mChildren;
223 
224     QWaylandAbstractDecoration *mWindowDecoration = nullptr;
225     bool mMouseEventsInContentArea = false;
226     Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
227 
228     WId mWindowId;
229     bool mWaitingForFrameCallback = false;
230     bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
231     bool mWaitingForUpdateDelivery = false;
232     int mFrameCallbackCheckIntervalTimerId = -1;
233     QElapsedTimer mFrameCallbackElapsedTimer;
234     struct ::wl_callback *mFrameCallback = nullptr;
235     QWaylandDisplay::FrameQueue mFrameQueue;
236     QWaitCondition mFrameSyncWait;
237 
238     // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
239     bool mWaitingForUpdate = false;
240 
241     QMutex mResizeLock;
242     bool mWaitingToApplyConfigure = false;
243     bool mCanResize = true;
244     bool mResizeDirty = false;
245     bool mResizeAfterSwap;
246     int mFrameCallbackTimeout = 100;
247     QVariantMap m_properties;
248 
249     bool mSentInitialResize = false;
250     QPoint mOffset;
251     int mScale = 1;
252     QPlatformScreen *mLastReportedScreen = nullptr;
253 
254     QIcon mWindowIcon;
255 
256     Qt::WindowFlags mFlags;
257     QRegion mMask;
258     QRegion mOpaqueArea;
259     Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState;
260 
261     QWaylandShmBackingStore *mBackingStore = nullptr;
262     QWaylandBuffer *mQueuedBuffer = nullptr;
263     QRegion mQueuedBufferDamage;
264 
265 private:
266     void setGeometry_helper(const QRect &rect);
267     void initWindow();
268     void initializeWlSurface();
269     bool shouldCreateShellSurface() const;
270     bool shouldCreateSubSurface() const;
271     void reset();
272     void sendExposeEvent(const QRect &rect);
273     static void closePopups(QWaylandWindow *parent);
274     QPlatformScreen *calculateScreenFromSurfaceEvents() const;
275     void setOpaqueArea(const QRegion &opaqueArea);
276     bool isOpaque() const;
277 
278     void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
279     void handleScreensChanged();
280     void sendRecursiveExposeEvent();
281 
282     bool mInResizeFromApplyConfigure = false;
283     bool lastVisible = false;
284     QRect mLastExposeGeometry;
285 
286     static const wl_callback_listener callbackListener;
287     void handleFrameCallback();
288 
289     static QWaylandWindow *mMouseGrab;
290 
291     QReadWriteLock mSurfaceLock;
292 
293     friend class QWaylandSubSurface;
294 };
295 
windowIcon()296 inline QIcon QWaylandWindow::windowIcon() const
297 {
298     return mWindowIcon;
299 }
300 
attachOffset()301 inline QPoint QWaylandWindow::attachOffset() const
302 {
303     return mOffset;
304 }
305 
306 }
307 
308 QT_END_NAMESPACE
309 
310 #endif // QWAYLANDWINDOW_H
311