1/****************************************************************************
2**
3** Copyright (C) 2018 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#include "qwaylandxdgsurfacev5_p.h"
41#include "qwaylandxdgshellv5_p.h"
42
43#include <QtWaylandClient/private/qwaylanddisplay_p.h>
44#include <QtWaylandClient/private/qwaylanddisplay_p.h>
45#include <QtWaylandClient/private/qwaylandwindow_p.h>
46#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
47#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
48#include <QtWaylandClient/private/qwaylandscreen_p.h>
49#include <QtWaylandClient/private/qwaylandextendedsurface_p.h>
50
51QT_BEGIN_NAMESPACE
52
53namespace QtWaylandClient {
54
55QWaylandXdgSurfaceV5::QWaylandXdgSurfaceV5(QWaylandXdgShellV5 *shell, QWaylandWindow *window)
56 : QWaylandShellSurface(window)
57 , QtWayland::xdg_surface_v5(shell->get_xdg_surface(surface: window->wlSurface()))
58 , m_window(window)
59 , m_shell(shell)
60{
61 if (window->display()->windowExtension())
62 m_extendedWindow = new QWaylandExtendedSurface(window);
63
64 updateTransientParent(parent: window->transientParent());
65}
66
67QWaylandXdgSurfaceV5::~QWaylandXdgSurfaceV5()
68{
69 if (m_acked.states & Qt::WindowActive)
70 window()->display()->handleWindowDeactivated(window: m_window);
71
72 xdg_surface_destroy(xdg_surface: object());
73 delete m_extendedWindow;
74}
75
76QtWayland::xdg_surface_v5::resize_edge QWaylandXdgSurfaceV5::convertToResizeEdges(Qt::Edges edges)
77{
78 return static_cast<enum resize_edge>(
79 ((edges & Qt::TopEdge) ? resize_edge_top : 0)
80 | ((edges & Qt::BottomEdge) ? resize_edge_bottom : 0)
81 | ((edges & Qt::LeftEdge) ? resize_edge_left : 0)
82 | ((edges & Qt::RightEdge) ? resize_edge_right : 0));
83}
84
85bool QWaylandXdgSurfaceV5::resize(QWaylandInputDevice *inputDevice, Qt::Edges edges)
86{
87 resize_edge resizeEdges = convertToResizeEdges(edges);
88 resize(seat: inputDevice->wl_seat(), serial: inputDevice->serial(), edges: resizeEdges);
89 return true;
90}
91
92bool QWaylandXdgSurfaceV5::move(QWaylandInputDevice *inputDevice)
93{
94 move(seat: inputDevice->wl_seat(),
95 serial: inputDevice->serial());
96 return true;
97}
98
99bool QWaylandXdgSurfaceV5::showWindowMenu(QWaylandInputDevice *seat)
100{
101 QPoint position = seat->pointerSurfacePosition().toPoint();
102 show_window_menu(seat: seat->wl_seat(), serial: seat->serial(), x: position.x(), y: position.y());
103 return true;
104}
105
106void QWaylandXdgSurfaceV5::updateTransientParent(QWaylandWindow *parent)
107{
108 if (!parent)
109 return;
110 auto parentXdgSurface = qobject_cast<QWaylandXdgSurfaceV5 *>(object: parent->shellSurface());
111 Q_ASSERT(parentXdgSurface);
112 set_parent(parentXdgSurface->object());
113}
114
115void QWaylandXdgSurfaceV5::setTitle(const QString & title)
116{
117 return QtWayland::xdg_surface_v5::set_title(title);
118}
119
120void QWaylandXdgSurfaceV5::setAppId(const QString & appId)
121{
122 return QtWayland::xdg_surface_v5::set_app_id(appId);
123}
124
125void QWaylandXdgSurfaceV5::raise()
126{
127 if (m_extendedWindow)
128 m_extendedWindow->raise();
129}
130
131void QWaylandXdgSurfaceV5::lower()
132{
133 if (m_extendedWindow)
134 m_extendedWindow->lower();
135}
136
137void QWaylandXdgSurfaceV5::setContentOrientationMask(Qt::ScreenOrientations orientation)
138{
139 if (m_extendedWindow)
140 m_extendedWindow->setContentOrientationMask(orientation);
141}
142
143void QWaylandXdgSurfaceV5::setWindowFlags(Qt::WindowFlags flags)
144{
145 if (m_extendedWindow)
146 m_extendedWindow->setWindowFlags(flags);
147}
148
149void QWaylandXdgSurfaceV5::sendProperty(const QString &name, const QVariant &value)
150{
151 if (m_extendedWindow)
152 m_extendedWindow->updateGenericProperty(name, value);
153}
154
155void QWaylandXdgSurfaceV5::applyConfigure()
156{
157 if (m_pending.isResizing)
158 m_normalSize = m_pending.size;
159 else if (!(m_acked.states & (Qt::WindowMaximized|Qt::WindowFullScreen)))
160 m_normalSize = m_window->windowFrameGeometry().size();
161
162 if ((m_pending.states & Qt::WindowActive) && !(m_acked.states & Qt::WindowActive))
163 m_window->display()->handleWindowActivated(window: m_window);
164
165 if (!(m_pending.states & Qt::WindowActive) && (m_acked.states & Qt::WindowActive))
166 m_window->display()->handleWindowDeactivated(window: m_window);
167
168 // TODO: none of the other plugins send WindowActive either, but is it on purpose?
169 Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
170
171 m_window->handleWindowStatesChanged(states: statesWithoutActive);
172 if (!m_pending.size.isEmpty())
173 m_window->resizeFromApplyConfigure(sizeWithMargins: m_pending.size);
174 else if (!m_normalSize.isEmpty())
175 m_window->resizeFromApplyConfigure(sizeWithMargins: m_normalSize);
176 ack_configure(serial: m_pending.serial);
177 m_acked = m_pending;
178}
179
180void QWaylandXdgSurfaceV5::requestWindowStates(Qt::WindowStates states)
181{
182 Qt::WindowStates changedStates = m_acked.states ^ states;
183
184 if (changedStates & Qt::WindowMaximized) {
185 if (states & Qt::WindowMaximized)
186 set_maximized();
187 else
188 unset_maximized();
189 }
190
191 if (changedStates & Qt::WindowFullScreen) {
192 if (states & Qt::WindowFullScreen)
193 set_fullscreen(nullptr);
194 else
195 unset_fullscreen();
196 }
197
198 // Minimized state is not reported by the protocol, so always send it
199 if (states & Qt::WindowMinimized) {
200 set_minimized();
201 window()->handleWindowStatesChanged(states: states & ~Qt::WindowMinimized);
202 }
203}
204
205bool QWaylandXdgSurfaceV5::wantsDecorations() const
206{
207 return !(m_pending.states & Qt::WindowFullScreen);
208}
209
210void QWaylandXdgSurfaceV5::xdg_surface_configure(int32_t width, int32_t height, struct wl_array *states,uint32_t serial)
211{
212 uint32_t *xdgStates = reinterpret_cast<uint32_t*>(states->data);
213 size_t numStates = states->size / sizeof(uint32_t);
214 m_pending.serial = serial;
215 m_pending.size = QSize(width, height);
216 m_pending.isResizing = false;
217 m_pending.states = Qt::WindowNoState;
218 for (size_t i = 0; i < numStates; i++) {
219 switch (xdgStates[i]) {
220 case XDG_SURFACE_STATE_MAXIMIZED:
221 m_pending.states |= Qt::WindowMaximized;
222 break;
223 case XDG_SURFACE_STATE_FULLSCREEN:
224 m_pending.states |= Qt::WindowFullScreen;
225 break;
226 case XDG_SURFACE_STATE_RESIZING:
227 m_pending.isResizing = true;
228 break;
229 case XDG_SURFACE_STATE_ACTIVATED:
230 m_pending.states |= Qt::WindowActive;
231 break;
232 default:
233 break;
234 }
235 }
236 m_window->applyConfigureWhenPossible();
237}
238
239void QWaylandXdgSurfaceV5::xdg_surface_close()
240{
241 m_window->window()->close();
242}
243
244}
245
246QT_END_NAMESPACE
247

source code of qtwayland/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgsurfacev5.cpp