File indexing completed on 2024-11-10 04:57:28
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"