mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2025-11-04 19:04:56 +11:00
wip ext-ws
This commit is contained in:
parent
05fbead660
commit
49fe1ca43f
18 changed files with 1040 additions and 0 deletions
|
|
@ -11,6 +11,7 @@ add_subdirectory(window)
|
||||||
add_subdirectory(io)
|
add_subdirectory(io)
|
||||||
add_subdirectory(widgets)
|
add_subdirectory(widgets)
|
||||||
add_subdirectory(ui)
|
add_subdirectory(ui)
|
||||||
|
add_subdirectory(windowmanager)
|
||||||
|
|
||||||
if (CRASH_REPORTER)
|
if (CRASH_REPORTER)
|
||||||
add_subdirectory(crash)
|
add_subdirectory(crash)
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ if (HYPRLAND)
|
||||||
add_subdirectory(hyprland)
|
add_subdirectory(hyprland)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(windowmanager)
|
||||||
|
|
||||||
# widgets for qmenu
|
# widgets for qmenu
|
||||||
target_link_libraries(quickshell-wayland PRIVATE
|
target_link_libraries(quickshell-wayland PRIVATE
|
||||||
Qt::Quick Qt::Widgets Qt::WaylandClient Qt::WaylandClientPrivate
|
Qt::Quick Qt::Widgets Qt::WaylandClient Qt::WaylandClientPrivate
|
||||||
|
|
|
||||||
20
src/wayland/windowmanager/CMakeLists.txt
Normal file
20
src/wayland/windowmanager/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
qt_add_library(quickshell-wayland-windowsystem STATIC
|
||||||
|
windowmanager.cpp
|
||||||
|
workspace.cpp
|
||||||
|
ext_workspace.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(quickshell-wayland-windowsystem-init OBJECT init.cpp)
|
||||||
|
target_link_libraries(quickshell-wayland-windowsystem-init PRIVATE Qt::Quick)
|
||||||
|
|
||||||
|
#wl_proto(wlp-ext-foreign-toplevel ext-foreign-toplevel-list-v1 "${WAYLAND_PROTOCOLS}/staging/ext-foreign-toplevel-list")
|
||||||
|
wl_proto(wlp-ext-workspace ext-workspace-v1 "${WAYLAND_PROTOCOLS}/staging/ext-workspace")
|
||||||
|
|
||||||
|
target_link_libraries(quickshell-wayland-windowsystem PRIVATE
|
||||||
|
Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
|
||||||
|
Qt::Quick # for pch? potentially, check w/ gcc
|
||||||
|
|
||||||
|
wlp-ext-foreign-toplevel wlp-ext-workspace
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(quickshell PRIVATE quickshell-wayland-windowsystem quickshell-wayland-windowsystem-init)
|
||||||
169
src/wayland/windowmanager/ext_workspace.cpp
Normal file
169
src/wayland/windowmanager/ext_workspace.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
#include "ext_workspace.hpp"
|
||||||
|
|
||||||
|
#include <qloggingcategory.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
#include <qtypes.h>
|
||||||
|
#include <qwayland-ext-workspace-v1.h>
|
||||||
|
#include <wayland-ext-workspace-v1-client-protocol.h>
|
||||||
|
|
||||||
|
namespace qs::wayland::workspace {
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(logWorkspace, "quickshell.wm.wayland.workspace");
|
||||||
|
|
||||||
|
WorkspaceManager::WorkspaceManager(): QWaylandClientExtensionTemplate(1) { this->initialize(); }
|
||||||
|
|
||||||
|
WorkspaceManager* WorkspaceManager::instance() {
|
||||||
|
static auto* instance = new WorkspaceManager();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::ext_workspace_manager_v1_workspace_group(
|
||||||
|
::ext_workspace_group_handle_v1* handle
|
||||||
|
) {
|
||||||
|
auto* group = new WorkspaceGroup(handle);
|
||||||
|
qCDebug(logWorkspace) << "Created group" << group;
|
||||||
|
this->mGroups.insert(handle, group);
|
||||||
|
emit this->groupCreated(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::ext_workspace_manager_v1_workspace(::ext_workspace_handle_v1* handle) {
|
||||||
|
auto* workspace = new Workspace(handle);
|
||||||
|
qCDebug(logWorkspace) << "Created workspace" << workspace;
|
||||||
|
this->mWorkspaces.insert(handle, workspace);
|
||||||
|
emit this->workspaceCreated(workspace);
|
||||||
|
};
|
||||||
|
|
||||||
|
void WorkspaceManager::destroyWorkspace(Workspace* workspace) {
|
||||||
|
this->mWorkspaces.remove(workspace->object());
|
||||||
|
this->destroyedWorkspaces.append(workspace);
|
||||||
|
emit this->workspaceDestroyed(workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::destroyGroup(WorkspaceGroup* group) {
|
||||||
|
this->mGroups.remove(group->object());
|
||||||
|
this->destroyedGroups.append(group);
|
||||||
|
emit this->groupDestroyed(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::ext_workspace_manager_v1_done() {
|
||||||
|
qCDebug(logWorkspace) << "Workspace changes done";
|
||||||
|
emit this->serverCommit();
|
||||||
|
|
||||||
|
for (auto* workspace: this->destroyedWorkspaces) delete workspace;
|
||||||
|
for (auto* group: this->destroyedGroups) delete group;
|
||||||
|
this->destroyedWorkspaces.clear();
|
||||||
|
this->destroyedGroups.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::ext_workspace_manager_v1_finished() {
|
||||||
|
qCWarning(logWorkspace) << "ext_workspace_manager_v1.finished() was received";
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspace::~Workspace() {
|
||||||
|
if (this->isInitialized()) this->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::ext_workspace_handle_v1_id(const QString& id) {
|
||||||
|
qCDebug(logWorkspace) << "Updated id for workspace" << this << "to" << id;
|
||||||
|
this->id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::ext_workspace_handle_v1_name(const QString& name) {
|
||||||
|
qCDebug(logWorkspace) << "Updated name for workspace" << this << "to" << name;
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::ext_workspace_handle_v1_coordinates(wl_array* coordinates) {
|
||||||
|
this->coordinates.clear();
|
||||||
|
|
||||||
|
auto* data = static_cast<qint32*>(coordinates->data);
|
||||||
|
auto size = static_cast<qsizetype>(coordinates->size / sizeof(qint32));
|
||||||
|
|
||||||
|
for (auto i = 0; i != size; ++i) {
|
||||||
|
this->coordinates.append(data[i]); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(logWorkspace) << "Updated coordinates for workspace" << this << "to" << this->coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::ext_workspace_handle_v1_state(quint32 state) {
|
||||||
|
this->active = state & ext_workspace_handle_v1::state_active;
|
||||||
|
this->urgent = state & ext_workspace_handle_v1::state_urgent;
|
||||||
|
this->hidden = state & ext_workspace_handle_v1::state_hidden;
|
||||||
|
|
||||||
|
qCDebug(logWorkspace).nospace() << "Updated state for workspace " << this
|
||||||
|
<< " to [active: " << this->active << ", urgent: " << this->urgent
|
||||||
|
<< ", hidden: " << this->hidden << ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::ext_workspace_handle_v1_capabilities(quint32 capabilities) {
|
||||||
|
this->canActivate = capabilities & ext_workspace_handle_v1::workspace_capabilities_activate;
|
||||||
|
this->canDeactivate = capabilities & ext_workspace_handle_v1::workspace_capabilities_deactivate;
|
||||||
|
this->canRemove = capabilities & ext_workspace_handle_v1::workspace_capabilities_remove;
|
||||||
|
this->canAssign = capabilities & ext_workspace_handle_v1::workspace_capabilities_assign;
|
||||||
|
|
||||||
|
qCDebug(logWorkspace).nospace() << "Updated capabilities for workspace " << this
|
||||||
|
<< " to [activate: " << this->canActivate
|
||||||
|
<< ", deactivate: " << this->canDeactivate
|
||||||
|
<< ", remove: " << this->canRemove
|
||||||
|
<< ", assign: " << this->canAssign << ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::ext_workspace_handle_v1_removed() {
|
||||||
|
qCDebug(logWorkspace) << "Destroyed workspace" << this;
|
||||||
|
WorkspaceManager::instance()->destroyWorkspace(this);
|
||||||
|
this->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::enterGroup(WorkspaceGroup* group) { this->group = group; }
|
||||||
|
|
||||||
|
void Workspace::leaveGroup(WorkspaceGroup* group) {
|
||||||
|
if (this->group == group) this->group = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspaceGroup::~WorkspaceGroup() {
|
||||||
|
if (this->isInitialized()) this->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::ext_workspace_group_handle_v1_capabilities(uint32_t capabilities) {
|
||||||
|
this->canCreateWorkspace =
|
||||||
|
capabilities & ext_workspace_group_handle_v1::group_capabilities_create_workspace;
|
||||||
|
|
||||||
|
qCDebug(logWorkspace).nospace() << "Updated capabilities for group " << this
|
||||||
|
<< " to [create_workspace: " << this->canCreateWorkspace << ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::ext_workspace_group_handle_v1_output_enter(::wl_output* output) {
|
||||||
|
qCDebug(logWorkspace) << "Output" << output << "added to group" << this;
|
||||||
|
this->screens.addOutput(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::ext_workspace_group_handle_v1_output_leave(::wl_output* output) {
|
||||||
|
qCDebug(logWorkspace) << "Output" << output << "removed from group" << this;
|
||||||
|
this->screens.removeOutput(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::ext_workspace_group_handle_v1_workspace_enter(::ext_workspace_handle_v1* handle
|
||||||
|
) {
|
||||||
|
auto* workspace = WorkspaceManager::instance()->mWorkspaces.value(handle);
|
||||||
|
qCDebug(logWorkspace) << "Workspace" << workspace << "added to group" << this;
|
||||||
|
|
||||||
|
if (workspace) workspace->enterGroup(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::ext_workspace_group_handle_v1_workspace_leave(::ext_workspace_handle_v1* handle
|
||||||
|
) {
|
||||||
|
auto* workspace = WorkspaceManager::instance()->mWorkspaces.value(handle);
|
||||||
|
qCDebug(logWorkspace) << "Workspace" << workspace << "removed from group" << this;
|
||||||
|
|
||||||
|
if (workspace) workspace->leaveGroup(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::ext_workspace_group_handle_v1_removed() {
|
||||||
|
qCDebug(logWorkspace) << "Destroyed group" << this;
|
||||||
|
WorkspaceManager::instance()->destroyGroup(this);
|
||||||
|
this->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qs::wayland::workspace
|
||||||
117
src/wayland/windowmanager/ext_workspace.hpp
Normal file
117
src/wayland/windowmanager/ext_workspace.hpp
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
|
#include <qlist.h>
|
||||||
|
#include <qloggingcategory.h>
|
||||||
|
#include <qscreen.h>
|
||||||
|
#include <qscreen_platform.h>
|
||||||
|
#include <qtclasshelpermacros.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
#include <qtypes.h>
|
||||||
|
#include <qwayland-ext-workspace-v1.h>
|
||||||
|
#include <qwaylandclientextension.h>
|
||||||
|
#include <wayland-ext-workspace-v1-client-protocol.h>
|
||||||
|
|
||||||
|
#include "../output_tracking.hpp"
|
||||||
|
|
||||||
|
namespace qs::wayland::workspace {
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(logWorkspace);
|
||||||
|
|
||||||
|
class WorkspaceGroup;
|
||||||
|
class Workspace;
|
||||||
|
|
||||||
|
class WorkspaceManager
|
||||||
|
: public QWaylandClientExtensionTemplate<WorkspaceManager>
|
||||||
|
, public QtWayland::ext_workspace_manager_v1 {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static WorkspaceManager* instance();
|
||||||
|
|
||||||
|
[[nodiscard]] QList<Workspace*> workspaces() { return this->mWorkspaces.values(); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void serverCommit();
|
||||||
|
void workspaceCreated(Workspace* workspace);
|
||||||
|
void workspaceDestroyed(Workspace* workspace);
|
||||||
|
void groupCreated(WorkspaceGroup* group);
|
||||||
|
void groupDestroyed(WorkspaceGroup* group);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ext_workspace_manager_v1_workspace_group(::ext_workspace_group_handle_v1* handle) override;
|
||||||
|
void ext_workspace_manager_v1_workspace(::ext_workspace_handle_v1* handle) override;
|
||||||
|
void ext_workspace_manager_v1_done() override;
|
||||||
|
void ext_workspace_manager_v1_finished() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
WorkspaceManager();
|
||||||
|
|
||||||
|
void destroyGroup(WorkspaceGroup* group);
|
||||||
|
void destroyWorkspace(Workspace* workspace);
|
||||||
|
|
||||||
|
QHash<::ext_workspace_handle_v1*, Workspace*> mWorkspaces;
|
||||||
|
QHash<::ext_workspace_group_handle_v1*, WorkspaceGroup*> mGroups;
|
||||||
|
QList<WorkspaceGroup*> destroyedGroups;
|
||||||
|
QList<Workspace*> destroyedWorkspaces;
|
||||||
|
|
||||||
|
friend class Workspace;
|
||||||
|
friend class WorkspaceGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Workspace: public QtWayland::ext_workspace_handle_v1 {
|
||||||
|
public:
|
||||||
|
Workspace(::ext_workspace_handle_v1* handle): QtWayland::ext_workspace_handle_v1(handle) {}
|
||||||
|
~Workspace() override;
|
||||||
|
Q_DISABLE_COPY_MOVE(Workspace);
|
||||||
|
|
||||||
|
QString id;
|
||||||
|
QString name;
|
||||||
|
QList<qint32> coordinates;
|
||||||
|
WorkspaceGroup* group = nullptr;
|
||||||
|
|
||||||
|
bool active : 1 = false;
|
||||||
|
bool urgent : 1 = false;
|
||||||
|
bool hidden : 1 = false;
|
||||||
|
|
||||||
|
bool canActivate : 1 = false;
|
||||||
|
bool canDeactivate : 1 = false;
|
||||||
|
bool canRemove : 1 = false;
|
||||||
|
bool canAssign : 1 = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ext_workspace_handle_v1_id(const QString& id) override;
|
||||||
|
void ext_workspace_handle_v1_name(const QString& name) override;
|
||||||
|
void ext_workspace_handle_v1_coordinates(wl_array* coordinates) override;
|
||||||
|
void ext_workspace_handle_v1_state(uint32_t state) override;
|
||||||
|
void ext_workspace_handle_v1_capabilities(uint32_t capabilities) override;
|
||||||
|
void ext_workspace_handle_v1_removed() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void enterGroup(WorkspaceGroup* group);
|
||||||
|
void leaveGroup(WorkspaceGroup* group);
|
||||||
|
|
||||||
|
friend class WorkspaceGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WorkspaceGroup: public QtWayland::ext_workspace_group_handle_v1 {
|
||||||
|
public:
|
||||||
|
WorkspaceGroup(::ext_workspace_group_handle_v1* handle)
|
||||||
|
: QtWayland::ext_workspace_group_handle_v1(handle) {}
|
||||||
|
|
||||||
|
~WorkspaceGroup() override;
|
||||||
|
Q_DISABLE_COPY_MOVE(WorkspaceGroup);
|
||||||
|
|
||||||
|
WlOutputTracker screens;
|
||||||
|
bool canCreateWorkspace : 1 = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ext_workspace_group_handle_v1_capabilities(uint32_t capabilities) override;
|
||||||
|
void ext_workspace_group_handle_v1_output_enter(::wl_output* output) override;
|
||||||
|
void ext_workspace_group_handle_v1_output_leave(::wl_output* output) override;
|
||||||
|
void ext_workspace_group_handle_v1_workspace_enter(::ext_workspace_handle_v1* handle) override;
|
||||||
|
void ext_workspace_group_handle_v1_workspace_leave(::ext_workspace_handle_v1* handle) override;
|
||||||
|
void ext_workspace_group_handle_v1_removed() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qs::wayland::workspace
|
||||||
21
src/wayland/windowmanager/init.cpp
Normal file
21
src/wayland/windowmanager/init.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include <qguiapplication.h>
|
||||||
|
|
||||||
|
#include "../../core/plugin.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm::wayland {
|
||||||
|
void installWmProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class WaylandWmPlugin: public QsEnginePlugin {
|
||||||
|
QList<QString> dependencies() override { return {"window"}; }
|
||||||
|
|
||||||
|
bool applies() override { return QGuiApplication::platformName() == "wayland"; }
|
||||||
|
|
||||||
|
void init() override { qs::wm::wayland::installWmProvider(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
QS_REGISTER_PLUGIN(WaylandWmPlugin);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
14
src/wayland/windowmanager/windowmanager.cpp
Normal file
14
src/wayland/windowmanager/windowmanager.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "windowmanager.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm::wayland {
|
||||||
|
|
||||||
|
WaylandWindowManager* WaylandWindowManager::instance() {
|
||||||
|
static auto* instance = new WaylandWindowManager();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void installWmProvider() {
|
||||||
|
qs::wm::WindowManager::setProvider([]() { return WaylandWindowManager::instance(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qs::wm::wayland
|
||||||
25
src/wayland/windowmanager/windowmanager.hpp
Normal file
25
src/wayland/windowmanager/windowmanager.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
#include "../../windowmanager/windowmanager.hpp"
|
||||||
|
#include "workspace.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm::wayland {
|
||||||
|
|
||||||
|
class WaylandWindowManager: public WindowManager {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static WaylandWindowManager* instance();
|
||||||
|
|
||||||
|
[[nodiscard]] UntypedObjectModel* workspaces() const override {
|
||||||
|
return &WorkspaceManager::instance()->mWorkspaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] UntypedObjectModel* workspaceGroups() const override {
|
||||||
|
return &WorkspaceManager::instance()->mWorkspaceGroups;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qs::wm::wayland
|
||||||
198
src/wayland/windowmanager/workspace.cpp
Normal file
198
src/wayland/windowmanager/workspace.cpp
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
#include "workspace.hpp"
|
||||||
|
|
||||||
|
#include <qlist.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <qloggingcategory.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qproperty.h>
|
||||||
|
|
||||||
|
#include "ext_workspace.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm::wayland {
|
||||||
|
|
||||||
|
WorkspaceManager::WorkspaceManager() {
|
||||||
|
auto* impl = impl::WorkspaceManager::instance();
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
impl,
|
||||||
|
&impl::WorkspaceManager::serverCommit,
|
||||||
|
this,
|
||||||
|
&WorkspaceManager::onServerCommit
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
impl,
|
||||||
|
&impl::WorkspaceManager::workspaceCreated,
|
||||||
|
this,
|
||||||
|
&WorkspaceManager::onWorkspaceCreated
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
impl,
|
||||||
|
&impl::WorkspaceManager::workspaceDestroyed,
|
||||||
|
this,
|
||||||
|
&WorkspaceManager::onWorkspaceDestroyed
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
impl,
|
||||||
|
&impl::WorkspaceManager::groupCreated,
|
||||||
|
this,
|
||||||
|
&WorkspaceManager::onGroupCreated
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(
|
||||||
|
impl,
|
||||||
|
&impl::WorkspaceManager::groupDestroyed,
|
||||||
|
this,
|
||||||
|
&WorkspaceManager::onGroupDestroyed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::commit() {
|
||||||
|
qCDebug(impl::logWorkspace) << "Committing workspaces";
|
||||||
|
impl::WorkspaceManager::instance()->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::onServerCommit() {
|
||||||
|
// Groups are created/destroyed around workspaces to avoid any nulls making it
|
||||||
|
// to the qml engine.
|
||||||
|
|
||||||
|
for (auto* groupImpl: this->pendingGroupCreations) {
|
||||||
|
auto* group = new WlWorkspaceGroup(this, groupImpl);
|
||||||
|
this->groupsByImpl.insert(groupImpl, group);
|
||||||
|
this->mWorkspaceGroups.insertObject(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* wsImpl: this->pendingWorkspaceCreations) {
|
||||||
|
auto* ws = new WlWorkspace(this, wsImpl);
|
||||||
|
this->workspaceByImpl.insert(wsImpl, ws);
|
||||||
|
this->mWorkspaces.insertObject(ws);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* wsImpl: this->pendingWorkspaceDestructions) {
|
||||||
|
this->mWorkspaces.removeObject(this->workspaceByImpl.value(wsImpl));
|
||||||
|
this->workspaceByImpl.remove(wsImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* groupImpl: this->pendingGroupDestructions) {
|
||||||
|
this->mWorkspaceGroups.removeObject(this->groupsByImpl.value(groupImpl));
|
||||||
|
this->groupsByImpl.remove(groupImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* ws: this->mWorkspaces.valueList()) ws->commitImpl();
|
||||||
|
for (auto* group: this->mWorkspaceGroups.valueList()) group->commitImpl();
|
||||||
|
|
||||||
|
this->pendingWorkspaceCreations.clear();
|
||||||
|
this->pendingWorkspaceDestructions.clear();
|
||||||
|
this->pendingGroupCreations.clear();
|
||||||
|
this->pendingGroupDestructions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::onWorkspaceCreated(impl::Workspace* workspace) {
|
||||||
|
this->pendingWorkspaceCreations.append(workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::onWorkspaceDestroyed(impl::Workspace* workspace) {
|
||||||
|
if (!this->pendingWorkspaceCreations.removeOne(workspace)) {
|
||||||
|
this->pendingWorkspaceDestructions.append(workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::onGroupCreated(impl::WorkspaceGroup* group) {
|
||||||
|
this->pendingGroupCreations.append(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceManager::onGroupDestroyed(impl::WorkspaceGroup* group) {
|
||||||
|
if (!this->pendingGroupCreations.removeOne(group)) {
|
||||||
|
this->pendingGroupDestructions.append(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspaceManager* WorkspaceManager::instance() {
|
||||||
|
static auto* instance = new WorkspaceManager();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
WlWorkspace::WlWorkspace(WorkspaceManager* manager, impl::Workspace* impl)
|
||||||
|
: Workspace(manager)
|
||||||
|
, impl(impl) {
|
||||||
|
this->commitImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WlWorkspace::commitImpl() {
|
||||||
|
Qt::beginPropertyUpdateGroup();
|
||||||
|
this->bId = this->impl->id;
|
||||||
|
this->bName = this->impl->name;
|
||||||
|
this->bActive = this->impl->active;
|
||||||
|
this->bShouldDisplay = !this->impl->hidden;
|
||||||
|
this->bUrgent = this->impl->urgent;
|
||||||
|
this->bCanActivate = this->impl->canActivate;
|
||||||
|
this->bCanDeactivate = this->impl->canDeactivate;
|
||||||
|
this->bCanSetGroup = this->impl->canAssign;
|
||||||
|
this->bGroup = this->manager()->groupsByImpl.value(this->impl->group);
|
||||||
|
Qt::endPropertyUpdateGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WlWorkspace::activate() {
|
||||||
|
if (!this->bCanActivate) {
|
||||||
|
qCritical(logWorkspace) << this << "cannot be activated";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(impl::logWorkspace) << "Calling activate() for" << this;
|
||||||
|
this->impl->activate();
|
||||||
|
WorkspaceManager::commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WlWorkspace::deactivate() {
|
||||||
|
if (!this->bCanDeactivate) {
|
||||||
|
qCritical(logWorkspace) << this << "cannot be deactivated";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(impl::logWorkspace) << "Calling deactivate() for" << this;
|
||||||
|
this->impl->deactivate();
|
||||||
|
WorkspaceManager::commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WlWorkspace::remove() {
|
||||||
|
if (!this->bCanRemove) {
|
||||||
|
qCritical(logWorkspace) << this << "cannot be removed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(impl::logWorkspace) << "Calling remove() for" << this;
|
||||||
|
this->impl->remove();
|
||||||
|
WorkspaceManager::commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WlWorkspace::setGroup(WorkspaceGroup* group) {
|
||||||
|
if (!this->bCanSetGroup) {
|
||||||
|
qCritical(logWorkspace) << this << "cannot be assigned to a group";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!group) {
|
||||||
|
qCritical(logWorkspace) << "Cannot set a workspace's group to null";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(impl::logWorkspace) << "Assigning" << this << "to" << group;
|
||||||
|
// NOLINTNEXTLINE: A WorkspaceGroup will always be a WlWorkspaceGroup under wayland.
|
||||||
|
this->impl->assign(static_cast<WlWorkspaceGroup*>(group)->impl->object());
|
||||||
|
WorkspaceManager::commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
WlWorkspaceGroup::WlWorkspaceGroup(WorkspaceManager* manager, impl::WorkspaceGroup* impl)
|
||||||
|
: WorkspaceGroup(manager)
|
||||||
|
, impl(impl) {
|
||||||
|
this->commitImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WlWorkspaceGroup::commitImpl() {
|
||||||
|
// TODO: will not commit the correct screens if missing qt repr at commit time
|
||||||
|
this->bScreens = this->impl->screens.screens();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qs::wm::wayland
|
||||||
85
src/wayland/windowmanager/workspace.hpp
Normal file
85
src/wayland/windowmanager/workspace.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qhash.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qproperty.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
#include "../../core/model.hpp"
|
||||||
|
#include "../../windowmanager/workspace.hpp"
|
||||||
|
#include "ext_workspace.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm::wayland {
|
||||||
|
namespace impl = qs::wayland::workspace;
|
||||||
|
|
||||||
|
class WlWorkspace;
|
||||||
|
class WlWorkspaceGroup;
|
||||||
|
|
||||||
|
class WorkspaceManager: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static WorkspaceManager* instance();
|
||||||
|
|
||||||
|
ObjectModel<WlWorkspace> mWorkspaces {this};
|
||||||
|
ObjectModel<WlWorkspaceGroup> mWorkspaceGroups {this};
|
||||||
|
|
||||||
|
static void commit();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onServerCommit();
|
||||||
|
void onWorkspaceCreated(impl::Workspace* workspace);
|
||||||
|
void onWorkspaceDestroyed(impl::Workspace* workspace);
|
||||||
|
void onGroupCreated(impl::WorkspaceGroup* group);
|
||||||
|
void onGroupDestroyed(impl::WorkspaceGroup* group);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WorkspaceManager();
|
||||||
|
|
||||||
|
QList<impl::Workspace*> pendingWorkspaceCreations;
|
||||||
|
QList<impl::Workspace*> pendingWorkspaceDestructions;
|
||||||
|
QHash<impl::Workspace*, WlWorkspace*> workspaceByImpl;
|
||||||
|
|
||||||
|
QList<impl::WorkspaceGroup*> pendingGroupCreations;
|
||||||
|
QList<impl::WorkspaceGroup*> pendingGroupDestructions;
|
||||||
|
QHash<impl::WorkspaceGroup*, WlWorkspaceGroup*> groupsByImpl;
|
||||||
|
|
||||||
|
friend class WlWorkspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WlWorkspace: public Workspace {
|
||||||
|
public:
|
||||||
|
WlWorkspace(WorkspaceManager* manager, impl::Workspace* impl);
|
||||||
|
|
||||||
|
void commitImpl();
|
||||||
|
|
||||||
|
void activate() override;
|
||||||
|
void deactivate() override;
|
||||||
|
void remove() override;
|
||||||
|
void setGroup(WorkspaceGroup* group) override;
|
||||||
|
|
||||||
|
[[nodiscard]] WorkspaceManager* manager() {
|
||||||
|
return static_cast<WorkspaceManager*>(this->parent()); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
impl::Workspace* impl = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WlWorkspaceGroup: public WorkspaceGroup {
|
||||||
|
public:
|
||||||
|
WlWorkspaceGroup(WorkspaceManager* manager, impl::WorkspaceGroup* impl);
|
||||||
|
|
||||||
|
void commitImpl();
|
||||||
|
|
||||||
|
[[nodiscard]] WorkspaceManager* manager() {
|
||||||
|
return static_cast<WorkspaceManager*>(this->parent()); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
impl::WorkspaceGroup* impl = nullptr;
|
||||||
|
|
||||||
|
friend class WlWorkspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qs::wm::wayland
|
||||||
18
src/windowmanager/CMakeLists.txt
Normal file
18
src/windowmanager/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
qt_add_library(quickshell-windowmanager STATIC
|
||||||
|
windowmanager.cpp
|
||||||
|
workspace.cpp
|
||||||
|
workspacemodel.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
qt_add_qml_module(quickshell-windowmanager
|
||||||
|
URI Quickshell.WindowManager
|
||||||
|
VERSION 0.1
|
||||||
|
DEPENDENCIES QtQuick
|
||||||
|
)
|
||||||
|
|
||||||
|
qs_add_module_deps_light(quickshell-windowmanager Quickshell)
|
||||||
|
|
||||||
|
install_qml_module(quickshell-windowmanager)
|
||||||
|
|
||||||
|
target_link_libraries(quickshell-windowmanager PRIVATE Qt::Quick)
|
||||||
|
target_link_libraries(quickshell PRIVATE quickshell-windowmanager)
|
||||||
112
src/windowmanager/test/manual/workspaces.qml
Normal file
112
src/windowmanager/test/manual/workspaces.qml
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls.Fusion
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.WindowManager
|
||||||
|
|
||||||
|
FloatingWindow {
|
||||||
|
ScrollView {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Repeater {
|
||||||
|
model: WindowManager.workspaceGroups
|
||||||
|
|
||||||
|
WrapperRectangle {
|
||||||
|
id: delegate
|
||||||
|
required property WorkspaceGroup modelData
|
||||||
|
color: "slategray"
|
||||||
|
margin: 5
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Label { text: delegate.modelData.toString() }
|
||||||
|
Label { text: `Screens: ${delegate.modelData.screens.map(s => s.name)}` }
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ScriptModel {
|
||||||
|
values: [...WindowManager.workspaces.values].filter(w => w.group == delegate.modelData)
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspaceDelegate {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ScriptModel {
|
||||||
|
values: WindowManager.workspaces.values.filter(w => w.group == null)
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkspaceDelegate {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component WorkspaceDelegate: WrapperRectangle {
|
||||||
|
id: delegate
|
||||||
|
required property Workspace modelData;
|
||||||
|
color: modelData.active ? "green" : "gray"
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Label { text: delegate.modelData.toString() }
|
||||||
|
Label { text: `Id: ${delegate.modelData.id} Name: ${delegate.modelData.name}` }
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Label { text: "Group:" }
|
||||||
|
ComboBox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitContentWidthPolicy: ComboBox.WidestText
|
||||||
|
enabled: delegate.modelData.canSetGroup
|
||||||
|
model: [...WindowManager.workspaceGroups.values].map(w => w.toString())
|
||||||
|
currentIndex: WindowManager.workspaceGroups.values.indexOf(delegate.modelData.group)
|
||||||
|
onActivated: i => delegate.modelData.setGroup(WindowManager.workspaceGroups.values[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
DisplayCheckBox {
|
||||||
|
text: "Active"
|
||||||
|
checked: delegate.modelData.active
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayCheckBox {
|
||||||
|
text: "Urgent"
|
||||||
|
checked: delegate.modelData.urgent
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayCheckBox {
|
||||||
|
text: "Should Display"
|
||||||
|
checked: delegate.modelData.shouldDisplay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Button {
|
||||||
|
text: "Activate"
|
||||||
|
enabled: delegate.modelData.canActivate
|
||||||
|
onClicked: delegate.modelData.activate()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Deactivate"
|
||||||
|
enabled: delegate.modelData.canDeactivate
|
||||||
|
onClicked: delegate.modelData.deactivate()
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Remove"
|
||||||
|
enabled: delegate.modelData.canRemove
|
||||||
|
onClicked: delegate.modelData.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component DisplayCheckBox: CheckBox {
|
||||||
|
enabled: false
|
||||||
|
palette.disabled.text: parent.palette.active.text
|
||||||
|
palette.disabled.windowText: parent.palette.active.windowText
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/windowmanager/windowmanager.cpp
Normal file
18
src/windowmanager/windowmanager.cpp
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "windowmanager.hpp"
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace qs::wm {
|
||||||
|
|
||||||
|
std::function<WindowManager*()> WindowManager::provider;
|
||||||
|
|
||||||
|
void WindowManager::setProvider(std::function<WindowManager*()> provider) {
|
||||||
|
WindowManager::provider = std::move(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowManager* WindowManager::instance() {
|
||||||
|
static auto* instance = WindowManager::provider();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qs::wm
|
||||||
50
src/windowmanager/windowmanager.hpp
Normal file
50
src/windowmanager/windowmanager.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
#include "../core/model.hpp"
|
||||||
|
#include "workspace.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm {
|
||||||
|
|
||||||
|
class WindowManager: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void setProvider(std::function<WindowManager*()> provider);
|
||||||
|
static WindowManager* instance();
|
||||||
|
|
||||||
|
[[nodiscard]] virtual UntypedObjectModel* workspaces() const {
|
||||||
|
return UntypedObjectModel::emptyInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] virtual UntypedObjectModel* workspaceGroups() const {
|
||||||
|
return UntypedObjectModel::emptyInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::function<WindowManager*()> provider;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowManagerQml: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
QML_NAMED_ELEMENT(WindowManager);
|
||||||
|
QML_SINGLETON;
|
||||||
|
Q_PROPERTY(UntypedObjectModel* workspaces READ workspaces CONSTANT);
|
||||||
|
Q_PROPERTY(UntypedObjectModel* workspaceGroups READ workspaceGroups CONSTANT);
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] static UntypedObjectModel* workspaces() {
|
||||||
|
return WindowManager::instance()->workspaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static UntypedObjectModel* workspaceGroups() {
|
||||||
|
return WindowManager::instance()->workspaceGroups();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qs::wm
|
||||||
31
src/windowmanager/workspace.cpp
Normal file
31
src/windowmanager/workspace.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#include "workspace.hpp"
|
||||||
|
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <qloggingcategory.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
#include "../core/qmlglobal.hpp"
|
||||||
|
|
||||||
|
namespace qs::wm {
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(logWorkspace, "quickshell.wm.workspace", QtWarningMsg);
|
||||||
|
|
||||||
|
void Workspace::activate() { qCCritical(logWorkspace) << this << "cannot be activated"; }
|
||||||
|
void Workspace::deactivate() { qCCritical(logWorkspace) << this << "cannot be deactivated"; }
|
||||||
|
void Workspace::remove() { qCCritical(logWorkspace) << this << "cannot be removed"; }
|
||||||
|
|
||||||
|
void Workspace::setGroup(WorkspaceGroup* /*group*/) {
|
||||||
|
qCCritical(logWorkspace) << this << "cannot be assigned to a group";
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceGroup::onScreensChanged() {
|
||||||
|
mCachedScreens.clear();
|
||||||
|
|
||||||
|
for (auto* screen: this->bScreens.value()) {
|
||||||
|
mCachedScreens.append(QuickshellTracked::instance()->screenInfo(screen));
|
||||||
|
}
|
||||||
|
|
||||||
|
emit this->screensChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qs::wm
|
||||||
119
src/windowmanager/workspace.hpp
Normal file
119
src/windowmanager/workspace.hpp
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
|
#include <qlist.h>
|
||||||
|
#include <qloggingcategory.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qproperty.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
#include <qscreen.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
#include <qtypes.h>
|
||||||
|
|
||||||
|
class QuickshellScreenInfo;
|
||||||
|
|
||||||
|
namespace qs::wm {
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(logWorkspace);
|
||||||
|
|
||||||
|
class WorkspaceGroup;
|
||||||
|
|
||||||
|
class Workspace: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
QML_ELEMENT;
|
||||||
|
QML_UNCREATABLE("");
|
||||||
|
// clang-format off
|
||||||
|
// persistent id
|
||||||
|
Q_PROPERTY(QString id READ default BINDABLE bindableId NOTIFY idChanged);
|
||||||
|
Q_PROPERTY(QString name READ default BINDABLE bindableName NOTIFY nameChanged);
|
||||||
|
// currently visible
|
||||||
|
Q_PROPERTY(bool active READ default BINDABLE bindableActive NOTIFY activeChanged);
|
||||||
|
Q_PROPERTY(WorkspaceGroup* group READ default BINDABLE bindableGroup NOTIFY groupChanged);
|
||||||
|
// in workspace pickers
|
||||||
|
Q_PROPERTY(bool shouldDisplay READ default BINDABLE bindableShouldDisplay NOTIFY shouldDisplayChanged);
|
||||||
|
Q_PROPERTY(bool urgent READ default BINDABLE bindableUrgent NOTIFY urgentChanged);
|
||||||
|
Q_PROPERTY(bool canActivate READ default BINDABLE bindableCanActivate NOTIFY canActivateChanged);
|
||||||
|
Q_PROPERTY(bool canDeactivate READ default BINDABLE bindableCanDeactivate NOTIFY canDeactivateChanged);
|
||||||
|
Q_PROPERTY(bool canRemove READ default BINDABLE bindableCanRemove NOTIFY canRemoveChanged);
|
||||||
|
Q_PROPERTY(bool canSetGroup READ default BINDABLE bindableCanSetGroup NOTIFY canSetGroupChanged);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Workspace(QObject* parent): QObject(parent) {}
|
||||||
|
|
||||||
|
Q_INVOKABLE virtual void activate();
|
||||||
|
Q_INVOKABLE virtual void deactivate();
|
||||||
|
Q_INVOKABLE virtual void remove();
|
||||||
|
Q_INVOKABLE virtual void setGroup(WorkspaceGroup* group);
|
||||||
|
|
||||||
|
[[nodiscard]] QBindable<QString> bindableId() const { return &this->bId; }
|
||||||
|
[[nodiscard]] QBindable<QString> bindableName() const { return &this->bName; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableActive() const { return &this->bActive; }
|
||||||
|
[[nodiscard]] QBindable<WorkspaceGroup*> bindableGroup() const { return &this->bGroup; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableShouldDisplay() const { return &this->bShouldDisplay; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableUrgent() const { return &this->bUrgent; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableCanActivate() const { return &this->bCanActivate; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableCanDeactivate() const { return &this->bCanDeactivate; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableCanRemove() const { return &this->bCanRemove; }
|
||||||
|
[[nodiscard]] QBindable<bool> bindableCanSetGroup() const { return &this->bCanSetGroup; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void idChanged();
|
||||||
|
void nameChanged();
|
||||||
|
void activeChanged();
|
||||||
|
void groupChanged();
|
||||||
|
void shouldDisplayChanged();
|
||||||
|
void urgentChanged();
|
||||||
|
void canActivateChanged();
|
||||||
|
void canDeactivateChanged();
|
||||||
|
void canRemoveChanged();
|
||||||
|
void canSetGroupChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, QString, bId, &Workspace::idChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, QString, bName, &Workspace::nameChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bActive, &Workspace::activeChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, WorkspaceGroup*, bGroup, &Workspace::groupChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bShouldDisplay, &Workspace::shouldDisplayChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bUrgent, &Workspace::urgentChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bCanActivate, &Workspace::canActivateChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bCanDeactivate, &Workspace::canDeactivateChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bCanRemove, &Workspace::canRemoveChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(Workspace, bool, bCanSetGroup, &Workspace::canSetGroupChanged);
|
||||||
|
//Q_OBJECT_BINDABLE_PROPERTY(Workspace, qint32, bIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WorkspaceGroup: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
QML_ELEMENT;
|
||||||
|
QML_UNCREATABLE("");
|
||||||
|
/// Screens the workspace group is present on.
|
||||||
|
///
|
||||||
|
/// > [!WARNING] This is not a model. Use @@Quickshell.ScriptModel if you need it to
|
||||||
|
/// > behave like one.
|
||||||
|
Q_PROPERTY(QList<QuickshellScreenInfo*> screens READ screens NOTIFY screensChanged);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WorkspaceGroup(QObject* parent): QObject(parent) {}
|
||||||
|
|
||||||
|
[[nodiscard]] const QList<QuickshellScreenInfo*>& screens() const { return this->mCachedScreens; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void screensChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onScreensChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(
|
||||||
|
WorkspaceGroup,
|
||||||
|
QList<QScreen*>,
|
||||||
|
bScreens,
|
||||||
|
&WorkspaceGroup::onScreensChanged
|
||||||
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<QuickshellScreenInfo*> mCachedScreens;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qs::wm
|
||||||
1
src/windowmanager/workspacemodel.cpp
Normal file
1
src/windowmanager/workspacemodel.cpp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include "workspacemodel.hpp"
|
||||||
39
src/windowmanager/workspacemodel.hpp
Normal file
39
src/windowmanager/workspacemodel.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qproperty.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
#include <qtypes.h>
|
||||||
|
|
||||||
|
namespace qs::windowsystem {
|
||||||
|
|
||||||
|
class WorkspaceModel: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
QML_ELEMENT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ConflictStrategy : quint8 {
|
||||||
|
KeepFirst = 0,
|
||||||
|
ShowDuplicates,
|
||||||
|
};
|
||||||
|
Q_ENUM(ConflictStrategy);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fromChanged();
|
||||||
|
void toChanged();
|
||||||
|
void screensChanged();
|
||||||
|
void conflictStrategyChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(WorkspaceModel, qint32, bFrom, &WorkspaceModel::fromChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(WorkspaceModel, qint32, bTo, &WorkspaceModel::toChanged);
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(
|
||||||
|
WorkspaceModel,
|
||||||
|
ConflictStrategy,
|
||||||
|
bConflictStrategy,
|
||||||
|
&WorkspaceModel::conflictStrategyChanged
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qs::windowsystem
|
||||||
Loading…
Add table
Add a link
Reference in a new issue