Skip to content

Commit 27f97c3

Browse files
committed
wayland/toplevel: refactor toplevel output tracking to its own file
1 parent 20c3da0 commit 27f97c3

File tree

6 files changed

+119
-82
lines changed

6 files changed

+119
-82
lines changed

src/wayland/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ qt_add_library(quickshell-wayland STATIC
7777
popupanchor.cpp
7878
xdgshell.cpp
7979
util.cpp
80+
output_tracking.cpp
8081
)
8182

8283
# required to make sure the constructor is linked

src/wayland/output_tracking.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include "output_tracking.hpp"
2+
3+
#include <private/qwaylanddisplay_p.h>
4+
#include <private/qwaylandintegration_p.h>
5+
#include <private/qwaylandscreen_p.h>
6+
#include <qguiapplication.h>
7+
#include <qnamespace.h>
8+
#include <qobject.h>
9+
#include <qscreen.h>
10+
#include <qtmetamacros.h>
11+
12+
namespace qs::wayland {
13+
14+
void WlOutputTracker::addOutput(::wl_output* output) {
15+
auto* display = QtWaylandClient::QWaylandIntegration::instance()->display();
16+
17+
if (auto* platformScreen = display->screenForOutput(output)) {
18+
auto* screen = platformScreen->screen();
19+
this->mScreens.append(screen);
20+
emit this->screenAdded(screen);
21+
} else {
22+
QObject::connect(
23+
static_cast<QGuiApplication*>(QGuiApplication::instance()), // NOLINT
24+
&QGuiApplication::screenAdded,
25+
this,
26+
&WlOutputTracker::onQScreenAdded,
27+
Qt::UniqueConnection
28+
);
29+
30+
this->mOutputs.append(output);
31+
}
32+
}
33+
34+
void WlOutputTracker::removeOutput(::wl_output* output) {
35+
auto* display = QtWaylandClient::QWaylandIntegration::instance()->display();
36+
37+
if (auto* platformScreen = display->screenForOutput(output)) {
38+
auto* screen = platformScreen->screen();
39+
this->mScreens.removeOne(screen);
40+
emit this->screenRemoved(screen);
41+
} else {
42+
this->mOutputs.removeOne(output);
43+
44+
if (this->mOutputs.isEmpty()) {
45+
QObject::disconnect(
46+
static_cast<QGuiApplication*>(QGuiApplication::instance()), // NOLINT
47+
nullptr,
48+
this,
49+
nullptr
50+
);
51+
}
52+
}
53+
}
54+
55+
void WlOutputTracker::onQScreenAdded(QScreen* screen) {
56+
if (auto* platformScreen = dynamic_cast<QtWaylandClient::QWaylandScreen*>(screen->handle())) {
57+
if (this->mOutputs.removeOne(platformScreen->output())) {
58+
this->mScreens.append(screen);
59+
emit this->screenAdded(screen);
60+
61+
if (this->mOutputs.isEmpty()) {
62+
QObject::disconnect(
63+
static_cast<QGuiApplication*>(QGuiApplication::instance()), // NOLINT
64+
nullptr,
65+
this,
66+
nullptr
67+
);
68+
}
69+
}
70+
}
71+
}
72+
73+
} // namespace qs::wayland

src/wayland/output_tracking.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <qlist.h>
4+
#include <qobject.h>
5+
#include <qscreen.h>
6+
#include <qtmetamacros.h>
7+
8+
struct wl_output;
9+
10+
namespace qs::wayland {
11+
12+
class WlOutputTracker: public QObject {
13+
Q_OBJECT;
14+
15+
public:
16+
[[nodiscard]] const QList<QScreen*>& screens() const { return this->mScreens; }
17+
18+
signals:
19+
void screenAdded(QScreen* screen);
20+
void screenRemoved(QScreen* screen);
21+
22+
public slots:
23+
void addOutput(::wl_output* output);
24+
void removeOutput(::wl_output* output);
25+
26+
private slots:
27+
void onQScreenAdded(QScreen* screen);
28+
29+
private:
30+
QList<QScreen*> mScreens;
31+
QList<::wl_output*> mOutputs;
32+
};
33+
34+
} // namespace qs::wayland

src/wayland/toplevel_management/handle.cpp

