mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-04-10 06:11:54 +10:00
254 lines
7.4 KiB
C++
254 lines
7.4 KiB
C++
#include "floatingwindow.hpp"
|
|
|
|
#include <qnamespace.h>
|
|
#include <qobject.h>
|
|
#include <qqmlengine.h>
|
|
#include <qqmlinfo.h>
|
|
#include <qtmetamacros.h>
|
|
#include <qtypes.h>
|
|
#include <qwindow.h>
|
|
|
|
#include "proxywindow.hpp"
|
|
#include "windowinterface.hpp"
|
|
|
|
ProxyFloatingWindow::ProxyFloatingWindow(QObject* parent): ProxyWindowBase(parent) {
|
|
this->bTargetVisible.setBinding([this] {
|
|
if (!this->bWantsVisible) return false;
|
|
auto* parent = this->bParentProxyWindow.value();
|
|
if (!parent) return true;
|
|
return parent->bindableBackerVisibility().value();
|
|
});
|
|
}
|
|
|
|
void ProxyFloatingWindow::targetVisibleChanged() {
|
|
if (this->window && this->bParentProxyWindow) {
|
|
auto* bw = this->bParentProxyWindow.value()->backingWindow();
|
|
|
|
if (bw != this->window->transientParent()) {
|
|
this->window->setTransientParent(bw);
|
|
}
|
|
}
|
|
|
|
this->ProxyWindowBase::setVisible(this->bTargetVisible);
|
|
}
|
|
|
|
void ProxyFloatingWindow::connectWindow() {
|
|
this->ProxyWindowBase::connectWindow();
|
|
|
|
this->window->setTitle(this->bTitle);
|
|
this->window->setMinimumSize(this->bMinimumSize);
|
|
this->window->setMaximumSize(this->bMaximumSize);
|
|
}
|
|
|
|
void ProxyFloatingWindow::completeWindow() {
|
|
this->ProxyWindowBase::completeWindow();
|
|
|
|
auto* parent = this->bParentProxyWindow.value();
|
|
this->window->setTransientParent(parent ? parent->backingWindow() : nullptr);
|
|
}
|
|
|
|
void ProxyFloatingWindow::postCompleteWindow() {
|
|
this->ProxyWindowBase::setVisible(this->bTargetVisible);
|
|
}
|
|
|
|
void ProxyFloatingWindow::onParentDestroyed() {
|
|
this->mParentWindow = nullptr;
|
|
this->bParentProxyWindow = nullptr;
|
|
emit this->parentWindowChanged();
|
|
}
|
|
|
|
void ProxyFloatingWindow::setVisible(bool visible) { this->bWantsVisible = visible; }
|
|
|
|
void ProxyFloatingWindow::trySetWidth(qint32 implicitWidth) {
|
|
if (!this->window->isVisible()) {
|
|
this->ProxyWindowBase::trySetWidth(implicitWidth);
|
|
}
|
|
}
|
|
|
|
void ProxyFloatingWindow::trySetHeight(qint32 implicitHeight) {
|
|
if (!this->window->isVisible()) {
|
|
this->ProxyWindowBase::trySetHeight(implicitHeight);
|
|
}
|
|
}
|
|
|
|
void ProxyFloatingWindow::onTitleChanged() {
|
|
if (this->window) this->window->setTitle(this->bTitle);
|
|
emit this->titleChanged();
|
|
}
|
|
|
|
void ProxyFloatingWindow::onMinimumSizeChanged() {
|
|
if (this->window) this->window->setMinimumSize(this->bMinimumSize);
|
|
emit this->minimumSizeChanged();
|
|
}
|
|
|
|
void ProxyFloatingWindow::onMaximumSizeChanged() {
|
|
if (this->window) this->window->setMaximumSize(this->bMaximumSize);
|
|
emit this->maximumSizeChanged();
|
|
}
|
|
|
|
QObject* ProxyFloatingWindow::parentWindow() const { return this->mParentWindow; }
|
|
|
|
void ProxyFloatingWindow::setParentWindow(QObject* window) {
|
|
if (window == this->mParentWindow) return;
|
|
|
|
if (this->window && this->window->isVisible()) {
|
|
qmlWarning(this) << "parentWindow cannot be changed after the window is visible.";
|
|
return;
|
|
}
|
|
|
|
if (this->bParentProxyWindow) {
|
|
QObject::disconnect(this->bParentProxyWindow, nullptr, this, nullptr);
|
|
}
|
|
|
|
if (this->mParentWindow) {
|
|
QObject::disconnect(this->mParentWindow, nullptr, this, nullptr);
|
|
}
|
|
|
|
this->mParentWindow = nullptr;
|
|
this->bParentProxyWindow = nullptr;
|
|
|
|
if (auto* proxy = ProxyWindowBase::forObject(window)) {
|
|
this->mParentWindow = window;
|
|
this->bParentProxyWindow = proxy;
|
|
|
|
QObject::connect(
|
|
this->mParentWindow,
|
|
&QObject::destroyed,
|
|
this,
|
|
&ProxyFloatingWindow::onParentDestroyed
|
|
);
|
|
}
|
|
|
|
emit this->parentWindowChanged();
|
|
}
|
|
|
|
// FloatingWindowInterface
|
|
|
|
FloatingWindowInterface::FloatingWindowInterface(QObject* parent)
|
|
: WindowInterface(parent)
|
|
, window(new ProxyFloatingWindow(this)) {
|
|
this->connectSignals();
|
|
|
|
// clang-format off
|
|
QObject::connect(this->window, &ProxyFloatingWindow::titleChanged, this, &FloatingWindowInterface::titleChanged);
|
|
QObject::connect(this->window, &ProxyFloatingWindow::minimumSizeChanged, this, &FloatingWindowInterface::minimumSizeChanged);
|
|
QObject::connect(this->window, &ProxyFloatingWindow::maximumSizeChanged, this, &FloatingWindowInterface::maximumSizeChanged);
|
|
QObject::connect(this->window, &ProxyFloatingWindow::parentWindowChanged, this, &FloatingWindowInterface::parentWindowChanged);
|
|
QObject::connect(this->window, &ProxyWindowBase::windowConnected, this, &FloatingWindowInterface::onWindowConnected);
|
|
// clang-format on
|
|
}
|
|
|
|
void FloatingWindowInterface::onReload(QObject* oldInstance) {
|
|
QQmlEngine::setContextForObject(this->window, QQmlEngine::contextForObject(this));
|
|
|
|
auto* old = qobject_cast<FloatingWindowInterface*>(oldInstance);
|
|
this->window->reload(old != nullptr ? old->window : nullptr);
|
|
}
|
|
|
|
ProxyWindowBase* FloatingWindowInterface::proxyWindow() const { return this->window; }
|
|
|
|
void FloatingWindowInterface::onWindowConnected() {
|
|
auto* qw = this->window->backingWindow();
|
|
if (qw) {
|
|
QObject::connect(
|
|
qw,
|
|
&QWindow::windowStateChanged,
|
|
this,
|
|
&FloatingWindowInterface::onWindowStateChanged
|
|
);
|
|
this->setMinimized(this->mMinimized);
|
|
this->setMaximized(this->mMaximized);
|
|
this->setFullscreen(this->mFullscreen);
|
|
this->onWindowStateChanged();
|
|
}
|
|
}
|
|
|
|
void FloatingWindowInterface::onWindowStateChanged() {
|
|
auto* qw = this->window->backingWindow();
|
|
auto states = qw ? qw->windowStates() : Qt::WindowStates();
|
|
|
|
auto minimized = states.testFlag(Qt::WindowMinimized);
|
|
auto maximized = states.testFlag(Qt::WindowMaximized);
|
|
auto fullscreen = states.testFlag(Qt::WindowFullScreen);
|
|
|
|
if (minimized != this->mWasMinimized) {
|
|
this->mWasMinimized = minimized;
|
|
emit this->minimizedChanged();
|
|
}
|
|
|
|
if (maximized != this->mWasMaximized) {
|
|
this->mWasMaximized = maximized;
|
|
emit this->maximizedChanged();
|
|
}
|
|
|
|
if (fullscreen != this->mWasFullscreen) {
|
|
this->mWasFullscreen = fullscreen;
|
|
emit this->fullscreenChanged();
|
|
}
|
|
}
|
|
|
|
bool FloatingWindowInterface::isMinimized() const {
|
|
auto* qw = this->window->backingWindow();
|
|
if (!qw) return this->mWasMinimized;
|
|
return qw->windowStates().testFlag(Qt::WindowMinimized);
|
|
}
|
|
|
|
void FloatingWindowInterface::setMinimized(bool minimized) {
|
|
this->mMinimized = minimized;
|
|
|
|
if (auto* qw = this->window->backingWindow()) {
|
|
auto states = qw->windowStates();
|
|
states.setFlag(Qt::WindowMinimized, minimized);
|
|
qw->setWindowStates(states);
|
|
}
|
|
}
|
|
|
|
bool FloatingWindowInterface::isMaximized() const {
|
|
auto* qw = this->window->backingWindow();
|
|
if (!qw) return this->mWasMaximized;
|
|
return qw->windowStates().testFlag(Qt::WindowMaximized);
|
|
}
|
|
|
|
void FloatingWindowInterface::setMaximized(bool maximized) {
|
|
this->mMaximized = maximized;
|
|
|
|
if (auto* qw = this->window->backingWindow()) {
|
|
auto states = qw->windowStates();
|
|
states.setFlag(Qt::WindowMaximized, maximized);
|
|
qw->setWindowStates(states);
|
|
}
|
|
}
|
|
|
|
bool FloatingWindowInterface::isFullscreen() const {
|
|
auto* qw = this->window->backingWindow();
|
|
if (!qw) return this->mWasFullscreen;
|
|
return qw->windowStates().testFlag(Qt::WindowFullScreen);
|
|
}
|
|
|
|
void FloatingWindowInterface::setFullscreen(bool fullscreen) {
|
|
this->mFullscreen = fullscreen;
|
|
|
|
if (auto* qw = this->window->backingWindow()) {
|
|
auto states = qw->windowStates();
|
|
states.setFlag(Qt::WindowFullScreen, fullscreen);
|
|
qw->setWindowStates(states);
|
|
}
|
|
}
|
|
|
|
bool FloatingWindowInterface::startSystemMove() const {
|
|
auto* qw = this->window->backingWindow();
|
|
if (!qw) return false;
|
|
return qw->startSystemMove();
|
|
}
|
|
|
|
bool FloatingWindowInterface::startSystemResize(Qt::Edges edges) const {
|
|
auto* qw = this->window->backingWindow();
|
|
if (!qw) return false;
|
|
return qw->startSystemResize(edges);
|
|
}
|
|
|
|
QObject* FloatingWindowInterface::parentWindow() const { return this->window->parentWindow(); }
|
|
|
|
void FloatingWindowInterface::setParentWindow(QObject* window) {
|
|
this->window->setParentWindow(window);
|
|
}
|