Branch data Line data Source code
1 : : // Copyright (C) 2021 The Qt Company Ltd.
2 : : // Copyright (C) 2019 Luxoft Sweden AB
3 : : // Copyright (C) 2018 Pelagicore AG
4 : : // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
5 : :
6 : :
7 : : #include "global.h"
8 : : #if QT_CONFIG(am_multi_process)
9 : : #include "logging.h"
10 : : #include "qml-utilities.h"
11 : : #include "applicationmanager.h"
12 : : #include "application.h"
13 : : #include "waylandwindow.h"
14 : : #include "waylandcompositor.h"
15 : : #include "waylandqtamserverextension_p.h"
16 : :
17 : : #include <QWaylandWlShellSurface>
18 : :
19 : : using namespace Qt::StringLiterals;
20 : :
21 : :
22 : : QT_BEGIN_NAMESPACE_AM
23 : :
24 : : bool WaylandWindow::m_watchdogEnabled = true;
25 : :
26 : 80 : WaylandWindow::WaylandWindow(Application *app, WindowSurface *surf)
27 : : : Window(app)
28 [ + - ]: 80 : , m_pingTimer(new QTimer(this))
29 [ + - + - ]: 80 : , m_pongTimer(new QTimer(this))
30 [ + - + - ]: 160 : , m_surface(surf)
31 : : {
32 [ + - ]: 80 : if (surf) {
33 : 80 : connect(surf, &WindowSurface::pong,
34 [ + - ]: 80 : this, &WaylandWindow::pongReceived);
35 [ + - ]: 80 : connect(m_surface, &QWaylandSurface::hasContentChanged, this, &WaylandWindow::onContentStateChanged);
36 [ + - ]: 80 : connect(m_surface, &QWaylandSurface::bufferSizeChanged, this, &Window::sizeChanged);
37 : :
38 [ + - ]: 80 : m_pingTimer->setInterval(1000);
39 [ + - ]: 80 : m_pingTimer->setSingleShot(true);
40 [ + - ]: 80 : connect(m_pingTimer, &QTimer::timeout, this, &WaylandWindow::pingTimeout);
41 [ + - ]: 80 : m_pongTimer->setInterval(2000);
42 [ + - ]: 80 : m_pongTimer->setSingleShot(true);
43 [ + - ]: 80 : connect(m_pongTimer, &QTimer::timeout, this, &WaylandWindow::pongTimeout);
44 : :
45 [ + - + - : 80 : connect(surf->compositor()->amExtension(), &WaylandQtAMServerExtension::windowPropertyChanged,
+ - ]
46 : 158 : this, [this](QWaylandSurface *surface, const QString &name, const QVariant &value) {
47 [ + + ]: 87 : if (surface == m_surface) {
48 : 71 : m_windowProperties[name] = value;
49 : 71 : emit windowPropertyChanged(name, value);
50 : : }
51 : 87 : });
52 : :
53 [ + - ]: 80 : connect(surf, &QWaylandSurface::surfaceDestroyed, this, [this]() {
54 : 80 : m_surface = nullptr;
55 : 80 : onContentStateChanged();
56 : 80 : emit waylandSurfaceChanged();
57 : 80 : });
58 : :
59 : : // Caching them so that Window::windowProperty and Window::windowProperties
60 : : // still return the expected values even after the underlying wayland surface
61 : : // is gone (content state NoSurface).
62 [ + - + - : 80 : m_windowProperties = m_surface->compositor()->amExtension()->windowProperties(m_surface);
+ - ]
63 : :
64 [ + - - + ]: 80 : if (m_surface->isPopup()) {
65 : 0 : connect(m_surface, &WindowSurface::popupGeometryChanged,
66 [ # # ]: 0 : this, &WaylandWindow::requestedPopupPositionChanged);
67 : : }
68 : :
69 : 80 : connect(m_surface, &WindowSurface::xdgSurfaceChanged,
70 [ + - ]: 80 : this, &WaylandWindow::waylandXdgSurfaceChanged);
71 : :
72 [ + - ]: 80 : enableOrDisablePing();
73 : : }
74 : 80 : }
75 : :
76 : 1 : void WaylandWindow::pongReceived()
77 : : {
78 : 1 : m_pongTimer->stop();
79 : 1 : m_pingTimer->start();
80 : 1 : }
81 : :
82 : 0 : void WaylandWindow::pongTimeout()
83 : : {
84 [ # # ]: 0 : if (!application())
85 : : return;
86 : :
87 [ # # # # : 0 : qCCritical(LogGraphics) << "Stopping application" << application()->id() << "because we did not receive a Wayland-Pong for" << m_pongTimer->interval() << "msec";
# # # # #
# # # # #
# # # # ]
88 : 0 : ApplicationManager::instance()->stopApplicationInternal(application(), true);
89 : : }
90 : :
91 : 2 : void WaylandWindow::pingTimeout()
92 : : {
93 : 2 : m_pingTimer->stop();
94 : 2 : m_pongTimer->start();
95 [ + - ]: 2 : if (m_surface)
96 : 2 : m_surface->ping();
97 : 2 : }
98 : :
99 : 58 : bool WaylandWindow::setWindowProperty(const QString &name, const QVariant &value)
100 : : {
101 [ + - ]: 58 : if (m_surface) {
102 : 58 : const QVariant v = convertFromJSVariant(value);
103 [ + - + - : 58 : m_surface->compositor()->amExtension()->setWindowProperty(m_surface, name, v);
+ - ]
104 : 58 : }
105 : 58 : return (m_surface);
106 : : }
107 : :
108 : 85 : QVariant WaylandWindow::windowProperty(const QString &name) const
109 : : {
110 [ + - ]: 85 : return m_windowProperties.value(name);
111 : : }
112 : :
113 : 1 : QVariantMap WaylandWindow::windowProperties() const
114 : : {
115 [ + - ]: 1 : return m_windowProperties;
116 : : }
117 : :
118 : 0 : bool WaylandWindow::isPopup() const
119 : : {
120 [ # # # # ]: 0 : return m_surface ? m_surface->isPopup() : false;
121 : : }
122 : :
123 : 0 : QPoint WaylandWindow::requestedPopupPosition() const
124 : : {
125 [ # # ]: 0 : return m_surface ? m_surface->popupGeometry().topLeft() : QPoint();
126 : : }
127 : :
128 : 372 : Window::ContentState WaylandWindow::contentState() const
129 : : {
130 [ + + ]: 372 : if (m_surface)
131 [ + + ]: 112 : return m_surface->hasContent() ? SurfaceWithContent : SurfaceNoContent;
132 : : else
133 : : return NoSurface;
134 : : }
135 : :
136 : 240 : void WaylandWindow::enableOrDisablePing()
137 : : {
138 [ + + ]: 240 : if (m_watchdogEnabled) {
139 : 6 : m_pingTimer->stop();
140 : 6 : m_pongTimer->stop();
141 : :
142 [ + + + + ]: 6 : if (m_surface && m_surface->hasContent())
143 : 2 : pingTimeout();
144 : : }
145 : 240 : }
146 : :
147 : 160 : void WaylandWindow::onContentStateChanged()
148 : : {
149 [ - - - - : 320 : qCDebug(LogGraphics) << this << "of" << applicationId() << "contentState changed to" << contentState();
- - - - -
- - - - -
- + ]
150 : :
151 : 160 : enableOrDisablePing();
152 : 160 : emit contentStateChanged();
153 : 160 : }
154 : :
155 : 0 : QString WaylandWindow::applicationId() const
156 : : {
157 [ # # ]: 0 : if (application())
158 : 0 : return application()->id();
159 [ # # # # ]: 0 : else if (m_surface && m_surface->client())
160 [ # # # # : 0 : return u"[pid: %1]"_s.arg(m_surface->client()->processId());
# # ]
161 : : else
162 : 0 : return u"[external app]"_s;
163 : : }
164 : :
165 : 492 : QSize WaylandWindow::size() const
166 : : {
167 : 492 : return m_surface->bufferSize();
168 : : }
169 : :
170 : 66 : void WaylandWindow::resize(const QSize &newSize)
171 : : {
172 [ + + ]: 66 : if (!m_surface)
173 : : return;
174 : :
175 [ - - - - : 130 : qCDebug(LogGraphics) << this << "of" << applicationId() << "sending resize request for surface"
- - - - -
- - - -
+ ]
176 [ # # # # : 0 : << m_surface << "to" << newSize;
# # ]
177 : :
178 : 65 : m_surface->sendResizing(newSize);
179 : : }
180 : :
181 : 0 : QWaylandQuickSurface* WaylandWindow::waylandSurface() const
182 : : {
183 : 0 : return m_surface;
184 : : }
185 : :
186 : 0 : QWaylandXdgSurface *WaylandWindow::waylandXdgSurface() const
187 : : {
188 [ # # # # ]: 0 : return m_surface ? m_surface->xdgSurface() : nullptr;
189 : : }
190 : :
191 : 6 : void WaylandWindow::close()
192 : : {
193 [ + + ]: 6 : if (m_surface)
194 : 5 : m_surface->close();
195 : 6 : }
196 : :
197 : : QT_END_NAMESPACE_AM
198 : :
199 : : #endif // QT_CONFIG(am_multi_process)
200 : :
201 : : #include "moc_waylandwindow.cpp"
|