Skip to content

Commit 6464ead

Browse files
committed
core/window: move input mask handling + commit scheduling to polish
1 parent d6b5852 commit 6464ead

File tree

7 files changed

+76
-32
lines changed

7 files changed

+76
-32
lines changed

src/core/region.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <qregion.h>
99
#include <qtmetamacros.h>
1010
#include <qtypes.h>
11+
#include <qvectornd.h>
1112

1213
PendingRegion::PendingRegion(QObject* parent): QObject(parent) {
1314
QObject::connect(this, &PendingRegion::shapeChanged, this, &PendingRegion::changed);
@@ -105,8 +106,19 @@ QRegion PendingRegion::applyTo(QRegion& region) const {
105106
return region;
106107
}
107108

109+
QRegion PendingRegion::applyTo(const QRect& rect) const {
110+
// if left as the default, dont combine it with the whole rect area, leave it as is.
111+
if (this->mIntersection == Intersection::Combine) {
112+
return this->build();
113+
} else {
114+
auto baseRegion = QRegion(rect);
115+
return this->applyTo(baseRegion);
116+
}
117+
}
118+
108119
void PendingRegion::regionsAppend(QQmlListProperty<PendingRegion>* prop, PendingRegion* region) {
109120
auto* self = static_cast<PendingRegion*>(prop->object); // NOLINT
121+
if (!region) return;
110122

111123
QObject::connect(region, &QObject::destroyed, self, &PendingRegion::onChildDestroyed);
112124
QObject::connect(region, &PendingRegion::changed, self, &PendingRegion::childrenChanged);

src/core/region.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class PendingRegion: public QObject {
9696
[[nodiscard]] bool empty() const;
9797
[[nodiscard]] QRegion build() const;
9898
[[nodiscard]] QRegion applyTo(QRegion& region) const;
99+
[[nodiscard]] QRegion applyTo(const QRect& rect) const;
99100

100101
RegionShape::Enum mShape = RegionShape::Rect;
101102
Intersection::Enum mIntersection = Intersection::Combine;
@@ -109,6 +110,11 @@ class PendingRegion: public QObject {
109110
void widthChanged();
110111
void heightChanged();
111112
void childrenChanged();
113+
114+
/// Triggered when the region's geometry changes.
115+
///
116+
/// In some cases the region does not update automatically.
117+
/// In those cases you can emit this signal manually.
112118
void changed();
113119

114120
private slots:

src/wayland/hyprland/surface/qml.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void HyprlandWindow::setOpacity(qreal opacity) {
6262

6363
if (this->surface) {
6464
this->surface->setOpacity(opacity);
65-
qs::wayland::util::scheduleCommit(this->mWaylandWindow);
65+
qs::wayland::util::scheduleCommit(this->proxyWindow);
6666
}
6767

6868
emit this->opacityChanged();
@@ -127,7 +127,7 @@ void HyprlandWindow::onWaylandSurfaceCreated() {
127127

128128
if (this->mOpacity != 1.0) {
129129
this->surface->setOpacity(this->mOpacity);
130-
qs::wayland::util::scheduleCommit(this->mWaylandWindow);
130+
qs::wayland::util::scheduleCommit(this->proxyWindow);
131131
}
132132
}
133133

src/wayland/util.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
#include "util.hpp"
22

3-
#include <private/qwaylandwindow_p.h>
4-
#include <qpa/qwindowsysteminterface.h>
3+
#include "../window/proxywindow.hpp"
54

65
namespace qs::wayland::util {
76

8-
void scheduleCommit(QtWaylandClient::QWaylandWindow* window) {
9-
// This seems to be one of the less offensive ways to force Qt to send a wl_surface.commit on its own terms.
10-
// Ideally we would trigger the commit more directly.
11-
QWindowSystemInterface::handleExposeEvent(
12-
window->window(),
13-
QRect(QPoint(), window->geometry().size())
14-
);
15-
}
7+
void scheduleCommit(ProxyWindowBase* window) { window->schedulePolish(); }
168

179
} // namespace qs::wayland::util

src/wayland/util.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#pragma once
22

3-
#include <private/qwaylandwindow_p.h>
3+
#include "../window/proxywindow.hpp"
44

55
namespace qs::wayland::util {
66

7-
void scheduleCommit(QtWaylandClient::QWaylandWindow* window);
7+
void scheduleCommit(ProxyWindowBase* window);
88

99
}

src/window/proxywindow.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@
2828

2929
ProxyWindowBase::ProxyWindowBase(QObject* parent)
3030
: Reloadable(parent)
31-
, mContentItem(new QQuickItem()) {
31+
, mContentItem(new ProxyWindowContentItem()) {
3232
QQmlEngine::setObjectOwnership(this->mContentItem, QQmlEngine::CppOwnership);
3333
this->mContentItem->setParent(this);
3434

3535
// clang-format off
36+
QObject::connect(this->mContentItem, &ProxyWindowContentItem::polished, this, &ProxyWindowBase::onPolished);
37+
3638
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onWidthChanged);
3739
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onHeightChanged);
3840

39-
QObject::connect(this, &ProxyWindowBase::maskChanged, this, &ProxyWindowBase::onMaskChanged);
4041
QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onMaskChanged);
4142
QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onMaskChanged);
4243

@@ -264,6 +265,12 @@ void ProxyWindowBase::setVisibleDirect(bool visible) {
264265
}
265266
}
266267

268+
void ProxyWindowBase::schedulePolish() {
269+
if (this->isVisibleDirect()) {
270+
this->mContentItem->polish();
271+
}
272+
}
273+
267274
void ProxyWindowBase::polishItems() {
268275
// Due to QTBUG-126704, layouts in invisible windows don't update their dimensions.
269276
// 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) {
385392
this->mMask = mask;
386393

387394
if (mask != nullptr) {
388-
mask->setParent(this);
389395
QObject::connect(mask, &QObject::destroyed, this, &ProxyWindowBase::onMaskDestroyed);
390-
QObject::connect(mask, &PendingRegion::changed, this, &ProxyWindowBase::maskChanged);
396+
QObject::connect(mask, &PendingRegion::changed, this, &ProxyWindowBase::onMaskChanged);
391397
}
392398

399+
this->onMaskChanged();
393400
emit this->maskChanged();
394401
}
395402

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

411418
void ProxyWindowBase::onMaskDestroyed() {
412419
this->mMask = nullptr;
420+
this->onMaskChanged();
413421
emit this->maskChanged();
414422
}
415423

416424
void ProxyWindowBase::updateMask() {
417-
QRegion mask;
418-
if (this->mMask != nullptr) {
419-
// if left as the default, dont combine it with the whole window area, leave it as is.
420-
if (this->mMask->mIntersection == Intersection::Combine) {
421-
mask = this->mMask->build();
422-
} else {
423-
auto windowRegion = QRegion(QRect(0, 0, this->width(), this->height()));
424-
mask = this->mMask->applyTo(windowRegion);
425-
}
426-
}
427-
428-
this->window->setFlag(Qt::WindowTransparentForInput, this->mMask != nullptr && mask.isEmpty());
429-
this->window->setMask(mask);
425+
this->pendingPolish.inputMask = true;
426+
this->schedulePolish();
430427
}
431428

432429
QQmlListProperty<QObject> ProxyWindowBase::data() {
@@ -463,3 +460,21 @@ void ProxiedWindow::exposeEvent(QExposeEvent* event) {
463460
this->QQuickWindow::exposeEvent(event);
464461
emit this->exposed();
465462
}
463+
464+
void ProxyWindowContentItem::updatePolish() { emit this->polished(); }
465+
466+
void ProxyWindowBase::onPolished() {
467+
if (this->pendingPolish.inputMask) {
468+
QRegion mask;
469+
if (this->mMask != nullptr) {
470+
mask = this->mMask->applyTo(QRect(0, 0, this->width(), this->height()));
471+
}
472+
473+
this->window->setFlag(Qt::WindowTransparentForInput, this->mMask != nullptr && mask.isEmpty());
474+
this->window->setMask(mask);
475+
476+
this->pendingPolish.inputMask = false;
477+
}
478+
479+
emit this->polished();
480+
}

src/window/proxywindow.hpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "windowinterface.hpp"
2121

2222
class ProxiedWindow;
23+
class ProxyWindowContentItem;
2324

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

89+
void schedulePolish();
90+
8891
[[nodiscard]] virtual qint32 x() const;
8992
[[nodiscard]] virtual qint32 y() const;
9093

@@ -124,13 +127,15 @@ class ProxyWindowBase: public Reloadable {
124127
void colorChanged();
125128
void maskChanged();
126129
void surfaceFormatChanged();
130+
void polished();
127131

128132
protected slots:
129133
virtual void onWidthChanged();
130134
virtual void onHeightChanged();
131135
void onMaskChanged();
132136
void onMaskDestroyed();
133137
void onScreenDestroyed();
138+
void onPolished();
134139
void runLints();
135140

136141
protected:
@@ -141,12 +146,16 @@ protected slots:
141146
QColor mColor = Qt::white;
142147
PendingRegion* mMask = nullptr;
143148
ProxiedWindow* window = nullptr;
144-
QQuickItem* mContentItem = nullptr;
149+
ProxyWindowContentItem* mContentItem = nullptr;
145150
bool reloadComplete = false;
146151
bool ranLints = false;
147152
QsSurfaceFormat qsSurfaceFormat;
148153
QSurfaceFormat mSurfaceFormat;
149154

155+
struct {
156+
bool inputMask : 1 = false;
157+
} pendingPolish;
158+
150159
private:
151160
void polishItems();
152161
void updateMask();
@@ -190,3 +199,13 @@ class ProxiedWindow: public QQuickWindow {
190199
private:
191200
ProxyWindowBase* mProxy;
192201
};
202+
203+
class ProxyWindowContentItem: public QQuickItem {
204+
Q_OBJECT;
205+
206+
signals:
207+
void polished();
208+
209+
protected:
210+
void updatePolish() override;
211+
};

0 commit comments

Comments
 (0)