File indexing completed on 2024-05-19 16:35:21

0001 /*
0002     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "layershell_v1_interface.h"
0008 #include "display.h"
0009 #include "surface_interface.h"
0010 #include "surfacerole_p.h"
0011 #include "utils/common.h"
0012 #include "xdgshell_interface_p.h"
0013 
0014 #include <QPointer>
0015 #include <QQueue>
0016 
0017 #include "qwayland-server-wlr-layer-shell-unstable-v1.h"
0018 
0019 namespace KWaylandServer
0020 {
0021 static const int s_version = 3;
0022 
0023 class LayerShellV1InterfacePrivate : public QtWaylandServer::zwlr_layer_shell_v1
0024 {
0025 public:
0026     LayerShellV1InterfacePrivate(LayerShellV1Interface *q, Display *display);
0027 
0028     LayerShellV1Interface *q;
0029     Display *display;
0030 
0031 protected:
0032     void zwlr_layer_shell_v1_get_layer_surface(Resource *resource,
0033                                                uint32_t id,
0034                                                struct ::wl_resource *surface_resource,
0035                                                struct ::wl_resource *output_resource,
0036                                                uint32_t layer,
0037                                                const QString &scope) override;
0038     void zwlr_layer_shell_v1_destroy(Resource *resource) override;
0039 };
0040 
0041 class LayerSurfaceV1State
0042 {
0043 public:
0044     LayerSurfaceV1Interface::Layer layer = LayerSurfaceV1Interface::BottomLayer;
0045     Qt::Edges anchor;
0046     QMargins margins;
0047     QSize desiredSize = QSize(0, 0);
0048     int exclusiveZone = 0;
0049     quint32 acknowledgedConfigure;
0050     bool acknowledgedConfigureIsSet = false;
0051     bool acceptsFocus = false;
0052 };
0053 
0054 class LayerSurfaceV1InterfacePrivate : public SurfaceRole, public QtWaylandServer::zwlr_layer_surface_v1
0055 {
0056 public:
0057     LayerSurfaceV1InterfacePrivate(LayerSurfaceV1Interface *q, SurfaceInterface *surface);
0058 
0059     void commit() override;
0060 
0061     LayerSurfaceV1Interface *q;
0062     LayerShellV1Interface *shell;
0063     QPointer<SurfaceInterface> surface;
0064     QPointer<OutputInterface> output;
0065     LayerSurfaceV1State current;
0066     LayerSurfaceV1State pending;
0067     QQueue<quint32> serials;
0068     QString scope;
0069     bool isClosed = false;
0070     bool isConfigured = false;
0071     bool isCommitted = false;
0072     bool firstBufferAttached = false;
0073 
0074 protected:
0075     void zwlr_layer_surface_v1_destroy_resource(Resource *resource) override;
0076     void zwlr_layer_surface_v1_set_size(Resource *resource, uint32_t width, uint32_t height) override;
0077     void zwlr_layer_surface_v1_set_anchor(Resource *resource, uint32_t anchor) override;
0078     void zwlr_layer_surface_v1_set_exclusive_zone(Resource *resource, int32_t zone) override;
0079     void zwlr_layer_surface_v1_set_margin(Resource *resource, int32_t top, int32_t right, int32_t bottom, int32_t left) override;
0080     void zwlr_layer_surface_v1_set_keyboard_interactivity(Resource *resource, uint32_t keyboard_interactivity) override;
0081     void zwlr_layer_surface_v1_get_popup(Resource *resource, struct ::wl_resource *popup) override;
0082     void zwlr_layer_surface_v1_ack_configure(Resource *resource, uint32_t serial) override;
0083     void zwlr_layer_surface_v1_destroy(Resource *resource) override;
0084     void zwlr_layer_surface_v1_set_layer(Resource *resource, uint32_t layer) override;
0085 };
0086 
0087 LayerShellV1InterfacePrivate::LayerShellV1InterfacePrivate(LayerShellV1Interface *q, Display *display)
0088     : QtWaylandServer::zwlr_layer_shell_v1(*display, s_version)
0089     , q(q)
0090     , display(display)
0091 {
0092 }
0093 
0094 void LayerShellV1InterfacePrivate::zwlr_layer_shell_v1_get_layer_surface(Resource *resource,
0095                                                                          uint32_t id,
0096                                                                          wl_resource *surface_resource,
0097                                                                          wl_resource *output_resource,
0098                                                                          uint32_t layer,
0099                                                                          const QString &scope)
0100 {
0101     SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
0102     OutputInterface *output = OutputInterface::get(output_resource);
0103 
0104     if (surface->buffer()) {
0105         wl_resource_post_error(resource->handle, error_already_constructed, "the wl_surface already has a buffer attached");
0106         return;
0107     }
0108 
0109     if (layer > layer_overlay) {
0110         wl_resource_post_error(resource->handle, error_invalid_layer, "invalid layer %d", layer);
0111         return;
0112     }
0113 
0114     SurfaceRole *surfaceRole = SurfaceRole::get(surface);
0115     if (surfaceRole) {
0116         wl_resource_post_error(resource->handle, error_role, "the wl_surface already has a role assigned %s", surfaceRole->name().constData());
0117         return;
0118     }
0119 
0120     wl_resource *layerSurfaceResource = wl_resource_create(resource->client(), &zwlr_layer_surface_v1_interface, resource->version(), id);
0121     if (!layerSurfaceResource) {
0122         wl_resource_post_no_memory(resource->handle);
0123         return;
0124     }
0125 
0126     auto layerSurface = new LayerSurfaceV1Interface(q, surface, output, LayerSurfaceV1Interface::Layer(layer), scope, layerSurfaceResource);
0127     Q_EMIT q->surfaceCreated(layerSurface);
0128 }
0129 
0130 void LayerShellV1InterfacePrivate::zwlr_layer_shell_v1_destroy(Resource *resource)
0131 {
0132     wl_resource_destroy(resource->handle);
0133 }
0134 
0135 LayerShellV1Interface::LayerShellV1Interface(Display *display, QObject *parent)
0136     : QObject(parent)
0137     , d(new LayerShellV1InterfacePrivate(this, display))
0138 {
0139 }
0140 
0141 LayerShellV1Interface::~LayerShellV1Interface()
0142 {
0143 }
0144 
0145 Display *LayerShellV1Interface::display() const
0146 {
0147     return d->display;
0148 }
0149 
0150 LayerSurfaceV1InterfacePrivate::LayerSurfaceV1InterfacePrivate(LayerSurfaceV1Interface *q, SurfaceInterface *surface)
0151     : SurfaceRole(surface, QByteArrayLiteral("layer_surface_v1"))
0152     , q(q)
0153     , surface(surface)
0154 {
0155 }
0156 
0157 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_destroy_resource(Resource *resource)
0158 {
0159     Q_EMIT q->aboutToBeDestroyed();
0160     delete q;
0161 }
0162 
0163 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_size(Resource *resource, uint32_t width, uint32_t height)
0164 {
0165     pending.desiredSize = QSize(width, height);
0166 }
0167 
0168 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_anchor(Resource *resource, uint32_t anchor)
0169 {
0170     const uint32_t anchorMask = anchor_top | anchor_left | anchor_right | anchor_bottom;
0171     if (anchor > anchorMask) {
0172         wl_resource_post_error(resource->handle, error_invalid_anchor, "invalid anchor %d", anchor);
0173         return;
0174     }
0175 
0176     pending.anchor = Qt::Edges();
0177 
0178     if (anchor & anchor_top) {
0179         pending.anchor |= Qt::TopEdge;
0180     }
0181 
0182     if (anchor & anchor_right) {
0183         pending.anchor |= Qt::RightEdge;
0184     }
0185 
0186     if (anchor & anchor_bottom) {
0187         pending.anchor |= Qt::BottomEdge;
0188     }
0189 
0190     if (anchor & anchor_left) {
0191         pending.anchor |= Qt::LeftEdge;
0192     }
0193 }
0194 
0195 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_exclusive_zone(Resource *, int32_t zone)
0196 {
0197     pending.exclusiveZone = zone;
0198 }
0199 
0200 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_margin(Resource *, int32_t top, int32_t right, int32_t bottom, int32_t left)
0201 {
0202     pending.margins = QMargins(left, top, right, bottom);
0203 }
0204 
0205 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_keyboard_interactivity(Resource *resource, uint32_t keyboard_interactivity)
0206 {
0207     pending.acceptsFocus = keyboard_interactivity;
0208 }
0209 
0210 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_get_popup(Resource *resource, struct ::wl_resource *popup_resource)
0211 {
0212     XdgPopupInterface *popup = XdgPopupInterface::get(popup_resource);
0213     XdgPopupInterfacePrivate *popupPrivate = XdgPopupInterfacePrivate::get(popup);
0214 
0215     if (popup->isConfigured()) {
0216         wl_resource_post_error(resource->handle, error_invalid_surface_state, "xdg_popup surface is already configured");
0217         return;
0218     }
0219 
0220     popupPrivate->parentSurface = surface;
0221 }
0222 
0223 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_ack_configure(Resource *resource, uint32_t serial)
0224 {
0225     if (!serials.contains(serial)) {
0226         wl_resource_post_error(resource->handle, error_invalid_surface_state, "invalid configure serial %d", serial);
0227         return;
0228     }
0229     while (!serials.isEmpty()) {
0230         const quint32 head = serials.takeFirst();
0231         if (head == serial) {
0232             break;
0233         }
0234     }
0235     if (!isClosed) {
0236         pending.acknowledgedConfigure = serial;
0237         pending.acknowledgedConfigureIsSet = true;
0238     }
0239 }
0240 
0241 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_destroy(Resource *resource)
0242 {
0243     wl_resource_destroy(resource->handle);
0244 }
0245 
0246 void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_layer(Resource *resource, uint32_t layer)
0247 {
0248     if (Q_UNLIKELY(layer > LayerShellV1InterfacePrivate::layer_overlay)) {
0249         wl_resource_post_error(resource->handle, LayerShellV1InterfacePrivate::error_invalid_layer, "invalid layer %d", layer);
0250         return;
0251     }
0252     pending.layer = LayerSurfaceV1Interface::Layer(layer);
0253 }
0254 
0255 void LayerSurfaceV1InterfacePrivate::commit()
0256 {
0257     if (isClosed) {
0258         return;
0259     }
0260 
0261     if (pending.acknowledgedConfigureIsSet) {
0262         current.acknowledgedConfigure = pending.acknowledgedConfigure;
0263         pending.acknowledgedConfigureIsSet = false;
0264         Q_EMIT q->configureAcknowledged(pending.acknowledgedConfigure);
0265     }
0266 
0267     if (Q_UNLIKELY(surface->isMapped() && !isConfigured)) {
0268         wl_resource_post_error(resource()->handle,
0269                                error_invalid_surface_state,
0270                                "a buffer has been attached to a layer surface prior "
0271                                "to the first layer_surface.configure event");
0272         return;
0273     }
0274 
0275     if (Q_UNLIKELY(pending.desiredSize.width() == 0 && (!(pending.anchor & Qt::LeftEdge) || !(pending.anchor & Qt::RightEdge)))) {
0276         wl_resource_post_error(resource()->handle,
0277                                error_invalid_size,
0278                                "the layer surface has a width of 0 but its anchor "
0279                                "doesn't include the left and the right screen edge");
0280         return;
0281     }
0282 
0283     if (Q_UNLIKELY(pending.desiredSize.height() == 0 && (!(pending.anchor & Qt::TopEdge) || !(pending.anchor & Qt::BottomEdge)))) {
0284         wl_resource_post_error(resource()->handle,
0285                                error_invalid_size,
0286                                "the layer surface has a height of 0 but its anchor "
0287                                "doesn't include the top and the bottom screen edge");
0288         return;
0289     }
0290 
0291     // detect reset
0292     if (!surface->isMapped() && firstBufferAttached) {
0293         isCommitted = false;
0294         firstBufferAttached = false;
0295         isConfigured = false;
0296 
0297         current = LayerSurfaceV1State();
0298         pending = LayerSurfaceV1State();
0299 
0300         return;
0301     }
0302 
0303     const LayerSurfaceV1State previous = std::exchange(current, pending);
0304 
0305     isCommitted = true; // Must set the committed state before emitting any signals.
0306     if (surface->isMapped()) {
0307         firstBufferAttached = true;
0308     }
0309 
0310     if (previous.acceptsFocus != current.acceptsFocus) {
0311         Q_EMIT q->acceptsFocusChanged();
0312     }
0313     if (previous.layer != current.layer) {
0314         Q_EMIT q->layerChanged();
0315     }
0316     if (previous.anchor != current.anchor) {
0317         Q_EMIT q->anchorChanged();
0318     }
0319     if (previous.desiredSize != current.desiredSize) {
0320         Q_EMIT q->desiredSizeChanged();
0321     }
0322     if (previous.exclusiveZone != current.exclusiveZone) {
0323         Q_EMIT q->exclusiveZoneChanged();
0324     }
0325     if (previous.margins != current.margins) {
0326         Q_EMIT q->marginsChanged();
0327     }
0328 }
0329 
0330 LayerSurfaceV1Interface::LayerSurfaceV1Interface(LayerShellV1Interface *shell,
0331                                                  SurfaceInterface *surface,
0332                                                  OutputInterface *output,
0333                                                  Layer layer,
0334                                                  const QString &scope,
0335                                                  wl_resource *resource)
0336     : d(new LayerSurfaceV1InterfacePrivate(this, surface))
0337 {
0338     d->current.layer = layer;
0339     d->pending.layer = layer;
0340 
0341     d->shell = shell;
0342     d->output = output;
0343     d->scope = scope;
0344 
0345     d->init(resource);
0346 }
0347 
0348 LayerSurfaceV1Interface::~LayerSurfaceV1Interface()
0349 {
0350 }
0351 
0352 bool LayerSurfaceV1Interface::isCommitted() const
0353 {
0354     return d->isCommitted;
0355 }
0356 
0357 SurfaceInterface *LayerSurfaceV1Interface::surface() const
0358 {
0359     return d->surface;
0360 }
0361 
0362 Qt::Edges LayerSurfaceV1Interface::anchor() const
0363 {
0364     return d->current.anchor;
0365 }
0366 
0367 QSize LayerSurfaceV1Interface::desiredSize() const
0368 {
0369     return d->current.desiredSize;
0370 }
0371 
0372 bool LayerSurfaceV1Interface::acceptsFocus() const
0373 {
0374     return d->current.acceptsFocus;
0375 }
0376 
0377 LayerSurfaceV1Interface::Layer LayerSurfaceV1Interface::layer() const
0378 {
0379     return d->current.layer;
0380 }
0381 
0382 QMargins LayerSurfaceV1Interface::margins() const
0383 {
0384     return d->current.margins;
0385 }
0386 
0387 int LayerSurfaceV1Interface::leftMargin() const
0388 {
0389     return d->current.margins.left();
0390 }
0391 
0392 int LayerSurfaceV1Interface::topMargin() const
0393 {
0394     return d->current.margins.top();
0395 }
0396 
0397 int LayerSurfaceV1Interface::rightMargin() const
0398 {
0399     return d->current.margins.right();
0400 }
0401 
0402 int LayerSurfaceV1Interface::bottomMargin() const
0403 {
0404     return d->current.margins.bottom();
0405 }
0406 
0407 int LayerSurfaceV1Interface::exclusiveZone() const
0408 {
0409     return d->current.exclusiveZone;
0410 }
0411 
0412 Qt::Edge LayerSurfaceV1Interface::exclusiveEdge() const
0413 {
0414     if (exclusiveZone() <= 0) {
0415         return Qt::Edge();
0416     }
0417     if (anchor() == (Qt::LeftEdge | Qt::TopEdge | Qt::RightEdge) || anchor() == Qt::TopEdge) {
0418         return Qt::TopEdge;
0419     }
0420     if (anchor() == (Qt::TopEdge | Qt::RightEdge | Qt::BottomEdge) || anchor() == Qt::RightEdge) {
0421         return Qt::RightEdge;
0422     }
0423     if (anchor() == (Qt::RightEdge | Qt::BottomEdge | Qt::LeftEdge) || anchor() == Qt::BottomEdge) {
0424         return Qt::BottomEdge;
0425     }
0426     if (anchor() == (Qt::BottomEdge | Qt::LeftEdge | Qt::TopEdge) || anchor() == Qt::LeftEdge) {
0427         return Qt::LeftEdge;
0428     }
0429     return Qt::Edge();
0430 }
0431 
0432 OutputInterface *LayerSurfaceV1Interface::output() const
0433 {
0434     return d->output;
0435 }
0436 
0437 QString LayerSurfaceV1Interface::scope() const
0438 {
0439     return d->scope;
0440 }
0441 
0442 quint32 LayerSurfaceV1Interface::sendConfigure(const QSize &size)
0443 {
0444     if (d->isClosed) {
0445         qCWarning(KWIN_CORE) << "Cannot configure a closed layer shell surface";
0446         return 0;
0447     }
0448 
0449     const uint32_t serial = d->shell->display()->nextSerial();
0450     d->serials << serial;
0451 
0452     d->send_configure(serial, size.width(), size.height());
0453     d->isConfigured = true;
0454 
0455     return serial;
0456 }
0457 
0458 void LayerSurfaceV1Interface::sendClosed()
0459 {
0460     if (!d->isClosed) {
0461         d->send_closed();
0462         d->isClosed = true;
0463     }
0464 }
0465 
0466 } // namespace KWaylandServer