mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-04-10 06:11:54 +10:00
Compare commits
No commits in common. "6705e2da778d216e81dbdc3764a3f50e89bfd87d" and "1b2519d9f3d963e575b8a1ef08fab47c7af0d1b3" have entirely different histories.
6705e2da77
...
1b2519d9f3
24 changed files with 0 additions and 1371 deletions
|
|
@ -26,7 +26,6 @@ set shell id.
|
||||||
- Added Quickshell version checking and version gated preprocessing.
|
- Added Quickshell version checking and version gated preprocessing.
|
||||||
- Added a way to detect if an icon is from the system icon theme or not.
|
- Added a way to detect if an icon is from the system icon theme or not.
|
||||||
- Added vulkan support to screencopy.
|
- Added vulkan support to screencopy.
|
||||||
- Added generic WindowManager interface implementing ext-workspace.
|
|
||||||
|
|
||||||
## Other Changes
|
## Other Changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ 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_HANDLER)
|
if (CRASH_HANDLER)
|
||||||
add_subdirectory(crash)
|
add_subdirectory(crash)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
#include "debuginfo.hpp"
|
#include "debuginfo.hpp"
|
||||||
#include <array>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <qconfig.h>
|
#include <qconfig.h>
|
||||||
|
|
@ -17,8 +14,6 @@
|
||||||
|
|
||||||
#include "build.hpp"
|
#include "build.hpp"
|
||||||
|
|
||||||
extern char** environ; // NOLINT
|
|
||||||
|
|
||||||
namespace qs::debuginfo {
|
namespace qs::debuginfo {
|
||||||
|
|
||||||
QString qsVersion() {
|
QString qsVersion() {
|
||||||
|
|
@ -124,31 +119,6 @@ QString systemInfo() {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString envInfo() {
|
|
||||||
QString info;
|
|
||||||
auto stream = QTextStream(&info);
|
|
||||||
|
|
||||||
for (auto** envp = environ; *envp != nullptr; ++envp) { // NOLINT
|
|
||||||
auto prefixes = std::array<std::string_view, 5> {
|
|
||||||
"QS_",
|
|
||||||
"QT_",
|
|
||||||
"QML_",
|
|
||||||
"QML2_",
|
|
||||||
"QSG_",
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto& prefix: prefixes) {
|
|
||||||
if (strncmp(prefix.data(), *envp, prefix.length()) == 0) goto print;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
|
|
||||||
print:
|
|
||||||
stream << *envp << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString combinedInfo() {
|
QString combinedInfo() {
|
||||||
QString info;
|
QString info;
|
||||||
auto stream = QTextStream(&info);
|
auto stream = QTextStream(&info);
|
||||||
|
|
@ -166,9 +136,6 @@ QString combinedInfo() {
|
||||||
stream << "\n===== System Information =====\n";
|
stream << "\n===== System Information =====\n";
|
||||||
stream << systemInfo();
|
stream << systemInfo();
|
||||||
|
|
||||||
stream << "\n===== Environment (trimmed) =====\n";
|
|
||||||
stream << envInfo();
|
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ QString qsVersion();
|
||||||
QString qtVersion();
|
QString qtVersion();
|
||||||
QString gpuInfo();
|
QString gpuInfo();
|
||||||
QString systemInfo();
|
QString systemInfo();
|
||||||
QString envInfo();
|
|
||||||
QString combinedInfo();
|
QString combinedInfo();
|
||||||
|
|
||||||
} // namespace qs::debuginfo
|
} // namespace qs::debuginfo
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,6 @@ list(APPEND WAYLAND_MODULES Quickshell.Wayland._IdleNotify)
|
||||||
add_subdirectory(shortcuts_inhibit)
|
add_subdirectory(shortcuts_inhibit)
|
||||||
list(APPEND WAYLAND_MODULES Quickshell.Wayland._ShortcutsInhibitor)
|
list(APPEND WAYLAND_MODULES Quickshell.Wayland._ShortcutsInhibitor)
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
qt_add_library(quickshell-wayland-windowsystem STATIC
|
|
||||||
windowmanager.cpp
|
|
||||||
windowset.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-workspace ext-workspace-v1 "${WAYLAND_PROTOCOLS}/staging/ext-workspace")
|
|
||||||
|
|
||||||
target_link_libraries(quickshell-wayland-windowsystem PRIVATE
|
|
||||||
Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
|
|
||||||
wlp-ext-workspace
|
|
||||||
)
|
|
||||||
|
|
||||||
qs_pch(quickshell-wayland-windowsystem SET large)
|
|
||||||
|
|
||||||
target_link_libraries(quickshell PRIVATE quickshell-wayland-windowsystem quickshell-wayland-windowsystem-init)
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
#include "ext_workspace.hpp"
|
|
||||||
|
|
||||||
#include <qcontainerfwd.h>
|
|
||||||
#include <qlogging.h>
|
|
||||||
#include <qloggingcategory.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 <wayland-util.h>
|
|
||||||
|
|
||||||
#include "../../core/logcat.hpp"
|
|
||||||
|
|
||||||
namespace qs::wayland::workspace {
|
|
||||||
|
|
||||||
QS_LOGGING_CATEGORY(logWorkspace, "quickshell.wm.wayland.workspace", QtWarningMsg);
|
|
||||||
|
|
||||||
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(quint32 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
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qcontainerfwd.h>
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qloggingcategory.h>
|
|
||||||
#include <qscreen.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 "../../core/logcat.hpp"
|
|
||||||
#include "../output_tracking.hpp"
|
|
||||||
|
|
||||||
namespace qs::wayland::workspace {
|
|
||||||
|
|
||||||
QS_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(quint32 state) override;
|
|
||||||
void ext_workspace_handle_v1_capabilities(quint32 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(quint32 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
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#include <qcontainerfwd.h>
|
|
||||||
#include <qguiapplication.h>
|
|
||||||
#include <qlist.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
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#include "windowmanager.hpp"
|
|
||||||
|
|
||||||
#include "../../windowmanager/windowmanager.hpp"
|
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm::wayland {
|
|
||||||
|
|
||||||
WaylandWindowManager* WaylandWindowManager::instance() {
|
|
||||||
static auto* instance = []() {
|
|
||||||
auto* wm = new WaylandWindowManager();
|
|
||||||
WindowsetManager::instance();
|
|
||||||
return wm;
|
|
||||||
}();
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void installWmProvider() { // NOLINT (misc-use-internal-linkage)
|
|
||||||
qs::wm::WindowManager::setProvider([]() { return WaylandWindowManager::instance(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace qs::wm::wayland
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qtmetamacros.h>
|
|
||||||
|
|
||||||
#include "../../windowmanager/windowmanager.hpp"
|
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm::wayland {
|
|
||||||
|
|
||||||
class WaylandWindowManager: public WindowManager {
|
|
||||||
Q_OBJECT;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static WaylandWindowManager* instance();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace qs::wm::wayland
|
|
||||||
|
|
@ -1,252 +0,0 @@
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qlogging.h>
|
|
||||||
#include <qloggingcategory.h>
|
|
||||||
#include <qnamespace.h>
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qobjectdefs.h>
|
|
||||||
#include <qproperty.h>
|
|
||||||
|
|
||||||
#include "../../windowmanager/windowmanager.hpp"
|
|
||||||
#include "../../windowmanager/windowset.hpp"
|
|
||||||
#include "../../windowmanager/screenprojection.hpp"
|
|
||||||
#include "ext_workspace.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm::wayland {
|
|
||||||
|
|
||||||
WindowsetManager::WindowsetManager() {
|
|
||||||
auto* impl = impl::WorkspaceManager::instance();
|
|
||||||
|
|
||||||
QObject::connect(
|
|
||||||
impl,
|
|
||||||
&impl::WorkspaceManager::serverCommit,
|
|
||||||
this,
|
|
||||||
&WindowsetManager::onServerCommit
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(
|
|
||||||
impl,
|
|
||||||
&impl::WorkspaceManager::workspaceCreated,
|
|
||||||
this,
|
|
||||||
&WindowsetManager::onWindowsetCreated
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(
|
|
||||||
impl,
|
|
||||||
&impl::WorkspaceManager::workspaceDestroyed,
|
|
||||||
this,
|
|
||||||
&WindowsetManager::onWindowsetDestroyed
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(
|
|
||||||
impl,
|
|
||||||
&impl::WorkspaceManager::groupCreated,
|
|
||||||
this,
|
|
||||||
&WindowsetManager::onProjectionCreated
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(
|
|
||||||
impl,
|
|
||||||
&impl::WorkspaceManager::groupDestroyed,
|
|
||||||
this,
|
|
||||||
&WindowsetManager::onProjectionDestroyed
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::scheduleCommit() {
|
|
||||||
if (this->commitScheduled) {
|
|
||||||
qCDebug(impl::logWorkspace) << "Workspace commit already scheduled.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(impl::logWorkspace) << "Scheduling workspace commit...";
|
|
||||||
this->commitScheduled = true;
|
|
||||||
QMetaObject::invokeMethod(this, &WindowsetManager::doCommit, Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::doCommit() { // NOLINT
|
|
||||||
qCDebug(impl::logWorkspace) << "Committing workspaces...";
|
|
||||||
impl::WorkspaceManager::instance()->commit();
|
|
||||||
this->commitScheduled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::onServerCommit() {
|
|
||||||
// Projections are created/destroyed around windowsets to avoid any nulls making it
|
|
||||||
// to the qml engine.
|
|
||||||
|
|
||||||
Qt::beginPropertyUpdateGroup();
|
|
||||||
|
|
||||||
auto* wm = WindowManager::instance();
|
|
||||||
auto windowsets = wm->bWindowsets.value();
|
|
||||||
auto projections = wm->bWindowsetProjections.value();
|
|
||||||
|
|
||||||
for (auto* projImpl: this->pendingProjectionCreations) {
|
|
||||||
auto* projection = new WlWindowsetProjection(this, projImpl);
|
|
||||||
this->projectionsByImpl.insert(projImpl, projection);
|
|
||||||
projections.append(projection);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* wsImpl: this->pendingWindowsetCreations) {
|
|
||||||
auto* ws = new WlWindowset(this, wsImpl);
|
|
||||||
this->windowsetByImpl.insert(wsImpl, ws);
|
|
||||||
windowsets.append(ws);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* wsImpl: this->pendingWindowsetDestructions) {
|
|
||||||
windowsets.removeOne(this->windowsetByImpl.value(wsImpl));
|
|
||||||
this->windowsetByImpl.remove(wsImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* projImpl: this->pendingProjectionDestructions) {
|
|
||||||
projections.removeOne(this->projectionsByImpl.value(projImpl));
|
|
||||||
this->projectionsByImpl.remove(projImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* ws: windowsets) {
|
|
||||||
static_cast<WlWindowset*>(ws)->commitImpl(); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* projection: projections) {
|
|
||||||
static_cast<WlWindowsetProjection*>(projection)->commitImpl(); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
this->pendingWindowsetCreations.clear();
|
|
||||||
this->pendingWindowsetDestructions.clear();
|
|
||||||
this->pendingProjectionCreations.clear();
|
|
||||||
this->pendingProjectionDestructions.clear();
|
|
||||||
|
|
||||||
wm->bWindowsets = windowsets;
|
|
||||||
wm->bWindowsetProjections = projections;
|
|
||||||
|
|
||||||
Qt::endPropertyUpdateGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::onWindowsetCreated(impl::Workspace* workspace) {
|
|
||||||
this->pendingWindowsetCreations.append(workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::onWindowsetDestroyed(impl::Workspace* workspace) {
|
|
||||||
if (!this->pendingWindowsetCreations.removeOne(workspace)) {
|
|
||||||
this->pendingWindowsetDestructions.append(workspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::onProjectionCreated(impl::WorkspaceGroup* group) {
|
|
||||||
this->pendingProjectionCreations.append(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsetManager::onProjectionDestroyed(impl::WorkspaceGroup* group) {
|
|
||||||
if (!this->pendingProjectionCreations.removeOne(group)) {
|
|
||||||
this->pendingProjectionDestructions.append(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowsetManager* WindowsetManager::instance() {
|
|
||||||
static auto* instance = new WindowsetManager();
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
WlWindowset::WlWindowset(WindowsetManager* manager, impl::Workspace* impl)
|
|
||||||
: Windowset(manager)
|
|
||||||
, impl(impl) {
|
|
||||||
this->commitImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WlWindowset::commitImpl() {
|
|
||||||
Qt::beginPropertyUpdateGroup();
|
|
||||||
this->bId = this->impl->id;
|
|
||||||
this->bName = this->impl->name;
|
|
||||||
this->bCoordinates = this->impl->coordinates;
|
|
||||||
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->bCanSetProjection = this->impl->canAssign;
|
|
||||||
this->bProjection = this->manager()->projectionsByImpl.value(this->impl->group);
|
|
||||||
Qt::endPropertyUpdateGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WlWindowset::activate() {
|
|
||||||
if (!this->bCanActivate) {
|
|
||||||
qCritical(logWorkspace) << this << "cannot be activated";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(impl::logWorkspace) << "Calling activate() for" << this;
|
|
||||||
this->impl->activate();
|
|
||||||
WindowsetManager::instance()->scheduleCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WlWindowset::deactivate() {
|
|
||||||
if (!this->bCanDeactivate) {
|
|
||||||
qCritical(logWorkspace) << this << "cannot be deactivated";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(impl::logWorkspace) << "Calling deactivate() for" << this;
|
|
||||||
this->impl->deactivate();
|
|
||||||
WindowsetManager::instance()->scheduleCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WlWindowset::remove() {
|
|
||||||
if (!this->bCanRemove) {
|
|
||||||
qCritical(logWorkspace) << this << "cannot be removed";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(impl::logWorkspace) << "Calling remove() for" << this;
|
|
||||||
this->impl->remove();
|
|
||||||
WindowsetManager::instance()->scheduleCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WlWindowset::setProjection(WindowsetProjection* projection) {
|
|
||||||
if (!this->bCanSetProjection) {
|
|
||||||
qCritical(logWorkspace) << this << "cannot be assigned to a projection";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!projection) {
|
|
||||||
qCritical(logWorkspace) << "Cannot set a windowset's projection to null";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WlWindowsetProjection* wlProjection = nullptr;
|
|
||||||
if (auto* p = dynamic_cast<WlWindowsetProjection*>(projection)) {
|
|
||||||
wlProjection = p;
|
|
||||||
} else if (auto* p = dynamic_cast<ScreenProjection*>(projection)) {
|
|
||||||
// In the 99% case, there will only be a single windowset on a screen.
|
|
||||||
// In the 1% case, the oldest projection (first in list) is most likely the desired one.
|
|
||||||
auto* screen = p->screen();
|
|
||||||
for (const auto& proj: WindowsetManager::instance()->projectionsByImpl.values()) {
|
|
||||||
if (proj->bQScreens.value().contains(screen)) {
|
|
||||||
wlProjection = proj;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wlProjection) {
|
|
||||||
qCritical(logWorkspace) << "Cannot set a windowset's projection to" << projection
|
|
||||||
<< "as no wayland projection could be derived.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(impl::logWorkspace) << "Assigning" << this << "to" << projection;
|
|
||||||
this->impl->assign(wlProjection->impl->object());
|
|
||||||
WindowsetManager::instance()->scheduleCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
WlWindowsetProjection::WlWindowsetProjection(WindowsetManager* manager, impl::WorkspaceGroup* impl)
|
|
||||||
: WindowsetProjection(manager)
|
|
||||||
, impl(impl) {
|
|
||||||
this->commitImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WlWindowsetProjection::commitImpl() {
|
|
||||||
// TODO: will not commit the correct screens if missing qt repr at commit time
|
|
||||||
this->bQScreens = this->impl->screens.screens();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace qs::wm::wayland
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qhash.h>
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qproperty.h>
|
|
||||||
#include <qtmetamacros.h>
|
|
||||||
|
|
||||||
#include "../../windowmanager/windowset.hpp"
|
|
||||||
#include "ext_workspace.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm::wayland {
|
|
||||||
namespace impl = qs::wayland::workspace;
|
|
||||||
|
|
||||||
class WlWindowset;
|
|
||||||
class WlWindowsetProjection;
|
|
||||||
|
|
||||||
class WindowsetManager: public QObject {
|
|
||||||
Q_OBJECT;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static WindowsetManager* instance();
|
|
||||||
|
|
||||||
void scheduleCommit();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void doCommit();
|
|
||||||
void onServerCommit();
|
|
||||||
void onWindowsetCreated(impl::Workspace* workspace);
|
|
||||||
void onWindowsetDestroyed(impl::Workspace* workspace);
|
|
||||||
void onProjectionCreated(impl::WorkspaceGroup* group);
|
|
||||||
void onProjectionDestroyed(impl::WorkspaceGroup* group);
|
|
||||||
|
|
||||||
private:
|
|
||||||
WindowsetManager();
|
|
||||||
|
|
||||||
bool commitScheduled = false;
|
|
||||||
|
|
||||||
QList<impl::Workspace*> pendingWindowsetCreations;
|
|
||||||
QList<impl::Workspace*> pendingWindowsetDestructions;
|
|
||||||
QHash<impl::Workspace*, WlWindowset*> windowsetByImpl;
|
|
||||||
|
|
||||||
QList<impl::WorkspaceGroup*> pendingProjectionCreations;
|
|
||||||
QList<impl::WorkspaceGroup*> pendingProjectionDestructions;
|
|
||||||
QHash<impl::WorkspaceGroup*, WlWindowsetProjection*> projectionsByImpl;
|
|
||||||
|
|
||||||
friend class WlWindowset;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WlWindowset: public Windowset {
|
|
||||||
public:
|
|
||||||
WlWindowset(WindowsetManager* manager, impl::Workspace* impl);
|
|
||||||
|
|
||||||
void commitImpl();
|
|
||||||
|
|
||||||
void activate() override;
|
|
||||||
void deactivate() override;
|
|
||||||
void remove() override;
|
|
||||||
void setProjection(WindowsetProjection* projection) override;
|
|
||||||
|
|
||||||
[[nodiscard]] WindowsetManager* manager() {
|
|
||||||
return static_cast<WindowsetManager*>(this->parent()); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
impl::Workspace* impl = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WlWindowsetProjection: public WindowsetProjection {
|
|
||||||
public:
|
|
||||||
WlWindowsetProjection(WindowsetManager* manager, impl::WorkspaceGroup* impl);
|
|
||||||
|
|
||||||
void commitImpl();
|
|
||||||
|
|
||||||
[[nodiscard]] WindowsetManager* manager() {
|
|
||||||
return static_cast<WindowsetManager*>(this->parent()); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
impl::WorkspaceGroup* impl = nullptr;
|
|
||||||
|
|
||||||
friend class WlWindowset;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace qs::wm::wayland
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
qt_add_library(quickshell-windowmanager STATIC
|
|
||||||
screenprojection.cpp
|
|
||||||
windowmanager.cpp
|
|
||||||
windowset.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)
|
|
||||||
|
|
||||||
qs_module_pch(quickshell-windowmanager SET large)
|
|
||||||
|
|
||||||
target_link_libraries(quickshell-windowmanager PRIVATE Qt::Quick)
|
|
||||||
target_link_libraries(quickshell PRIVATE quickshell-windowmanagerplugin)
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
name = "Quickshell.WindowManager"
|
|
||||||
description = "Window manager interface"
|
|
||||||
headers = [
|
|
||||||
"windowmanager.hpp",
|
|
||||||
"windowset.hpp",
|
|
||||||
"screenprojection.hpp",
|
|
||||||
]
|
|
||||||
-----
|
|
||||||
Currently only supports the [ext-workspace-v1](https://wayland.app/protocols/ext-workspace-v1) wayland protocol.
|
|
||||||
Support will be expanded in future releases.
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
#include "screenprojection.hpp"
|
|
||||||
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qscreen.h>
|
|
||||||
|
|
||||||
#include "windowmanager.hpp"
|
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm {
|
|
||||||
|
|
||||||
ScreenProjection::ScreenProjection(QScreen* screen, QObject* parent)
|
|
||||||
: WindowsetProjection(parent)
|
|
||||||
, mScreen(screen) {
|
|
||||||
this->bQScreens = {screen};
|
|
||||||
this->bWindowsets.setBinding([this]() {
|
|
||||||
QList<Windowset*> result;
|
|
||||||
for (auto* ws: WindowManager::instance()->bindableWindowsets().value()) {
|
|
||||||
auto* proj = ws->bindableProjection().value();
|
|
||||||
if (proj && proj->bindableQScreens().value().contains(this->mScreen)) {
|
|
||||||
result.append(ws);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QScreen* ScreenProjection::screen() const { return this->mScreen; }
|
|
||||||
|
|
||||||
} // namespace qs::wm
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qqmlintegration.h>
|
|
||||||
#include <qscreen.h>
|
|
||||||
#include <qtmetamacros.h>
|
|
||||||
|
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm {
|
|
||||||
|
|
||||||
///! WindowsetProjection covering one specific screen.
|
|
||||||
/// A ScreenProjection is a special type of @@WindowsetProjection which aggregates
|
|
||||||
/// all windowsets across all projections covering a specific screen.
|
|
||||||
///
|
|
||||||
/// When used with @@Windowset.setProjection(), an arbitrary projection on the screen
|
|
||||||
/// will be picked. Usually there is only one.
|
|
||||||
///
|
|
||||||
/// Use @@WindowManager.screenProjection() to get a ScreenProjection for a given screen.
|
|
||||||
class ScreenProjection: public WindowsetProjection {
|
|
||||||
Q_OBJECT;
|
|
||||||
QML_ELEMENT;
|
|
||||||
QML_UNCREATABLE("");
|
|
||||||
|
|
||||||
public:
|
|
||||||
ScreenProjection(QScreen* screen, QObject* parent);
|
|
||||||
|
|
||||||
[[nodiscard]] QScreen* screen() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QScreen* mScreen;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace qs::wm
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls.Fusion
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import Quickshell.WindowManager
|
|
||||||
|
|
||||||
WrapperRectangle {
|
|
||||||
id: delegate
|
|
||||||
required property Windowset modelData;
|
|
||||||
color: modelData.active ? "green" : "gray"
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Label { text: delegate.modelData.toString() }
|
|
||||||
Label { text: `Id: ${delegate.modelData.id} Name: ${delegate.modelData.name}` }
|
|
||||||
Label { text: `Coordinates: ${delegate.modelData.coordinates.toString()}`}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Label { text: "Group:" }
|
|
||||||
ComboBox {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
implicitContentWidthPolicy: ComboBox.WidestText
|
|
||||||
enabled: delegate.modelData.canSetProjection
|
|
||||||
model: [...WindowManager.windowsetProjections].map(w => w.toString())
|
|
||||||
currentIndex: WindowManager.windowsetProjections.indexOf(delegate.modelData.projection)
|
|
||||||
onActivated: i => delegate.modelData.setProjection(WindowManager.windowsetProjections[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Label { text: "Screen:" }
|
|
||||||
ComboBox {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
implicitContentWidthPolicy: ComboBox.WidestText
|
|
||||||
enabled: delegate.modelData.canSetProjection
|
|
||||||
model: [...Quickshell.screens].map(w => w.name)
|
|
||||||
currentIndex: Quickshell.screens.indexOf(delegate.modelData.projection.screens[0])
|
|
||||||
onActivated: i => delegate.modelData.setProjection(WindowManager.screenProjection(Quickshell.screens[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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
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: Quickshell.screens
|
|
||||||
|
|
||||||
WrapperRectangle {
|
|
||||||
id: delegate
|
|
||||||
required property ShellScreen modelData
|
|
||||||
color: "slategray"
|
|
||||||
margin: 5
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Label { text: `Screen: ${delegate.modelData.name}` }
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: ScriptModel {
|
|
||||||
values: WindowManager.screenProjection(delegate.modelData).windowsets
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkspaceDelegate {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: ScriptModel {
|
|
||||||
values: WindowManager.windowsets.filter(w => w.projection == null)
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkspaceDelegate {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
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.windowsetProjections
|
|
||||||
|
|
||||||
WrapperRectangle {
|
|
||||||
id: delegate
|
|
||||||
required property WindowsetProjection 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: delegate.modelData.windowsets
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkspaceDelegate {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: ScriptModel {
|
|
||||||
values: WindowManager.windowsets.filter(w => w.projection == null)
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkspaceDelegate {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#include "windowmanager.hpp"
|
|
||||||
#include <functional>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <qobject.h>
|
|
||||||
|
|
||||||
#include "../core/qmlscreen.hpp"
|
|
||||||
#include "screenprojection.hpp"
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScreenProjection* WindowManager::screenProjection(QuickshellScreenInfo* screen) {
|
|
||||||
auto* qscreen = screen->screen;
|
|
||||||
auto it = this->mScreenProjections.find(qscreen);
|
|
||||||
if (it != this->mScreenProjections.end()) {
|
|
||||||
return *it;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* projection = new ScreenProjection(qscreen, this);
|
|
||||||
this->mScreenProjections.insert(qscreen, projection);
|
|
||||||
|
|
||||||
QObject::connect(qscreen, &QObject::destroyed, this, [this, projection, qscreen]() {
|
|
||||||
this->mScreenProjections.remove(qscreen);
|
|
||||||
delete projection;
|
|
||||||
});
|
|
||||||
|
|
||||||
return projection;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace qs::wm
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include <qhash.h>
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qproperty.h>
|
|
||||||
#include <qqmlintegration.h>
|
|
||||||
#include <qscreen.h>
|
|
||||||
#include <qtmetamacros.h>
|
|
||||||
|
|
||||||
#include "../core/qmlscreen.hpp"
|
|
||||||
#include "screenprojection.hpp"
|
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm {
|
|
||||||
|
|
||||||
class WindowManager: public QObject {
|
|
||||||
Q_OBJECT;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void setProvider(std::function<WindowManager*()> provider);
|
|
||||||
static WindowManager* instance();
|
|
||||||
|
|
||||||
Q_INVOKABLE ScreenProjection* screenProjection(QuickshellScreenInfo* screen);
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<QList<Windowset*>> bindableWindowsets() const {
|
|
||||||
return &this->bWindowsets;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<QList<WindowsetProjection*>> bindableWindowsetProjections() const {
|
|
||||||
return &this->bWindowsetProjections;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void windowsetsChanged();
|
|
||||||
void windowsetProjectionsChanged();
|
|
||||||
|
|
||||||
public:
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(
|
|
||||||
WindowManager,
|
|
||||||
QList<Windowset*>,
|
|
||||||
bWindowsets,
|
|
||||||
&WindowManager::windowsetsChanged
|
|
||||||
);
|
|
||||||
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(
|
|
||||||
WindowManager,
|
|
||||||
QList<WindowsetProjection*>,
|
|
||||||
bWindowsetProjections,
|
|
||||||
&WindowManager::windowsetProjectionsChanged
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::function<WindowManager*()> provider;
|
|
||||||
QHash<QScreen*, ScreenProjection*> mScreenProjections;
|
|
||||||
};
|
|
||||||
|
|
||||||
///! Window management interfaces exposed by the window manager.
|
|
||||||
class WindowManagerQml: public QObject {
|
|
||||||
Q_OBJECT;
|
|
||||||
QML_NAMED_ELEMENT(WindowManager);
|
|
||||||
QML_SINGLETON;
|
|
||||||
// clang-format off
|
|
||||||
/// All windowsets tracked by the WM across all projections.
|
|
||||||
Q_PROPERTY(QList<Windowset*> windowsets READ default BINDABLE bindableWindowsets);
|
|
||||||
/// All windowset projections tracked by the WM. Does not include
|
|
||||||
/// internal projections from @@screenProjection().
|
|
||||||
Q_PROPERTY(QList<WindowsetProjection*> windowsetProjections READ default BINDABLE bindableWindowsetProjections);
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Returns an internal WindowsetProjection that covers a single screen and contains all
|
|
||||||
/// windowsets on that screen, regardless of the WM-specified projection. Depending on
|
|
||||||
/// how the WM lays out its actual projections, multiple ScreenProjections may contain
|
|
||||||
/// the same Windowsets.
|
|
||||||
Q_INVOKABLE static ScreenProjection* screenProjection(QuickshellScreenInfo* screen) {
|
|
||||||
return WindowManager::instance()->screenProjection(screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static QBindable<QList<Windowset*>> bindableWindowsets() {
|
|
||||||
return WindowManager::instance()->bindableWindowsets();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static QBindable<QList<WindowsetProjection*>> bindableWindowsetProjections() {
|
|
||||||
return WindowManager::instance()->bindableWindowsetProjections();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace qs::wm
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
#include "windowset.hpp"
|
|
||||||
|
|
||||||
#include <qlist.h>
|
|
||||||
#include <qlogging.h>
|
|
||||||
#include <qloggingcategory.h>
|
|
||||||
#include <qobject.h>
|
|
||||||
|
|
||||||
#include "../core/qmlglobal.hpp"
|
|
||||||
#include "windowmanager.hpp"
|
|
||||||
|
|
||||||
namespace qs::wm {
|
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(logWorkspace, "quickshell.wm.workspace", QtWarningMsg);
|
|
||||||
|
|
||||||
void Windowset::activate() { qCCritical(logWorkspace) << this << "cannot be activated"; }
|
|
||||||
void Windowset::deactivate() { qCCritical(logWorkspace) << this << "cannot be deactivated"; }
|
|
||||||
void Windowset::remove() { qCCritical(logWorkspace) << this << "cannot be removed"; }
|
|
||||||
|
|
||||||
void Windowset::setProjection(WindowsetProjection* /*projection*/) {
|
|
||||||
qCCritical(logWorkspace) << this << "cannot be assigned to a projection";
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowsetProjection::WindowsetProjection(QObject* parent): QObject(parent) {
|
|
||||||
this->bWindowsets.setBinding([this] {
|
|
||||||
QList<Windowset*> result;
|
|
||||||
for (auto* ws: WindowManager::instance()->bindableWindowsets().value()) {
|
|
||||||
if (ws->bindableProjection().value() == this) {
|
|
||||||
result.append(ws);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
this->bScreens.setBinding([this] {
|
|
||||||
QList<QuickshellScreenInfo*> screens;
|
|
||||||
|
|
||||||
for (auto* screen: this->bQScreens.value()) {
|
|
||||||
screens.append(QuickshellTracked::instance()->screenInfo(screen));
|
|
||||||
}
|
|
||||||
|
|
||||||
return screens;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace qs::wm
|
|
||||||
|
|
@ -1,175 +0,0 @@
|
||||||
#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 WindowsetProjection;
|
|
||||||
|
|
||||||
///! A group of windows worked with by a user, usually known as a Workspace or Tag.
|
|
||||||
/// A Windowset is a generic type that encompasses both "Workspaces" and "Tags" in window managers.
|
|
||||||
/// Because the definition encompasses both you may not necessarily need all features.
|
|
||||||
class Windowset: public QObject {
|
|
||||||
Q_OBJECT;
|
|
||||||
QML_ELEMENT;
|
|
||||||
QML_UNCREATABLE("");
|
|
||||||
// clang-format off
|
|
||||||
/// A persistent internal identifier for the windowset. This property should be identical
|
|
||||||
/// across restarts and destruction/recreation of a windowset.
|
|
||||||
Q_PROPERTY(QString id READ default NOTIFY idChanged BINDABLE bindableId);
|
|
||||||
/// Human readable name of the windowset.
|
|
||||||
Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName);
|
|
||||||
/// Coordinates of the workspace, represented as an N-dimensional array. Most WMs
|
|
||||||
/// will only expose one coordinate. If more than one is exposed, the first is
|
|
||||||
/// conventionally X, the second Y, and the third Z.
|
|
||||||
Q_PROPERTY(QList<qint32> coordinates READ default NOTIFY coordinatesChanged BINDABLE bindableCoordinates);
|
|
||||||
/// True if the windowset is currently active. In a workspace based WM, this means the
|
|
||||||
/// represented workspace is current. In a tag based WM, this means the represented tag
|
|
||||||
/// is active.
|
|
||||||
Q_PROPERTY(bool active READ default NOTIFY activeChanged BINDABLE bindableActive);
|
|
||||||
/// The projection this windowset is a member of. A projection is the set of screens covered by
|
|
||||||
/// a windowset.
|
|
||||||
Q_PROPERTY(WindowsetProjection* projection READ default NOTIFY projectionChanged BINDABLE bindableProjection);
|
|
||||||
/// If false, this windowset should generally be hidden from workspace pickers.
|
|
||||||
Q_PROPERTY(bool shouldDisplay READ default NOTIFY shouldDisplayChanged BINDABLE bindableShouldDisplay);
|
|
||||||
/// If true, a window in this windowset has been marked as urgent.
|
|
||||||
Q_PROPERTY(bool urgent READ default NOTIFY urgentChanged BINDABLE bindableUrgent);
|
|
||||||
/// If true, the windowset can be activated. In a workspace based WM, this will make the workspace
|
|
||||||
/// current, in a tag based wm, the tag will be activated.
|
|
||||||
Q_PROPERTY(bool canActivate READ default NOTIFY canActivateChanged BINDABLE bindableCanActivate);
|
|
||||||
/// If true, the windowset can be deactivated. In a workspace based WM, deactivation is usually implicit
|
|
||||||
/// and based on activation of another workspace.
|
|
||||||
Q_PROPERTY(bool canDeactivate READ default NOTIFY canDeactivateChanged BINDABLE bindableCanDeactivate);
|
|
||||||
/// If true, the windowset can be removed. This may be done implicitly by the WM as well.
|
|
||||||
Q_PROPERTY(bool canRemove READ default NOTIFY canRemoveChanged BINDABLE bindableCanRemove);
|
|
||||||
/// If true, the windowset can be moved to a different projection.
|
|
||||||
Q_PROPERTY(bool canSetProjection READ default NOTIFY canSetProjectionChanged BINDABLE bindableCanSetProjection);
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Windowset(QObject* parent): QObject(parent) {}
|
|
||||||
|
|
||||||
/// Activate the windowset, making it the current workspace on a workspace based WM, or activating
|
|
||||||
/// the tag on a tag based WM. Requires @@canActivate.
|
|
||||||
Q_INVOKABLE virtual void activate();
|
|
||||||
/// Deactivate the windowset, hiding it. Requires @@canDeactivate.
|
|
||||||
Q_INVOKABLE virtual void deactivate();
|
|
||||||
/// Remove or destroy the windowset. Requires @@canRemove.
|
|
||||||
Q_INVOKABLE virtual void remove();
|
|
||||||
/// Move the windowset to a different projection. A projection represents the set of screens
|
|
||||||
/// a workspace spans. Requires @@canSetProjection.
|
|
||||||
Q_INVOKABLE virtual void setProjection(WindowsetProjection* projection);
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<QString> bindableId() const { return &this->bId; }
|
|
||||||
[[nodiscard]] QBindable<QString> bindableName() const { return &this->bName; }
|
|
||||||
[[nodiscard]] QBindable<QList<qint32>> bindableCoordinates() const { return &this->bCoordinates; }
|
|
||||||
[[nodiscard]] QBindable<bool> bindableActive() const { return &this->bActive; }
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<WindowsetProjection*> bindableProjection() const {
|
|
||||||
return &this->bProjection;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[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> bindableCanSetProjection() const {
|
|
||||||
return &this->bCanSetProjection;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void idChanged();
|
|
||||||
void nameChanged();
|
|
||||||
void coordinatesChanged();
|
|
||||||
void activeChanged();
|
|
||||||
void projectionChanged();
|
|
||||||
void shouldDisplayChanged();
|
|
||||||
void urgentChanged();
|
|
||||||
void canActivateChanged();
|
|
||||||
void canDeactivateChanged();
|
|
||||||
void canRemoveChanged();
|
|
||||||
void canSetProjectionChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// clang-format off
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, QString, bId, &Windowset::idChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, QString, bName, &Windowset::nameChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, QList<qint32>, bCoordinates);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bActive, &Windowset::activeChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, WindowsetProjection*, bProjection, &Windowset::projectionChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bShouldDisplay, &Windowset::shouldDisplayChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bUrgent, &Windowset::urgentChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bCanActivate, &Windowset::canActivateChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bCanDeactivate, &Windowset::canDeactivateChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bCanRemove, &Windowset::canRemoveChanged);
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(Windowset, bool, bCanSetProjection, &Windowset::canSetProjectionChanged);
|
|
||||||
// clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
///! A space occupiable by a Windowset.
|
|
||||||
/// A WindowsetProjection represents a space that can be occupied by one or more @@Windowset$s.
|
|
||||||
/// The space is one or more screens. Multiple projections may occupy the same screens.
|
|
||||||
///
|
|
||||||
/// @@WindowManager.screenProjection() can be used to get a projection representing all
|
|
||||||
/// @@Windowset$s on a given screen regardless of the WM's actual projection layout.
|
|
||||||
class WindowsetProjection: public QObject {
|
|
||||||
Q_OBJECT;
|
|
||||||
QML_ELEMENT;
|
|
||||||
QML_UNCREATABLE("");
|
|
||||||
// clang-format off
|
|
||||||
/// Screens the windowset projection spans, often a single screen or all screens.
|
|
||||||
Q_PROPERTY(QList<QuickshellScreenInfo*> screens READ default NOTIFY screensChanged BINDABLE bindableScreens);
|
|
||||||
/// Windowsets that are currently present on the projection.
|
|
||||||
Q_PROPERTY(QList<Windowset*> windowsets READ default NOTIFY windowsetsChanged BINDABLE bindableWindowsets);
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit WindowsetProjection(QObject* parent);
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<QList<QuickshellScreenInfo*>> bindableScreens() const {
|
|
||||||
return &this->bScreens;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<QList<QScreen*>> bindableQScreens() const { return &this->bQScreens; }
|
|
||||||
|
|
||||||
[[nodiscard]] QBindable<QList<Windowset*>> bindableWindowsets() const {
|
|
||||||
return &this->bWindowsets;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void screensChanged();
|
|
||||||
void windowsetsChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(WindowsetProjection, QList<QScreen*>, bQScreens);
|
|
||||||
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(
|
|
||||||
WindowsetProjection,
|
|
||||||
QList<QuickshellScreenInfo*>,
|
|
||||||
bScreens,
|
|
||||||
&WindowsetProjection::screensChanged
|
|
||||||
);
|
|
||||||
|
|
||||||
Q_OBJECT_BINDABLE_PROPERTY(
|
|
||||||
WindowsetProjection,
|
|
||||||
QList<Windowset*>,
|
|
||||||
bWindowsets,
|
|
||||||
&WindowsetProjection::windowsetsChanged
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace qs::wm
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue