File indexing completed on 2023-11-26 12:08:26
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/window.h" 0009 #include "layershellqt_logging.h" 0010 #include "qwaylandlayersurface_p.h" 0011 0012 #include <QtWaylandClient/private/qwaylandscreen_p.h> 0013 #include <QtWaylandClient/private/qwaylandsurface_p.h> 0014 #include <QtWaylandClient/private/qwaylandwindow_p.h> 0015 0016 namespace LayerShellQt 0017 { 0018 QWaylandLayerSurface::QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window) 0019 : QtWaylandClient::QWaylandShellSurface(window) 0020 , QtWayland::zwlr_layer_surface_v1() 0021 , m_interface(Window::get(window->window())) 0022 { 0023 wl_output *output = nullptr; 0024 if (m_interface->screenConfiguration() == Window::ScreenFromQWindow) { 0025 auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(window->window()->screen()->handle()); 0026 // Qt will always assign a screen to a window, but if the compositor has no screens available a dummy QScreen object is created 0027 // this will not cast to a QWaylandScreen 0028 if (!waylandScreen) { 0029 qCWarning(LAYERSHELLQT) << "Creating a layer shell for placeholder screen. This will be positioned incorrectly"; 0030 } else { 0031 output = waylandScreen->output(); 0032 } 0033 } 0034 init(shell->get_layer_surface(window->waylandSurface()->object(), output, m_interface->layer(), m_interface->scope())); 0035 connect(m_interface, &Window::layerChanged, this, [this]() { 0036 setLayer(m_interface->layer()); 0037 }); 0038 0039 set_anchor(m_interface->anchors()); 0040 connect(m_interface, &Window::anchorsChanged, this, [this]() { 0041 set_anchor(m_interface->anchors()); 0042 }); 0043 setExclusiveZone(m_interface->exclusionZone()); 0044 connect(m_interface, &Window::exclusionZoneChanged, this, [this]() { 0045 setExclusiveZone(m_interface->exclusionZone()); 0046 }); 0047 0048 setMargins(m_interface->margins()); 0049 connect(m_interface, &Window::marginsChanged, this, [this]() { 0050 setMargins(m_interface->margins()); 0051 }); 0052 0053 setKeyboardInteractivity(m_interface->keyboardInteractivity()); 0054 connect(m_interface, &Window::keyboardInteractivityChanged, this, [this]() { 0055 setKeyboardInteractivity(m_interface->keyboardInteractivity()); 0056 }); 0057 0058 QSize size = window->surfaceSize(); 0059 const Window::Anchors anchors = m_interface->anchors(); 0060 if ((anchors & Window::AnchorLeft) && (anchors & Window::AnchorRight)) { 0061 size.setWidth(0); 0062 } 0063 if ((anchors & Window::AnchorTop) && (anchors & Window::AnchorBottom)) { 0064 size.setHeight(0); 0065 } 0066 if (size.isValid() && size != QSize(0, 0)) { 0067 set_size(size.width(), size.height()); 0068 } 0069 } 0070 0071 QWaylandLayerSurface::~QWaylandLayerSurface() 0072 { 0073 destroy(); 0074 } 0075 0076 void QWaylandLayerSurface::zwlr_layer_surface_v1_closed() 0077 { 0078 if (m_interface->closeOnDismissed()) { 0079 window()->window()->close(); 0080 } 0081 } 0082 0083 void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height) 0084 { 0085 ack_configure(serial); 0086 m_pendingSize = QSize(width, height); 0087 0088 if (!m_configured) { 0089 m_configured = true; 0090 window()->resizeFromApplyConfigure(m_pendingSize); 0091 window()->handleExpose(QRect(QPoint(), m_pendingSize)); 0092 } else { 0093 // Later configures are resizes, so we have to queue them up for a time when we 0094 // are not painting to the window. 0095 window()->applyConfigureWhenPossible(); 0096 } 0097 } 0098 0099 #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) 0100 void QWaylandLayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface *popup) 0101 { 0102 std::any anyRole = popup->surfaceRole(); 0103 0104 if (auto role = std::any_cast<::xdg_popup *>(&anyRole)) { 0105 get_popup(*role); 0106 } else { 0107 qCWarning(LAYERSHELLQT) << "Cannot attach popup of unknown type"; 0108 } 0109 } 0110 #endif 0111 0112 void QWaylandLayerSurface::applyConfigure() 0113 { 0114 window()->resizeFromApplyConfigure(m_pendingSize); 0115 } 0116 0117 void QWaylandLayerSurface::setAnchor(uint anchor) 0118 { 0119 set_anchor(anchor); 0120 } 0121 0122 void QWaylandLayerSurface::setExclusiveZone(int32_t zone) 0123 { 0124 set_exclusive_zone(zone); 0125 } 0126 0127 void QWaylandLayerSurface::setMargins(const QMargins &margins) 0128 { 0129 set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); 0130 } 0131 0132 void QWaylandLayerSurface::setKeyboardInteractivity(uint32_t interactivity) 0133 { 0134 set_keyboard_interactivity(interactivity); 0135 } 0136 0137 void QWaylandLayerSurface::setLayer(uint32_t layer) 0138 { 0139 if (zwlr_layer_surface_v1_get_version(object()) >= ZWLR_LAYER_SURFACE_V1_SET_LAYER_SINCE_VERSION) 0140 set_layer(layer); 0141 } 0142 0143 void QWaylandLayerSurface::setWindowGeometry(const QRect &geometry) 0144 { 0145 const bool horizontallyConstrained = m_interface->anchors() & (Window::AnchorLeft & Window::AnchorRight); 0146 const bool verticallyConstrained = m_interface->anchors() & (Window::AnchorTop & Window::AnchorBottom); 0147 0148 QSize size = geometry.size(); 0149 if (horizontallyConstrained) { 0150 size.setWidth(0); 0151 } 0152 if (verticallyConstrained) { 0153 size.setHeight(0); 0154 } 0155 set_size(size.width(), size.height()); 0156 } 0157 0158 }