File indexing completed on 2024-04-14 15:37:30

0001 /*
0002  *   SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *   SPDX-FileCopyrightText: 2018 Drew DeVault <sir@cmpwn.com>
0004  *
0005  *   SPDX-License-Identifier: LGPL-3.0-or-later
0006  */
0007 
0008 #include "interfaces/shell.h"
0009 #include "layershellqt_logging.h"
0010 #include "qwaylandlayershell_p.h"
0011 #include "qwaylandlayersurface_p.h"
0012 
0013 #include <QtWaylandClient/private/qwaylandscreen_p.h>
0014 #include <QtWaylandClient/private/qwaylandsurface_p.h>
0015 #include <QtWaylandClient/private/qwaylandwindow_p.h>
0016 
0017 namespace LayerShellQt
0018 {
0019 QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window)
0020     : QtWaylandClient::QWaylandShellSurface(window)
0021     , QtWayland::zwlr_layer_surface_v1()
0022 {
0023     LayerShellQt::Window *interface = Window::get(window->window());
0024     Q_ASSERT(interface);
0025 
0026     wl_output *output = nullptr;
0027     QScreen *screen = interface->desiredOutput();
0028     if (screen) {
0029         auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(screen->handle());
0030         // Qt will always assign a screen to a window, but if the compositor has no screens available a dummy QScreen object is created
0031         // this will not cast to a QWaylandScreen
0032         if (!waylandScreen) {
0033             qCWarning(LAYERSHELLQT) << "Creating a layer shell for placeholder screen. This will be positioned incorrectly";
0034         } else {
0035             output = waylandScreen->output();
0036         }
0037     }
0038     init(shell->get_layer_surface(window->waylandSurface()->object(), output, interface->layer(), interface->scope()));
0039     connect(interface, &Window::layerChanged, this, [this, interface]() {
0040         setLayer(interface->layer());
0041     });
0042 
0043     set_anchor(interface->anchors());
0044     connect(interface, &Window::anchorsChanged, this, [this, interface]() {
0045         set_anchor(interface->anchors());
0046     });
0047     setExclusiveZone(interface->exclusionZone());
0048     connect(interface, &Window::exclusionZoneChanged, this, [this, interface]() {
0049         setExclusiveZone(interface->exclusionZone());
0050     });
0051 
0052     setMargins(interface->margins());
0053     connect(interface, &Window::marginsChanged, this, [this, interface]() {
0054         setMargins(interface->margins());
0055     });
0056 
0057     setKeyboardInteractivity(interface->keyboardInteractivity());
0058     connect(interface, &Window::keyboardInteractivityChanged, this, [this, interface]() {
0059         setKeyboardInteractivity(interface->keyboardInteractivity());
0060     });
0061 
0062     QSize size = window->surfaceSize();
0063     const Window::Anchors anchors = interface->anchors();
0064     if ((anchors & Window::AnchorLeft) && (anchors & Window::AnchorRight)) {
0065         size.setWidth(0);
0066     }
0067     if ((anchors & Window::AnchorTop) && (anchors & Window::AnchorBottom)) {
0068         size.setHeight(0);
0069     }
0070     if (size.isValid() && size != QSize(0, 0)) {
0071         set_size(size.width(), size.height());
0072     }
0073 }
0074 
0075 QWaylandLayerSurface::~QWaylandLayerSurface()
0076 {
0077     destroy();
0078 }
0079 
0080 void QWaylandLayerSurface::zwlr_layer_surface_v1_closed()
0081 {
0082     window()->window()->close();
0083 }
0084 
0085 void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height)
0086 {
0087     ack_configure(serial);
0088     m_pendingSize = QSize(width, height);
0089 
0090     if (!m_configured) {
0091         m_configured = true;
0092         window()->resizeFromApplyConfigure(m_pendingSize);
0093         window()->handleExpose(QRect(QPoint(), m_pendingSize));
0094     } else {
0095         // Later configures are resizes, so we have to queue them up for a time when we
0096         // are not painting to the window.
0097         window()->applyConfigureWhenPossible();
0098     }
0099 }
0100 
0101 void QWaylandLayerSurface::applyConfigure()
0102 {
0103     window()->resizeFromApplyConfigure(m_pendingSize);
0104 }
0105 
0106 void QWaylandLayerSurface::setAnchor(uint anchor)
0107 {
0108     set_anchor(anchor);
0109 }
0110 
0111 void QWaylandLayerSurface::setExclusiveZone(int32_t zone)
0112 {
0113     set_exclusive_zone(zone);
0114 }
0115 
0116 void QWaylandLayerSurface::setMargins(const QMargins &margins)
0117 {
0118     set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
0119 }
0120 
0121 void QWaylandLayerSurface::setKeyboardInteractivity(uint32_t interactivity)
0122 {
0123     set_keyboard_interactivity(interactivity);
0124 }
0125 
0126 void QWaylandLayerSurface::setLayer(uint32_t layer)
0127 {
0128     if (zwlr_layer_surface_v1_get_version(object()) >= ZWLR_LAYER_SURFACE_V1_SET_LAYER_SINCE_VERSION)
0129         set_layer(layer);
0130 }
0131 
0132 }