Directory: | ./ |
---|---|
File: | src/client/xdg_shell.cpp |
Date: | 2024-01-22 17:25:27 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 82 | 90 | 91.1% |
Branches: | 14 | 28 | 50.0% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> | ||
3 | SPDX-FileCopyrightText: 2021 Roman Gilg <subdiff@gmail.com> | ||
4 | |||
5 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only | ||
6 | */ | ||
7 | #include "xdg_shell.h" | ||
8 | |||
9 | #include "xdg_shell_popup.h" | ||
10 | #include "xdg_shell_positioner.h" | ||
11 | #include "xdg_shell_toplevel.h" | ||
12 | |||
13 | #include "event_queue.h" | ||
14 | #include "seat.h" | ||
15 | #include "surface.h" | ||
16 | #include "wayland_pointer_p.h" | ||
17 | |||
18 | #include <wayland-xdg-shell-client-protocol.h> | ||
19 | |||
20 | namespace Wrapland::Client | ||
21 | { | ||
22 | |||
23 | 81 | class Q_DECL_HIDDEN XdgShell::Private | |
24 | { | ||
25 | public: | ||
26 | virtual ~Private(); | ||
27 | |||
28 | void setup(xdg_wm_base* shell); | ||
29 | void release(); | ||
30 | bool isValid() const; | ||
31 | |||
32 | 6 | operator xdg_wm_base*() | |
33 | { | ||
34 | 6 | return xdg_shell_base; | |
35 | } | ||
36 | operator xdg_wm_base*() const | ||
37 | { | ||
38 | return xdg_shell_base; | ||
39 | } | ||
40 | |||
41 | XdgShellToplevel* getXdgToplevel(Surface* surface, QObject* parent); | ||
42 | XdgShellPopup* get_xdg_popup(Surface* surface, | ||
43 | xdg_surface* parentSurface, | ||
44 | xdg_shell_positioner_data positioner_data, | ||
45 | QObject* parent); | ||
46 | xdg_shell_positioner* get_xdg_positioner(xdg_shell_positioner_data data, QObject* parent); | ||
47 | |||
48 | 81 | EventQueue* queue = nullptr; | |
49 | |||
50 | private: | ||
51 | static void pingCallback(void* data, struct xdg_wm_base* shell, uint32_t serial); | ||
52 | |||
53 | WaylandPointer<xdg_wm_base, xdg_wm_base_destroy> xdg_shell_base; | ||
54 | static const struct xdg_wm_base_listener s_shellListener; | ||
55 | }; | ||
56 | |||
57 | 162 | XdgShell::Private::~Private() = default; | |
58 | |||
59 | struct xdg_wm_base_listener const XdgShell::Private::s_shellListener = { | ||
60 | pingCallback, | ||
61 | }; | ||
62 | |||
63 | 1 | void XdgShell::Private::pingCallback(void* data, struct xdg_wm_base* shell, uint32_t serial) | |
64 | { | ||
65 | Q_UNUSED(data) | ||
66 | 1 | xdg_wm_base_pong(shell, serial); | |
67 | 1 | } | |
68 | |||
69 | 81 | void XdgShell::Private::setup(xdg_wm_base* shell) | |
70 | { | ||
71 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | Q_ASSERT(shell); |
72 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | Q_ASSERT(!xdg_shell_base); |
73 | 81 | xdg_shell_base.setup(shell); | |
74 | 81 | xdg_wm_base_add_listener(shell, &s_shellListener, this); | |
75 | 81 | } | |
76 | |||
77 | 83 | void XdgShell::Private::release() | |
78 | { | ||
79 | 83 | xdg_shell_base.release(); | |
80 | 83 | } | |
81 | |||
82 | 151 | bool XdgShell::Private::isValid() const | |
83 | { | ||
84 | 151 | return xdg_shell_base.isValid(); | |
85 | } | ||
86 | |||
87 | 67 | XdgShellToplevel* XdgShell::Private::getXdgToplevel(Surface* surface, QObject* parent) | |
88 | { | ||
89 |
1/2✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
|
67 | Q_ASSERT(isValid()); |
90 | 67 | auto ss = xdg_wm_base_get_xdg_surface(xdg_shell_base, *surface); | |
91 | |||
92 |
1/2✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
|
67 | if (!ss) { |
93 | ✗ | return nullptr; | |
94 | } | ||
95 | |||
96 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | auto s = new XdgShellToplevel(parent); |
97 | 67 | auto toplevel = xdg_surface_get_toplevel(ss); | |
98 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
|
67 | if (queue) { |
99 | 67 | queue->addProxy(ss); | |
100 | 67 | queue->addProxy(toplevel); | |
101 | 67 | } | |
102 | 67 | s->setup(ss, toplevel); | |
103 | 67 | return s; | |
104 | 67 | } | |
105 | |||
106 | 11 | XdgShellPopup* XdgShell::Private::get_xdg_popup(Surface* surface, | |
107 | xdg_surface* parentSurface, | ||
108 | xdg_shell_positioner_data positioner_data, | ||
109 | QObject* parent) | ||
110 | { | ||
111 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | Q_ASSERT(isValid()); |
112 | 11 | auto ss = xdg_wm_base_get_xdg_surface(xdg_shell_base, *surface); | |
113 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | if (!ss) { |
114 | ✗ | return nullptr; | |
115 | } | ||
116 | |||
117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | XdgShellPopup* s = new XdgShellPopup(parent); |
118 | 11 | auto positioner = get_xdg_positioner(positioner_data, nullptr); | |
119 | 11 | auto popup = xdg_surface_get_popup(ss, parentSurface, *positioner); | |
120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (queue) { |
121 | // deliberately not adding the positioner because the positioner has no events sent to it | ||
122 | 11 | queue->addProxy(ss); | |
123 | 11 | queue->addProxy(popup); | |
124 | 11 | } | |
125 | 11 | s->setup(ss, popup); | |
126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | delete positioner; |
127 | |||
128 | 11 | return s; | |
129 | 11 | } | |
130 | |||
131 | 12 | xdg_shell_positioner* XdgShell::Private::get_xdg_positioner(xdg_shell_positioner_data data, | |
132 | QObject* parent) | ||
133 | { | ||
134 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | auto positioner = new xdg_shell_positioner(parent); |
135 | 12 | positioner->setup(xdg_wm_base_create_positioner(xdg_shell_base)); | |
136 | 12 | positioner->set_data(std::move(data)); | |
137 | |||
138 | // Deliberately not adding the positioner to the queue because it has no events sent to it. | ||
139 | 12 | return positioner; | |
140 | } | ||
141 | |||
142 | 81 | XdgShell::XdgShell(QObject* parent) | |
143 | 81 | : QObject(parent) | |
144 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | , d_ptr{new Private} |
145 | 81 | { | |
146 | 81 | } | |
147 | |||
148 | 162 | XdgShell::~XdgShell() | |
149 | 162 | { | |
150 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | release(); |
151 | 162 | } | |
152 | |||
153 | 81 | void XdgShell::setup(xdg_wm_base* xdg_wm_base) | |
154 | { | ||
155 | 81 | d_ptr->setup(xdg_wm_base); | |
156 | 81 | } | |
157 | |||
158 | 83 | void XdgShell::release() | |
159 | { | ||
160 | 83 | d_ptr->release(); | |
161 | 83 | } | |
162 | |||
163 | 81 | void XdgShell::setEventQueue(EventQueue* queue) | |
164 | { | ||
165 | 81 | d_ptr->queue = queue; | |
166 | 81 | } | |
167 | |||
168 | ✗ | EventQueue* XdgShell::eventQueue() | |
169 | { | ||
170 | ✗ | return d_ptr->queue; | |
171 | } | ||
172 | |||
173 | 6 | XdgShell::operator xdg_wm_base*() | |
174 | { | ||
175 | 6 | return *(d_ptr.get()); | |
176 | } | ||
177 | |||
178 | ✗ | XdgShell::operator xdg_wm_base*() const | |
179 | { | ||
180 | ✗ | return *(d_ptr.get()); | |
181 | } | ||
182 | |||
183 | 73 | bool XdgShell::isValid() const | |
184 | { | ||
185 | 73 | return d_ptr->isValid(); | |
186 | } | ||
187 | |||
188 | 67 | XdgShellToplevel* XdgShell::create_toplevel(Surface* surface, QObject* parent) | |
189 | { | ||
190 | 67 | return d_ptr->getXdgToplevel(surface, parent); | |
191 | } | ||
192 | |||
193 | 10 | XdgShellPopup* XdgShell::create_popup(Surface* surface, | |
194 | XdgShellToplevel* parentSurface, | ||
195 | xdg_shell_positioner_data positioner_data, | ||
196 | QObject* parent) | ||
197 | { | ||
198 | 10 | return d_ptr->get_xdg_popup(surface, *parentSurface, std::move(positioner_data), parent); | |
199 | } | ||
200 | |||
201 | ✗ | XdgShellPopup* XdgShell::create_popup(Surface* surface, | |
202 | XdgShellPopup* parentSurface, | ||
203 | xdg_shell_positioner_data positioner_data, | ||
204 | QObject* parent) | ||
205 | { | ||
206 | ✗ | return d_ptr->get_xdg_popup(surface, *parentSurface, std::move(positioner_data), parent); | |
207 | } | ||
208 | |||
209 | XdgShellPopup* | ||
210 | 1 | XdgShell::create_popup(Surface* surface, xdg_shell_positioner_data positioner_data, QObject* parent) | |
211 | { | ||
212 | 1 | return d_ptr->get_xdg_popup(surface, nullptr, std::move(positioner_data), parent); | |
213 | } | ||
214 | |||
215 | 1 | xdg_shell_positioner* XdgShell::create_positioner(xdg_shell_positioner_data data, QObject* parent) | |
216 | { | ||
217 | 1 | return d_ptr->get_xdg_positioner(std::move(data), parent); | |
218 | } | ||
219 | |||
220 | } | ||
221 |