File indexing completed on 2024-05-12 05:32:22

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