feat: add ProxyShellWindow.exclusionMode

This commit is contained in:
outfoxxed 2024-02-12 23:09:34 -08:00
parent bb16054b84
commit ad2450762b
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
2 changed files with 85 additions and 1 deletions

View file

@ -7,6 +7,7 @@
#include <qquickitem.h>
#include <qquickwindow.h>
#include <qscreen.h>
#include <qtmetamacros.h>
#include <qtypes.h>
#include <qwindow.h>
@ -31,6 +32,11 @@ void ProxyShellWindow::earlyInit(QObject* old) {
QObject::connect(this->shellWindow, &LayerShellQt::Window::marginsChanged, this, &ProxyShellWindow::marginsChanged);
QObject::connect(this->shellWindow, &LayerShellQt::Window::layerChanged, this, &ProxyShellWindow::layerChanged);
QObject::connect(this->shellWindow, &LayerShellQt::Window::keyboardInteractivityChanged, this, &ProxyShellWindow::keyboardFocusChanged);
QObject::connect(this->window, &QWindow::widthChanged, this, &ProxyShellWindow::updateExclusionZone);
QObject::connect(this->window, &QWindow::heightChanged, this, &ProxyShellWindow::updateExclusionZone);
QObject::connect(this, &ProxyShellWindow::anchorsChanged, this, &ProxyShellWindow::updateExclusionZone);
QObject::connect(this, &ProxyShellWindow::marginsChanged, this, &ProxyShellWindow::updateExclusionZone);
// clang-format on
}
@ -40,6 +46,7 @@ void ProxyShellWindow::componentComplete() {
// The default anchor settings are a hazard because they cover the entire screen.
// We opt for 0 anchors by default to avoid blocking user input.
this->setAnchors(this->stagingAnchors);
this->updateExclusionZone();
// Make sure we signal changes from anchors, but only if this is a reload.
// If we do it on first load then it sends an extra change at 0px.
@ -135,10 +142,36 @@ Anchors ProxyShellWindow::anchors() const {
return anchors;
}
void ProxyShellWindow::setExclusiveZone(qint32 zone) { this->shellWindow->setExclusiveZone(zone); }
void ProxyShellWindow::setExclusiveZone(qint32 zone) {
if (zone < 0) zone = 0;
if (zone == this->requestedExclusionZone) return;
this->requestedExclusionZone = zone;
if (this->exclusionMode() == ExclusionMode::Normal) {
this->shellWindow->setExclusiveZone(zone);
emit this->exclusionZoneChanged();
}
}
qint32 ProxyShellWindow::exclusiveZone() const { return this->shellWindow->exclusionZone(); }
ExclusionMode::Enum ProxyShellWindow::exclusionMode() const { return this->mExclusionMode; }
void ProxyShellWindow::setExclusionMode(ExclusionMode::Enum exclusionMode) {
if (exclusionMode == this->mExclusionMode) return;
this->mExclusionMode = exclusionMode;
if (exclusionMode == ExclusionMode::Normal) {
this->shellWindow->setExclusiveZone(this->requestedExclusionZone);
emit this->exclusionZoneChanged();
} else if (exclusionMode == ExclusionMode::Ignore) {
this->shellWindow->setExclusiveZone(-1);
emit this->exclusionZoneChanged();
} else {
this->updateExclusionZone();
}
}
void ProxyShellWindow::setMargins(Margins margins) {
auto lsMargins = QMargins(margins.mLeft, margins.mTop, margins.mRight, margins.mBottom);
this->shellWindow->setMargins(lsMargins);
@ -252,3 +285,24 @@ void ProxyShellWindow::setCloseOnDismissed(bool close) {
}
bool ProxyShellWindow::closeOnDismissed() const { return this->shellWindow->closeOnDismissed(); }
void ProxyShellWindow::updateExclusionZone() {
if (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->shellWindow->setExclusiveZone(zone);
emit this->exclusionZoneChanged();
}
}
}

View file

@ -42,6 +42,25 @@ public:
qint32 mBottom = 0;
};
namespace ExclusionMode { // NOLINT
Q_NAMESPACE;
QML_ELEMENT;
enum Enum {
/// Respect the exclusion zone of other shell layers and optionally set one
Normal = 0,
/// Ignore exclusion zones of other shell layers. You cannot set an exclusion zone in this mode.
Ignore = 1,
/// Decide the exclusion zone based on the window dimensions and anchors.
///
/// Will attempt to reseve exactly enough space for the window and its margins if
/// exactly 3 anchors are connected.
Auto = 2,
};
Q_ENUM_NS(Enum);
} // namespace ExclusionMode
namespace Layer { // NOLINT
Q_NAMESPACE;
QML_ELEMENT;
@ -131,6 +150,8 @@ class ProxyShellWindow: public ProxyWindowBase {
/// > [!INFO] Some systems will require exactly 3 anchors to be attached for the exclusion zone to take
/// > effect.
Q_PROPERTY(qint32 exclusionZone READ exclusiveZone WRITE setExclusiveZone NOTIFY exclusionZoneChanged);
/// Defaults to `ExclusionMode.Normal`.
Q_PROPERTY(ExclusionMode::Enum exclusionMode READ exclusionMode WRITE setExclusionMode NOTIFY exclusionModeChanged);
/// Offsets from the sides of the screen.
///
/// > [!INFO] Only applies to edges with anchors
@ -172,6 +193,9 @@ public:
void setExclusiveZone(qint32 zone);
[[nodiscard]] qint32 exclusiveZone() const;
void setExclusionMode(ExclusionMode::Enum exclusionMode);
[[nodiscard]] ExclusionMode::Enum exclusionMode() const;
void setMargins(Margins margins);
[[nodiscard]] Margins margins() const;
@ -195,12 +219,18 @@ signals:
void anchorsChanged();
void marginsChanged();
void exclusionZoneChanged();
void exclusionModeChanged();
void layerChanged();
void keyboardFocusChanged();
private slots:
void updateExclusionZone();
private:
LayerShellQt::Window* shellWindow = nullptr;
bool anchorsInitialized = false;
ExclusionMode::Enum mExclusionMode = ExclusionMode::Normal;
qint32 requestedExclusionZone = 0;
// needed to ensure size dosent fuck up when changing layershell attachments
// along with setWidth and setHeight overrides