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