forked from quickshell/quickshell
feat(wayland): create cross platform window interfaces
Internally this also refactors a ton of code around the wayland layershell. Note that attachment failures are still broken and platform interfaces are hardcoded.
This commit is contained in:
parent
4a82949854
commit
c2930783ea
20 changed files with 591 additions and 402 deletions
|
@ -2,7 +2,7 @@ qt_add_library(quickshell-wayland STATIC
|
|||
shell_integration.cpp
|
||||
layer_surface.cpp
|
||||
layershell.cpp
|
||||
waylandshellwindow.cpp
|
||||
waylandlayershell.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(quickshell-wayland URI QuickShell.Wayland)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <qtypes.h>
|
||||
#include <qwayland-wlr-layer-shell-unstable-v1.h>
|
||||
|
||||
#include "../core/shellwindow.hpp"
|
||||
#include "../core/panelinterface.hpp"
|
||||
#include "layershell.hpp"
|
||||
#include "shell_integration.hpp"
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "layershell.hpp"
|
||||
#include "shell_integration.hpp"
|
||||
|
||||
class Q_WAYLANDCLIENT_EXPORT QSWaylandLayerSurface
|
||||
class QSWaylandLayerSurface
|
||||
: public QtWaylandClient::QWaylandShellSurface
|
||||
, public QtWayland::zwlr_layer_surface_v1 {
|
||||
public:
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <qvariant.h>
|
||||
#include <qwindow.h>
|
||||
|
||||
#include "../core/shellwindow.hpp"
|
||||
#include "../core/panelinterface.hpp"
|
||||
#include "layer_surface.hpp"
|
||||
#include "shell_integration.hpp"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <qtypes.h>
|
||||
#include <qwindow.h>
|
||||
|
||||
#include "../core/shellwindow.hpp"
|
||||
#include "../core/panelinterface.hpp"
|
||||
|
||||
namespace Layer { // NOLINT
|
||||
Q_NAMESPACE;
|
||||
|
@ -14,8 +14,12 @@ QML_ELEMENT;
|
|||
|
||||
enum Enum {
|
||||
Background = 0,
|
||||
/// Above background, usually below windows
|
||||
Bottom = 1,
|
||||
/// Commonly used for panels, app launchers, and docks.
|
||||
/// Usually renders over normal windows and below fullscreen windows.
|
||||
Top = 2,
|
||||
/// Usually renders over fullscreen windows
|
||||
Overlay = 3,
|
||||
};
|
||||
Q_ENUM_NS(Enum);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <qtwaylandclientexports.h>
|
||||
#include <qwayland-wlr-layer-shell-unstable-v1.h>
|
||||
|
||||
class Q_WAYLANDCLIENT_EXPORT QSWaylandLayerShellIntegration
|
||||
class QSWaylandLayerShellIntegration
|
||||
: public QtWaylandClient::QWaylandShellIntegrationTemplate<QSWaylandLayerShellIntegration>
|
||||
, public QtWayland::zwlr_layer_shell_v1 {
|
||||
public:
|
||||
|
|
179
src/wayland/waylandlayershell.cpp
Normal file
179
src/wayland/waylandlayershell.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
#include "waylandlayershell.hpp"
|
||||
#include <utility>
|
||||
|
||||
#include <qlogging.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qquickitem.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../core/panelinterface.hpp"
|
||||
#include "../core/proxywindow.hpp"
|
||||
#include "../core/qmlscreen.hpp"
|
||||
#include "layershell.hpp"
|
||||
|
||||
WaylandLayershell::WaylandLayershell(QObject* parent)
|
||||
: ProxyWindowBase(parent)
|
||||
, ext(new LayershellWindowExtension(this)) {}
|
||||
|
||||
void WaylandLayershell::setupWindow() {
|
||||
this->ProxyWindowBase::setupWindow();
|
||||
|
||||
// clang-format off
|
||||
QObject::connect(this->ext, &LayershellWindowExtension::layerChanged, this, &WaylandLayershell::layerChanged);
|
||||
QObject::connect(this->ext, &LayershellWindowExtension::keyboardFocusChanged, this, &WaylandLayershell::keyboardFocusChanged);
|
||||
QObject::connect(this->ext, &LayershellWindowExtension::anchorsChanged, this, &WaylandLayershell::anchorsChanged);
|
||||
QObject::connect(this->ext, &LayershellWindowExtension::exclusiveZoneChanged, this, &WaylandLayershell::exclusiveZoneChanged);
|
||||
QObject::connect(this->ext, &LayershellWindowExtension::marginsChanged, this, &WaylandLayershell::marginsChanged);
|
||||
|
||||
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &WaylandLayershell::updateAutoExclusion);
|
||||
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &WaylandLayershell::updateAutoExclusion);
|
||||
QObject::connect(this, &WaylandLayershell::anchorsChanged, this, &WaylandLayershell::updateAutoExclusion);
|
||||
QObject::connect(this, &WaylandLayershell::marginsChanged, this, &WaylandLayershell::updateAutoExclusion);
|
||||
// clang-format on
|
||||
|
||||
if (!this->ext->attach(this->window)) {
|
||||
// todo: discard window
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandLayershell::setWidth(qint32 width) {
|
||||
this->mWidth = width;
|
||||
|
||||
// only update the actual size if not blocked by anchors
|
||||
if (!this->ext->anchors().horizontalConstraint()) {
|
||||
this->ProxyWindowBase::setWidth(width);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandLayershell::setHeight(qint32 height) {
|
||||
this->mHeight = height;
|
||||
|
||||
// only update the actual size if not blocked by anchors
|
||||
if (!this->ext->anchors().verticalConstraint()) {
|
||||
this->ProxyWindowBase::setHeight(height);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandLayershell::setScreen(QuickShellScreenInfo* screen) {
|
||||
this->ProxyWindowBase::setScreen(screen);
|
||||
this->ext->setUseWindowScreen(screen != nullptr);
|
||||
}
|
||||
|
||||
// NOLINTBEGIN
|
||||
#define extPair(type, get, set) \
|
||||
type WaylandLayershell::get() const { return this->ext->get(); } \
|
||||
void WaylandLayershell::set(type value) { this->ext->set(value); }
|
||||
|
||||
extPair(Layer::Enum, layer, setLayer);
|
||||
extPair(KeyboardFocus::Enum, keyboardFocus, setKeyboardFocus);
|
||||
extPair(Margins, margins, setMargins);
|
||||
// NOLINTEND
|
||||
|
||||
Anchors WaylandLayershell::anchors() const { return this->ext->anchors(); }
|
||||
|
||||
void WaylandLayershell::setAnchors(Anchors anchors) {
|
||||
this->ext->setAnchors(anchors);
|
||||
|
||||
// explicitly set width values are tracked so the entire screen isn't covered if an anchor is removed.
|
||||
if (!anchors.horizontalConstraint()) this->ProxyWindowBase::setWidth(this->mWidth);
|
||||
if (!anchors.verticalConstraint()) this->ProxyWindowBase::setHeight(this->mHeight);
|
||||
}
|
||||
|
||||
QString WaylandLayershell::ns() const { return this->ext->ns(); }
|
||||
|
||||
void WaylandLayershell::setNamespace(QString ns) {
|
||||
this->ext->setNamespace(std::move(ns));
|
||||
emit this->namespaceChanged();
|
||||
}
|
||||
|
||||
qint32 WaylandLayershell::exclusiveZone() const { return this->ext->exclusiveZone(); }
|
||||
|
||||
void WaylandLayershell::setExclusiveZone(qint32 exclusiveZone) {
|
||||
qDebug() << "set exclusion" << exclusiveZone;
|
||||
this->mExclusiveZone = exclusiveZone;
|
||||
|
||||
if (this->mExclusionMode == ExclusionMode::Normal) {
|
||||
this->ext->setExclusiveZone(exclusiveZone);
|
||||
}
|
||||
}
|
||||
|
||||
ExclusionMode::Enum WaylandLayershell::exclusionMode() const { return this->mExclusionMode; }
|
||||
|
||||
void WaylandLayershell::setExclusionMode(ExclusionMode::Enum exclusionMode) {
|
||||
this->mExclusionMode = exclusionMode;
|
||||
if (exclusionMode == ExclusionMode::Normal) {
|
||||
this->ext->setExclusiveZone(this->mExclusiveZone);
|
||||
} else if (exclusionMode == ExclusionMode::Ignore) {
|
||||
this->ext->setExclusiveZone(-1);
|
||||
} else {
|
||||
this->setAutoExclusion();
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandLayershell::setAutoExclusion() {
|
||||
const auto anchors = this->anchors();
|
||||
auto zone = 0;
|
||||
|
||||
if (anchors.horizontalConstraint()) zone = this->height();
|
||||
else if (anchors.verticalConstraint()) zone = this->width();
|
||||
|
||||
this->ext->setExclusiveZone(zone);
|
||||
}
|
||||
|
||||
void WaylandLayershell::updateAutoExclusion() {
|
||||
if (this->mExclusionMode == ExclusionMode::Auto) {
|
||||
this->setAutoExclusion();
|
||||
}
|
||||
}
|
||||
|
||||
// WaylandPanelInterface
|
||||
|
||||
WaylandPanelInterface::WaylandPanelInterface(QObject* parent)
|
||||
: PanelWindowInterface(parent)
|
||||
, layer(new WaylandLayershell(this)) {
|
||||
|
||||
// clang-format off
|
||||
QObject::connect(this->layer, &ProxyWindowBase::windowConnected, this, &WaylandPanelInterface::windowConnected);
|
||||
QObject::connect(this->layer, &ProxyWindowBase::visibleChanged, this, &WaylandPanelInterface::visibleChanged);
|
||||
QObject::connect(this->layer, &ProxyWindowBase::heightChanged, this, &WaylandPanelInterface::heightChanged);
|
||||
QObject::connect(this->layer, &ProxyWindowBase::widthChanged, this, &WaylandPanelInterface::widthChanged);
|
||||
QObject::connect(this->layer, &ProxyWindowBase::screenChanged, this, &WaylandPanelInterface::screenChanged);
|
||||
QObject::connect(this->layer, &ProxyWindowBase::colorChanged, this, &WaylandPanelInterface::colorChanged);
|
||||
QObject::connect(this->layer, &ProxyWindowBase::maskChanged, this, &WaylandPanelInterface::maskChanged);
|
||||
|
||||
// panel specific
|
||||
QObject::connect(this->layer, &WaylandLayershell::anchorsChanged, this, &WaylandPanelInterface::anchorsChanged);
|
||||
QObject::connect(this->layer, &WaylandLayershell::marginsChanged, this, &WaylandPanelInterface::marginsChanged);
|
||||
QObject::connect(this->layer, &WaylandLayershell::exclusiveZoneChanged, this, &WaylandPanelInterface::exclusiveZoneChanged);
|
||||
QObject::connect(this->layer, &WaylandLayershell::exclusionModeChanged, this, &WaylandPanelInterface::exclusionModeChanged);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void WaylandPanelInterface::onReload(QObject* oldInstance) {
|
||||
auto* old = qobject_cast<WaylandPanelInterface*>(oldInstance);
|
||||
this->layer->onReload(old != nullptr ? old->layer : nullptr);
|
||||
}
|
||||
|
||||
QQmlListProperty<QObject> WaylandPanelInterface::data() { return this->layer->data(); }
|
||||
QQuickItem* WaylandPanelInterface::contentItem() const { return this->layer->contentItem(); }
|
||||
|
||||
// NOLINTBEGIN
|
||||
#define proxyPair(type, get, set) \
|
||||
type WaylandPanelInterface::get() const { return this->layer->get(); } \
|
||||
void WaylandPanelInterface::set(type value) { this->layer->set(value); }
|
||||
|
||||
proxyPair(bool, isVisible, setVisible);
|
||||
proxyPair(qint32, width, setWidth);
|
||||
proxyPair(qint32, height, setHeight);
|
||||
proxyPair(QuickShellScreenInfo*, screen, setScreen);
|
||||
proxyPair(QColor, color, setColor);
|
||||
proxyPair(PendingRegion*, mask, setMask);
|
||||
|
||||
// panel specific
|
||||
proxyPair(Anchors, anchors, setAnchors);
|
||||
proxyPair(Margins, margins, setMargins);
|
||||
proxyPair(qint32, exclusiveZone, setExclusiveZone);
|
||||
proxyPair(ExclusionMode::Enum, exclusionMode, setExclusionMode);
|
||||
// NOLINTEND
|
131
src/wayland/waylandlayershell.hpp
Normal file
131
src/wayland/waylandlayershell.hpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
#pragma once
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../core/proxywindow.hpp"
|
||||
#include "layershell.hpp"
|
||||
|
||||
class WaylandLayershell: public ProxyWindowBase {
|
||||
// clang-format off
|
||||
Q_OBJECT;
|
||||
/// The shell layer the window sits in. Defaults to `Layer.Top`.
|
||||
Q_PROPERTY(Layer::Enum layer READ layer WRITE setLayer NOTIFY layerChanged);
|
||||
/// Similar to the class property of windows. Can be used to identify the window to external tools.
|
||||
///
|
||||
/// Cannot be set after windowConnected.
|
||||
Q_PROPERTY(QString namespace READ ns WRITE setNamespace);
|
||||
/// The degree of keyboard focus taken. Defaults to `KeyboardFocus.None`.
|
||||
Q_PROPERTY(KeyboardFocus::Enum keyboardFocus READ keyboardFocus WRITE setKeyboardFocus NOTIFY keyboardFocusChanged);
|
||||
|
||||
Q_PROPERTY(Anchors anchors READ anchors WRITE setAnchors NOTIFY anchorsChanged);
|
||||
Q_PROPERTY(qint32 exclusiveZone READ exclusiveZone WRITE setExclusiveZone NOTIFY exclusiveZoneChanged);
|
||||
Q_PROPERTY(ExclusionMode::Enum exclusionMode READ exclusionMode WRITE setExclusionMode NOTIFY exclusionModeChanged);
|
||||
Q_PROPERTY(Margins margins READ margins WRITE setMargins NOTIFY marginsChanged);
|
||||
QML_ELEMENT;
|
||||
// clang-format on
|
||||
|
||||
public:
|
||||
explicit WaylandLayershell(QObject* parent = nullptr);
|
||||
|
||||
void setupWindow() override;
|
||||
|
||||
void setWidth(qint32 width) override;
|
||||
void setHeight(qint32 height) override;
|
||||
|
||||
void setScreen(QuickShellScreenInfo* screen) override;
|
||||
|
||||
[[nodiscard]] Layer::Enum layer() const;
|
||||
void setLayer(Layer::Enum layer); // NOLINT
|
||||
|
||||
[[nodiscard]] QString ns() const;
|
||||
void setNamespace(QString ns);
|
||||
|
||||
[[nodiscard]] KeyboardFocus::Enum keyboardFocus() const;
|
||||
void setKeyboardFocus(KeyboardFocus::Enum focus); // NOLINT
|
||||
|
||||
[[nodiscard]] Anchors anchors() const;
|
||||
void setAnchors(Anchors anchors);
|
||||
|
||||
[[nodiscard]] qint32 exclusiveZone() const;
|
||||
void setExclusiveZone(qint32 exclusiveZone);
|
||||
|
||||
[[nodiscard]] ExclusionMode::Enum exclusionMode() const;
|
||||
void setExclusionMode(ExclusionMode::Enum exclusionMode);
|
||||
|
||||
[[nodiscard]] Margins margins() const;
|
||||
void setMargins(Margins margins); // NOLINT
|
||||
|
||||
signals:
|
||||
void layerChanged();
|
||||
void namespaceChanged();
|
||||
void keyboardFocusChanged();
|
||||
void anchorsChanged();
|
||||
void exclusiveZoneChanged();
|
||||
void exclusionModeChanged();
|
||||
void marginsChanged();
|
||||
|
||||
private slots:
|
||||
void updateAutoExclusion();
|
||||
|
||||
private:
|
||||
void setAutoExclusion();
|
||||
|
||||
LayershellWindowExtension* ext;
|
||||
|
||||
ExclusionMode::Enum mExclusionMode = ExclusionMode::Auto;
|
||||
qint32 mExclusiveZone = 0;
|
||||
};
|
||||
|
||||
class WaylandPanelInterface: public PanelWindowInterface {
|
||||
Q_OBJECT;
|
||||
QML_NAMED_ELEMENT(PanelWindow); // temp
|
||||
|
||||
public:
|
||||
explicit WaylandPanelInterface(QObject* parent = nullptr);
|
||||
|
||||
void onReload(QObject* oldInstance) override;
|
||||
|
||||
[[nodiscard]] QQuickItem* contentItem() const override;
|
||||
|
||||
// NOLINTBEGIN
|
||||
[[nodiscard]] bool isVisible() const override;
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
[[nodiscard]] qint32 width() const override;
|
||||
void setWidth(qint32 width) override;
|
||||
|
||||
[[nodiscard]] qint32 height() const override;
|
||||
void setHeight(qint32 height) override;
|
||||
|
||||
[[nodiscard]] QuickShellScreenInfo* screen() const override;
|
||||
void setScreen(QuickShellScreenInfo* screen) override;
|
||||
|
||||
[[nodiscard]] QColor color() const override;
|
||||
void setColor(QColor color) override;
|
||||
|
||||
[[nodiscard]] PendingRegion* mask() const override;
|
||||
void setMask(PendingRegion* mask) override;
|
||||
|
||||
[[nodiscard]] QQmlListProperty<QObject> data() override;
|
||||
|
||||
// panel specific
|
||||
|
||||
[[nodiscard]] Anchors anchors() const override;
|
||||
void setAnchors(Anchors anchors) override;
|
||||
|
||||
[[nodiscard]] Margins margins() const override;
|
||||
void setMargins(Margins margins) override;
|
||||
|
||||
[[nodiscard]] qint32 exclusiveZone() const override;
|
||||
void setExclusiveZone(qint32 exclusiveZone) override;
|
||||
|
||||
[[nodiscard]] ExclusionMode::Enum exclusionMode() const override;
|
||||
void setExclusionMode(ExclusionMode::Enum exclusionMode) override;
|
||||
// NOLINTEND
|
||||
|
||||
private:
|
||||
WaylandLayershell* layer;
|
||||
};
|
|
@ -1,174 +0,0 @@
|
|||
#include "waylandshellwindow.hpp"
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qqmlcontext.h>
|
||||
#include <qquickwindow.h>
|
||||
#include <qtypes.h>
|
||||
#include <qwindow.h>
|
||||
|
||||
#include "../core/proxywindow.hpp"
|
||||
#include "../core/shellwindow.hpp"
|
||||
#include "layershell.hpp"
|
||||
|
||||
WaylandShellWindow::WaylandShellWindow(QObject* parent)
|
||||
: ProxyShellWindow(parent)
|
||||
, mWayland(new WaylandShellWindowExtensions(this))
|
||||
, windowExtension(new LayershellWindowExtension(this)) {}
|
||||
|
||||
void WaylandShellWindow::setupWindow() {
|
||||
this->ProxyShellWindow::setupWindow();
|
||||
|
||||
// clang-format off
|
||||
QObject::connect(this->windowExtension, &LayershellWindowExtension::anchorsChanged, this, &ProxyShellWindow::anchorsChanged);
|
||||
QObject::connect(this->windowExtension, &LayershellWindowExtension::marginsChanged, this, &ProxyShellWindow::marginsChanged);
|
||||
QObject::connect(this->windowExtension, &LayershellWindowExtension::exclusiveZoneChanged, this, &ProxyShellWindow::exclusionZoneChanged);
|
||||
|
||||
QObject::connect(
|
||||
this->windowExtension, &LayershellWindowExtension::layerChanged,
|
||||
this->mWayland, &WaylandShellWindowExtensions::layerChanged
|
||||
);
|
||||
QObject::connect(
|
||||
this->windowExtension, &LayershellWindowExtension::keyboardFocusChanged,
|
||||
this->mWayland, &WaylandShellWindowExtensions::keyboardFocusChanged
|
||||
);
|
||||
|
||||
QObject::connect(this->window, &QWindow::widthChanged, this, &WaylandShellWindow::updateExclusionZone);
|
||||
QObject::connect(this->window, &QWindow::heightChanged, this, &WaylandShellWindow::updateExclusionZone);
|
||||
QObject::connect(this, &ProxyShellWindow::anchorsChanged, this, &WaylandShellWindow::updateExclusionZone);
|
||||
QObject::connect(this, &ProxyShellWindow::marginsChanged, this, &WaylandShellWindow::updateExclusionZone);
|
||||
// clang-format on
|
||||
|
||||
this->setMargins(this->mMargins);
|
||||
this->setExclusionMode(this->mExclusionMode); // also sets exclusion zone
|
||||
|
||||
if (!this->windowExtension->attach(this->window)) {
|
||||
// todo: discard window
|
||||
}
|
||||
|
||||
this->connected = true;
|
||||
}
|
||||
|
||||
QQuickWindow* WaylandShellWindow::disownWindow() { return this->ProxyWindowBase::disownWindow(); }
|
||||
|
||||
void WaylandShellWindow::setWidth(qint32 width) {
|
||||
this->mWidth = width;
|
||||
|
||||
// only update the actual size if not blocked by anchors
|
||||
if (!this->windowExtension->anchors().horizontalConstraint()) {
|
||||
this->ProxyShellWindow::setWidth(width);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandShellWindow::onWidthChanged() {
|
||||
this->ProxyShellWindow::onWidthChanged();
|
||||
|
||||
// change the remembered width only when not horizontally constrained.
|
||||
if (this->window != nullptr && !this->windowExtension->anchors().horizontalConstraint()) {
|
||||
this->mWidth = this->window->width();
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandShellWindow::setHeight(qint32 height) {
|
||||
this->mHeight = height;
|
||||
|
||||
// only update the actual size if not blocked by anchors
|
||||
if (!this->windowExtension->anchors().verticalConstraint()) {
|
||||
this->ProxyShellWindow::setHeight(height);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandShellWindow::onHeightChanged() {
|
||||
this->ProxyShellWindow::onHeightChanged();
|
||||
|
||||
// change the remembered height only when not vertically constrained.
|
||||
if (this->window != nullptr && !this->windowExtension->anchors().verticalConstraint()) {
|
||||
this->mHeight = this->window->height();
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandShellWindow::setAnchors(Anchors anchors) {
|
||||
this->windowExtension->setAnchors(anchors);
|
||||
this->setHeight(this->mHeight);
|
||||
this->setWidth(this->mWidth);
|
||||
}
|
||||
|
||||
Anchors WaylandShellWindow::anchors() const { return this->windowExtension->anchors(); }
|
||||
|
||||
void WaylandShellWindow::setExclusiveZone(qint32 zone) {
|
||||
this->windowExtension->setExclusiveZone(zone);
|
||||
}
|
||||
|
||||
qint32 WaylandShellWindow::exclusiveZone() const { return this->windowExtension->exclusiveZone(); }
|
||||
|
||||
ExclusionMode::Enum WaylandShellWindow::exclusionMode() const { return this->mExclusionMode; }
|
||||
|
||||
void WaylandShellWindow::setExclusionMode(ExclusionMode::Enum exclusionMode) {
|
||||
if (this->connected && exclusionMode == this->mExclusionMode) return;
|
||||
this->mExclusionMode = exclusionMode;
|
||||
|
||||
if (this->window != nullptr) {
|
||||
if (exclusionMode == ExclusionMode::Normal) {
|
||||
this->windowExtension->setExclusiveZone(this->mExclusionZone);
|
||||
} else if (exclusionMode == ExclusionMode::Ignore) {
|
||||
this->windowExtension->setExclusiveZone(-1);
|
||||
} else {
|
||||
this->updateExclusionZone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandShellWindow::setMargins(Margins margins) { this->windowExtension->setMargins(margins); }
|
||||
|
||||
Margins WaylandShellWindow::margins() const { return this->windowExtension->margins(); }
|
||||
|
||||
void WaylandShellWindowExtensions::setLayer(Layer::Enum layer) {
|
||||
this->window->windowExtension->setLayer(layer);
|
||||
}
|
||||
|
||||
Layer::Enum WaylandShellWindowExtensions::layer() const {
|
||||
return this->window->windowExtension->layer();
|
||||
}
|
||||
|
||||
void WaylandShellWindowExtensions::setNamespace(const QString& ns) {
|
||||
if (this->window->windowExtension->isConfigured()) {
|
||||
auto* context = QQmlEngine::contextForObject(this);
|
||||
if (context != nullptr) {
|
||||
context->engine()->throwError(QString("Cannot change shell window namespace post-configure.")
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this->window->windowExtension->setNamespace(ns);
|
||||
}
|
||||
|
||||
QString WaylandShellWindowExtensions::ns() const { return this->window->windowExtension->ns(); }
|
||||
|
||||
void WaylandShellWindowExtensions::setKeyboardFocus(KeyboardFocus::Enum focus) {
|
||||
this->window->windowExtension->setKeyboardFocus(focus);
|
||||
}
|
||||
|
||||
KeyboardFocus::Enum WaylandShellWindowExtensions::keyboardFocus() const {
|
||||
return this->window->windowExtension->keyboardFocus();
|
||||
}
|
||||
|
||||
void WaylandShellWindow::updateExclusionZone() {
|
||||
if (this->window != nullptr && this->exclusionMode() == ExclusionMode::Auto) {
|
||||
auto anchors = this->anchors();
|
||||
|
||||
auto zone = -1;
|
||||
|
||||
if (anchors.mTop && anchors.mBottom) {
|
||||
if (anchors.mLeft) zone = this->width() + this->margins().mLeft;
|
||||
else if (anchors.mRight) zone = this->width() + this->margins().mRight;
|
||||
} else if (anchors.mLeft && anchors.mRight) {
|
||||
if (anchors.mTop) zone = this->height() + this->margins().mTop;
|
||||
else if (anchors.mBottom) zone = this->height() + this->margins().mBottom;
|
||||
}
|
||||
|
||||
if (zone != -1) {
|
||||
this->windowExtension->setExclusiveZone(zone);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qqmlengine.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../core/shellwindow.hpp"
|
||||
#include "layershell.hpp"
|
||||
|
||||
class WaylandShellWindowExtensions;
|
||||
|
||||
class WaylandShellWindow: public ProxyShellWindow {
|
||||
Q_OBJECT;
|
||||
Q_PROPERTY(WaylandShellWindowExtensions* wayland MEMBER mWayland CONSTANT);
|
||||
QML_NAMED_ELEMENT(ShellWindow);
|
||||
|
||||
public:
|
||||
explicit WaylandShellWindow(QObject* parent = nullptr);
|
||||
|
||||
WaylandShellWindowExtensions* wayland();
|
||||
|
||||
void setupWindow() override;
|
||||
QQuickWindow* disownWindow() override;
|
||||
|
||||
void setWidth(qint32 width) override;
|
||||
void setHeight(qint32 height) override;
|
||||
|
||||
void setAnchors(Anchors anchors) override;
|
||||
[[nodiscard]] Anchors anchors() const override;
|
||||
|
||||
void setExclusiveZone(qint32 zone) override;
|
||||
[[nodiscard]] qint32 exclusiveZone() const override;
|
||||
|
||||
void setExclusionMode(ExclusionMode::Enum exclusionMode) override;
|
||||
[[nodiscard]] ExclusionMode::Enum exclusionMode() const override;
|
||||
|
||||
void setMargins(Margins margins) override;
|
||||
[[nodiscard]] Margins margins() const override;
|
||||
|
||||
protected slots:
|
||||
void updateExclusionZone();
|
||||
void onWidthChanged() override;
|
||||
void onHeightChanged() override;
|
||||
|
||||
private:
|
||||
WaylandShellWindowExtensions* mWayland = nullptr;
|
||||
|
||||
LayershellWindowExtension* windowExtension;
|
||||
bool connected = false;
|
||||
|
||||
friend class WaylandShellWindowExtensions;
|
||||
};
|
||||
|
||||
class WaylandShellWindowExtensions: public QObject {
|
||||
Q_OBJECT;
|
||||
// clang-format off
|
||||
/// The shell layer the window sits in. Defaults to `Layer.Top`.
|
||||
Q_PROPERTY(Layer::Enum layer READ layer WRITE setLayer NOTIFY layerChanged);
|
||||
/// Similar to the class property of windows. Can be used to identify the window to external tools.
|
||||
Q_PROPERTY(QString namespace READ ns WRITE setNamespace);
|
||||
/// The degree of keyboard focus taken. Defaults to `KeyboardFocus.None`.
|
||||
Q_PROPERTY(KeyboardFocus::Enum keyboardFocus READ keyboardFocus WRITE setKeyboardFocus NOTIFY keyboardFocusChanged);
|
||||
// clang-format on
|
||||
QML_ELEMENT;
|
||||
QML_UNCREATABLE("WaylandShellWindowExtensions cannot be created");
|
||||
|
||||
public:
|
||||
explicit WaylandShellWindowExtensions(WaylandShellWindow* window)
|
||||
: QObject(window)
|
||||
, window(window) {}
|
||||
|
||||
void setLayer(Layer::Enum layer);
|
||||
[[nodiscard]] Layer::Enum layer() const;
|
||||
|
||||
void setNamespace(const QString& ns);
|
||||
[[nodiscard]] QString ns() const;
|
||||
|
||||
void setKeyboardFocus(KeyboardFocus::Enum focus);
|
||||
[[nodiscard]] KeyboardFocus::Enum keyboardFocus() const;
|
||||
|
||||
void setScreenConfiguration(ScreenConfiguration::Enum configuration);
|
||||
[[nodiscard]] ScreenConfiguration::Enum screenConfiguration() const;
|
||||
|
||||
signals:
|
||||
void layerChanged();
|
||||
void keyboardFocusChanged();
|
||||
|
||||
private:
|
||||
WaylandShellWindow* window;
|
||||
|
||||
friend class WaylandShellWindow;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue