8 #include "generic_shell_surface_p.h"
10 #include "output_interface.h"
11 #include "resource_p.h"
12 #include "seat_interface.h"
13 #include "surface_interface.h"
14 #include "xdgshell_interface_p.h"
15 #include "xdgshell_v5_interface_p.h"
17 #include "../compat/wayland-xdg-shell-v5-server-protocol.h"
23 class XdgShellV5Interface::Private :
public XdgShellInterface::Private
26 Private(XdgShellV5Interface *q, Display *d);
31 void createSurface(wl_client *client, uint32_t version, uint32_t
id, SurfaceInterface *surface, wl_resource *parentResource);
32 void createPopup(wl_client *client,
35 SurfaceInterface *surface,
36 SurfaceInterface *parent,
40 wl_resource *parentResource);
41 void bind(wl_client *client, uint32_t version, uint32_t
id)
override;
42 quint32 ping(XdgShellSurfaceInterface *surface)
override;
44 static void unbind(wl_resource *resource);
45 static Private *cast(wl_resource *r)
47 return reinterpret_cast<Private *
>(wl_resource_get_user_data(r));
52 static void destroyCallback(wl_client *client, wl_resource *resource);
53 static void useUnstableVersionCallback(wl_client *client, wl_resource *resource, int32_t version);
54 static void getXdgSurfaceCallback(wl_client *client, wl_resource *resource, uint32_t
id, wl_resource *surface);
55 static void getXdgPopupCallback(wl_client *client,
56 wl_resource *resource,
64 static void pongCallback(wl_client *client, wl_resource *resource, uint32_t serial);
66 XdgShellV5Interface *q;
67 static const struct zxdg_shell_v5_interface s_interface;
68 static const quint32 s_version;
71 class XdgPopupV5Interface::Private :
public XdgShellPopupInterface::Private
74 Private(XdgPopupV5Interface *q, XdgShellV5Interface *c, SurfaceInterface *surface, wl_resource *parentResource);
77 QRect windowGeometry()
const override;
78 void commit()
override;
79 void popupDone()
override;
81 XdgPopupV5Interface *q_func()
83 return reinterpret_cast<XdgPopupV5Interface *
>(q);
87 static const struct zxdg_popup_v5_interface s_interface;
90 const quint32 XdgShellV5Interface::Private::s_version = 1;
93 const struct zxdg_shell_v5_interface XdgShellV5Interface::Private::s_interface = {destroyCallback,
94 useUnstableVersionCallback,
95 getXdgSurfaceCallback,
100 void XdgShellV5Interface::Private::destroyCallback(wl_client *client, wl_resource *resource)
104 wl_resource_destroy(resource);
107 void XdgShellV5Interface::Private::useUnstableVersionCallback(wl_client *client, wl_resource *resource, int32_t version)
115 void XdgShellV5Interface::Private::getXdgSurfaceCallback(wl_client *client, wl_resource *resource, uint32_t
id, wl_resource *surface)
117 auto s = cast(resource);
118 s->createSurface(client, wl_resource_get_version(resource),
id,
SurfaceInterface::get(surface), resource);
121 void XdgShellV5Interface::Private::createSurface(wl_client *client, uint32_t version, uint32_t
id, SurfaceInterface *surface, wl_resource *parentResource)
123 auto it = std::find_if(surfaces.constBegin(), surfaces.constEnd(), [surface](XdgSurfaceV5Interface *s) {
124 return surface == s->surface();
126 if (it != surfaces.constEnd()) {
127 wl_resource_post_error(surface->resource(), ZXDG_SHELL_V5_ERROR_ROLE,
"ShellSurface already created");
130 XdgSurfaceV5Interface *shellSurface =
new XdgSurfaceV5Interface(q, surface, parentResource);
131 surfaces << shellSurface;
132 QObject::connect(shellSurface, &XdgSurfaceV5Interface::destroyed, q, [
this, shellSurface] {
133 surfaces.removeAll(shellSurface);
135 shellSurface->d->create(display->getConnection(client), version,
id);
136 Q_EMIT q->surfaceCreated(shellSurface);
139 void XdgShellV5Interface::Private::getXdgPopupCallback(wl_client *client,
140 wl_resource *resource,
142 wl_resource *surface,
149 auto s = cast(resource);
150 s->createPopup(client,
151 wl_resource_get_version(resource),
155 SeatInterface::get(seat),
161 void XdgShellV5Interface::Private::createPopup(wl_client *client,
164 SurfaceInterface *surface,
165 SurfaceInterface *parent,
169 wl_resource *parentResource)
171 XdgPopupV5Interface *popupSurface =
new XdgPopupV5Interface(q, surface, parentResource);
172 auto d = popupSurface->d_func();
178 d->create(display->getConnection(client), version,
id);
181 Q_EMIT q->popupCreated(popupSurface, seat, serial);
184 Q_EMIT q->xdgPopupCreated(popupSurface);
185 Q_EMIT popupSurface->grabRequested(seat, serial);
188 void XdgShellV5Interface::Private::pongCallback(wl_client *client, wl_resource *resource, uint32_t serial)
191 auto s = cast(resource);
192 auto timerIt = s->pingTimers.find(serial);
193 if (timerIt != s->pingTimers.end() && timerIt.value()->isActive()) {
194 delete timerIt.value();
195 s->pingTimers.erase(timerIt);
196 Q_EMIT s->q->pongReceived(serial);
200 XdgShellV5Interface::Private::Private(XdgShellV5Interface *q, Display *d)
206 void XdgShellV5Interface::Private::bind(wl_client *client, uint32_t version, uint32_t
id)
208 auto c = display->getConnection(client);
209 auto resource = c->createResource(&zxdg_shell_v5_interface, qMin(version, s_version),
id);
211 wl_client_post_no_memory(client);
214 resources[client] = resource;
215 wl_resource_set_implementation(resource, &s_interface,
this, unbind);
218 void XdgShellV5Interface::Private::unbind(wl_resource *resource)
220 auto s = cast(resource);
221 auto client = wl_resource_get_client(resource);
222 s->resources.remove(client);
225 XdgSurfaceV5Interface *XdgShellV5Interface::getSurface(wl_resource *resource)
231 auto it = std::find_if(d->surfaces.constBegin(), d->surfaces.constEnd(), [resource](XdgSurfaceV5Interface *surface) {
232 return surface->resource() == resource;
234 if (it != d->surfaces.constEnd()) {
240 quint32 XdgShellV5Interface::Private::ping(XdgShellSurfaceInterface *surface)
242 auto client = surface->client()->client();
245 auto clientXdgShellResource = resources.value(client);
246 if (!clientXdgShellResource) {
249 const quint32 pingSerial = display->nextSerial();
252 setupTimer(pingSerial);
256 XdgShellV5Interface::Private *XdgShellV5Interface::d_func()
const
258 return reinterpret_cast<Private *
>(d.data());
261 class XdgSurfaceV5Interface::Private :
public XdgShellSurfaceInterface::Private
264 Private(XdgSurfaceV5Interface *q, XdgShellV5Interface *c, SurfaceInterface *surface, wl_resource *parentResource);
267 QRect windowGeometry()
const override;
268 QSize minimumSize()
const override;
269 QSize maximumSize()
const override;
270 void close()
override;
271 void commit()
override;
274 XdgSurfaceV5Interface *q_func()
276 return reinterpret_cast<XdgSurfaceV5Interface *
>(q);
280 static void setParentCallback(wl_client *client, wl_resource *resource, wl_resource *parent);
281 static void showWindowMenuCallback(wl_client *client, wl_resource *resource, wl_resource *seat, uint32_t serial, int32_t x, int32_t y);
282 static void ackConfigureCallback(wl_client *client, wl_resource *resource, uint32_t serial);
283 static void setWindowGeometryCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height);
284 static void setMaximizedCallback(wl_client *client, wl_resource *resource);
285 static void unsetMaximizedCallback(wl_client *client, wl_resource *resource);
286 static void setFullscreenCallback(wl_client *client, wl_resource *resource, wl_resource *output);
287 static void unsetFullscreenCallback(wl_client *client, wl_resource *resource);
288 static void setMinimizedCallback(wl_client *client, wl_resource *resource);
290 static const struct zxdg_surface_v5_interface s_interface;
292 struct ShellSurfaceState {
293 QRect windowGeometry;
295 bool windowGeometryIsSet =
false;
298 ShellSurfaceState m_currentState;
299 ShellSurfaceState m_pendingState;
305 Qt::Edges edgesToQtEdges(zxdg_surface_v5_resize_edge edges)
309 case ZXDG_SURFACE_V5_RESIZE_EDGE_TOP:
312 case ZXDG_SURFACE_V5_RESIZE_EDGE_BOTTOM:
315 case ZXDG_SURFACE_V5_RESIZE_EDGE_LEFT:
318 case ZXDG_SURFACE_V5_RESIZE_EDGE_TOP_LEFT:
321 case ZXDG_SURFACE_V5_RESIZE_EDGE_BOTTOM_LEFT:
324 case ZXDG_SURFACE_V5_RESIZE_EDGE_RIGHT:
327 case ZXDG_SURFACE_V5_RESIZE_EDGE_TOP_RIGHT:
330 case ZXDG_SURFACE_V5_RESIZE_EDGE_BOTTOM_RIGHT:
333 case ZXDG_SURFACE_V5_RESIZE_EDGE_NONE:
344 const struct zxdg_surface_v5_interface XdgSurfaceV5Interface::Private::s_interface = {resourceDestroyedCallback,
348 showWindowMenuCallback,
350 resizeCallback<zxdg_surface_v5_resize_edge>,
351 ackConfigureCallback,
352 setWindowGeometryCallback,
353 setMaximizedCallback,
354 unsetMaximizedCallback,
355 setFullscreenCallback,
356 unsetFullscreenCallback,
357 setMinimizedCallback};
360 void XdgSurfaceV5Interface::Private::setParentCallback(wl_client *client, wl_resource *resource, wl_resource *parent)
362 auto s = cast<Private>(resource);
363 Q_ASSERT(client == *s->client);
364 auto parentSurface =
static_cast<XdgShellV5Interface *
>(s->q->global())->getSurface(parent);
365 if (s->parent.data() != parentSurface) {
367 Q_EMIT s->q_func()->transientForChanged();
371 void XdgSurfaceV5Interface::Private::showWindowMenuCallback(wl_client *client, wl_resource *resource, wl_resource *seat, uint32_t serial, int32_t x, int32_t y)
373 auto s = cast<Private>(resource);
374 Q_ASSERT(client == *s->client);
375 Q_EMIT s->q_func()->windowMenuRequested(SeatInterface::get(seat), serial,
QPoint(x, y));
378 void XdgSurfaceV5Interface::Private::ackConfigureCallback(wl_client *client, wl_resource *resource, uint32_t serial)
380 auto s = cast<Private>(resource);
381 Q_ASSERT(client == *s->client);
382 if (!s->configureSerials.contains(serial)) {
386 while (!s->configureSerials.isEmpty()) {
387 quint32 i = s->configureSerials.takeFirst();
388 Q_EMIT s->q_func()->configureAcknowledged(i);
395 void XdgSurfaceV5Interface::Private::setWindowGeometryCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
397 if (width < 0 || height < 0) {
398 wl_resource_post_error(resource, -1,
"Tried to set invalid xdg-surface geometry");
401 auto s = cast<Private>(resource);
402 Q_ASSERT(client == *s->client);
403 s->m_pendingState.windowGeometry =
QRect(x, y, width, height);
404 s->m_pendingState.windowGeometryIsSet =
true;
407 void XdgSurfaceV5Interface::Private::setMaximizedCallback(wl_client *client, wl_resource *resource)
409 auto s = cast<Private>(resource);
410 Q_ASSERT(client == *s->client);
411 s->q_func()->maximizedChanged(
true);
414 void XdgSurfaceV5Interface::Private::unsetMaximizedCallback(wl_client *client, wl_resource *resource)
416 auto s = cast<Private>(resource);
417 Q_ASSERT(client == *s->client);
418 s->q_func()->maximizedChanged(
false);
421 void XdgSurfaceV5Interface::Private::setFullscreenCallback(wl_client *client, wl_resource *resource, wl_resource *output)
423 auto s = cast<Private>(resource);
424 Q_ASSERT(client == *s->client);
425 OutputInterface *o =
nullptr;
427 o = OutputInterface::get(output);
429 s->q_func()->fullscreenChanged(
true, o);
432 void XdgSurfaceV5Interface::Private::unsetFullscreenCallback(wl_client *client, wl_resource *resource)
434 auto s = cast<Private>(resource);
435 Q_ASSERT(client == *s->client);
436 s->q_func()->fullscreenChanged(
false,
nullptr);
439 void XdgSurfaceV5Interface::Private::setMinimizedCallback(wl_client *client, wl_resource *resource)
441 auto s = cast<Private>(resource);
442 Q_ASSERT(client == *s->client);
443 s->q_func()->minimizeRequested();
446 XdgSurfaceV5Interface::Private::Private(XdgSurfaceV5Interface *q, XdgShellV5Interface *c, SurfaceInterface *surface, wl_resource *parentResource)
451 XdgSurfaceV5Interface::Private::~Private() =
default;
453 QRect XdgSurfaceV5Interface::Private::windowGeometry()
const
455 return m_currentState.windowGeometry;
458 QSize XdgSurfaceV5Interface::Private::minimumSize()
const
463 QSize XdgSurfaceV5Interface::Private::maximumSize()
const
465 return QSize(INT_MAX, INT_MAX);
468 void XdgSurfaceV5Interface::Private::close()
474 void XdgSurfaceV5Interface::Private::commit()
476 const bool windowGeometryChanged = m_pendingState.windowGeometryIsSet;
478 if (windowGeometryChanged) {
479 m_currentState.windowGeometry = m_pendingState.windowGeometry;
482 m_pendingState = ShellSurfaceState{};
484 if (windowGeometryChanged) {
485 Q_EMIT q_func()->windowGeometryChanged(m_currentState.windowGeometry);
489 quint32 XdgSurfaceV5Interface::Private::configure(States states,
const QSize &size)
494 const quint32 serial = global->display()->nextSerial();
496 wl_array_init(&state);
497 if (states.testFlag(State::Maximized)) {
498 uint32_t *s =
reinterpret_cast<uint32_t *
>(wl_array_add(&state,
sizeof(uint32_t)));
501 if (states.testFlag(State::Fullscreen)) {
502 uint32_t *s =
reinterpret_cast<uint32_t *
>(wl_array_add(&state,
sizeof(uint32_t)));
505 if (states.testFlag(State::Resizing)) {
506 uint32_t *s =
reinterpret_cast<uint32_t *
>(wl_array_add(&state,
sizeof(uint32_t)));
509 if (states.testFlag(State::Activated)) {
510 uint32_t *s =
reinterpret_cast<uint32_t *
>(wl_array_add(&state,
sizeof(uint32_t)));
513 configureSerials << serial;
516 wl_array_release(&state);
522 const struct zxdg_popup_v5_interface XdgPopupV5Interface::Private::s_interface = {resourceDestroyedCallback};
525 XdgPopupV5Interface::Private::Private(XdgPopupV5Interface *q, XdgShellV5Interface *c, SurfaceInterface *surface, wl_resource *parentResource)
530 XdgPopupV5Interface::Private::~Private() =
default;
532 QRect XdgPopupV5Interface::Private::windowGeometry()
const
537 void XdgPopupV5Interface::Private::commit()
541 void XdgPopupV5Interface::Private::popupDone()
551 XdgShellV5Interface::XdgShellV5Interface(Display *display,
QObject *parent)
552 : XdgShellInterface(new Private(this, display), parent)
556 XdgShellV5Interface::~XdgShellV5Interface() =
default;
558 XdgSurfaceV5Interface::XdgSurfaceV5Interface(XdgShellV5Interface *parent, SurfaceInterface *surface, wl_resource *parentResource)
559 : KWayland::Server::XdgShellSurfaceInterface(new Private(this, parent, surface, parentResource))
563 XdgSurfaceV5Interface::~XdgSurfaceV5Interface() =
default;
565 XdgPopupV5Interface::XdgPopupV5Interface(XdgShellV5Interface *parent, SurfaceInterface *surface, wl_resource *parentResource)
566 : XdgShellPopupInterface(new Private(this, parent, surface, parentResource))
570 XdgPopupV5Interface::~XdgPopupV5Interface() =
default;
572 XdgPopupV5Interface::Private *XdgPopupV5Interface::d_func()
const
574 return reinterpret_cast<Private *
>(d.data());