Skip to content

Commit 893626e

Browse files
committed
wip ext-ws
1 parent 767a8ef commit 893626e

18 files changed

+764
-0
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_subdirectory(window)
1111
add_subdirectory(io)
1212
add_subdirectory(widgets)
1313
add_subdirectory(ui)
14+
add_subdirectory(windowmanager)
1415

1516
if (CRASH_REPORTER)
1617
add_subdirectory(crash)

src/wayland/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ if (HYPRLAND)
113113
add_subdirectory(hyprland)
114114
endif()
115115

116+
add_subdirectory(windowmanager)
117+
116118
# widgets for qmenu
117119
target_link_libraries(quickshell-wayland PRIVATE
118120
Qt::Quick Qt::Widgets Qt::WaylandClient Qt::WaylandClientPrivate
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
qt_add_library(quickshell-wayland-windowsystem STATIC
2+
windowmanager.cpp
3+
workspace.cpp
4+
ext_workspace.cpp
5+
)
6+
7+
add_library(quickshell-wayland-windowsystem-init OBJECT init.cpp)
8+
target_link_libraries(quickshell-wayland-windowsystem-init PRIVATE Qt::Quick)
9+
10+
#wl_proto(wlp-ext-foreign-toplevel ext-foreign-toplevel-list-v1 "${WAYLAND_PROTOCOLS}/staging/ext-foreign-toplevel-list")
11+
wl_proto(wlp-ext-workspace ext-workspace-v1 "${WAYLAND_PROTOCOLS}/staging/ext-workspace")
12+
13+
target_link_libraries(quickshell-wayland-windowsystem PRIVATE
14+
Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
15+
Qt::Quick # for pch? potentially, check w/ gcc
16+
17+
wlp-ext-foreign-toplevel wlp-ext-workspace
18+
)
19+
20+
target_link_libraries(quickshell PRIVATE quickshell-wayland-windowsystem quickshell-wayland-windowsystem-init)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#include "ext_workspace.hpp"
2+
3+
#include <qloggingcategory.h>
4+
#include <qtmetamacros.h>
5+
#include <qtypes.h>
6+
7+
#include "qwayland-ext-workspace-v1.h"
8+
#include "wayland-ext-workspace-v1-client-protocol.h"
9+
10+
namespace qs::wayland::workspace {
11+
12+
namespace {
13+
Q_LOGGING_CATEGORY(logWorkspace, "quickshell.wm.wayland.workspace");
14+
}
15+
16+
WorkspaceManager::WorkspaceManager(): QWaylandClientExtensionTemplate(1) { this->initialize(); }
17+
18+
WorkspaceManager* WorkspaceManager::instance() {
19+
static auto* instance = new WorkspaceManager();
20+
return instance;
21+
}
22+
23+
void WorkspaceManager::ext_workspace_manager_v1_workspace_group(
24+
::ext_workspace_group_handle_v1* workspaceGroup
25+
) {
26+
// todo
27+
}
28+
29+
void WorkspaceManager::ext_workspace_manager_v1_workspace(::ext_workspace_handle_v1* workspace) {
30+
auto* qws = new Workspace(workspace);
31+
qCDebug(logWorkspace) << "Created workspace" << qws;
32+
this->mWorkspaces.insert(workspace, qws);
33+
emit this->workspaceCreated(qws);
34+
};
35+
36+
void WorkspaceManager::destroyWorkspace(Workspace* workspace) {
37+
this->destroyedWorkspaces.append(workspace);
38+
emit this->workspaceDestroyed(workspace);
39+
}
40+
41+
void WorkspaceManager::ext_workspace_manager_v1_done() {
42+
qCDebug(logWorkspace) << "Workspace changes done";
43+
emit this->serverCommit();
44+
45+
for (auto* workspace: this->destroyedWorkspaces) delete workspace;
46+
this->destroyedWorkspaces.clear();
47+
}
48+
49+
void WorkspaceManager::ext_workspace_manager_v1_finished() {
50+
// todo
51+
}
52+
53+
WorkspaceGroup::~WorkspaceGroup() { this->destroy(); }
54+
void WorkspaceGroup::ext_workspace_group_handle_v1_removed() { delete this; }
55+
56+
Workspace::~Workspace() {
57+
if (this->isInitialized()) this->destroy();
58+
}
59+
60+
void Workspace::ext_workspace_handle_v1_id(const QString& id) {
61+
qCDebug(logWorkspace) << "Updated id for" << this << "to" << id;
62+
this->id = id;
63+
}
64+
65+
void Workspace::ext_workspace_handle_v1_name(const QString& name) {
66+
qCDebug(logWorkspace) << "Updated name for" << this << "to" << name;
67+
this->name = name;
68+
}
69+
70+
void Workspace::ext_workspace_handle_v1_coordinates(wl_array* coordinates) {
71+
this->coordinates.clear();
72+
73+
auto* data = static_cast<qint32*>(coordinates->data);
74+
auto size = static_cast<qsizetype>(coordinates->size / sizeof(qint32));
75+
76+
for (auto i = 0; i != size; ++i) {
77+
this->coordinates.append(data[i]); // NOLINT
78+
}
79+
80+
qCDebug(logWorkspace) << "Updated coordinates for" << this << "to" << this->coordinates;
81+
}
82+
83+
void Workspace::ext_workspace_handle_v1_state(quint32 state) {
84+
this->active = state & QtWayland::ext_workspace_handle_v1::state_active;
85+
this->urgent = state & QtWayland::ext_workspace_handle_v1::state_urgent;
86+
this->hidden = state & QtWayland::ext_workspace_handle_v1::state_hidden;
87+
88+
qCDebug(logWorkspace).nospace() << "Updated state for " << this << " to [active: " << this->active
89+
<< ", urgent: " << this->urgent << ", hidden: " << this->hidden
90+
<< ']';
91+
}
92+
93+
void Workspace::ext_workspace_handle_v1_capabilities(quint32 capabilities) {
94+
this->canActivate =
95+
capabilities & QtWayland::ext_workspace_handle_v1::workspace_capabilities_activate;
96+
this->canDeactivate =
97+
capabilities & QtWayland::ext_workspace_handle_v1::workspace_capabilities_deactivate;
98+
this->canRemove =
99+
capabilities & QtWayland::ext_workspace_handle_v1::workspace_capabilities_remove;
100+
this->canAssign =
101+
capabilities & QtWayland::ext_workspace_handle_v1::workspace_capabilities_assign;
102+
103+
qCDebug(logWorkspace).nospace() << "Updated capabilities for " << this
104+
<< " to [activate: " << this->canActivate
105+
<< ", deactivate: " << this->canDeactivate
106+
<< ", remove: " << this->canRemove
107+
<< ", assign: " << this->canAssign << ']';
108+
}
109+
110+
void Workspace::ext_workspace_handle_v1_removed() {
111+
qCDebug(logWorkspace) << "Destroyed workspace" << this;
112+
this->destroy();
113+
WorkspaceManager::instance()->destroyWorkspace(this);
114+
}
115+
116+
} // namespace qs::wayland::workspace
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#pragma once
2+
3+
#include <qcontainerfwd.h>
4+
#include <qlist.h>
5+
#include <qloggingcategory.h>
6+
#include <qscreen.h>
7+
#include <qscreen_platform.h>
8+
#include <qtclasshelpermacros.h>
9+
#include <qtmetamacros.h>
10+
#include <qtypes.h>
11+
#include <qwayland-ext-workspace-v1.h>
12+
#include <qwaylandclientextension.h>
13+
#include <wayland-ext-workspace-v1-client-protocol.h>
14+
15+
namespace qs::wayland::workspace {
16+
17+
class WorkspaceGroup;
18+
class Workspace;
19+
20+
class WorkspaceManager
21+
: public QWaylandClientExtensionTemplate<WorkspaceManager>
22+
, public QtWayland::ext_workspace_manager_v1 {
23+
Q_OBJECT;
24+
25+
public:
26+
static WorkspaceManager* instance();
27+
28+
[[nodiscard]] QList<Workspace*> workspaces() { return this->mWorkspaces.values(); }
29+
30+
signals:
31+
void serverCommit();
32+
void workspaceCreated(Workspace* workspace);
33+
void workspaceDestroyed(Workspace* workspace);
34+
35+
protected:
36+
void ext_workspace_manager_v1_workspace_group(::ext_workspace_group_handle_v1* workspaceGroup
37+
) override;
38+
void ext_workspace_manager_v1_workspace(::ext_workspace_handle_v1* workspace) override;
39+
void ext_workspace_manager_v1_done() override;
40+
void ext_workspace_manager_v1_finished() override;
41+
42+
private:
43+
WorkspaceManager();
44+
45+
void destroyWorkspace(Workspace* workspace);
46+
47+
QHash<::ext_workspace_group_handle_v1*, WorkspaceGroup*> mGroups;
48+
QHash<::ext_workspace_handle_v1*, Workspace*> mWorkspaces;
49+
QList<Workspace*> destroyedWorkspaces;
50+
51+
friend class WorkspaceGroup;
52+
friend class Workspace;
53+
};
54+
55+
class WorkspaceGroup: public QtWayland::ext_workspace_group_handle_v1 {
56+
public:
57+
WorkspaceGroup(::ext_workspace_group_handle_v1* handle)
58+
: QtWayland::ext_workspace_group_handle_v1(handle) {}
59+
~WorkspaceGroup() override;
60+
Q_DISABLE_COPY_MOVE(WorkspaceGroup);
61+
62+
protected:
63+
/*void ext_workspace_group_handle_v1_capabilities(uint32_t capabilities) override;
64+
void ext_workspace_group_handle_v1_output_enter(::wl_output* output) override;
65+
void ext_workspace_group_handle_v1_output_leave(::wl_output* output) override;
66+
void ext_workspace_group_handle_v1_workspace_enter(::ext_workspace_handle_v1* workspace) override;
67+
void ext_workspace_group_handle_v1_workspace_leave(::ext_workspace_handle_v1* workspace) override;*/
68+
void ext_workspace_group_handle_v1_removed() override;
69+
70+
private:
71+
QList<QScreen*> screens;
72+
QList<wl_output*> pendingScreens;
73+
};
74+
75+
class Workspace: public QtWayland::ext_workspace_handle_v1 {
76+
public:
77+
Workspace(::ext_workspace_handle_v1* handle): QtWayland::ext_workspace_handle_v1(handle) {}
78+
~Workspace() override;
79+
Q_DISABLE_COPY_MOVE(Workspace);
80+
81+
QString id;
82+
QString name;
83+
QList<qint32> coordinates;
84+
85+
bool active : 1 = false;
86+
bool urgent : 1 = false;
87+
bool hidden : 1 = false;
88+
89+
bool canActivate : 1 = false;
90+
bool canDeactivate : 1 = false;
91+
bool canRemove : 1 = false;
92+
bool canAssign : 1 = false;
93+
94+
protected:
95+
void ext_workspace_handle_v1_id(const QString& id) override;
96+
void ext_workspace_handle_v1_name(const QString& name) override;
97+
void ext_workspace_handle_v1_coordinates(wl_array* coordinates) override;
98+
void ext_workspace_handle_v1_state(uint32_t state) override;
99+
void ext_workspace_handle_v1_capabilities(uint32_t capabilities) override;
100+
void ext_workspace_handle_v1_removed() override;
101+
102+
private:
103+
//void enterGroup(WorkspaceGroup* group);
104+
//void leaveGroup(WorkspaceGroup* group);
105+
106+
friend class WorkspaceGroup;
107+
};
108+
109+
} // namespace qs::wayland::workspace

src/wayland/windowmanager/init.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <qguiapplication.h>
2+
3+
#include "../../core/plugin.hpp"
4+
5+
namespace qs::wm::wayland {
6+
void installWmProvider();
7+
}
8+
9+
namespace {
10+
11+
class WaylandWmPlugin: public QsEnginePlugin {
12+
QList<QString> dependencies() override { return {"window"}; }
13+
14+
bool applies() override { return QGuiApplication::platformName() == "wayland"; }
15+
16+
void init() override { qs::wm::wayland::installWmProvider(); }
17+
};
18+
19+
QS_REGISTER_PLUGIN(WaylandWmPlugin);
20+
21+
} // namespace
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import QtQuick
2+
import QtQuick.Controls.Fusion
3+
import QtQuick.Layouts
4+
import Quickshell
5+
import Quickshell.Widgets
6+
import Quickshell.WindowManager
7+
8+
FloatingWindow {
9+
ColumnLayout {
10+
Repeater {
11+
model: WindowManager.workspaces
12+
13+
WrapperRectangle {
14+
id: delegate
15+
required property Workspace modelData;
16+
color: modelData.active ? "limegreen" : "gray"
17+
18+
ColumnLayout {
19+
Label { text: delegate.modelData.toString() }
20+
21+
RowLayout {
22+
DisplayCheckBox {
23+
text: "Active"
24+
checked: delegate.modelData.active
25+
}
26+
27+
DisplayCheckBox {
28+
text: "Urgent"
29+
checked: delegate.modelData.urgent
30+
}
31+
32+
DisplayCheckBox {
33+
text: "Should Display"
34+
checked: delegate.modelData.shouldDisplay
35+
}
36+
}
37+
38+
RowLayout {
39+
Button {
40+
text: "Activate"
41+
enabled: delegate.modelData.canActivate
42+
onClicked: delegate.modelData.activate()
43+
}
44+
45+
Button {
46+
text: "Deactivate"
47+
enabled: delegate.modelData.canDeactivate
48+
onClicked: delegate.modelData.deactivate()
49+
}
50+
51+
Button {
52+
text: "Remove"
53+
enabled: delegate.modelData.canRemove
54+
onClicked: delegate.modelData.remove()
55+
}
56+
}
57+
}
58+
}
59+
}
60+
}
61+
62+
component DisplayCheckBox: CheckBox {
63+
enabled: false
64+
palette.disabled.text: palette.active.text
65+
palette.disabled.windowText: palette.active.windowText
66+
}
67+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "windowmanager.hpp"
2+
3+
namespace qs::wm::wayland {
4+
5+
WaylandWindowManager* WaylandWindowManager::instance() {
6+
static auto* instance = new WaylandWindowManager();
7+
return instance;
8+
}
9+
10+
void installWmProvider() {
11+
qs::wm::WindowManager::setProvider([]() { return WaylandWindowManager::instance(); });
12+
}
13+
14+
} // namespace qs::wm::wayland
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <qtmetamacros.h>
4+
5+
#include "../../windowmanager/windowmanager.hpp"
6+
#include "workspace.hpp"
7+
8+
namespace qs::wm::wayland {
9+
10+
class WaylandWindowManager: public WindowManager {
11+
Q_OBJECT;
12+
13+
public:
14+
static WaylandWindowManager* instance();
15+
16+
[[nodiscard]] UntypedObjectModel* workspaces() const override {
17+
return &WorkspaceManager::instance()->mWorkspaces;
18+
}
19+
};
20+
21+
} // namespace qs::wm::wayland

0 commit comments

Comments
 (0)