Lines changed: 4 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ namespace qs::wayland::toplevel_management::impl {
2323

2424
QString ToplevelHandle::appId() const { return this->mAppId; }
2525
QString ToplevelHandle::title() const { return this->mTitle; }
26-
QVector<QScreen*> ToplevelHandle::visibleScreens() const { return this->mVisibleScreens; }
2726
ToplevelHandle* ToplevelHandle::parent() const { return this->mParent; }
2827
bool ToplevelHandle::activated() const { return this->mActivated; }
2928
bool ToplevelHandle::maximized() const { return this->mMaximized; }
@@ -181,59 +180,13 @@ void ToplevelHandle::zwlr_foreign_toplevel_handle_v1_state(wl_array* stateArray)
181180
}
182181

183182
void ToplevelHandle::zwlr_foreign_toplevel_handle_v1_output_enter(wl_output* output) {
184-
auto* display = QtWaylandClient::QWaylandIntegration::instance()->display();
185-
186-
auto* platformScreen = display->screenForOutput(output);
187-
if (!platformScreen) {
188-
qCDebug(logToplevelManagement) << this << "got pending output enter" << output;
189-
190-
if (this->mPendingVisibleScreens.isEmpty()) {
191-
QObject::connect(
192-
static_cast<QGuiApplication*>(QGuiApplication::instance()), // NOLINT
193-
&QGuiApplication::screenAdded,
194-
this,
195-
&ToplevelHandle::onScreenAdded
196-
);
197-
}
198-
199-
this->mPendingVisibleScreens.append(output);
200-
return;
201-
}
202-
203-
auto* screen = platformScreen->screen();
204-
205-
qCDebug(logToplevelManagement) << this << "got output enter" << screen;
206-
207-
this->mVisibleScreens.append(screen);
208-
emit this->visibleScreenAdded(screen);
183+
qCDebug(logToplevelManagement) << this << "got output enter" << output;
184+
this->visibleScreens.addOutput(output);
209185
}
210186

211187
void ToplevelHandle::zwlr_foreign_toplevel_handle_v1_output_leave(wl_output* output) {
212-
auto* display = QtWaylandClient::QWaylandIntegration::instance()->display();
213-
auto* platformScreen = display->screenForOutput(output);
214-
215-
if (!this->mPendingVisibleScreens.isEmpty()) {
216-
this->mPendingVisibleScreens.removeOne(output);
217-
218-
if (this->mPendingVisibleScreens.isEmpty()) {
219-
qCDebug(logToplevelManagement) << this << "got pending output leave" << output;
220-
221-
QObject::disconnect(
222-
static_cast<QGuiApplication*>(QGuiApplication::instance()), // NOLINT
223-
nullptr,
224-
this,
225-
nullptr
226-
);
227-
}
228-
}
229-
230-
if (!platformScreen) return;
231-
auto* screen = platformScreen->screen();
232-
233-
qCDebug(logToplevelManagement) << this << "got output leave" << screen;
234-
235-
this->mVisibleScreens.removeOne(screen);
236-
emit this->visibleScreenRemoved(screen);
188+
qCDebug(logToplevelManagement) << this << "got output leave" << output;
189+
this->visibleScreens.removeOutput(output);
237190
}
238191

239192
void ToplevelHandle::zwlr_foreign_toplevel_handle_v1_parent(
@@ -262,26 +215,4 @@ void ToplevelHandle::onParentClosed() {
262215
emit this->parentChanged();
263216
}
264217

265-
void ToplevelHandle::onScreenAdded(QScreen* screen) {
266-
auto* waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen*>(screen->handle());
267-
if (!waylandScreen) return;
268-
269-
auto* output = waylandScreen->output();
270-
271-
if (this->mPendingVisibleScreens.removeOne(output)) {
272-
qCDebug(logToplevelManagement) << this << "got pending entered output init" << screen;
273-
this->mVisibleScreens.append(screen);
274-
emit this->visibleScreenAdded(screen);
275-
}
276-
277-
if (this->mPendingVisibleScreens.isEmpty()) {
278-
QObject::disconnect(
279-
static_cast<QGuiApplication*>(QGuiApplication::instance()), // NOLINT
280-
nullptr,
281-
this,
282-
nullptr
283-
);
284-
}
285-
}
286-
287218
} // namespace qs::wayland::toplevel_management::impl

