File indexing completed on 2024-09-29 04:54:08
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #include "window.h" 0008 #include "../qwaylandlayershellintegration_p.h" 0009 0010 #include <layershellqt_logging.h> 0011 0012 #include <QPointer> 0013 #include <optional> 0014 0015 #include <QtWaylandClient/private/qwaylandwindow_p.h> 0016 0017 using namespace LayerShellQt; 0018 0019 class LayerShellQt::WindowPrivate 0020 { 0021 public: 0022 WindowPrivate(QWindow *window) 0023 : parentWindow(window) 0024 { 0025 } 0026 0027 QWindow *parentWindow; 0028 QString scope = QStringLiteral("window"); 0029 Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight}; 0030 int32_t exclusionZone = 0; 0031 Window::Anchor exclusiveEdge = Window::AnchorNone; 0032 Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand; 0033 Window::Layer layer = Window::LayerTop; 0034 QMargins margins; 0035 Window::ScreenConfiguration screenConfiguration = Window::ScreenFromQWindow; 0036 bool closeOnDismissed = true; 0037 }; 0038 0039 static QMap<QWindow *, Window *> s_map; 0040 0041 Window::~Window() 0042 { 0043 s_map.remove(d->parentWindow); 0044 } 0045 0046 void Window::setAnchors(Anchors anchors) 0047 { 0048 if (d->anchors != anchors) { 0049 d->anchors = anchors; 0050 Q_EMIT anchorsChanged(); 0051 } 0052 } 0053 0054 Window::Anchors Window::anchors() const 0055 { 0056 return d->anchors; 0057 } 0058 0059 void Window::setExclusiveZone(int32_t zone) 0060 { 0061 if (d->exclusionZone != zone) { 0062 d->exclusionZone = zone; 0063 Q_EMIT exclusionZoneChanged(); 0064 } 0065 } 0066 0067 int32_t Window::exclusionZone() const 0068 { 0069 return d->exclusionZone; 0070 } 0071 0072 void Window::setExclusiveEdge(Window::Anchor edge) 0073 { 0074 if (d->exclusiveEdge == edge) { 0075 return; 0076 } 0077 0078 d->exclusiveEdge = edge; 0079 Q_EMIT exclusiveEdgeChanged(); 0080 } 0081 0082 Window::Anchor Window::exclusiveEdge() const 0083 { 0084 return d->exclusiveEdge; 0085 } 0086 0087 void Window::setMargins(const QMargins &margins) 0088 { 0089 if (d->margins != margins) { 0090 d->margins = margins; 0091 Q_EMIT marginsChanged(); 0092 } 0093 } 0094 0095 QMargins Window::margins() const 0096 { 0097 return d->margins; 0098 } 0099 0100 void Window::setKeyboardInteractivity(KeyboardInteractivity interactivity) 0101 { 0102 if (d->keyboardInteractivity != interactivity) { 0103 d->keyboardInteractivity = interactivity; 0104 Q_EMIT keyboardInteractivityChanged(); 0105 } 0106 } 0107 0108 Window::KeyboardInteractivity Window::keyboardInteractivity() const 0109 { 0110 return d->keyboardInteractivity; 0111 } 0112 0113 void Window::setLayer(Layer layer) 0114 { 0115 if (d->layer != layer) { 0116 d->layer = layer; 0117 Q_EMIT layerChanged(); 0118 } 0119 } 0120 0121 void Window::setScope(const QString &scope) 0122 { 0123 d->scope = scope; 0124 // this is static and must be set before the platform window is created 0125 } 0126 0127 QString Window::scope() const 0128 { 0129 return d->scope; 0130 } 0131 0132 Window::Layer Window::layer() const 0133 { 0134 return d->layer; 0135 } 0136 0137 Window::ScreenConfiguration Window::screenConfiguration() const 0138 { 0139 return d->screenConfiguration; 0140 } 0141 0142 void Window::setScreenConfiguration(Window::ScreenConfiguration screenConfiguration) 0143 { 0144 d->screenConfiguration = screenConfiguration; 0145 } 0146 0147 bool Window::closeOnDismissed() const 0148 { 0149 return d->closeOnDismissed; 0150 } 0151 0152 void Window::setCloseOnDismissed(bool close) 0153 { 0154 d->closeOnDismissed = close; 0155 } 0156 0157 Window::Window(QWindow *window) 0158 : QObject(window) 0159 , d(new WindowPrivate(window)) 0160 { 0161 s_map.insert(d->parentWindow, this); 0162 0163 window->create(); 0164 0165 auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window->handle()); 0166 if (!waylandWindow) { 0167 qCWarning(LAYERSHELLQT) << window << "is not a wayland window. Not creating zwlr_layer_surface"; 0168 return; 0169 } 0170 0171 static QWaylandLayerShellIntegration *shellIntegration = nullptr; 0172 if (!shellIntegration) { 0173 shellIntegration = new QWaylandLayerShellIntegration(); 0174 if (!shellIntegration->initialize(waylandWindow->display())) { 0175 delete shellIntegration; 0176 shellIntegration = nullptr; 0177 qCWarning(LAYERSHELLQT) << "Failed to initialize layer-shell integration, possibly because compositor does not support the layer-shell protocol"; 0178 return; 0179 } 0180 } 0181 0182 waylandWindow->setShellIntegration(shellIntegration); 0183 } 0184 0185 Window *Window::get(QWindow *window) 0186 { 0187 if (!window) { 0188 return nullptr; 0189 } 0190 0191 auto layerShellWindow = s_map.value(window); 0192 if (layerShellWindow) { 0193 return layerShellWindow; 0194 } 0195 return new Window(window); 0196 } 0197 0198 Window *Window::qmlAttachedProperties(QObject *object) 0199 { 0200 return get(qobject_cast<QWindow *>(object)); 0201 }