Skip to content

Commit

Permalink
core/window: move input mask handling + commit scheduling to polish
Browse files Browse the repository at this point in the history
  • Loading branch information
outfoxxed committed Jan 20, 2025
1 parent d6b5852 commit 6464ead
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 32 deletions.
12 changes: 12 additions & 0 deletions src/core/region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <qregion.h>
#include <qtmetamacros.h>
#include <qtypes.h>
#include <qvectornd.h>

PendingRegion::PendingRegion(QObject* parent): QObject(parent) {
QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed);
Expand Down Expand Up @@ -105,8 +106,19 @@ QRegion PendingRegion::applyTo(QRegion& region) const {
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) {
auto* self = static_cast<PendingRegion*>(prop->object); // NOLINT
if (!region) return;

QObject::connect(region, &QObject::destroyed, self, &PendingRegion::onChildDestroyed);
QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged);
Expand Down
6 changes: 6 additions & 0 deletions src/core/region.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class PendingRegion: public QObject {
[[nodiscard]] bool empty() const;
[[nodiscard]] QRegion build() const;
[[nodiscard]] QRegion applyTo(QRegion& region) const;
[[nodiscard]] QRegion applyTo(const QRect& rect) const;

RegionShape::Enum mShape = RegionShape::Rect;
Intersection::Enum mIntersection = Intersection::Combine;
Expand All @@ -109,6 +110,11 @@ class PendingRegion: public QObject {
void widthChanged();
void heightChanged();
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();

private slots:
Expand Down
4 changes: 2 additions & 2 deletions src/wayland/hyprland/surface/qml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void HyprlandWindow::setOpacity(qreal opacity) {

if (this->surface) {
this->surface->setOpacity(opacity);
qs::wayland::util::scheduleCommit(this->mWaylandWindow);
qs::wayland::util::scheduleCommit(this->proxyWindow);
}

emit this->opacityChanged();
Expand Down Expand Up @@ -127,7 +127,7 @@ void HyprlandWindow::onWaylandSurfaceCreated() {

if (this->mOpacity != 1.0) {
this->surface->setOpacity(this->mOpacity);
qs::wayland::util::scheduleCommit(this->mWaylandWindow);
qs::wayland::util::scheduleCommit(this->proxyWindow);
}
}

Expand Down
12 changes: 2 additions & 10 deletions src/wayland/util.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
#include "util.hpp"

#include <private/qwaylandwindow_p.h>
#include <qpa/qwindowsysteminterface.h>
#include "../window/proxywindow.hpp"

namespace qs::wayland::util {

void scheduleCommit(QtWaylandClient::QWaylandWindow* window) {
// 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())
);
}
void scheduleCommit(ProxyWindowBase* window) { window->schedulePolish(); }

} // namespace qs::wayland::util
4 changes: 2 additions & 2 deletions src/wayland/util.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

#include <private/qwaylandwindow_p.h>
#include "../window/proxywindow.hpp"

namespace qs::wayland::util {

void scheduleCommit(QtWaylandClient::QWaylandWindow* window);
void scheduleCommit(ProxyWindowBase* window);

}
49 changes: 32 additions & 17 deletions src/window/proxywindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@

ProxyWindowBase::ProxyWindowBase(QObject* parent)
: Reloadable(parent)
, mContentItem(new QQuickItem()) {
, mContentItem(new ProxyWindowContentItem()) {
QQmlEngine::setObjectOwnership(this->mContentItem, QQmlEngine::CppOwnership);
this->mContentItem->setParent(this);

// clang-format off
QObject::connect(this->mContentItem, &ProxyWindowContentItem::polished, this, &ProxyWindowBase::onPolished);

QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onWidthChanged);
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::heightChanged, this, &ProxyWindowBase::onMaskChanged);

Expand Down Expand Up @@ -264,6 +265,12 @@ void ProxyWindowBase::setVisibleDirect(bool visible) {
}
}

void ProxyWindowBase::schedulePolish() {
if (this->isVisibleDirect()) {
this->mContentItem->polish();
}
}

void ProxyWindowBase::polishItems() {
// 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
Expand Down Expand Up @@ -385,11 +392,11 @@ void ProxyWindowBase::setMask(PendingRegion* mask) {
this->mMask = mask;

if (mask != nullptr) {
mask->setParent(this);
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();
}

Expand All @@ -410,23 +417,13 @@ void ProxyWindowBase::onMaskChanged() {

void ProxyWindowBase::onMaskDestroyed() {
this->mMask = nullptr;
this->onMaskChanged();
emit this->maskChanged();
}

void ProxyWindowBase::updateMask() {
QRegion mask;
if (this->mMask != nullptr) {
// 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);
this->pendingPolish.inputMask = true;
this->schedulePolish();
}

QQmlListProperty<QObject> ProxyWindowBase::data() {
Expand Down Expand Up @@ -463,3 +460,21 @@ void ProxiedWindow::exposeEvent(QExposeEvent* event) {
this->QQuickWindow::exposeEvent(event);
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();
}
21 changes: 20 additions & 1 deletion src/window/proxywindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "windowinterface.hpp"

class ProxiedWindow;
class ProxyWindowContentItem;

// Proxy to an actual window exposing a limited property set with the ability to
// transfer it to a new window.
Expand Down Expand Up @@ -85,6 +86,8 @@ class ProxyWindowBase: public Reloadable {
virtual void setVisible(bool visible);
virtual void setVisibleDirect(bool visible);

void schedulePolish();

[[nodiscard]] virtual qint32 x() const;
[[nodiscard]] virtual qint32 y() const;

Expand Down Expand Up @@ -124,13 +127,15 @@ class ProxyWindowBase: public Reloadable {
void colorChanged();
void maskChanged();
void surfaceFormatChanged();
void polished();

protected slots:
virtual void onWidthChanged();
virtual void onHeightChanged();
void onMaskChanged();
void onMaskDestroyed();
void onScreenDestroyed();
void onPolished();
void runLints();

protected:
Expand All @@ -141,12 +146,16 @@ protected slots:
QColor mColor = Qt::white;
PendingRegion* mMask = nullptr;
ProxiedWindow* window = nullptr;
QQuickItem* mContentItem = nullptr;
ProxyWindowContentItem* mContentItem = nullptr;
bool reloadComplete = false;
bool ranLints = false;
QsSurfaceFormat qsSurfaceFormat;
QSurfaceFormat mSurfaceFormat;

struct {
bool inputMask : 1 = false;
} pendingPolish;

private:
void polishItems();
void updateMask();
Expand Down Expand Up @@ -190,3 +199,13 @@ class ProxiedWindow: public QQuickWindow {
private:
ProxyWindowBase* mProxy;
};

class ProxyWindowContentItem: public QQuickItem {
Q_OBJECT;

signals:
void polished();

protected:
void updatePolish() override;
};

0 comments on commit 6464ead

Please sign in to comment.