src/wayland/toplevel_management/handle.hpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <qwayland-wlr-foreign-toplevel-management-unstable-v1.h>
77
#include <qwindow.h>
88

9+
#include "../output_tracking.hpp"
910
#include "wayland-wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
1011

1112
namespace qs::wayland::toplevel_management::impl {
@@ -18,7 +19,6 @@ class ToplevelHandle
1819
public:
1920
[[nodiscard]] QString appId() const;
2021
[[nodiscard]] QString title() const;
21-
[[nodiscard]] QVector<QScreen*> visibleScreens() const;
2222
[[nodiscard]] ToplevelHandle* parent() const;
2323
[[nodiscard]] bool activated() const;
2424
[[nodiscard]] bool maximized() const;
@@ -32,6 +32,8 @@ class ToplevelHandle
3232
void fullscreenOn(QScreen* screen);
3333
void setRectangle(QWindow* window, QRect rect);
3434

35+
WlOutputTracker visibleScreens;
36+
3537
signals:
3638
// sent after the first done event.
3739
void ready();
@@ -40,8 +42,6 @@ class ToplevelHandle
4042

4143
void appIdChanged();
4244
void titleChanged();
43-
void visibleScreenAdded(QScreen* screen);
44-
void visibleScreenRemoved(QScreen* screen);
4545
void parentChanged();
4646
void activatedChanged();
4747
void maximizedChanged();
@@ -51,7 +51,6 @@ class ToplevelHandle
5151
private slots:
5252
void onParentClosed();
5353
void onRectWindowDestroyed();
54-
void onScreenAdded(QScreen* screen);
5554

5655
private:
5756
void zwlr_foreign_toplevel_handle_v1_done() override;
@@ -66,8 +65,6 @@ private slots:
6665
bool isReady = false;
6766
QString mAppId;
6867
QString mTitle;
69-
QVector<QScreen*> mVisibleScreens;
70-
QVector<wl_output*> mPendingVisibleScreens;
7168
ToplevelHandle* mParent = nullptr;
7269
bool mActivated = false;
7370
bool mMaximized = false;

src/wayland/toplevel_management/qml.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../../core/util.hpp"
1111
#include "../../window/proxywindow.hpp"
1212
#include "../../window/windowinterface.hpp"
13+
#include "../output_tracking.hpp"
1314
#include "handle.hpp"
1415
#include "manager.hpp"
1516

@@ -22,8 +23,8 @@ Toplevel::Toplevel(impl::ToplevelHandle* handle, QObject* parent): QObject(paren
2223
QObject::connect(handle, &impl::ToplevelHandle::titleChanged, this, &Toplevel::titleChanged);
2324
QObject::connect(handle, &impl::ToplevelHandle::parentChanged, this, &Toplevel::parentChanged);
2425
QObject::connect(handle, &impl::ToplevelHandle::activatedChanged, this, &Toplevel::activatedChanged);
25-
QObject::connect(handle, &impl::ToplevelHandle::visibleScreenAdded, this, &Toplevel::screensChanged);
26-
QObject::connect(handle, &impl::ToplevelHandle::visibleScreenRemoved, this, &Toplevel::screensChanged);
26+
QObject::connect(&handle->visibleScreens, &WlOutputTracker::screenAdded, this, &Toplevel::screensChanged);
27+
QObject::connect(&handle->visibleScreens, &WlOutputTracker::screenRemoved, this, &Toplevel::screensChanged);
2728
QObject::connect(handle, &impl::ToplevelHandle::maximizedChanged, this, &Toplevel::maximizedChanged);
2829
QObject::connect(handle, &impl::ToplevelHandle::minimizedChanged, this, &Toplevel::minimizedChanged);
2930
QObject::connect(handle, &impl::ToplevelHandle::fullscreenChanged, this, &Toplevel::fullscreenChanged);
@@ -50,7 +51,7 @@ bool Toplevel::activated() const { return this->handle->activated(); }
5051
QList<QuickshellScreenInfo*> Toplevel::screens() const {
5152
QList<QuickshellScreenInfo*> screens;
5253

53-
for (auto* screen: this->handle->visibleScreens()) {
54+
for (auto* screen: this->handle->visibleScreens.screens()) {
5455
screens.push_back(QuickshellTracked::instance()->screenInfo(screen));
5556
}
5657

0 commit comments

Comments
 (0)