core/window: move input mask handling + commit scheduling to polish
This commit is contained in:
parent
d6b58521e9
commit
a0ddc18a5f
6 changed files with 74 additions and 30 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <qregion.h>
|
#include <qregion.h>
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
#include <qtypes.h>
|
#include <qtypes.h>
|
||||||
|
#include <qvectornd.h>
|
||||||
|
|
||||||
PendingRegion::PendingRegion(QObject* parent): QObject(parent) {
|
PendingRegion::PendingRegion(QObject* parent): QObject(parent) {
|
||||||
QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed);
|
QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed);
|
||||||
|
@ -105,8 +106,19 @@ QRegion PendingRegion::applyTo(QRegion& region) const {
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRegion PendingRegion::applyTo(const QRect& rect) const {
|
||||||
|
// if left as the default, dont combine it with the whole rect area, leave it as is.
|
||||||
|
if (this->mIntersection == Intersection::Combine) {
|
||||||
|
return this->build();
|
||||||
|
} else {
|
||||||
|
auto baseRegion = QRegion(rect);
|
||||||
|
return this->applyTo(baseRegion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PendingRegion::regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region) {
|
void PendingRegion::regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region) {
|
||||||
auto* self = static_cast<PendingRegion*>(prop->object); // NOLINT
|
auto* self = static_cast<PendingRegion*>(prop->object); // NOLINT
|
||||||
|
if (!region) return;
|
||||||
|
|
||||||
QObject::connect(region, &QObject::destroyed, self, &PendingRegion::onChildDestroyed);
|
QObject::connect(region, &QObject::destroyed, self, &PendingRegion::onChildDestroyed);
|
||||||
QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged);
|
QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged);
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
[[nodiscard]] bool empty() const;
|
[[nodiscard]] bool empty() const;
|
||||||
[[nodiscard]] QRegion build() const;
|
[[nodiscard]] QRegion build() const;
|
||||||
[[nodiscard]] QRegion applyTo(QRegion& region) const;
|
[[nodiscard]] QRegion applyTo(QRegion& region) const;
|
||||||
|
[[nodiscard]] QRegion applyTo(const QRect& rect) const;
|
||||||
|
|
||||||
RegionShape::Enum mShape = RegionShape::Rect;
|
RegionShape::Enum mShape = RegionShape::Rect;
|
||||||
Intersection::Enum mIntersection = Intersection::Combine;
|
Intersection::Enum mIntersection = Intersection::Combine;
|
||||||
|
@ -109,6 +110,11 @@ signals:
|
||||||
void widthChanged();
|
void widthChanged();
|
||||||
void heightChanged();
|
void heightChanged();
|
||||||
void childrenChanged();
|
void childrenChanged();
|
||||||
|
|
||||||
|
/// Triggered when the region's geometry changes.
|
||||||
|
///
|
||||||
|
/// In some cases the region does not update automatically.
|
||||||
|
/// In those cases you can emit this signal manually.
|
||||||
void changed();
|
void changed();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
#include <private/qwaylandwindow_p.h>
|
#include "../window/proxywindow.hpp"
|
||||||
#include <qpa/qwindowsysteminterface.h>
|
|
||||||
|
|
||||||
namespace qs::wayland::util {
|
namespace qs::wayland::util {
|
||||||
|
|
||||||
void scheduleCommit(QtWaylandClient::QWaylandWindow* window) {
|
void scheduleCommit(ProxyWindowBase* window) { window->schedulePolish(); }
|
||||||
// This seems to be one of the less offensive ways to force Qt to send a wl_surface.commit on its own terms.
|
|
||||||
// Ideally we would trigger the commit more directly.
|
|
||||||
QWindowSystemInterface::handleExposeEvent(
|
|
||||||
window->window(),
|
|
||||||
QRect(QPoint(), window->geometry().size())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace qs::wayland::util
|
} // namespace qs::wayland::util
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <private/qwaylandwindow_p.h>
|
#include "../window/proxywindow.hpp"
|
||||||
|
|
||||||
namespace qs::wayland::util {
|
namespace qs::wayland::util {
|
||||||
|
|
||||||
void scheduleCommit(QtWaylandClient::QWaylandWindow* window);
|
void scheduleCommit(ProxyWindowBase* window);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,15 +28,16 @@
|
||||||
|
|
||||||
ProxyWindowBase::ProxyWindowBase(QObject* parent)
|
ProxyWindowBase::ProxyWindowBase(QObject* parent)
|
||||||
: Reloadable(parent)
|
: Reloadable(parent)
|
||||||
, mContentItem(new QQuickItem()) {
|
, mContentItem(new ProxyWindowContentItem()) {
|
||||||
QQmlEngine::setObjectOwnership(this->mContentItem, QQmlEngine::CppOwnership);
|
QQmlEngine::setObjectOwnership(this->mContentItem, QQmlEngine::CppOwnership);
|
||||||
this->mContentItem->setParent(this);
|
this->mContentItem->setParent(this);
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
QObject::connect(this->mContentItem, &ProxyWindowContentItem::polished, this, &ProxyWindowBase::onPolished);
|
||||||
|
|
||||||
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onWidthChanged);
|
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onWidthChanged);
|
||||||
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onHeightChanged);
|
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onHeightChanged);
|
||||||
|
|
||||||
QObject::connect(this, &ProxyWindowBase::maskChanged, this, &ProxyWindowBase::onMaskChanged);
|
|
||||||
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onMaskChanged);
|
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onMaskChanged);
|
||||||
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onMaskChanged);
|
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onMaskChanged);
|
||||||
|
|
||||||
|
@ -264,6 +265,12 @@ void ProxyWindowBase::setVisibleDirect(bool visible) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProxyWindowBase::schedulePolish() {
|
||||||
|
if (this->isVisibleDirect()) {
|
||||||
|
this->mContentItem->polish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProxyWindowBase::polishItems() {
|
void ProxyWindowBase::polishItems() {
|
||||||
// Due to QTBUG-126704, layouts in invisible windows don't update their dimensions.
|
// Due to QTBUG-126704, layouts in invisible windows don't update their dimensions.
|
||||||
// Usually this isn't an issue, but it is when the size of a window is based on the size
|
// Usually this isn't an issue, but it is when the size of a window is based on the size
|
||||||
|
@ -385,11 +392,11 @@ void ProxyWindowBase::setMask(PendingRegion* mask) {
|
||||||
this->mMask = mask;
|
this->mMask = mask;
|
||||||
|
|
||||||
if (mask != nullptr) {
|
if (mask != nullptr) {
|
||||||
mask->setParent(this);
|
|
||||||
QObject::connect(mask, &QObject::destroyed, this, &ProxyWindowBase::onMaskDestroyed);
|
QObject::connect(mask, &QObject::destroyed, this, &ProxyWindowBase::onMaskDestroyed);
|
||||||
QObject::connect(mask, &PendingRegion::changed, this, &ProxyWindowBase::maskChanged);
|
QObject::connect(mask, &PendingRegion::changed, this, &ProxyWindowBase::onMaskChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->onMaskChanged();
|
||||||
emit this->maskChanged();
|
emit this->maskChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,23 +417,13 @@ void ProxyWindowBase::onMaskChanged() {
|
||||||
|
|
||||||
void ProxyWindowBase::onMaskDestroyed() {
|
void ProxyWindowBase::onMaskDestroyed() {
|
||||||
this->mMask = nullptr;
|
this->mMask = nullptr;
|
||||||
|
this->onMaskChanged();
|
||||||
emit this->maskChanged();
|
emit this->maskChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyWindowBase::updateMask() {
|
void ProxyWindowBase::updateMask() {
|
||||||
QRegion mask;
|
this->pendingPolish.inputMask = true;
|
||||||
if (this->mMask != nullptr) {
|
this->schedulePolish();
|
||||||
// if left as the default, dont combine it with the whole window area, leave it as is.
|
|
||||||
if (this->mMask->mIntersection == Intersection::Combine) {
|
|
||||||
mask = this->mMask->build();
|
|
||||||
} else {
|
|
||||||
auto windowRegion = QRegion(QRect(0, 0, this->width(), this->height()));
|
|
||||||
mask = this->mMask->applyTo(windowRegion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->window->setFlag(Qt::WindowTransparentForInput, this->mMask != nullptr && mask.isEmpty());
|
|
||||||
this->window->setMask(mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlListProperty<QObject> ProxyWindowBase::data() {
|
QQmlListProperty<QObject> ProxyWindowBase::data() {
|
||||||
|
@ -463,3 +460,21 @@ void ProxiedWindow::exposeEvent(QExposeEvent* event) {
|
||||||
this->QQuickWindow::exposeEvent(event);
|
this->QQuickWindow::exposeEvent(event);
|
||||||
emit this->exposed();
|
emit this->exposed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProxyWindowContentItem::updatePolish() { emit this->polished(); }
|
||||||
|
|
||||||
|
void ProxyWindowBase::onPolished() {
|
||||||
|
if (this->pendingPolish.inputMask) {
|
||||||
|
QRegion mask;
|
||||||
|
if (this->mMask != nullptr) {
|
||||||
|
mask = this->mMask->applyTo(QRect(0, 0, this->width(), this->height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->window->setFlag(Qt::WindowTransparentForInput, this->mMask != nullptr && mask.isEmpty());
|
||||||
|
this->window->setMask(mask);
|
||||||
|
|
||||||
|
this->pendingPolish.inputMask = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit this->polished();
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "windowinterface.hpp"
|
#include "windowinterface.hpp"
|
||||||
|
|
||||||
class ProxiedWindow;
|
class ProxiedWindow;
|
||||||
|
class ProxyWindowContentItem;
|
||||||
|
|
||||||
// Proxy to an actual window exposing a limited property set with the ability to
|
// Proxy to an actual window exposing a limited property set with the ability to
|
||||||
// transfer it to a new window.
|
// transfer it to a new window.
|
||||||
|
@ -85,6 +86,8 @@ public:
|
||||||
virtual void setVisible(bool visible);
|
virtual void setVisible(bool visible);
|
||||||
virtual void setVisibleDirect(bool visible);
|
virtual void setVisibleDirect(bool visible);
|
||||||
|
|
||||||
|
void schedulePolish();
|
||||||
|
|
||||||
[[nodiscard]] virtual qint32 x() const;
|
[[nodiscard]] virtual qint32 x() const;
|
||||||
[[nodiscard]] virtual qint32 y() const;
|
[[nodiscard]] virtual qint32 y() const;
|
||||||
|
|
||||||
|
@ -124,6 +127,7 @@ signals:
|
||||||
void colorChanged();
|
void colorChanged();
|
||||||
void maskChanged();
|
void maskChanged();
|
||||||
void surfaceFormatChanged();
|
void surfaceFormatChanged();
|
||||||
|
void polished();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
virtual void onWidthChanged();
|
virtual void onWidthChanged();
|
||||||
|
@ -131,6 +135,7 @@ protected slots:
|
||||||
void onMaskChanged();
|
void onMaskChanged();
|
||||||
void onMaskDestroyed();
|
void onMaskDestroyed();
|
||||||
void onScreenDestroyed();
|
void onScreenDestroyed();
|
||||||
|
void onPolished();
|
||||||
void runLints();
|
void runLints();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -141,12 +146,16 @@ protected:
|
||||||
QColor mColor = Qt::white;
|
QColor mColor = Qt::white;
|
||||||
PendingRegion* mMask = nullptr;
|
PendingRegion* mMask = nullptr;
|
||||||
ProxiedWindow* window = nullptr;
|
ProxiedWindow* window = nullptr;
|
||||||
QQuickItem* mContentItem = nullptr;
|
ProxyWindowContentItem* mContentItem = nullptr;
|
||||||
bool reloadComplete = false;
|
bool reloadComplete = false;
|
||||||
bool ranLints = false;
|
bool ranLints = false;
|
||||||
QsSurfaceFormat qsSurfaceFormat;
|
QsSurfaceFormat qsSurfaceFormat;
|
||||||
QSurfaceFormat mSurfaceFormat;
|
QSurfaceFormat mSurfaceFormat;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool inputMask : 1 = false;
|
||||||
|
} pendingPolish;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void polishItems();
|
void polishItems();
|
||||||
void updateMask();
|
void updateMask();
|
||||||
|
@ -190,3 +199,13 @@ protected:
|
||||||
private:
|
private:
|
||||||
ProxyWindowBase* mProxy;
|
ProxyWindowBase* mProxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ProxyWindowContentItem: public QQuickItem {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void polished();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void updatePolish() override;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue