1 /********************************************************************
2 Copyright 2020 Faveraux Adrien <ad1rie3@hotmail.fr>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), which shall
10 act as a proxy defined in Section 6 of version 3 of the license.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
20 #include "plasma_shell_p.h"
21
22 #include <wayland-server.h>
23
24 namespace Wrapland::Server
25 {
26
27 const struct org_kde_plasma_shell_interface PlasmaShell::Private::s_interface = {
28 cb<createSurfaceCallback>,
29 };
30
Private(Display * display,PlasmaShell * qptr)31 PlasmaShell::Private::Private(Display* display, PlasmaShell* qptr)
32 : PlasmaShellGlobal(qptr, display, &org_kde_plasma_shell_interface, &s_interface)
33 {
34 create();
35 }
36
37 PlasmaShell::Private::~Private() = default;
38
createSurfaceCallback(PlasmaShellBind * bind,uint32_t id,wl_resource * surface)39 void PlasmaShell::Private::createSurfaceCallback(PlasmaShellBind* bind,
40 uint32_t id,
41 wl_resource* surface)
42 {
43 auto priv = bind->global()->handle()->d_ptr.get();
44 priv->createSurface(bind, id, Wayland::Resource<Surface>::handle(surface));
45 }
46
createSurface(PlasmaShellBind * bind,uint32_t id,Surface * surface)47 void PlasmaShell::Private::createSurface(PlasmaShellBind* bind, uint32_t id, Surface* surface)
48 {
49 auto it = std::find_if(surfaces.constBegin(),
50 surfaces.constEnd(),
51 [surface](PlasmaShellSurface* s) { return surface == s->surface(); });
52 if (it != surfaces.constEnd()) {
53 surface->d_ptr->postError(WL_DISPLAY_ERROR_INVALID_OBJECT,
54 "PlasmaShellSurface already created");
55 return;
56 }
57
58 auto shellSurface
59 = new PlasmaShellSurface(bind->client()->handle(), bind->version(), id, surface, handle());
60
61 surfaces << shellSurface;
62 QObject::connect(shellSurface,
63 &PlasmaShellSurface::resourceDestroyed,
64 handle(),
65 [this, shellSurface] { surfaces.removeAll(shellSurface); });
66 Q_EMIT handle()->surfaceCreated(shellSurface);
67 }
68
PlasmaShell(Display * display,QObject * parent)69 PlasmaShell::PlasmaShell(Display* display, QObject* parent)
70 : QObject(parent)
71 , d_ptr(new Private(display, this))
72 {
73 }
74
75 PlasmaShell::~PlasmaShell() = default;
76
77 /*********************************
78 * ShellSurfaceInterface
79 *********************************/
80
81 const struct org_kde_plasma_surface_interface PlasmaShellSurface::Private::s_interface = {
82 destroyCallback,
83 setOutputCallback,
84 setPositionCallback,
85 setRoleCallback,
86 setPanelBehaviorCallback,
87 setSkipTaskbarCallback,
88 panelAutoHideHideCallback,
89 panelAutoHideShowCallback,
90 panelTakesFocusCallback,
91 setSkipSwitcherCallback,
92 };
93
Private(Client * client,uint32_t version,uint32_t id,Surface * surface,PlasmaShell * shell,PlasmaShellSurface * qptr)94 PlasmaShellSurface::Private::Private(Client* client,
95 uint32_t version,
96 uint32_t id,
97 Surface* surface,
98 PlasmaShell* shell,
99 PlasmaShellSurface* qptr)
100 : Wayland::Resource<PlasmaShellSurface>(client,
101 version,
102 id,
103 &org_kde_plasma_surface_interface,
104 &s_interface,
105 qptr)
106 , surface(surface)
107 , shell(shell)
108
109 {
110 }
111
112 PlasmaShellSurface::Private::~Private() = default;
113
setOutputCallback(wl_client * wlClient,wl_resource * wlResource,wl_resource * output)114 void PlasmaShellSurface::Private::setOutputCallback([[maybe_unused]] wl_client* wlClient,
115 [[maybe_unused]] wl_resource* wlResource,
116 [[maybe_unused]] wl_resource* output)
117 {
118 // TODO(unknown author): implement
119 }
120
setPositionCallback(wl_client * wlClient,wl_resource * wlResource,int32_t x,int32_t y)121 void PlasmaShellSurface::Private::setPositionCallback([[maybe_unused]] wl_client* wlClient,
122 wl_resource* wlResource,
123 int32_t x,
124 int32_t y)
125 {
126 auto priv = handle(wlResource)->d_ptr;
127 priv->setPosition(QPoint(x, y));
128 }
129
setPosition(const QPoint & globalPos)130 void PlasmaShellSurface::Private::setPosition(const QPoint& globalPos)
131 {
132 if (m_globalPos == globalPos && m_positionSet) {
133 return;
134 }
135 m_positionSet = true;
136 m_globalPos = globalPos;
137 Q_EMIT handle()->positionChanged();
138 }
139
setRoleCallback(wl_client * wlClient,wl_resource * wlResource,uint32_t role)140 void PlasmaShellSurface::Private::setRoleCallback([[maybe_unused]] wl_client* wlClient,
141 wl_resource* wlResource,
142 uint32_t role)
143 {
144 auto priv = handle(wlResource)->d_ptr;
145 priv->setRole(role);
146 }
147
setRole(uint32_t role)148 void PlasmaShellSurface::Private::setRole(uint32_t role)
149 {
150 Role r = Role::Normal;
151 switch (role) {
152 case ORG_KDE_PLASMA_SURFACE_ROLE_DESKTOP:
153 r = Role::Desktop;
154 break;
155 case ORG_KDE_PLASMA_SURFACE_ROLE_PANEL:
156 r = Role::Panel;
157 break;
158 case ORG_KDE_PLASMA_SURFACE_ROLE_ONSCREENDISPLAY:
159 r = Role::OnScreenDisplay;
160 break;
161 case ORG_KDE_PLASMA_SURFACE_ROLE_NOTIFICATION:
162 r = Role::Notification;
163 break;
164 case ORG_KDE_PLASMA_SURFACE_ROLE_TOOLTIP:
165 r = Role::ToolTip;
166 break;
167 case ORG_KDE_PLASMA_SURFACE_ROLE_CRITICALNOTIFICATION:
168 r = Role::CriticalNotification;
169 break;
170 case ORG_KDE_PLASMA_SURFACE_ROLE_NORMAL:
171 default:
172 r = Role::Normal;
173 break;
174 }
175 if (r == m_role) {
176 return;
177 }
178 m_role = r;
179 Q_EMIT handle()->roleChanged();
180 }
181
setPanelBehaviorCallback(wl_client * wlClient,wl_resource * wlResource,uint32_t flag)182 void PlasmaShellSurface::Private::setPanelBehaviorCallback([[maybe_unused]] wl_client* wlClient,
183 wl_resource* wlResource,
184 uint32_t flag)
185 {
186 auto priv = handle(wlResource)->d_ptr;
187 priv->setPanelBehavior(org_kde_plasma_surface_panel_behavior(flag));
188 }
189
setSkipTaskbarCallback(wl_client * wlClient,wl_resource * wlResource,uint32_t skip)190 void PlasmaShellSurface::Private::setSkipTaskbarCallback([[maybe_unused]] wl_client* wlClient,
191 wl_resource* wlResource,
192 uint32_t skip)
193 {
194 auto priv = handle(wlResource)->d_ptr;
195 priv->m_skipTaskbar = static_cast<bool>(skip);
196 Q_EMIT priv->handle()->skipTaskbarChanged();
197 }
198
setSkipSwitcherCallback(wl_client * wlClient,wl_resource * wlResource,uint32_t skip)199 void PlasmaShellSurface::Private::setSkipSwitcherCallback([[maybe_unused]] wl_client* wlClient,
200 wl_resource* wlResource,
201 uint32_t skip)
202 {
203 auto priv = handle(wlResource)->d_ptr;
204 priv->m_skipSwitcher = static_cast<bool>(skip);
205 Q_EMIT priv->handle()->skipSwitcherChanged();
206 }
207
panelAutoHideHideCallback(wl_client * wlClient,wl_resource * wlResource)208 void PlasmaShellSurface::Private::panelAutoHideHideCallback([[maybe_unused]] wl_client* wlClient,
209 wl_resource* wlResource)
210 {
211 auto priv = handle(wlResource)->d_ptr;
212 if (priv->m_role != Role::Panel
213 || (priv->m_panelBehavior != PanelBehavior::AutoHide
214 && priv->m_panelBehavior != PanelBehavior::WindowsCanCover)) {
215 priv->postError(ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
216 return;
217 }
218 Q_EMIT priv->handle()->panelAutoHideHideRequested();
219 }
220
panelAutoHideShowCallback(wl_client * wlClient,wl_resource * wlResource)221 void PlasmaShellSurface::Private::panelAutoHideShowCallback([[maybe_unused]] wl_client* wlClient,
222 wl_resource* wlResource)
223 {
224 auto priv = handle(wlResource)->d_ptr;
225 if (priv->m_role != Role::Panel || priv->m_panelBehavior != PanelBehavior::AutoHide) {
226 priv->postError(ORG_KDE_PLASMA_SURFACE_ERROR_PANEL_NOT_AUTO_HIDE, "Not an auto hide panel");
227 return;
228 }
229 Q_EMIT priv->handle()->panelAutoHideShowRequested();
230 }
231
panelTakesFocusCallback(wl_client * wlClient,wl_resource * wlResource,uint32_t takesFocus)232 void PlasmaShellSurface::Private::panelTakesFocusCallback([[maybe_unused]] wl_client* wlClient,
233 wl_resource* wlResource,
234 uint32_t takesFocus)
235 {
236 auto priv = handle(wlResource)->d_ptr;
237 if (priv->panelTakesFocus == takesFocus) {
238 return;
239 }
240 priv->panelTakesFocus = takesFocus;
241 Q_EMIT priv->handle()->panelTakesFocusChanged();
242 }
243
setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior)244 void PlasmaShellSurface::Private::setPanelBehavior(org_kde_plasma_surface_panel_behavior behavior)
245 {
246 PanelBehavior newBehavior = PanelBehavior::AlwaysVisible;
247 switch (behavior) {
248 case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_AUTO_HIDE:
249 newBehavior = PanelBehavior::AutoHide;
250 break;
251 case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_WINDOWS_CAN_COVER:
252 newBehavior = PanelBehavior::WindowsCanCover;
253 break;
254 case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_WINDOWS_GO_BELOW:
255 newBehavior = PanelBehavior::WindowsGoBelow;
256 break;
257 case ORG_KDE_PLASMA_SURFACE_PANEL_BEHAVIOR_ALWAYS_VISIBLE:
258 default:
259 break;
260 }
261 if (m_panelBehavior == newBehavior) {
262 return;
263 }
264 m_panelBehavior = newBehavior;
265 Q_EMIT handle()->panelBehaviorChanged();
266 }
267
PlasmaShellSurface(Client * client,uint32_t version,uint32_t id,Surface * surface,PlasmaShell * shell)268 PlasmaShellSurface::PlasmaShellSurface(Client* client,
269 uint32_t version,
270 uint32_t id,
271 Surface* surface,
272 PlasmaShell* shell)
273 : QObject(nullptr)
274 , d_ptr(new Private(client, version, id, surface, shell, this))
275
276 {
277 auto unsetSurface = [this] { d_ptr->surface = nullptr; };
278 connect(surface, &Surface::resourceDestroyed, this, unsetSurface);
279 }
280
surface() const281 Surface* PlasmaShellSurface::surface() const
282 {
283 return d_ptr->surface;
284 }
285
shell() const286 PlasmaShell* PlasmaShellSurface::shell() const
287 {
288 return d_ptr->shell;
289 }
290
resource() const291 wl_resource* PlasmaShellSurface::resource() const
292 {
293 return d_ptr->resource();
294 }
295
client() const296 Client* PlasmaShellSurface::client() const
297 {
298 return d_ptr->client()->handle();
299 }
300
position() const301 QPoint PlasmaShellSurface::position() const
302 {
303 return d_ptr->m_globalPos;
304 }
305
role() const306 PlasmaShellSurface::Role PlasmaShellSurface::role() const
307 {
308 return d_ptr->m_role;
309 }
310
isPositionSet() const311 bool PlasmaShellSurface::isPositionSet() const
312 {
313 return d_ptr->m_positionSet;
314 }
315
panelBehavior() const316 PlasmaShellSurface::PanelBehavior PlasmaShellSurface::panelBehavior() const
317 {
318 return d_ptr->m_panelBehavior;
319 }
320
skipTaskbar() const321 bool PlasmaShellSurface::skipTaskbar() const
322 {
323 return d_ptr->m_skipTaskbar;
324 }
325
skipSwitcher() const326 bool PlasmaShellSurface::skipSwitcher() const
327 {
328 return d_ptr->m_skipSwitcher;
329 }
330
hideAutoHidingPanel()331 void PlasmaShellSurface::hideAutoHidingPanel()
332 {
333 d_ptr->send<org_kde_plasma_surface_send_auto_hidden_panel_hidden>();
334 }
335
showAutoHidingPanel()336 void PlasmaShellSurface::showAutoHidingPanel()
337 {
338 d_ptr->send<org_kde_plasma_surface_send_auto_hidden_panel_shown>();
339 }
340
panelTakesFocus() const341 bool PlasmaShellSurface::panelTakesFocus() const
342 {
343 return d_ptr->panelTakesFocus;
344 }
345
get(wl_resource * native)346 PlasmaShellSurface* PlasmaShellSurface::get(wl_resource* native)
347 {
348 if (native == nullptr) {
349 return nullptr;
350 }
351 return Private::handle(native);
352 }
353
354 }
355