summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif/shell
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif/shell')
-rw-r--r--accounts/gkleen@sif/shell/default.nix123
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt190
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/Chrono.cpp83
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/Chrono.hpp55
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.cpp102
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.hpp52
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.cpp18
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.hpp21
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp41
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp26
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp288
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp193
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/customplugin.h7
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/default.nix32
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml28
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml445
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Session.xml146
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml821
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml1100
-rw-r--r--accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml359
-rw-r--r--accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml172
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Bar.qml142
-rw-r--r--accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml139
-rw-r--r--accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml117
-rw-r--r--accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml84
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Clock.qml295
-rw-r--r--accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml112
-rw-r--r--accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml47
-rw-r--r--accounts/gkleen@sif/shell/quickshell/LockSurface.qml227
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Lockscreen.qml128
-rw-r--r--accounts/gkleen@sif/shell/quickshell/LockscreenInhibitorWidget.qml48
-rw-r--r--accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml35
-rw-r--r--accounts/gkleen@sif/shell/quickshell/NiriIdle.qml30
-rw-r--r--accounts/gkleen@sif/shell/quickshell/NotificationDisplay.qml340
-rw-r--r--accounts/gkleen@sif/shell/quickshell/NotificationInhibitorWidget.qml266
-rw-r--r--accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml483
-rw-r--r--accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml49
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml107
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/GpgAgent.qml18
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml23
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml8
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml217
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml162
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml63
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/ScreenRecord.qml63
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/WallpaperSelector.qml8
-rw-r--r--accounts/gkleen@sif/shell/quickshell/Services/Worktime.qml84
-rw-r--r--accounts/gkleen@sif/shell/quickshell/SystemTray.qml201
-rw-r--r--accounts/gkleen@sif/shell/quickshell/UnixIPC.qml106
-rw-r--r--accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml163
-rw-r--r--accounts/gkleen@sif/shell/quickshell/WallpaperBackground.qml89
-rw-r--r--accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml56
-rw-r--r--accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml204
-rw-r--r--accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml212
-rw-r--r--accounts/gkleen@sif/shell/quickshell/YtDlpWidget.qml190
-rw-r--r--accounts/gkleen@sif/shell/quickshell/displaymanager.qml115
-rw-r--r--accounts/gkleen@sif/shell/quickshell/shell.qml53
57 files changed, 8986 insertions, 0 deletions
diff --git a/accounts/gkleen@sif/shell/default.nix b/accounts/gkleen@sif/shell/default.nix
new file mode 100644
index 00000000..09eb6863
--- /dev/null
+++ b/accounts/gkleen@sif/shell/default.nix
@@ -0,0 +1,123 @@
1{ config, pkgs, lib, ... }:
2
3{
4 config = {
5 programs.quickshell = {
6 enable = true;
7 package = pkgs.symlinkJoin {
8 pname = pkgs.quickshell.pname + "-wrapped";
9 inherit (pkgs.quickshell) version meta;
10 paths = [ pkgs.quickshell ];
11 buildInputs = [ pkgs.makeWrapper ];
12 postBuild = ''
13 for binary in quickshell qs; do
14 wrapProgram $out/bin/$binary \
15 --prefix QT_PLUGIN_PATH : ${pkgs.qt6.qtimageformats}/${pkgs.qt6.qtbase.qtPluginPrefix} \
16 --prefix QML_IMPORT_PATH : ${pkgs.qt6Packages.callPackage ./quickshell-plugins {}}/${pkgs.qt6.qtbase.qtQmlPrefix}
17 done
18 '';
19 };
20 config = {
21 src = ./quickshell;
22 replacements = {
23 ignore_workspaces = builtins.toJSON (map ({ name, ... }: name) config.programs.niri.scratchspaces);
24 wallpapers = builtins.toJSON (pkgs.stdenvNoCC.mkDerivation {
25 name = "wallpapers";
26 srcs = [
27 (pkgs.fetchurl {
28 url = "https://esawebb.org/media/archives/images/publicationtiff10k/carinanebula3.tif";
29 hash = "sha256-YxZEweDKJfvfrdxb/QFmgJhcZDEJYxotoHrG+RRn1tw=";
30 })
31 (pkgs.fetchurl {
32 url = "https://esawebb.org/media/archives/images/original/pillarsofcreation_composite.tif";
33 hash = "sha256-qRiODxR0lZWdxgYXna0fNRFFDErpBJDwOJuQl6sNjRc=";
34 })
35 (pkgs.fetchurl {
36 url = "https://esawebb.org/media/archives/images/publicationtiff10k/weic2212a.tif";
37 hash = "sha256-l2fqE/z//C1a0xkvZwsnwPbTSb+WuA11h+SUl3E1dhw=";
38 })
39 (pkgs.fetchurl {
40 url = "https://esawebb.org/media/archives/images/publicationtiff10k/weic2415a.tif";
41 hash = "sha256-onBy7cPoUpDuzQStbY2E+qmlGgSLXPwFCLX53ukAb4c=";
42 })
43 (pkgs.fetchurl {
44 url = "https://esawebb.org/media/archives/images/publicationtiff10k/weic2330a.tif";
45 hash = "sha256-nn0ZtjZIrPcpj3YcLTsrL7XiXvyh3QYgCSmdDMD+3OM=";
46 })
47 (pkgs.fetchurl {
48 url = "https://esawebb.org/media/archives/images/original/weic2426a.tif";
49 hash = "sha256-EDnfPn3GE9jt6XPqiGInP7E2F3Az7d25NqATSWltDv0=";
50 })
51 (pkgs.fetchurl {
52 url = "https://esawebb.org/media/archives/images/original/weic2503a.tif";
53 hash = "sha256-3/RX6RQp8naELcgReHPd5/zhJkoCjnA10w5BEnNo+qI=";
54 })
55 (pkgs.fetchurl {
56 url = "https://esawebb.org/media/archives/images/original/weic2506a.tif";
57 hash = "sha256-aDld0aoY1owRxDVf7Jcyw71TH42M1foYotxn2thyFYw=";
58 })
59 (pkgs.fetchurl {
60 url = "https://esawebb.org/media/archives/images/original/weic2514a.tif";
61 hash = "sha256-jTi1G1Ofo5xsF6ggrbtYJHxqLaCQ7edM5B3uORiVQtg=";
62 })
63 (pkgs.fetchurl {
64 url = "https://esawebb.org/media/archives/images/original/weic2425c.tif";
65 hash = "sha256-oaEOexSJHEGj090dJF3ct5HAoR+Y5gRiPrUlxdvnTRo=";
66 })
67 (pkgs.fetchurl {
68 url = "https://esawebb.org/media/archives/images/original/weic2605c.tif";
69 hash = "sha256-IwWfgkz84LFXkfk77anb5e0Mf0wWiIszum7UC3yZn0U=";
70 })
71 ];
72
73 dontUnpack = true;
74
75 buildInputs = [ pkgs.imagemagick ];
76 buildPhase = ''
77 runHook preBuild
78
79 typeset sources=($srcs)
80
81 mkdir -p $out
82 magick ''${sources[0]} -crop 10000x5625+0+79 +repage -define webp:target-size=10000000 $out/carinanebula3.webp
83 magick ''${sources[1]} -crop 6716x3778+329+80 +repage -define webp:target-size=10000000 $out/pillarsofcreation_composite.webp
84 magick ''${sources[2]} -crop 10000x5625+0+79 +repage -define webp:target-size=10000000 $out/weic2212a.webp
85 magick ''${sources[3]} -crop 7650x4302+1166+389 +repage -define webp:target-size=10000000 $out/weic2415a.webp
86 magick ''${sources[4]} -crop 8732x4912+0+434 +repage -define webp:target-size=10000000 $out/weic2330a.webp
87 magick ''${sources[5]} -crop 5302x2982+636+0 +repage -define webp:target-size=10000000 $out/weic2426a.webp
88 magick ''${sources[6]} -crop 4328x2434+0+906 +repage -define webp:target-size=10000000 $out/weic2503a.webp
89 magick ''${sources[7]} -crop 4152x2335+0+666 +repage -define webp:target-size=10000000 $out/weic2506a.webp
90 magick ''${sources[8]} -crop 4320x2430+0+0 +repage -define webp:target-size=10000000 $out/weic2514a.webp
91 magick ''${sources[9]} -crop 5863x3298+0+477 +repage -define webp:target-size=10000000 $out/weic2425c.webp
92 magick ''${sources[10]} -crop 3990x2244+0+1379 +repage -define webp:target-size=10000000 $out/weic2605c.webp
93
94 runHook postBuild
95 '';
96 });
97 niri_session = builtins.toJSON [
98 (pkgs.writeShellScript "niri-session" ''
99 exec ${lib.getExe pkgs.dex} -w ${config.programs.niri.package}/share/wayland-sessions/niri.desktop &>/tmp/niri-session-$$.log
100 '')
101 # (lib.getExe pkgs.dex)
102 # "${config.programs.niri.package}/share/wayland-sessions/niri.desktop"
103 ];
104 username = builtins.toJSON config.home.username;
105 mdi = builtins.toJSON (pkgs.fetchFromGitHub {
106 owner = "Templarian";
107 repo = "MaterialDesign";
108 rev = "2424e748e0cc63ab7b9c095a099b9fe239b737c0";
109 hash = "sha256-QMGl7soAhErrrnY3aKOZpt49yebkSNzy10p/v5OaqQ0=";
110 });
111 worktime = builtins.toJSON (lib.getExe pkgs.worktime);
112 slurp = builtins.toJSON (lib.getExe pkgs.slurp);
113 wf-recorder = builtins.toJSON (lib.getExe pkgs.wf-recorder);
114 };
115 };
116 };
117 systemd.user.services.quickshell = {
118 Service = {
119 RuntimeDirectory = "quickshell";
120 };
121 };
122 };
123}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt b/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt
new file mode 100644
index 00000000..6b4f0d48
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt
@@ -0,0 +1,190 @@
1set(INSTALL_QMLDIR "" CACHE STRING "QML install dir")
2set(INSTALL_QML_PREFIX "" CACHE STRING "QML install prefix")
3
4# There doesn't seem to be a standard cross-distro qml install path.
5if ("${INSTALL_QMLDIR}" STREQUAL "" AND "${INSTALL_QML_PREFIX}" STREQUAL "")
6 message(WARNING "Neither INSTALL_QMLDIR nor INSTALL_QML_PREFIX is set. QML modules will not be installed.")
7else()
8 if ("${INSTALL_QMLDIR}" STREQUAL "")
9 set(QML_FULL_INSTALLDIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_QML_PREFIX}")
10 else()
11 set(QML_FULL_INSTALLDIR "${INSTALL_QMLDIR}")
12 endif()
13
14 message(STATUS "QML install dir: ${QML_FULL_INSTALLDIR}")
15endif()
16
17# Install a given target as a QML module. This is mostly pulled from ECM, as there does not seem
18# to be an official way to do it.
19# see https://github.com/KDE/extra-cmake-modules/blob/fe0f606bf7f222e36f7560fd7a2c33ef993e23bb/modules/ECMQmlModule6.cmake#L160
20function(install_qml_module arg_TARGET)
21 if (NOT DEFINED QML_FULL_INSTALLDIR)
22 return()
23 endif()
24
25 qt_query_qml_module(${arg_TARGET}
26 URI module_uri
27 VERSION module_version
28 PLUGIN_TARGET module_plugin_target
29 TARGET_PATH module_target_path
30 QMLDIR module_qmldir
31 TYPEINFO module_typeinfo
32 QML_FILES module_qml_files
33 RESOURCES module_resources
34 )
35
36 set(module_dir "${QML_FULL_INSTALLDIR}/${module_target_path}")
37
38 if (NOT TARGET "${module_plugin_target}")
39 message(FATAL_ERROR "install_qml_modules called for a target without a plugin")
40 endif()
41
42 get_target_property(target_type "${arg_TARGET}" TYPE)
43 if (NOT "${target_type}" STREQUAL "STATIC_LIBRARY")
44 install(
45 TARGETS "${arg_TARGET}"
46 LIBRARY DESTINATION "${module_dir}"
47 RUNTIME DESTINATION "${module_dir}"
48 )
49
50 install(
51 TARGETS "${module_plugin_target}"
52 LIBRARY DESTINATION "${module_dir}"
53 RUNTIME DESTINATION "${module_dir}"
54 )
55 endif()
56
57 install(FILES "${module_qmldir}" DESTINATION "${module_dir}")
58 install(FILES "${module_typeinfo}" DESTINATION "${module_dir}")
59
60 # Install QML files
61 list(LENGTH module_qml_files num_files)
62 if (NOT "${module_qml_files}" MATCHES "NOTFOUND" AND ${num_files} GREATER 0)
63 qt_query_qml_module(${arg_TARGET} QML_FILES_DEPLOY_PATHS qml_files_deploy_paths)
64
65 math(EXPR last_index "${num_files} - 1")
66 foreach(i RANGE 0 ${last_index})
67 list(GET module_qml_files ${i} src_file)
68 list(GET qml_files_deploy_paths ${i} deploy_path)
69 get_filename_component(dst_name "${deploy_path}" NAME)
70 get_filename_component(dest_dir "${deploy_path}" DIRECTORY)
71 install(FILES "${src_file}" DESTINATION "${module_dir}/${dest_dir}" RENAME "${dst_name}")
72 endforeach()
73 endif()
74
75 # Install resources
76 list(LENGTH module_resources num_files)
77 if (NOT "${module_resources}" MATCHES "NOTFOUND" AND ${num_files} GREATER 0)
78 qt_query_qml_module(${arg_TARGET} RESOURCES_DEPLOY_PATHS resources_deploy_paths)
79
80 math(EXPR last_index "${num_files} - 1")
81 foreach(i RANGE 0 ${last_index})
82 list(GET module_resources ${i} src_file)
83 list(GET resources_deploy_paths ${i} deploy_path)
84 get_filename_component(dst_name "${deploy_path}" NAME)
85 get_filename_component(dest_dir "${deploy_path}" DIRECTORY)
86 install(FILES "${src_file}" DESTINATION "${module_dir}/${dest_dir}" RENAME "${dst_name}")
87 endforeach()
88 endif()
89endfunction()
90
91
92cmake_minimum_required(VERSION 3.20)
93project(custom LANGUAGES CXX)
94
95find_package(Qt6 REQUIRED COMPONENTS Core Qml DBus)
96
97qt_standard_project_setup(REQUIRES 6.6)
98
99qt6_policy(SET QTP0001 NEW)
100qt6_add_qml_module(customplugin
101 URI "Custom"
102 PLUGIN_TARGET customplugin
103)
104
105set_source_files_properties(org.keepassxc.KeePassXC.MainWindow.xml PROPERTIES
106 CLASSNAME DBusKeePassXC
107 NO_NAMESPACE TRUE
108)
109qt_add_dbus_interface(DBUS_INTERFACES
110 org.keepassxc.KeePassXC.MainWindow.xml
111 dbus_keepassxc
112)
113
114set_source_files_properties(org.freedesktop.systemd1.Manager.xml PROPERTIES
115 CLASSNAME DBusSystemdManager
116 NO_NAMESPACE TRUE
117 INCLUDE ListUnitsEntry.hpp
118)
119qt_add_dbus_interface(DBUS_INTERFACES
120 org.freedesktop.systemd1.Manager.xml
121 dbus_systemd_manager
122)
123
124set_source_files_properties(org.freedesktop.login1.Manager.xml PROPERTIES
125 CLASSNAME DBusLogindManager
126 NO_NAMESPACE TRUE
127)
128qt_add_dbus_interface(DBUS_INTERFACES
129 org.freedesktop.login1.Manager.xml
130 dbus_logind_manager
131)
132
133set_source_files_properties(org.freedesktop.login1.Session.xml PROPERTIES
134 CLASSNAME DBusLogindSession
135 NO_NAMESPACE TRUE
136)
137qt_add_dbus_interface(DBUS_INTERFACES
138 org.freedesktop.login1.Session.xml
139 dbus_logind_session
140)
141
142set_source_files_properties(org.freedesktop.systemd1.Unit.xml PROPERTIES
143 CLASSNAME DBusSystemdUnit
144 NO_NAMESPACE TRUE
145)
146qt_add_dbus_interface(DBUS_INTERFACES
147 org.freedesktop.systemd1.Unit.xml
148 dbus_systemd_unit
149)
150
151set_source_files_properties(org.freedesktop.systemd1.Service.xml PROPERTIES
152 CLASSNAME DBusSystemdService
153 NO_NAMESPACE TRUE
154)
155qt_add_dbus_interface(DBUS_INTERFACES
156 org.freedesktop.systemd1.Service.xml
157 dbus_systemd_service
158)
159
160set_source_files_properties(org.freedesktop.DBus.Properties.xml PROPERTIES
161 CLASSNAME DBusProperties
162 NO_NAMESPACE TRUE
163)
164qt_add_dbus_interface(DBUS_INTERFACES
165 org.freedesktop.DBus.Properties.xml
166 dbus_properties
167)
168
169include_directories(${CMAKE_SOURCE_DIR}/build)
170include_directories(${QUICKSHELL_SRC}/src)
171
172target_compile_features(customplugin PUBLIC cxx_std_26)
173
174target_link_libraries(customplugin PRIVATE
175 Qt6::Core
176 Qt6::Qml
177 Qt6::DBus
178)
179
180target_sources(customplugin PRIVATE
181 Chrono.cpp Chrono.hpp
182 FileSelector.cpp FileSelector.hpp
183 KeePassXC.cpp KeePassXC.hpp
184 Systemd.cpp Systemd.hpp
185 ListUnitsEntry.cpp ListUnitsEntry.hpp
186 ${DBUS_INTERFACES}
187 ${QUICKSHELL_SRC}/src/core/model.cpp ${QUICKSHELL_SRC}/src/core/model.hpp
188)
189
190install_qml_module(customplugin)
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Chrono.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/Chrono.cpp
new file mode 100644
index 00000000..22b3469b
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/Chrono.cpp
@@ -0,0 +1,83 @@
1#include "Chrono.hpp"
2
3#include <format>
4#include <iostream>
5#include <cmath>
6
7Chrono::Chrono(QObject* parent): QObject(parent) {
8 QObject::connect(&this->timer, &QTimer::timeout, this, &Chrono::onTimeout);
9 this->update();
10}
11
12bool Chrono::enabled() const { return this->mEnabled; }
13
14void Chrono::setEnabled(bool enabled) {
15 if (enabled == this->mEnabled) return;
16 this->mEnabled = enabled;
17 emit this->enabledChanged();
18 this->update();
19}
20
21Chrono::Precision Chrono::precision() const { return this->mPrecision; }
22
23void Chrono::setPrecision(Chrono::Precision precision) {
24 if (precision == this->mPrecision) return;
25 this->mPrecision = precision;
26 emit this->precisionChanged();
27 this->update();
28}
29
30void Chrono::onTimeout() {
31 this->setTime(this->targetTime);
32 this->schedule(this->targetTime);
33}
34
35void Chrono::update() {
36 if (this->mEnabled) {
37 this->setTime(std::chrono::time_point<std::chrono::system_clock>());
38 this->schedule(std::chrono::time_point<std::chrono::system_clock>());
39 } else {
40 this->timer.stop();
41 }
42}
43
44void Chrono::setTime(const std::chrono::time_point<std::chrono::system_clock>& targetTime) {
45 using namespace std::chrono_literals;
46
47 auto currentTime = std::chrono::system_clock::now();
48 auto offset = std::chrono::duration_cast<std::chrono::milliseconds>(targetTime - currentTime);
49 this->currentTime = abs(offset) < 500ms ? targetTime : currentTime;
50
51 switch (this->mPrecision) {
52 case Chrono::Hours: this->currentTime = std::chrono::time_point_cast<std::chrono::hours>(this->currentTime);
53 case Chrono::Minutes: this->currentTime = std::chrono::time_point_cast<std::chrono::minutes>(this->currentTime);
54 case Chrono::Seconds: this->currentTime = std::chrono::time_point_cast<std::chrono::seconds>(this->currentTime);
55 }
56
57 emit this->dateChanged();
58}
59
60void Chrono::schedule(const std::chrono::time_point<std::chrono::system_clock>& targetTime) {
61 using namespace std::chrono_literals;
62
63 auto currentTime = std::chrono::system_clock::now();
64 auto offset = std::chrono::duration_cast<std::chrono::milliseconds>(targetTime - currentTime);
65 auto nextTime = abs(offset) < 500ms ? targetTime : currentTime;
66
67 switch (this->mPrecision) {
68 case Chrono::Hours: nextTime = std::chrono::time_point_cast<std::chrono::hours>(nextTime) + 1h;
69 case Chrono::Minutes: nextTime = std::chrono::time_point_cast<std::chrono::minutes>(nextTime) + 1min;
70 case Chrono::Seconds: nextTime = std::chrono::time_point_cast<std::chrono::seconds>(nextTime) + 1s;
71 }
72
73 this->targetTime = nextTime;
74 this->timer.start(std::chrono::duration_cast<std::chrono::milliseconds>(nextTime - currentTime));
75}
76
77QString Chrono::format(const QString& fmt) const {
78 return QString::fromStdString(std::format(std::runtime_format(fmt.toStdString()), std::chrono::zoned_time(std::chrono::current_zone(), std::chrono::time_point_cast<std::chrono::seconds>(this->currentTime))));
79}
80
81QDateTime Chrono::date() const {
82 return QDateTime::fromStdTimePoint(std::chrono::time_point_cast<std::chrono::milliseconds>(this->currentTime));
83}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Chrono.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/Chrono.hpp
new file mode 100644
index 00000000..04080187
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/Chrono.hpp
@@ -0,0 +1,55 @@
1#pragma once
2
3#include <chrono>
4
5#include <QDateTime>
6#include <QObject>
7#include <QTimer>
8
9#include <qqmlintegration.h>
10
11class Chrono : public QObject {
12 Q_OBJECT;
13 Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged);
14 Q_PROPERTY(Chrono::Precision precision READ precision WRITE setPrecision NOTIFY precisionChanged);
15 Q_PROPERTY(QDateTime date READ date NOTIFY dateChanged)
16 QML_ELEMENT;
17
18public:
19 enum Precision : quint8 {
20 Hours = 1,
21 Minutes = 2,
22 Seconds = 3,
23 };
24 Q_ENUM(Precision);
25
26 explicit Chrono(QObject* parent = nullptr);
27
28 bool enabled() const;
29 void setEnabled(bool enabled);
30
31 Chrono::Precision precision() const;
32 void setPrecision(Chrono::Precision precision);
33
34 Q_INVOKABLE QString format(const QString& fmt) const;
35
36 QDateTime date() const;
37
38signals:
39 void enabledChanged();
40 void precisionChanged();
41 void dateChanged();
42
43private slots:
44 void onTimeout();
45
46private:
47 bool mEnabled = true;
48 Chrono::Precision mPrecision = Chrono::Seconds;
49 QTimer timer;
50 std::chrono::time_point<std::chrono::system_clock> currentTime, targetTime;
51
52 void update();
53 void setTime(const std::chrono::time_point<std::chrono::system_clock>& targetTime);
54 void schedule(const std::chrono::time_point<std::chrono::system_clock>& targetTime);
55};
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.cpp
new file mode 100644
index 00000000..d7051d2a
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.cpp
@@ -0,0 +1,102 @@
1#include "FileSelector.hpp"
2
3#include <sstream>
4#include <vector>
5#include <random>
6#include <algorithm>
7
8#include <iostream>
9#include <format>
10
11namespace fs = std::filesystem;
12
13FileSelector::FileSelector(QObject* parent): QObject(parent) {
14 QObject::connect(&this->timer, &QTimer::timeout, this, &FileSelector::onTimeout);
15 this->timer.setTimerType(Qt::PreciseTimer);
16}
17
18QString FileSelector::directory() const {
19 return QString::fromStdString(this->mDirectory->string());
20}
21void FileSelector::setDirectory(QString directory) {
22 this->mDirectory = directory.toStdString();
23 if (this->mDirectory && this->mEpoch)
24 this->update();
25 emit this->directoryChanged();
26}
27
28unsigned int FileSelector::epoch() const {
29 return std::chrono::duration_cast<std::chrono::milliseconds>(*this->mEpoch).count();
30}
31void FileSelector::setEpoch(unsigned int epoch) {
32 this->mEpoch = std::chrono::milliseconds{epoch};
33 if (this->mDirectory && this->mEpoch)
34 this->update();
35 emit this->epochChanged();
36}
37
38QString FileSelector::seed() const {
39 return this->mSeed;
40}
41void FileSelector::setSeed(QString seed) {
42 this->mSeed = seed;
43 emit this->seedChanged();
44 if (this->mDirectory && this->mEpoch)
45 emit this->selectedChanged();
46}
47
48QString FileSelector::selected() const {
49 if (!this->mDirectory || !this->mEpoch)
50 return QString();
51
52 std::vector<fs::path> shuffled(this->mFiles.begin(), this->mFiles.end());
53 std::sort(shuffled.begin(), shuffled.end());
54
55 auto currentTime = std::chrono::system_clock::now();
56 uint64_t currentEpoch = currentTime.time_since_epoch() / *this->mEpoch;
57 std::chrono::milliseconds timeInEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime.time_since_epoch()) % *this->mEpoch;
58
59 std::ostringstream seed;
60 seed << this->mSeed.size() << ";" << this->mSeed.toStdString() << ";";
61 seed << *this->mEpoch << ";";
62 seed << currentEpoch << ";";
63 seed << this->mDirectory->string().size() << ";" << *this->mDirectory << ";";
64 seed << this->mFiles.size() << ";";
65 for (const fs::path& p: this->mFiles)
66 seed << p.string().size() << ";" << p << ";";
67
68 std::vector<std::seed_seq::result_type> v;
69 v.reserve(seed.str().size());
70 for (const char& c: seed.str())
71 v.push_back(c);
72
73 std::seed_seq engine_seed(v.begin(), v.end());
74 std::mt19937 g(engine_seed);
75 std::shuffle(shuffled.begin(), shuffled.end(), g);
76
77 std::vector<fs::path>::size_type ix = shuffled.size() * timeInEpoch / *this->mEpoch;
78 return QString::fromStdString((*this->mDirectory / shuffled[ix]).string());
79}
80
81void FileSelector::onTimeout() {
82 if (!this->mFiles.size())
83 return;
84
85 auto currentTime = std::chrono::system_clock::now();
86 uint64_t currentMinorEpoch = currentTime.time_since_epoch() / (*this->mEpoch / this->mFiles.size());
87 auto nextTime = std::chrono::time_point<std::chrono::system_clock>((currentMinorEpoch + 1) * (*this->mEpoch / this->mFiles.size()));
88 this->timer.start(std::chrono::duration_cast<std::chrono::milliseconds>(nextTime - currentTime));
89
90 emit this->selectedChanged();
91}
92
93void FileSelector::update() {
94 this->mFiles = std::set<fs::path>{};
95 for (const fs::directory_entry& entry:
96 fs::recursive_directory_iterator(*this->mDirectory, fs::directory_options::follow_directory_symlink))
97 {
98 this->mFiles.insert(fs::relative(entry, *this->mDirectory));
99 }
100
101 this->onTimeout();
102}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.hpp
new file mode 100644
index 00000000..72c4f2a7
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/FileSelector.hpp
@@ -0,0 +1,52 @@
1#pragma once
2
3#include <filesystem>
4#include <chrono>
5#include <set>
6#include <optional>
7
8#include <QObject>
9#include <QTimer>
10
11#include <qqmlintegration.h>
12
13class FileSelector : public QObject {
14 Q_OBJECT;
15 Q_PROPERTY(QString directory READ directory WRITE setDirectory NOTIFY directoryChanged REQUIRED);
16 Q_PROPERTY(unsigned int epoch READ epoch WRITE setEpoch NOTIFY epochChanged REQUIRED);
17 Q_PROPERTY(QString seed READ seed WRITE setSeed NOTIFY seedChanged);
18 Q_PROPERTY(QString selected READ selected NOTIFY selectedChanged);
19 QML_ELEMENT;
20
21public:
22 explicit FileSelector(QObject* parent = nullptr);
23
24 QString directory() const;
25 void setDirectory(QString directory);
26
27 unsigned int epoch() const;
28 void setEpoch(unsigned int epoch);
29
30 QString seed() const;
31 void setSeed(QString seed);
32
33 QString selected() const;
34
35signals:
36 void directoryChanged();
37 void epochChanged();
38 void seedChanged();
39 void selectedChanged();
40
41private slots:
42 void onTimeout();
43
44private:
45 std::optional<std::filesystem::path> mDirectory;
46 std::optional<std::chrono::milliseconds> mEpoch;
47 std::set<std::filesystem::path> mFiles;
48 QString mSeed;
49 QTimer timer;
50
51 void update();
52};
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.cpp
new file mode 100644
index 00000000..f6e4dd6e
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.cpp
@@ -0,0 +1,18 @@
1#include "KeePassXC.hpp"
2
3#include <QDBusConnection>
4
5KeePassXC::KeePassXC() {
6 this->service = new DBusKeePassXC(DBusKeePassXC::staticInterfaceName(), "/keepassxc", QDBusConnection::sessionBus(), this);
7}
8KeePassXC::~KeePassXC() {
9 if (this->service)
10 delete this->service;
11}
12
13void KeePassXC::lockAllDatabases() {
14 if (!this->service)
15 return;
16
17 this->service->lockAllDatabases();
18}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.hpp
new file mode 100644
index 00000000..c4cd71e0
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/KeePassXC.hpp
@@ -0,0 +1,21 @@
1#pragma once
2
3#include "dbus_keepassxc.h"
4
5#include <QObject>
6#include <QtQmlIntegration/qqmlintegration.h>
7
8class KeePassXC : public QObject {
9 Q_OBJECT;
10 QML_SINGLETON;
11 QML_ELEMENT;
12
13public:
14 explicit KeePassXC();
15 ~KeePassXC();
16
17 Q_INVOKABLE void lockAllDatabases();
18
19private:
20 DBusKeePassXC* service = nullptr;
21};
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp
new file mode 100644
index 00000000..c1f9537c
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp
@@ -0,0 +1,41 @@
1#include "ListUnitsEntry.hpp"
2
3void ListUnitsEntry::registerMetaType() {
4 qRegisterMetaType<ListUnitsEntry>("ListUnitsEntry");
5 qDBusRegisterMetaType<ListUnitsEntry>();
6}
7
8QDBusArgument& operator<<(QDBusArgument& argument, const ListUnitsEntry& entry) {
9 argument.beginStructure();
10 argument
11 << entry.primaryName
12 << entry.description
13 << entry.loadState
14 << entry.activeState
15 << entry.subState
16 << entry.followingUnit
17 << entry.unitPath
18 << entry.jobId
19 << entry.jobType
20 << entry.jobPath;
21 argument.endStructure();
22
23 return argument;
24}
25const QDBusArgument& operator>>(const QDBusArgument& argument, ListUnitsEntry& entry) {
26 argument.beginStructure();
27 argument
28 >> entry.primaryName
29 >> entry.description
30 >> entry.loadState
31 >> entry.activeState
32 >> entry.subState
33 >> entry.followingUnit
34 >> entry.unitPath
35 >> entry.jobId
36 >> entry.jobType
37 >> entry.jobPath;
38 argument.endStructure();
39
40 return argument;
41}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp
new file mode 100644
index 00000000..15d789b9
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp
@@ -0,0 +1,26 @@
1#pragma once
2
3#include <QtDBus>
4#include <QtTypes>
5
6struct ListUnitsEntry {
7 QString primaryName;
8 QString description;
9 QString loadState;
10 QString activeState;
11 QString subState;
12 QString followingUnit;
13 QDBusObjectPath unitPath;
14 uint jobId;
15 QString jobType;
16 QDBusObjectPath jobPath;
17
18 friend QDBusArgument& operator<<(QDBusArgument& argument, const ListUnitsEntry& entry);
19 friend const QDBusArgument& operator>>(const QDBusArgument& argument, ListUnitsEntry& entry);
20 static void registerMetaType();
21};
22
23Q_DECLARE_METATYPE(ListUnitsEntry)
24
25using ListUnitsResult = QList<ListUnitsEntry>;
26Q_DECLARE_METATYPE(ListUnitsResult)
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp
new file mode 100644
index 00000000..6376b527
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp
@@ -0,0 +1,288 @@
1#include "Systemd.hpp"
2
3#include <sstream>
4
5#include <QDBusConnection>
6#include <QDBusReply>
7#include <QDebug>
8#include <QDBusUnixFileDescriptor>
9#include <QDBusObjectPath>
10
11#include <set>
12
13Systemd::Systemd(QObject* parent) : QObject(parent) {
14 ListUnitsEntry::registerMetaType();
15 qDBusRegisterMetaType<ListUnitsResult>();
16
17 this->systemdManager = new DBusSystemdManager(
18 "org.freedesktop.systemd1",
19 "/org/freedesktop/systemd1",
20 QDBusConnection::sessionBus(),
21 this
22 );
23 this->logindManager = new DBusLogindManager(
24 "org.freedesktop.login1",
25 "/org/freedesktop/login1",
26 QDBusConnection::systemBus(),
27 this
28 );
29
30
31 QDBusReply<QDBusObjectPath> sessionPath = this->logindManager->GetSession("auto");
32 // qDebug() << sessionPath;
33 this->logindSession = new DBusLogindSession(
34 "org.freedesktop.login1",
35 sessionPath.value().path(),
36 QDBusConnection::systemBus(),
37 this
38 );
39 this->logindSessionProperties = new DBusProperties(
40 "org.freedesktop.login1",
41 sessionPath.value().path(),
42 QDBusConnection::systemBus(),
43 this
44 );
45
46 QObject::connect(this->logindManager, &DBusLogindManager::PrepareForShutdown, this, &Systemd::shutdown);
47 QObject::connect(this->logindManager, &DBusLogindManager::PrepareForSleep, this, &Systemd::sleep);
48 QObject::connect(this->logindSession, &DBusLogindSession::Lock, this, &Systemd::lock);
49 QObject::connect(this->logindSession, &DBusLogindSession::Unlock, this, &Systemd::unlock);
50 QObject::connect(this->logindSessionProperties, &DBusProperties::PropertiesChanged, this, &Systemd::onLogindSessionPropertiesChanged);
51 this->systemdManager->Subscribe();
52 QObject::connect(this->systemdManager, &DBusSystemdManager::UnitNew, this, &Systemd::onUserUnitNew);
53 QObject::connect(this->systemdManager, &DBusSystemdManager::UnitRemoved, this, &Systemd::onUserUnitRemoved);
54
55 for (const auto& unit: this->systemdManager->ListUnits().value())
56 this->onUserUnitNew(unit.primaryName, unit.unitPath);
57}
58
59void Systemd::onLogindSessionPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) {
60 if (changed_properties.contains("IdleHint") || invalidated_properties.contains("IdleHint"))
61 emit this->idleHintChanged();
62 if (changed_properties.contains("LockedHint") || invalidated_properties.contains("LockedHint"))
63 emit this->lockedHintChanged();
64}
65void Systemd::onUserUnitNew(const QString& id, const QDBusObjectPath& object_path) {
66 for (auto unit: this->mUserUnits.valueList())
67 if (unit->path() == object_path)
68 return;
69
70 for (const auto& unit: this->systemdManager->ListUnits().value())
71 if (unit.unitPath == object_path) {
72 this->mUserUnits.insertObject(new SystemdUnit(this, object_path, id));
73 return;
74 }
75}
76void Systemd::onUserUnitRemoved(const QString& id, const QDBusObjectPath& object_path) {
77 std::set<SystemdUnit*> toRemove;
78 for (auto unit: this->mUserUnits.valueList())
79 if (unit->path() == object_path)
80 toRemove.insert(unit);
81
82 for (auto unit: toRemove) {
83 this->mUserUnits.removeObject(unit);
84 delete unit;
85 }
86}
87
88SystemdUnit::SystemdUnit(QObject* parent, const QDBusObjectPath& path, const QString& id): QObject(parent), mPath(path), mId(id) {
89 this->mUnitProperties = new DBusProperties(
90 "org.freedesktop.systemd1",
91 this->path().path(),
92 QDBusConnection::sessionBus(),
93 this
94 );
95}
96std::unique_ptr<DBusSystemdUnit> SystemdUnit::systemdUnit() {
97 return std::make_unique<DBusSystemdUnit>(
98 "org.freedesktop.systemd1",
99 this->path().path(),
100 QDBusConnection::sessionBus(),
101 nullptr
102 );
103}
104std::unique_ptr<DBusSystemdService> SystemdUnit::systemdService() {
105 if (!this->id().endsWith(".service"))
106 return std::unique_ptr<DBusSystemdService>();
107
108 return std::make_unique<DBusSystemdService>(
109 "org.freedesktop.systemd1",
110 this->path().path(),
111 QDBusConnection::sessionBus(),
112 nullptr
113 );
114}
115QList<QString> SystemdUnit::runtimeDirectory() {
116 if (std::unique_ptr<DBusSystemdService> systemdService = this->systemdService()) {
117 if (!this->mRuntimeDirectory)
118 this->mRuntimeDirectory = systemdService->runtimeDirectory();
119 return *this->mRuntimeDirectory;
120 }
121
122 return QList<QString>{};
123}
124QString SystemdUnit::activeState() {
125 if (!this->mActiveState) {
126 QObject::connect(this->mUnitProperties, &DBusProperties::PropertiesChanged, this, &SystemdUnit::onUnitPropertiesChanged);
127 this->mActiveState = this->systemdUnit()->activeState();
128 }
129
130 return *this->mActiveState;
131}
132
133const QDBusObjectPath& SystemdUnit::path() const { return this->mPath; }
134const QString& SystemdUnit::id() const { return this->mId; }
135void SystemdUnit::onUnitPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) {
136 if (changed_properties.contains("ActiveState") || invalidated_properties.contains("ActiveState")) {
137 this->mActiveState = this->systemdUnit()->activeState();
138 emit this->activeStateChanged();
139 }
140}
141
142void Systemd::stopUserUnit(const QString& unit, const QString& mode) { this->systemdManager->StopUnit(unit, mode); }
143
144void Systemd::setBrightness(const QString& subsystem, const QString& name, quint32 brightness) { this->logindSession->SetBrightness(subsystem, name, brightness); }
145
146bool Systemd::idleHint() { return this->logindSession->idleHint(); }
147void Systemd::setIdleHint(bool idle) { this->logindSession->SetIdleHint(idle); }
148bool Systemd::lockedHint() { return this->logindSession->lockedHint(); }
149void Systemd::setLockedHint(bool locked) { this->logindSession->SetLockedHint(locked); }
150void Systemd::lockSession() { this->logindSession->call("Lock"); }
151void Systemd::suspend() { this->logindManager->Suspend(true); }
152void Systemd::hibernate() { this->logindManager->Hibernate(true); }
153
154ObjectModel<SystemdUnit>* Systemd::userUnits() { return &this->mUserUnits; }
155
156std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::WhatItem what) {
157 if (what == SystemdInhibitorParams::Shutdown)
158 return "shutdown";
159 else if (what == SystemdInhibitorParams::Sleep)
160 return "sleep";
161 else if (what == SystemdInhibitorParams::Idle)
162 return "idle";
163 else if (what == SystemdInhibitorParams::HandlePowerKey)
164 return "handle-power-key";
165 else if (what == SystemdInhibitorParams::HandleSuspendKey)
166 return "handle-suspend-key";
167 else if (what == SystemdInhibitorParams::HandleHibernateKey)
168 return "handle-hibernate-key";
169 else if (what == SystemdInhibitorParams::HandleLidSwitch)
170 return "handle-lid-switch";
171 return "";
172}
173
174std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::What what) {
175 std::ostringstream res;
176 bool first = true;
177 for (const WhatItem& item: SystemdInhibitorParams::allWhatItems) {
178 if (!(what & item))
179 continue;
180
181 if (!first)
182 res << ":";
183 else
184 first = false;
185 res << SystemdInhibitorParams::toString(item);
186 }
187 return res.str();
188}
189
190std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::Mode mode) {
191 if (mode == SystemdInhibitorParams::Block)
192 return "block";
193 else if (mode == SystemdInhibitorParams::BlockWeak)
194 return "block-weak";
195 else if (mode == SystemdInhibitorParams::Delay)
196 return "delay";
197 return "";
198}
199
200bool SystemdInhibitor::enabled() const { return static_cast<bool>(this->activeInhibitor); }
201void SystemdInhibitor::setEnabled(bool enabled) {
202 this->mEnabled = enabled;
203
204 if (enabled)
205 this->update();
206 else
207 this->release();
208}
209
210SystemdInhibitorParams::What SystemdInhibitor::what() const { return this->mWhat; }
211void SystemdInhibitor::setWhat(SystemdInhibitorParams::What what) {
212 this->mWhat = what;
213 this->update();
214}
215
216QString SystemdInhibitor::who() const { return this->mWho; }
217void SystemdInhibitor::setWho(QString who) {
218 this->mWho = who;
219 this->update();
220}
221
222QString SystemdInhibitor::why() const { return this->mWhy; }
223void SystemdInhibitor::setWhy(QString why) {
224 this->mWhy = why;
225 this->update();
226}
227
228SystemdInhibitorParams::Mode SystemdInhibitor::mode() const { return this->mMode; }
229void SystemdInhibitor::setMode(SystemdInhibitorParams::Mode mode) {
230 this->mMode = mode;
231 this->update();
232}
233
234SystemdInhibitor::ActiveSystemdInhibitor::ActiveSystemdInhibitor(SystemdInhibitorParams::What what_, QString who_, QString why_, SystemdInhibitorParams::Mode mode_): what(what_), who(who_), why(why_), mode(mode_) {
235 DBusLogindManager logindManager(
236 "org.freedesktop.login1",
237 "/org/freedesktop/login1",
238 QDBusConnection::systemBus()
239 );
240 QDBusReply<QDBusUnixFileDescriptor> fd_ = logindManager.Inhibit(QString::fromStdString(SystemdInhibitorParams::toString(what)), who, why, QString::fromStdString(SystemdInhibitorParams::toString(mode)));
241 if (fd_.error().isValid())
242 throw fd_.error();
243 this->fd = ::dup(fd_.value().fileDescriptor());
244}
245SystemdInhibitor::ActiveSystemdInhibitor::~ActiveSystemdInhibitor() {
246 if (this->fd != -1)
247 ::close(this->fd);
248}
249
250void SystemdInhibitor::release() {
251 if (!this->activeInhibitor)
252 return;
253
254 this->activeInhibitor.reset();
255 emit this->enabledChanged();
256}
257
258void SystemdInhibitor::update() {
259 if (!this->mWhat || this->mWho.isEmpty() || this->mWhy.isEmpty() || !this->mMode || !this->mEnabled)
260 if (this->activeInhibitor)
261 this->release();
262 else
263 return;
264
265 if (this->activeInhibitor && this->mWhat == this->activeInhibitor->what && this->mWho == this->activeInhibitor->who && this->mWhy == this->activeInhibitor->why && this->mMode == this->activeInhibitor->mode)
266 return;
267
268 std::unique_ptr<ActiveSystemdInhibitor> otherInhibitor;
269 try {
270 otherInhibitor.reset(new SystemdInhibitor::ActiveSystemdInhibitor(this->mWhat, this->mWho, this->mWhy, this->mMode));
271 } catch (const QDBusError& err) {
272 qCritical().noquote()
273 << err.name().toStdString() << " " << err.message().toStdString();
274 return;
275 }
276 this->activeInhibitor.swap(otherInhibitor);
277
278 if (!otherInhibitor && this->activeInhibitor)
279 emit this->enabledChanged();
280 if (otherInhibitor && otherInhibitor->what != this->activeInhibitor->what)
281 emit this->whatChanged();
282 if (otherInhibitor && otherInhibitor->who != this->activeInhibitor->who)
283 emit this->whoChanged();
284 if (otherInhibitor && otherInhibitor->why != this->activeInhibitor->why)
285 emit this->whyChanged();
286 if (otherInhibitor && otherInhibitor->mode != this->activeInhibitor->mode)
287 emit this->modeChanged();
288}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp
new file mode 100644
index 00000000..98f73d8f
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp
@@ -0,0 +1,193 @@
1#pragma once
2
3#include <cstdint>
4#include <memory>
5#include <string>
6#include <optional>
7
8#include <QObject>
9#include <QDBusInterface>
10#include <QtQmlIntegration/qqmlintegration.h>
11
12#include "dbus_systemd_manager.h"
13#include "dbus_logind_manager.h"
14#include "dbus_logind_session.h"
15#include "dbus_systemd_unit.h"
16#include "dbus_systemd_service.h"
17#include "dbus_properties.h"
18
19#include "core/model.hpp"
20
21class SystemdUnit : public QObject {
22 Q_OBJECT;
23 QML_ELEMENT;
24 QML_UNCREATABLE("SystemdUnits cannot be created directly");
25
26public:
27 explicit SystemdUnit(QObject* parent, const QDBusObjectPath& path, const QString& id);
28
29 Q_PROPERTY(QDBusObjectPath path READ path CONSTANT);
30 Q_PROPERTY(QString id READ id CONSTANT);
31 Q_PROPERTY(QList<QString> runtimeDirectory READ runtimeDirectory CONSTANT);
32 Q_PROPERTY(QString activeState READ activeState NOTIFY activeStateChanged);
33
34 const QDBusObjectPath& path() const;
35 const QString& id() const;
36 QList<QString> runtimeDirectory();
37 QString activeState();
38
39signals:
40 void activeStateChanged();
41
42private slots:
43 void onUnitPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties);
44
45private:
46 std::unique_ptr<DBusSystemdUnit> systemdUnit();
47 std::unique_ptr<DBusSystemdService> systemdService();
48
49 DBusProperties* mUnitProperties;
50 QDBusObjectPath mPath;
51 QString mId;
52 std::optional<QString> mActiveState;
53 std::optional<QList<QString>> mRuntimeDirectory;
54};
55
56class Systemd : public QObject {
57 Q_OBJECT;
58 QML_SINGLETON;
59 QML_ELEMENT;
60
61public:
62 explicit Systemd(QObject* parent = nullptr);
63
64 Q_PROPERTY(bool idleHint READ idleHint WRITE setIdleHint NOTIFY idleHintChanged)
65 Q_PROPERTY(bool lockedHint READ lockedHint WRITE setLockedHint NOTIFY lockedHintChanged)
66 Q_PROPERTY(UntypedObjectModel* userUnits READ userUnits CONSTANT)
67
68 Q_INVOKABLE void stopUserUnit(const QString& unit, const QString& mode);
69 Q_INVOKABLE void setBrightness(const QString& subsystem, const QString& name, quint32 brightness);
70 Q_INVOKABLE void setIdleHint(bool idle);
71 Q_INVOKABLE void setLockedHint(bool locked);
72 Q_INVOKABLE void lockSession();
73 Q_INVOKABLE void suspend();
74 Q_INVOKABLE void hibernate();
75
76 bool idleHint();
77 bool lockedHint();
78 ObjectModel<SystemdUnit>* userUnits();
79
80signals:
81 void shutdown(bool before);
82 void sleep(bool before);
83 void lock();
84 void unlock();
85 void idleHintChanged();
86 void lockedHintChanged();
87
88private slots:
89 void onLogindSessionPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties);
90 void onUserUnitNew(const QString& id, const QDBusObjectPath& objectPath);
91 void onUserUnitRemoved(const QString& id, const QDBusObjectPath& objectPath);
92
93private:
94 DBusSystemdManager* systemdManager;
95 DBusLogindManager* logindManager;
96 DBusLogindSession* logindSession;
97 DBusProperties* logindSessionProperties;
98
99 ObjectModel<SystemdUnit> mUserUnits{this};
100};
101
102class SystemdInhibitorParams : public QObject {
103 Q_OBJECT;
104 QML_ELEMENT;
105 QML_SINGLETON;
106
107public:
108 enum WhatItem : uint8_t {
109 Shutdown = 0b1,
110 Sleep = 0b10,
111 Idle = 0b100,
112 HandlePowerKey = 0b1000,
113 HandleSuspendKey = 0b10000,
114 HandleHibernateKey = 0b100000,
115 HandleLidSwitch = 0b1000000,
116 };
117 Q_ENUM(WhatItem);
118 Q_DECLARE_FLAGS(What, WhatItem);
119
120 enum Mode : uint8_t {
121 Block = 1,
122 BlockWeak = 2,
123 Delay = 3,
124 };
125 Q_ENUM(Mode);
126
127 Q_INVOKABLE static std::string toString(WhatItem what);
128 Q_INVOKABLE static std::string toString(What what);
129 Q_INVOKABLE static std::string toString(Mode mode);
130
131 static constexpr WhatItem allWhatItems[] = { Shutdown, Sleep, Idle, HandlePowerKey, HandleSuspendKey, HandleHibernateKey, HandleLidSwitch };
132};
133Q_DECLARE_OPERATORS_FOR_FLAGS(SystemdInhibitorParams::What)
134
135class SystemdInhibitor : public QObject {
136 Q_OBJECT;
137 Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged);
138 Q_PROPERTY(SystemdInhibitorParams::What what READ what WRITE setWhat NOTIFY whatChanged);
139 Q_PROPERTY(QString who READ who WRITE setWho NOTIFY whoChanged);
140 Q_PROPERTY(QString why READ why WRITE setWhy NOTIFY whyChanged);
141 Q_PROPERTY(SystemdInhibitorParams::Mode mode READ mode WRITE setMode NOTIFY modeChanged);
142 QML_ELEMENT;
143
144public:
145 explicit SystemdInhibitor(QObject* parent = nullptr): QObject(parent) {}
146
147 bool enabled() const;
148 void setEnabled(bool enabled);
149
150 SystemdInhibitorParams::What what() const;
151 void setWhat(SystemdInhibitorParams::What what);
152
153 QString who() const;
154 void setWho(QString who);
155
156 QString why() const;
157 void setWhy(QString why);
158
159 SystemdInhibitorParams::Mode mode() const;
160 void setMode(SystemdInhibitorParams::Mode mode);
161
162 Q_INVOKABLE void release();
163
164signals:
165 void enabledChanged();
166 void whatChanged();
167 void whoChanged();
168 void whyChanged();
169 void modeChanged();
170
171private:
172 class ActiveSystemdInhibitor {
173 public:
174 uint32_t fd = -1;
175 SystemdInhibitorParams::What what;
176 QString who;
177 QString why;
178 SystemdInhibitorParams::Mode mode;
179
180 ActiveSystemdInhibitor(SystemdInhibitorParams::What what_, QString who_, QString why_, SystemdInhibitorParams::Mode mode_);
181 ~ActiveSystemdInhibitor();
182 };
183
184 void update();
185
186 bool mEnabled = true;
187 std::unique_ptr<ActiveSystemdInhibitor> activeInhibitor;
188 SystemdInhibitorParams::What mWhat = static_cast<SystemdInhibitorParams::What>(0);
189 QString mWho;
190 QString mWhy;
191 SystemdInhibitorParams::Mode mMode = static_cast<SystemdInhibitorParams::Mode>(0);
192};
193
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/customplugin.h b/accounts/gkleen@sif/shell/quickshell-plugins/customplugin.h
new file mode 100644
index 00000000..e66ba9e3
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/customplugin.h
@@ -0,0 +1,7 @@
1#include <QQmlEngineExtensionPlugin>
2
3class CustomPlugin : public QQmlEngineExtensionPlugin
4{
5 Q_OBJECT
6 Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
7};
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/default.nix b/accounts/gkleen@sif/shell/quickshell-plugins/default.nix
new file mode 100644
index 00000000..dfe93bca
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/default.nix
@@ -0,0 +1,32 @@
1{ lib
2, stdenv
3, cmake
4, qt6
5, fmt
6, keepassxc
7, systemd
8, quickshell
9}:
10
11stdenv.mkDerivation rec {
12 name = "quickshell-custom";
13
14 src = ./.;
15
16 prePatch = ''
17 cp ${keepassxc.src}/src/gui/org.keepassxc.KeePassXC.MainWindow.xml .
18 '';
19
20 nativeBuildInputs = [ cmake qt6.wrapQtAppsHook ];
21 buildInputs = [
22 qt6.qtbase
23 qt6.qtdeclarative
24 ];
25
26 cmakeFlags = [
27 (lib.cmakeFeature "INSTALL_QML_PREFIX" qt6.qtbase.qtQmlPrefix)
28 (lib.cmakeOptionType "string" "QUICKSHELL_SRC" (toString quickshell.src))
29 ];
30
31 LC_ALL = "C.UTF-8";
32}
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml
new file mode 100644
index 00000000..7588e7a5
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml
@@ -0,0 +1,28 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
2"https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3<node>
4 <interface name="org.freedesktop.DBus.Properties">
5 <method name="Get">
6 <arg name="interface_name" direction="in" type="s"/>
7 <arg name="property_name" direction="in" type="s"/>
8 <arg name="value" direction="out" type="v"/>
9 </method>
10 <method name="GetAll">
11 <arg name="interface_name" direction="in" type="s"/>
12 <arg name="props" direction="out" type="a{sv}"/>
13 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
14 </method>
15 <method name="Set">
16 <arg name="interface_name" direction="in" type="s"/>
17 <arg name="property_name" direction="in" type="s"/>
18 <arg name="value" direction="in" type="v"/>
19 </method>
20 <signal name="PropertiesChanged">
21 <arg type="s" name="interface_name"/>
22 <arg type="a{sv}" name="changed_properties"/>
23 <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
24 <arg type="as" name="invalidated_properties"/>
25 </signal>
26 </interface>
27</node>
28
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml
new file mode 100644
index 00000000..120a06d9
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml
@@ -0,0 +1,445 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
2"https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3<node>
4 <interface name="org.freedesktop.login1.Manager">
5 <property name="EnableWallMessages" type="b" access="readwrite">
6 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
7 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
8 </property>
9 <property name="WallMessage" type="s" access="readwrite">
10 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
11 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
12 </property>
13 <property name="NAutoVTs" type="u" access="read">
14 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
15 </property>
16 <property name="KillOnlyUsers" type="as" access="read">
17 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
18 </property>
19 <property name="KillExcludeUsers" type="as" access="read">
20 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
21 </property>
22 <property name="KillUserProcesses" type="b" access="read">
23 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
24 </property>
25 <property name="RebootParameter" type="s" access="read">
26 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
27 </property>
28 <property name="RebootToFirmwareSetup" type="b" access="read">
29 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
30 </property>
31 <property name="RebootToBootLoaderMenu" type="t" access="read">
32 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
33 </property>
34 <property name="RebootToBootLoaderEntry" type="s" access="read">
35 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
36 </property>
37 <property name="BootLoaderEntries" type="as" access="read">
38 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
39 </property>
40 <property name="IdleHint" type="b" access="read">
41 </property>
42 <property name="IdleSinceHint" type="t" access="read">
43 </property>
44 <property name="IdleSinceHintMonotonic" type="t" access="read">
45 </property>
46 <property name="BlockInhibited" type="s" access="read">
47 </property>
48 <property name="BlockWeakInhibited" type="s" access="read">
49 </property>
50 <property name="DelayInhibited" type="s" access="read">
51 </property>
52 <property name="InhibitDelayMaxUSec" type="t" access="read">
53 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
54 </property>
55 <property name="UserStopDelayUSec" type="t" access="read">
56 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
57 </property>
58 <property name="SleepOperation" type="as" access="read">
59 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
60 </property>
61 <property name="HandlePowerKey" type="s" access="read">
62 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
63 </property>
64 <property name="HandlePowerKeyLongPress" type="s" access="read">
65 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
66 </property>
67 <property name="HandleRebootKey" type="s" access="read">
68 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
69 </property>
70 <property name="HandleRebootKeyLongPress" type="s" access="read">
71 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
72 </property>
73 <property name="HandleSuspendKey" type="s" access="read">
74 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
75 </property>
76 <property name="HandleSuspendKeyLongPress" type="s" access="read">
77 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
78 </property>
79 <property name="HandleHibernateKey" type="s" access="read">
80 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
81 </property>
82 <property name="HandleHibernateKeyLongPress" type="s" access="read">
83 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
84 </property>
85 <property name="HandleLidSwitch" type="s" access="read">
86 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
87 </property>
88 <property name="HandleLidSwitchExternalPower" type="s" access="read">
89 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
90 </property>
91 <property name="HandleLidSwitchDocked" type="s" access="read">
92 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
93 </property>
94 <property name="HandleSecureAttentionKey" type="s" access="read">
95 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
96 </property>
97 <property name="HoldoffTimeoutUSec" type="t" access="read">
98 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
99 </property>
100 <property name="IdleAction" type="s" access="read">
101 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
102 </property>
103 <property name="IdleActionUSec" type="t" access="read">
104 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
105 </property>
106 <property name="PreparingForShutdown" type="b" access="read">
107 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
108 </property>
109 <property name="PreparingForShutdownWithMetadata" type="a{sv}" access="read">
110 <annotation name="org.qtproject.QtDBus.QtTypeName" value="QVariantMap"/>
111 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
112 </property>
113 <property name="PreparingForSleep" type="b" access="read">
114 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
115 </property>
116 <!-- <property name="ScheduledShutdown" type="(st)" access="read"> -->
117 <!-- </property> -->
118 <property name="DesignatedMaintenanceTime" type="s" access="read">
119 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
120 </property>
121 <property name="Docked" type="b" access="read">
122 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
123 </property>
124 <property name="LidClosed" type="b" access="read">
125 </property>
126 <property name="OnExternalPower" type="b" access="read">
127 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
128 </property>
129 <property name="RemoveIPC" type="b" access="read">
130 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
131 </property>
132 <property name="RuntimeDirectorySize" type="t" access="read">
133 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
134 </property>
135 <property name="RuntimeDirectoryInodesMax" type="t" access="read">
136 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
137 </property>
138 <property name="InhibitorsMax" type="t" access="read">
139 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
140 </property>
141 <property name="NCurrentInhibitors" type="t" access="read">
142 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
143 </property>
144 <property name="SessionsMax" type="t" access="read">
145 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
146 </property>
147 <property name="NCurrentSessions" type="t" access="read">
148 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
149 </property>
150 <property name="StopIdleSessionUSec" type="t" access="read">
151 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
152 </property>
153 <method name="GetSession">
154 <arg type="s" name="session_id" direction="in"/>
155 <arg type="o" name="object_path" direction="out"/>
156 </method>
157 <method name="GetSessionByPID">
158 <arg type="u" name="pid" direction="in"/>
159 <arg type="o" name="object_path" direction="out"/>
160 </method>
161 <method name="GetUser">
162 <arg type="u" name="uid" direction="in"/>
163 <arg type="o" name="object_path" direction="out"/>
164 </method>
165 <method name="GetUserByPID">
166 <arg type="u" name="pid" direction="in"/>
167 <arg type="o" name="object_path" direction="out"/>
168 </method>
169 <method name="GetSeat">
170 <arg type="s" name="seat_id" direction="in"/>
171 <arg type="o" name="object_path" direction="out"/>
172 </method>
173 <!-- <method name="ListSessions"> -->
174 <!-- <arg type="a(susso)" name="sessions" direction="out"/> -->
175 <!-- </method> -->
176 <!-- <method name="ListSessionsEx"> -->
177 <!-- <arg type="a(sussussbto)" name="sessions" direction="out"/> -->
178 <!-- </method> -->
179 <!-- <method name="ListUsers"> -->
180 <!-- <arg type="a(uso)" name="users" direction="out"/> -->
181 <!-- </method> -->
182 <!-- <method name="ListSeats"> -->
183 <!-- <arg type="a(so)" name="seats" direction="out"/> -->
184 <!-- </method> -->
185 <!-- <method name="ListInhibitors"> -->
186 <!-- <arg type="a(ssssuu)" name="inhibitors" direction="out"/> -->
187 <!-- </method> -->
188 <!-- <method name="CreateSession"> -->
189 <!-- <arg type="u" name="uid" direction="in"/> -->
190 <!-- <arg type="u" name="pid" direction="in"/> -->
191 <!-- <arg type="s" name="service" direction="in"/> -->
192 <!-- <arg type="s" name="type" direction="in"/> -->
193 <!-- <arg type="s" name="class" direction="in"/> -->
194 <!-- <arg type="s" name="desktop" direction="in"/> -->
195 <!-- <arg type="s" name="seat_id" direction="in"/> -->
196 <!-- <arg type="u" name="vtnr" direction="in"/> -->
197 <!-- <arg type="s" name="tty" direction="in"/> -->
198 <!-- <arg type="s" name="display" direction="in"/> -->
199 <!-- <arg type="b" name="remote" direction="in"/> -->
200 <!-- <arg type="s" name="remote_user" direction="in"/> -->
201 <!-- <arg type="s" name="remote_host" direction="in"/> -->
202 <!-- <arg type="a(sv)" name="properties" direction="in"/> -->
203 <!-- <arg type="s" name="session_id" direction="out"/> -->
204 <!-- <arg type="o" name="object_path" direction="out"/> -->
205 <!-- <arg type="s" name="runtime_path" direction="out"/> -->
206 <!-- <arg type="h" name="fifo_fd" direction="out"/> -->
207 <!-- <arg type="u" name="uid" direction="out"/> -->
208 <!-- <arg type="s" name="seat_id" direction="out"/> -->
209 <!-- <arg type="u" name="vtnr" direction="out"/> -->
210 <!-- <arg type="b" name="existing" direction="out"/> -->
211 <!-- <annotation name="org.freedesktop.systemd1.Privileged" value="true"/> -->
212 <!-- </method> -->
213 <!-- <method name="CreateSessionWithPIDFD"> -->
214 <!-- <arg type="u" name="uid" direction="in"/> -->
215 <!-- <arg type="h" name="pidfd" direction="in"/> -->
216 <!-- <arg type="s" name="service" direction="in"/> -->
217 <!-- <arg type="s" name="type" direction="in"/> -->
218 <!-- <arg type="s" name="class" direction="in"/> -->
219 <!-- <arg type="s" name="desktop" direction="in"/> -->
220 <!-- <arg type="s" name="seat_id" direction="in"/> -->
221 <!-- <arg type="u" name="vtnr" direction="in"/> -->
222 <!-- <arg type="s" name="tty" direction="in"/> -->
223 <!-- <arg type="s" name="display" direction="in"/> -->
224 <!-- <arg type="b" name="remote" direction="in"/> -->
225 <!-- <arg type="s" name="remote_user" direction="in"/> -->
226 <!-- <arg type="s" name="remote_host" direction="in"/> -->
227 <!-- <arg type="t" name="flags" direction="in"/> -->
228 <!-- <arg type="a(sv)" name="properties" direction="in"/> -->
229 <!-- <arg type="s" name="session_id" direction="out"/> -->
230 <!-- <arg type="o" name="object_path" direction="out"/> -->
231 <!-- <arg type="s" name="runtime_path" direction="out"/> -->
232 <!-- <arg type="h" name="fifo_fd" direction="out"/> -->
233 <!-- <arg type="u" name="uid" direction="out"/> -->
234 <!-- <arg type="s" name="seat_id" direction="out"/> -->
235 <!-- <arg type="u" name="vtnr" direction="out"/> -->
236 <!-- <arg type="b" name="existing" direction="out"/> -->
237 <!-- <annotation name="org.freedesktop.systemd1.Privileged" value="true"/> -->
238 <!-- </method> -->
239 <method name="ReleaseSession">
240 <arg type="s" name="session_id" direction="in"/>
241 </method>
242 <method name="ActivateSession">
243 <arg type="s" name="session_id" direction="in"/>
244 </method>
245 <method name="ActivateSessionOnSeat">
246 <arg type="s" name="session_id" direction="in"/>
247 <arg type="s" name="seat_id" direction="in"/>
248 </method>
249 <method name="LockSession">
250 <arg type="s" name="session_id" direction="in"/>
251 </method>
252 <method name="UnlockSession">
253 <arg type="s" name="session_id" direction="in"/>
254 </method>
255 <method name="LockSessions">
256 </method>
257 <method name="UnlockSessions">
258 </method>
259 <method name="KillSession">
260 <arg type="s" name="session_id" direction="in"/>
261 <arg type="s" name="whom" direction="in"/>
262 <arg type="i" name="signal_number" direction="in"/>
263 </method>
264 <method name="KillUser">
265 <arg type="u" name="uid" direction="in"/>
266 <arg type="i" name="signal_number" direction="in"/>
267 </method>
268 <method name="TerminateSession">
269 <arg type="s" name="session_id" direction="in"/>
270 </method>
271 <method name="TerminateUser">
272 <arg type="u" name="uid" direction="in"/>
273 </method>
274 <method name="TerminateSeat">
275 <arg type="s" name="seat_id" direction="in"/>
276 </method>
277 <method name="SetUserLinger">
278 <arg type="u" name="uid" direction="in"/>
279 <arg type="b" name="enable" direction="in"/>
280 <arg type="b" name="interactive" direction="in"/>
281 </method>
282 <method name="AttachDevice">
283 <arg type="s" name="seat_id" direction="in"/>
284 <arg type="s" name="sysfs_path" direction="in"/>
285 <arg type="b" name="interactive" direction="in"/>
286 </method>
287 <method name="FlushDevices">
288 <arg type="b" name="interactive" direction="in"/>
289 </method>
290 <method name="PowerOff">
291 <arg type="b" name="interactive" direction="in"/>
292 </method>
293 <method name="PowerOffWithFlags">
294 <arg type="t" name="flags" direction="in"/>
295 </method>
296 <method name="Reboot">
297 <arg type="b" name="interactive" direction="in"/>
298 </method>
299 <method name="RebootWithFlags">
300 <arg type="t" name="flags" direction="in"/>
301 </method>
302 <method name="Halt">
303 <arg type="b" name="interactive" direction="in"/>
304 </method>
305 <method name="HaltWithFlags">
306 <arg type="t" name="flags" direction="in"/>
307 </method>
308 <method name="Suspend">
309 <arg type="b" name="interactive" direction="in"/>
310 </method>
311 <method name="SuspendWithFlags">
312 <arg type="t" name="flags" direction="in"/>
313 </method>
314 <method name="Hibernate">
315 <arg type="b" name="interactive" direction="in"/>
316 </method>
317 <method name="HibernateWithFlags">
318 <arg type="t" name="flags" direction="in"/>
319 </method>
320 <method name="HybridSleep">
321 <arg type="b" name="interactive" direction="in"/>
322 </method>
323 <method name="HybridSleepWithFlags">
324 <arg type="t" name="flags" direction="in"/>
325 </method>
326 <method name="SuspendThenHibernate">
327 <arg type="b" name="interactive" direction="in"/>
328 </method>
329 <method name="SuspendThenHibernateWithFlags">
330 <arg type="t" name="flags" direction="in"/>
331 </method>
332 <method name="Sleep">
333 <arg type="t" name="flags" direction="in"/>
334 </method>
335 <method name="CanPowerOff">
336 <arg type="s" name="result" direction="out"/>
337 </method>
338 <method name="CanReboot">
339 <arg type="s" name="result" direction="out"/>
340 </method>
341 <method name="CanHalt">
342 <arg type="s" name="result" direction="out"/>
343 </method>
344 <method name="CanSuspend">
345 <arg type="s" name="result" direction="out"/>
346 </method>
347 <method name="CanHibernate">
348 <arg type="s" name="result" direction="out"/>
349 </method>
350 <method name="CanHybridSleep">
351 <arg type="s" name="result" direction="out"/>
352 </method>
353 <method name="CanSuspendThenHibernate">
354 <arg type="s" name="result" direction="out"/>
355 </method>
356 <method name="CanSleep">
357 <arg type="s" name="result" direction="out"/>
358 </method>
359 <method name="ScheduleShutdown">
360 <arg type="s" name="type" direction="in"/>
361 <arg type="t" name="usec" direction="in"/>
362 </method>
363 <method name="CancelScheduledShutdown">
364 <arg type="b" name="cancelled" direction="out"/>
365 </method>
366 <method name="Inhibit">
367 <arg type="s" name="what" direction="in"/>
368 <arg type="s" name="who" direction="in"/>
369 <arg type="s" name="why" direction="in"/>
370 <arg type="s" name="mode" direction="in"/>
371 <arg type="h" name="pipe_fd" direction="out"/>
372 </method>
373 <method name="CanRebootParameter">
374 <arg type="s" name="result" direction="out"/>
375 </method>
376 <method name="SetRebootParameter">
377 <arg type="s" name="parameter" direction="in"/>
378 </method>
379 <method name="CanRebootToFirmwareSetup">
380 <arg type="s" name="result" direction="out"/>
381 </method>
382 <method name="SetRebootToFirmwareSetup">
383 <arg type="b" name="enable" direction="in"/>
384 </method>
385 <method name="CanRebootToBootLoaderMenu">
386 <arg type="s" name="result" direction="out"/>
387 </method>
388 <method name="SetRebootToBootLoaderMenu">
389 <arg type="t" name="timeout" direction="in"/>
390 </method>
391 <method name="CanRebootToBootLoaderEntry">
392 <arg type="s" name="result" direction="out"/>
393 </method>
394 <method name="SetRebootToBootLoaderEntry">
395 <arg type="s" name="boot_loader_entry" direction="in"/>
396 </method>
397 <method name="SetWallMessage">
398 <arg type="s" name="wall_message" direction="in"/>
399 <arg type="b" name="enable" direction="in"/>
400 </method>
401 <signal name="SecureAttentionKey">
402 <arg type="s" name="seat_id"/>
403 <arg type="o" name="object_path"/>
404 </signal>
405 <signal name="SessionNew">
406 <arg type="s" name="session_id"/>
407 <arg type="o" name="object_path"/>
408 </signal>
409 <signal name="SessionRemoved">
410 <arg type="s" name="session_id"/>
411 <arg type="o" name="object_path"/>
412 </signal>
413 <signal name="UserNew">
414 <arg type="u" name="uid"/>
415 <arg type="o" name="object_path"/>
416 </signal>
417 <signal name="UserRemoved">
418 <arg type="u" name="uid"/>
419 <arg type="o" name="object_path"/>
420 </signal>
421 <signal name="SeatNew">
422 <arg type="s" name="seat_id"/>
423 <arg type="o" name="object_path"/>
424 </signal>
425 <signal name="SeatRemoved">
426 <arg type="s" name="seat_id"/>
427 <arg type="o" name="object_path"/>
428 </signal>
429 <signal name="PrepareForShutdown">
430 <arg type="b" name="start"/>
431 </signal>
432 <signal name="PrepareForShutdownWithMetadata">
433 <arg type="b" name="start"/>
434 <arg type="a{sv}" name="metadata"/>
435 <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
436 </signal>
437 <signal name="PrepareForSleep">
438 <arg type="b" name="start"/>
439 </signal>
440 </interface>
441 <node name="user"/>
442 <node name="session"/>
443 <node name="seat"/>
444</node>
445
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Session.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Session.xml
new file mode 100644
index 00000000..7d6fc8ee
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.login1.Session.xml
@@ -0,0 +1,146 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
2"https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3<node>
4 <interface name="org.freedesktop.login1.Session">
5 <property name="Id" type="s" access="read">
6 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
7 </property>
8 <property name="User" type="o" access="read">
9 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
10 </property>
11 <property name="Name" type="s" access="read">
12 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
13 </property>
14 <property name="Timestamp" type="t" access="read">
15 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
16 </property>
17 <property name="TimestampMonotonic" type="t" access="read">
18 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
19 </property>
20 <property name="VTNr" type="u" access="read">
21 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
22 </property>
23 <property name="Seat" type="o" access="read">
24 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
25 </property>
26 <property name="TTY" type="s" access="read">
27 </property>
28 <property name="Display" type="s" access="read">
29 </property>
30 <property name="Remote" type="b" access="read">
31 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
32 </property>
33 <property name="RemoteHost" type="s" access="read">
34 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
35 </property>
36 <property name="RemoteUser" type="s" access="read">
37 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
38 </property>
39 <property name="Service" type="s" access="read">
40 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
41 </property>
42 <property name="Desktop" type="s" access="read">
43 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
44 </property>
45 <property name="Scope" type="s" access="read">
46 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
47 </property>
48 <property name="Leader" type="u" access="read">
49 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
50 </property>
51 <property name="Audit" type="u" access="read">
52 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
53 </property>
54 <property name="Type" type="s" access="read">
55 </property>
56 <!-- <property name="Class" type="s" access="read"> -->
57 <!-- </property> -->
58 <property name="Active" type="b" access="read">
59 </property>
60 <property name="State" type="s" access="read">
61 </property>
62 <property name="IdleHint" type="b" access="read">
63 </property>
64 <property name="IdleSinceHint" type="t" access="read">
65 </property>
66 <property name="IdleSinceHintMonotonic" type="t" access="read">
67 </property>
68 <property name="CanIdle" type="b" access="read">
69 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
70 </property>
71 <property name="CanLock" type="b" access="read">
72 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
73 </property>
74 <property name="LockedHint" type="b" access="read">
75 </property>
76 <method name="Terminate">
77 </method>
78 <method name="Activate">
79 </method>
80 <!-- <method name="Lock"> -->
81 <!-- </method> -->
82 <!-- <method name="Unlock"> -->
83 <!-- </method> -->
84 <method name="SetIdleHint">
85 <arg type="b" name="idle" direction="in"/>
86 </method>
87 <method name="SetLockedHint">
88 <arg type="b" name="locked" direction="in"/>
89 </method>
90 <method name="Kill">
91 <arg type="s" name="whom" direction="in"/>
92 <arg type="i" name="signal_number" direction="in"/>
93 </method>
94 <method name="TakeControl">
95 <arg type="b" name="force" direction="in"/>
96 </method>
97 <method name="ReleaseControl">
98 </method>
99 <method name="SetType">
100 <arg type="s" name="type" direction="in"/>
101 </method>
102 <!-- <method name="SetClass"> -->
103 <!-- <arg type="s" name="class" direction="in"/> -->
104 <!-- </method> -->
105 <method name="SetDisplay">
106 <arg type="s" name="display" direction="in"/>
107 </method>
108 <method name="SetTTY">
109 <arg type="h" name="tty_fd" direction="in"/>
110 </method>
111 <method name="TakeDevice">
112 <arg type="u" name="major" direction="in"/>
113 <arg type="u" name="minor" direction="in"/>
114 <arg type="h" name="fd" direction="out"/>
115 <arg type="b" name="inactive" direction="out"/>
116 </method>
117 <method name="ReleaseDevice">
118 <arg type="u" name="major" direction="in"/>
119 <arg type="u" name="minor" direction="in"/>
120 </method>
121 <method name="PauseDeviceComplete">
122 <arg type="u" name="major" direction="in"/>
123 <arg type="u" name="minor" direction="in"/>
124 </method>
125 <method name="SetBrightness">
126 <arg type="s" name="subsystem" direction="in"/>
127 <arg type="s" name="name" direction="in"/>
128 <arg type="u" name="brightness" direction="in"/>
129 </method>
130 <signal name="PauseDevice">
131 <arg type="u" name="major"/>
132 <arg type="u" name="minor"/>
133 <arg type="s" name="type"/>
134 </signal>
135 <signal name="ResumeDevice">
136 <arg type="u" name="major"/>
137 <arg type="u" name="minor"/>
138 <arg type="h" name="fd"/>
139 </signal>
140 <signal name="Lock">
141 </signal>
142 <signal name="Unlock">
143 </signal>
144 </interface>
145</node>
146
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml
new file mode 100644
index 00000000..1dadbc55
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml
@@ -0,0 +1,821 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
2"https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3<node>
4 <interface name="org.freedesktop.systemd1.Manager">
5 <property name="Version" type="s" access="read">
6 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
7 </property>
8 <property name="Features" type="s" access="read">
9 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
10 </property>
11 <property name="Virtualization" type="s" access="read">
12 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
13 </property>
14 <property name="ConfidentialVirtualization" type="s" access="read">
15 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
16 </property>
17 <property name="Architecture" type="s" access="read">
18 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
19 </property>
20 <property name="Tainted" type="s" access="read">
21 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
22 </property>
23 <property name="FirmwareTimestamp" type="t" access="read">
24 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
25 </property>
26 <property name="FirmwareTimestampMonotonic" type="t" access="read">
27 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
28 </property>
29 <property name="LoaderTimestamp" type="t" access="read">
30 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
31 </property>
32 <property name="LoaderTimestampMonotonic" type="t" access="read">
33 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
34 </property>
35 <property name="KernelTimestamp" type="t" access="read">
36 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
37 </property>
38 <property name="KernelTimestampMonotonic" type="t" access="read">
39 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
40 </property>
41 <property name="InitRDTimestamp" type="t" access="read">
42 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
43 </property>
44 <property name="InitRDTimestampMonotonic" type="t" access="read">
45 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
46 </property>
47 <property name="UserspaceTimestamp" type="t" access="read">
48 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
49 </property>
50 <property name="UserspaceTimestampMonotonic" type="t" access="read">
51 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
52 </property>
53 <property name="FinishTimestamp" type="t" access="read">
54 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
55 </property>
56 <property name="FinishTimestampMonotonic" type="t" access="read">
57 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
58 </property>
59 <property name="ShutdownStartTimestamp" type="t" access="read">
60 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
61 </property>
62 <property name="ShutdownStartTimestampMonotonic" type="t" access="read">
63 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
64 </property>
65 <property name="SecurityStartTimestamp" type="t" access="read">
66 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
67 </property>
68 <property name="SecurityStartTimestampMonotonic" type="t" access="read">
69 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
70 </property>
71 <property name="SecurityFinishTimestamp" type="t" access="read">
72 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
73 </property>
74 <property name="SecurityFinishTimestampMonotonic" type="t" access="read">
75 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
76 </property>
77 <property name="GeneratorsStartTimestamp" type="t" access="read">
78 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
79 </property>
80 <property name="GeneratorsStartTimestampMonotonic" type="t" access="read">
81 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
82 </property>
83 <property name="GeneratorsFinishTimestamp" type="t" access="read">
84 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
85 </property>
86 <property name="GeneratorsFinishTimestampMonotonic" type="t" access="read">
87 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
88 </property>
89 <property name="UnitsLoadStartTimestamp" type="t" access="read">
90 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
91 </property>
92 <property name="UnitsLoadStartTimestampMonotonic" type="t" access="read">
93 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
94 </property>
95 <property name="UnitsLoadFinishTimestamp" type="t" access="read">
96 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
97 </property>
98 <property name="UnitsLoadFinishTimestampMonotonic" type="t" access="read">
99 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
100 </property>
101 <property name="UnitsLoadTimestamp" type="t" access="read">
102 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
103 </property>
104 <property name="UnitsLoadTimestampMonotonic" type="t" access="read">
105 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
106 </property>
107 <property name="InitRDSecurityStartTimestamp" type="t" access="read">
108 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
109 </property>
110 <property name="InitRDSecurityStartTimestampMonotonic" type="t" access="read">
111 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
112 </property>
113 <property name="InitRDSecurityFinishTimestamp" type="t" access="read">
114 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
115 </property>
116 <property name="InitRDSecurityFinishTimestampMonotonic" type="t" access="read">
117 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
118 </property>
119 <property name="InitRDGeneratorsStartTimestamp" type="t" access="read">
120 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
121 </property>
122 <property name="InitRDGeneratorsStartTimestampMonotonic" type="t" access="read">
123 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
124 </property>
125 <property name="InitRDGeneratorsFinishTimestamp" type="t" access="read">
126 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
127 </property>
128 <property name="InitRDGeneratorsFinishTimestampMonotonic" type="t" access="read">
129 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
130 </property>
131 <property name="InitRDUnitsLoadStartTimestamp" type="t" access="read">
132 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
133 </property>
134 <property name="InitRDUnitsLoadStartTimestampMonotonic" type="t" access="read">
135 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
136 </property>
137 <property name="InitRDUnitsLoadFinishTimestamp" type="t" access="read">
138 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
139 </property>
140 <property name="InitRDUnitsLoadFinishTimestampMonotonic" type="t" access="read">
141 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
142 </property>
143 <property name="LogLevel" type="s" access="readwrite">
144 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
145 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
146 </property>
147 <property name="LogTarget" type="s" access="readwrite">
148 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
149 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
150 </property>
151 <property name="NNames" type="u" access="read">
152 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
153 </property>
154 <property name="NFailedUnits" type="u" access="read">
155 </property>
156 <property name="NJobs" type="u" access="read">
157 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
158 </property>
159 <property name="NInstalledJobs" type="u" access="read">
160 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
161 </property>
162 <property name="NFailedJobs" type="u" access="read">
163 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
164 </property>
165 <property name="Progress" type="d" access="read">
166 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
167 </property>
168 <property name="Environment" type="as" access="read">
169 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
170 </property>
171 <property name="ConfirmSpawn" type="b" access="read">
172 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
173 </property>
174 <property name="ShowStatus" type="b" access="read">
175 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
176 </property>
177 <property name="UnitPath" type="as" access="read">
178 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
179 </property>
180 <property name="DefaultStandardOutput" type="s" access="read">
181 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
182 </property>
183 <property name="DefaultStandardError" type="s" access="read">
184 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
185 </property>
186 <property name="WatchdogDevice" type="s" access="read">
187 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
188 </property>
189 <property name="WatchdogLastPingTimestamp" type="t" access="read">
190 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
191 </property>
192 <property name="WatchdogLastPingTimestampMonotonic" type="t" access="read">
193 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
194 </property>
195 <property name="RuntimeWatchdogUSec" type="t" access="readwrite">
196 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
197 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
198 </property>
199 <property name="RuntimeWatchdogPreUSec" type="t" access="readwrite">
200 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
201 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
202 </property>
203 <property name="RuntimeWatchdogPreGovernor" type="s" access="readwrite">
204 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
205 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
206 </property>
207 <property name="RebootWatchdogUSec" type="t" access="readwrite">
208 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
209 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
210 </property>
211 <property name="KExecWatchdogUSec" type="t" access="readwrite">
212 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
213 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
214 </property>
215 <property name="ServiceWatchdogs" type="b" access="readwrite">
216 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
217 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
218 </property>
219 <property name="ControlGroup" type="s" access="read">
220 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
221 </property>
222 <property name="SystemState" type="s" access="read">
223 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
224 </property>
225 <property name="ExitCode" type="y" access="read">
226 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
227 </property>
228 <property name="DefaultTimerAccuracyUSec" type="t" access="read">
229 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
230 </property>
231 <property name="DefaultTimeoutStartUSec" type="t" access="read">
232 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
233 </property>
234 <property name="DefaultTimeoutStopUSec" type="t" access="read">
235 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
236 </property>
237 <property name="DefaultTimeoutAbortUSec" type="t" access="read">
238 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
239 </property>
240 <property name="DefaultDeviceTimeoutUSec" type="t" access="read">
241 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
242 </property>
243 <property name="DefaultRestartUSec" type="t" access="read">
244 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
245 </property>
246 <property name="DefaultStartLimitIntervalUSec" type="t" access="read">
247 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
248 </property>
249 <property name="DefaultStartLimitBurst" type="u" access="read">
250 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
251 </property>
252 <property name="DefaultCPUAccounting" type="b" access="read">
253 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
254 </property>
255 <property name="DefaultBlockIOAccounting" type="b" access="read">
256 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
257 </property>
258 <property name="DefaultIOAccounting" type="b" access="read">
259 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
260 </property>
261 <property name="DefaultIPAccounting" type="b" access="read">
262 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
263 </property>
264 <property name="DefaultMemoryAccounting" type="b" access="read">
265 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
266 </property>
267 <property name="DefaultTasksAccounting" type="b" access="read">
268 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
269 </property>
270 <property name="DefaultLimitCPU" type="t" access="read">
271 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
272 </property>
273 <property name="DefaultLimitCPUSoft" type="t" access="read">
274 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
275 </property>
276 <property name="DefaultLimitFSIZE" type="t" access="read">
277 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
278 </property>
279 <property name="DefaultLimitFSIZESoft" type="t" access="read">
280 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
281 </property>
282 <property name="DefaultLimitDATA" type="t" access="read">
283 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
284 </property>
285 <property name="DefaultLimitDATASoft" type="t" access="read">
286 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
287 </property>
288 <property name="DefaultLimitSTACK" type="t" access="read">
289 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
290 </property>
291 <property name="DefaultLimitSTACKSoft" type="t" access="read">
292 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
293 </property>
294 <property name="DefaultLimitCORE" type="t" access="read">
295 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
296 </property>
297 <property name="DefaultLimitCORESoft" type="t" access="read">
298 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
299 </property>
300 <property name="DefaultLimitRSS" type="t" access="read">
301 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
302 </property>
303 <property name="DefaultLimitRSSSoft" type="t" access="read">
304 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
305 </property>
306 <property name="DefaultLimitNOFILE" type="t" access="read">
307 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
308 </property>
309 <property name="DefaultLimitNOFILESoft" type="t" access="read">
310 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
311 </property>
312 <property name="DefaultLimitAS" type="t" access="read">
313 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
314 </property>
315 <property name="DefaultLimitASSoft" type="t" access="read">
316 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
317 </property>
318 <property name="DefaultLimitNPROC" type="t" access="read">
319 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
320 </property>
321 <property name="DefaultLimitNPROCSoft" type="t" access="read">
322 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
323 </property>
324 <property name="DefaultLimitMEMLOCK" type="t" access="read">
325 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
326 </property>
327 <property name="DefaultLimitMEMLOCKSoft" type="t" access="read">
328 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
329 </property>
330 <property name="DefaultLimitLOCKS" type="t" access="read">
331 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
332 </property>
333 <property name="DefaultLimitLOCKSSoft" type="t" access="read">
334 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
335 </property>
336 <property name="DefaultLimitSIGPENDING" type="t" access="read">
337 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
338 </property>
339 <property name="DefaultLimitSIGPENDINGSoft" type="t" access="read">
340 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
341 </property>
342 <property name="DefaultLimitMSGQUEUE" type="t" access="read">
343 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
344 </property>
345 <property name="DefaultLimitMSGQUEUESoft" type="t" access="read">
346 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
347 </property>
348 <property name="DefaultLimitNICE" type="t" access="read">
349 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
350 </property>
351 <property name="DefaultLimitNICESoft" type="t" access="read">
352 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
353 </property>
354 <property name="DefaultLimitRTPRIO" type="t" access="read">
355 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
356 </property>
357 <property name="DefaultLimitRTPRIOSoft" type="t" access="read">
358 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
359 </property>
360 <property name="DefaultLimitRTTIME" type="t" access="read">
361 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
362 </property>
363 <property name="DefaultLimitRTTIMESoft" type="t" access="read">
364 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
365 </property>
366 <property name="DefaultTasksMax" type="t" access="read">
367 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
368 </property>
369 <property name="DefaultMemoryPressureThresholdUSec" type="t" access="read">
370 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
371 </property>
372 <property name="DefaultMemoryPressureWatch" type="s" access="read">
373 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
374 </property>
375 <property name="TimerSlackNSec" type="t" access="read">
376 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
377 </property>
378 <property name="DefaultOOMPolicy" type="s" access="read">
379 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
380 </property>
381 <property name="DefaultOOMScoreAdjust" type="i" access="read">
382 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
383 </property>
384 <property name="CtrlAltDelBurstAction" type="s" access="read">
385 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
386 </property>
387 <property name="SoftRebootsCount" type="u" access="read">
388 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
389 </property>
390 <method name="GetUnit">
391 <arg type="s" name="name" direction="in"/>
392 <arg type="o" name="unit" direction="out"/>
393 </method>
394 <method name="GetUnitByPID">
395 <arg type="u" name="pid" direction="in"/>
396 <arg type="o" name="unit" direction="out"/>
397 </method>
398 <method name="GetUnitByInvocationID">
399 <arg type="ay" name="invocation_id" direction="in"/>
400 <arg type="o" name="unit" direction="out"/>
401 </method>
402 <method name="GetUnitByControlGroup">
403 <arg type="s" name="cgroup" direction="in"/>
404 <arg type="o" name="unit" direction="out"/>
405 </method>
406 <method name="GetUnitByPIDFD">
407 <arg type="h" name="pidfd" direction="in"/>
408 <arg type="o" name="unit" direction="out"/>
409 <arg type="s" name="unit_id" direction="out"/>
410 <arg type="ay" name="invocation_id" direction="out"/>
411 </method>
412 <method name="LoadUnit">
413 <arg type="s" name="name" direction="in"/>
414 <arg type="o" name="unit" direction="out"/>
415 </method>
416 <method name="StartUnit">
417 <arg type="s" name="name" direction="in"/>
418 <arg type="s" name="mode" direction="in"/>
419 <arg type="o" name="job" direction="out"/>
420 </method>
421 <method name="StartUnitWithFlags">
422 <arg type="s" name="name" direction="in"/>
423 <arg type="s" name="mode" direction="in"/>
424 <arg type="t" name="flags" direction="in"/>
425 <arg type="o" name="job" direction="out"/>
426 </method>
427 <method name="StartUnitReplace">
428 <arg type="s" name="old_unit" direction="in"/>
429 <arg type="s" name="new_unit" direction="in"/>
430 <arg type="s" name="mode" direction="in"/>
431 <arg type="o" name="job" direction="out"/>
432 </method>
433 <method name="StopUnit">
434 <arg type="s" name="name" direction="in"/>
435 <arg type="s" name="mode" direction="in"/>
436 <arg type="o" name="job" direction="out"/>
437 </method>
438 <method name="ReloadUnit">
439 <arg type="s" name="name" direction="in"/>
440 <arg type="s" name="mode" direction="in"/>
441 <arg type="o" name="job" direction="out"/>
442 </method>
443 <method name="RestartUnit">
444 <arg type="s" name="name" direction="in"/>
445 <arg type="s" name="mode" direction="in"/>
446 <arg type="o" name="job" direction="out"/>
447 </method>
448 <method name="TryRestartUnit">
449 <arg type="s" name="name" direction="in"/>
450 <arg type="s" name="mode" direction="in"/>
451 <arg type="o" name="job" direction="out"/>
452 </method>
453 <method name="ReloadOrRestartUnit">
454 <arg type="s" name="name" direction="in"/>
455 <arg type="s" name="mode" direction="in"/>
456 <arg type="o" name="job" direction="out"/>
457 </method>
458 <method name="ReloadOrTryRestartUnit">
459 <arg type="s" name="name" direction="in"/>
460 <arg type="s" name="mode" direction="in"/>
461 <arg type="o" name="job" direction="out"/>
462 </method>
463 <!-- <method name="EnqueueUnitJob"> -->
464 <!-- <arg type="s" name="name" direction="in"/> -->
465 <!-- <arg type="s" name="job_type" direction="in"/> -->
466 <!-- <arg type="s" name="job_mode" direction="in"/> -->
467 <!-- <arg type="u" name="job_id" direction="out"/> -->
468 <!-- <arg type="o" name="job_path" direction="out"/> -->
469 <!-- <arg type="s" name="unit_id" direction="out"/> -->
470 <!-- <arg type="o" name="unit_path" direction="out"/> -->
471 <!-- <arg type="s" name="job_type" direction="out"/> -->
472 <!-- <arg type="a(uosos)" name="affected_jobs" direction="out"/> -->
473 <!-- </method> -->
474 <method name="KillUnit">
475 <arg type="s" name="name" direction="in"/>
476 <arg type="s" name="whom" direction="in"/>
477 <arg type="i" name="signal" direction="in"/>
478 </method>
479 <method name="QueueSignalUnit">
480 <arg type="s" name="name" direction="in"/>
481 <arg type="s" name="whom" direction="in"/>
482 <arg type="i" name="signal" direction="in"/>
483 <arg type="i" name="value" direction="in"/>
484 </method>
485 <method name="CleanUnit">
486 <arg type="s" name="name" direction="in"/>
487 <arg type="as" name="mask" direction="in"/>
488 </method>
489 <method name="FreezeUnit">
490 <arg type="s" name="name" direction="in"/>
491 </method>
492 <method name="ThawUnit">
493 <arg type="s" name="name" direction="in"/>
494 </method>
495 <method name="ResetFailedUnit">
496 <arg type="s" name="name" direction="in"/>
497 </method>
498 <!-- <method name="SetUnitProperties"> -->
499 <!-- <arg type="s" name="name" direction="in"/> -->
500 <!-- <arg type="b" name="runtime" direction="in"/> -->
501 <!-- <arg type="a(sv)" name="properties" direction="in"/> -->
502 <!-- </method> -->
503 <method name="BindMountUnit">
504 <arg type="s" name="name" direction="in"/>
505 <arg type="s" name="source" direction="in"/>
506 <arg type="s" name="destination" direction="in"/>
507 <arg type="b" name="read_only" direction="in"/>
508 <arg type="b" name="mkdir" direction="in"/>
509 </method>
510 <!-- <method name="MountImageUnit"> -->
511 <!-- <arg type="s" name="name" direction="in"/> -->
512 <!-- <arg type="s" name="source" direction="in"/> -->
513 <!-- <arg type="s" name="destination" direction="in"/> -->
514 <!-- <arg type="b" name="read_only" direction="in"/> -->
515 <!-- <arg type="b" name="mkdir" direction="in"/> -->
516 <!-- <arg type="a(ss)" name="options" direction="in"/> -->
517 <!-- </method> -->
518 <method name="RefUnit">
519 <arg type="s" name="name" direction="in"/>
520 </method>
521 <method name="UnrefUnit">
522 <arg type="s" name="name" direction="in"/>
523 </method>
524 <!-- <method name="StartTransientUnit"> -->
525 <!-- <arg type="s" name="name" direction="in"/> -->
526 <!-- <arg type="s" name="mode" direction="in"/> -->
527 <!-- <arg type="a(sv)" name="properties" direction="in"/> -->
528 <!-- <arg type="a(sa(sv))" name="aux" direction="in"/> -->
529 <!-- <arg type="o" name="job" direction="out"/> -->
530 <!-- </method> -->
531 <!-- <method name="GetUnitProcesses"> -->
532 <!-- <arg type="s" name="name" direction="in"/> -->
533 <!-- <arg type="a(sus)" name="processes" direction="out"/> -->
534 <!-- </method> -->
535 <!-- <method name="AttachProcessesToUnit"> -->
536 <!-- <arg type="s" name="unit_name" direction="in"/> -->
537 <!-- <arg type="s" name="subcgroup" direction="in"/> -->
538 <!-- <arg type="au" name="pids" direction="in"/> -->
539 <!-- </method> -->
540 <method name="AbandonScope">
541 <arg type="s" name="name" direction="in"/>
542 </method>
543 <method name="GetJob">
544 <arg type="u" name="id" direction="in"/>
545 <arg type="o" name="job" direction="out"/>
546 </method>
547 <!-- <method name="GetJobAfter"> -->
548 <!-- <arg type="u" name="id" direction="in"/> -->
549 <!-- <arg type="a(usssoo)" name="jobs" direction="out"/> -->
550 <!-- </method> -->
551 <!-- <method name="GetJobBefore"> -->
552 <!-- <arg type="u" name="id" direction="in"/> -->
553 <!-- <arg type="a(usssoo)" name="jobs" direction="out"/> -->
554 <!-- </method> -->
555 <method name="CancelJob">
556 <arg type="u" name="id" direction="in"/>
557 </method>
558 <method name="ClearJobs">
559 </method>
560 <method name="ResetFailed">
561 </method>
562 <method name="SetShowStatus">
563 <arg type="s" name="mode" direction="in"/>
564 </method>
565 <method name="ListUnits">
566 <arg type="a(ssssssouso)" name="units" direction="out"/>
567 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ListUnitsResult"/>
568 </method>
569 <method name="ListUnitsFiltered">
570 <arg type="as" name="states" direction="in"/>
571 <arg type="a(ssssssouso)" name="units" direction="out"/>
572 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ListUnitsResult"/>
573 </method>
574 <method name="ListUnitsByPatterns">
575 <arg type="as" name="states" direction="in"/>
576 <arg type="as" name="patterns" direction="in"/>
577 <arg type="a(ssssssouso)" name="units" direction="out"/>
578 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ListUnitsResult"/>
579 </method>
580 <method name="ListUnitsByNames">
581 <arg type="as" name="names" direction="in"/>
582 <arg type="a(ssssssouso)" name="units" direction="out"/>
583 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ListUnitsResult"/>
584 </method>
585 <!-- <method name="ListJobs"> -->
586 <!-- <arg type="a(usssoo)" name="jobs" direction="out"/> -->
587 <!-- </method> -->
588 <method name="Subscribe">
589 </method>
590 <method name="Unsubscribe">
591 </method>
592 <method name="Dump">
593 <arg type="s" name="output" direction="out"/>
594 </method>
595 <method name="DumpUnitsMatchingPatterns">
596 <arg type="as" name="patterns" direction="in"/>
597 <arg type="s" name="output" direction="out"/>
598 </method>
599 <method name="DumpByFileDescriptor">
600 <arg type="h" name="fd" direction="out"/>
601 </method>
602 <method name="DumpUnitsMatchingPatternsByFileDescriptor">
603 <arg type="as" name="patterns" direction="in"/>
604 <arg type="h" name="fd" direction="out"/>
605 </method>
606 <method name="Reload">
607 </method>
608 <method name="Reexecute">
609 <annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
610 </method>
611 <method name="Exit">
612 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
613 </method>
614 <method name="Reboot">
615 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
616 </method>
617 <method name="SoftReboot">
618 <arg type="s" name="new_root" direction="in"/>
619 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
620 </method>
621 <method name="PowerOff">
622 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
623 </method>
624 <method name="Halt">
625 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
626 </method>
627 <method name="KExec">
628 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
629 </method>
630 <method name="SwitchRoot">
631 <arg type="s" name="new_root" direction="in"/>
632 <arg type="s" name="init" direction="in"/>
633 <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
634 </method>
635 <method name="SetEnvironment">
636 <arg type="as" name="assignments" direction="in"/>
637 </method>
638 <method name="UnsetEnvironment">
639 <arg type="as" name="names" direction="in"/>
640 </method>
641 <method name="UnsetAndSetEnvironment">
642 <arg type="as" name="names" direction="in"/>
643 <arg type="as" name="assignments" direction="in"/>
644 </method>
645 <method name="EnqueueMarkedJobs">
646 <arg type="ao" name="jobs" direction="out"/>
647 </method>
648 <!-- <method name="ListUnitFiles"> -->
649 <!-- <arg type="a(ss)" name="unit_files" direction="out"/> -->
650 <!-- </method> -->
651 <!-- <method name="ListUnitFilesByPatterns"> -->
652 <!-- <arg type="as" name="states" direction="in"/> -->
653 <!-- <arg type="as" name="patterns" direction="in"/> -->
654 <!-- <arg type="a(ss)" name="unit_files" direction="out"/> -->
655 <!-- </method> -->
656 <method name="GetUnitFileState">
657 <arg type="s" name="file" direction="in"/>
658 <arg type="s" name="state" direction="out"/>
659 </method>
660 <!-- <method name="EnableUnitFiles"> -->
661 <!-- <arg type="as" name="files" direction="in"/> -->
662 <!-- <arg type="b" name="runtime" direction="in"/> -->
663 <!-- <arg type="b" name="force" direction="in"/> -->
664 <!-- <arg type="b" name="carries_install_info" direction="out"/> -->
665 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
666 <!-- </method> -->
667 <!-- <method name="DisableUnitFiles"> -->
668 <!-- <arg type="as" name="files" direction="in"/> -->
669 <!-- <arg type="b" name="runtime" direction="in"/> -->
670 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
671 <!-- </method> -->
672 <!-- <method name="EnableUnitFilesWithFlags"> -->
673 <!-- <arg type="as" name="files" direction="in"/> -->
674 <!-- <arg type="t" name="flags" direction="in"/> -->
675 <!-- <arg type="b" name="carries_install_info" direction="out"/> -->
676 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
677 <!-- </method> -->
678 <!-- <method name="DisableUnitFilesWithFlags"> -->
679 <!-- <arg type="as" name="files" direction="in"/> -->
680 <!-- <arg type="t" name="flags" direction="in"/> -->
681 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
682 <!-- </method> -->
683 <!-- <method name="DisableUnitFilesWithFlagsAndInstallInfo"> -->
684 <!-- <arg type="as" name="files" direction="in"/> -->
685 <!-- <arg type="t" name="flags" direction="in"/> -->
686 <!-- <arg type="b" name="carries_install_info" direction="out"/> -->
687 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
688 <!-- </method> -->
689 <!-- <method name="ReenableUnitFiles"> -->
690 <!-- <arg type="as" name="files" direction="in"/> -->
691 <!-- <arg type="b" name="runtime" direction="in"/> -->
692 <!-- <arg type="b" name="force" direction="in"/> -->
693 <!-- <arg type="b" name="carries_install_info" direction="out"/> -->
694 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
695 <!-- </method> -->
696 <!-- <method name="LinkUnitFiles"> -->
697 <!-- <arg type="as" name="files" direction="in"/> -->
698 <!-- <arg type="b" name="runtime" direction="in"/> -->
699 <!-- <arg type="b" name="force" direction="in"/> -->
700 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
701 <!-- </method> -->
702 <!-- <method name="PresetUnitFiles"> -->
703 <!-- <arg type="as" name="files" direction="in"/> -->
704 <!-- <arg type="b" name="runtime" direction="in"/> -->
705 <!-- <arg type="b" name="force" direction="in"/> -->
706 <!-- <arg type="b" name="carries_install_info" direction="out"/> -->
707 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
708 <!-- </method> -->
709 <!-- <method name="PresetUnitFilesWithMode"> -->
710 <!-- <arg type="as" name="files" direction="in"/> -->
711 <!-- <arg type="s" name="mode" direction="in"/> -->
712 <!-- <arg type="b" name="runtime" direction="in"/> -->
713 <!-- <arg type="b" name="force" direction="in"/> -->
714 <!-- <arg type="b" name="carries_install_info" direction="out"/> -->
715 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
716 <!-- </method> -->
717 <!-- <method name="MaskUnitFiles"> -->
718 <!-- <arg type="as" name="files" direction="in"/> -->
719 <!-- <arg type="b" name="runtime" direction="in"/> -->
720 <!-- <arg type="b" name="force" direction="in"/> -->
721 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
722 <!-- </method> -->
723 <!-- <method name="UnmaskUnitFiles"> -->
724 <!-- <arg type="as" name="files" direction="in"/> -->
725 <!-- <arg type="b" name="runtime" direction="in"/> -->
726 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
727 <!-- </method> -->
728 <!-- <method name="RevertUnitFiles"> -->
729 <!-- <arg type="as" name="files" direction="in"/> -->
730 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
731 <!-- </method> -->
732 <!-- <method name="SetDefaultTarget"> -->
733 <!-- <arg type="s" name="name" direction="in"/> -->
734 <!-- <arg type="b" name="force" direction="in"/> -->
735 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
736 <!-- </method> -->
737 <method name="GetDefaultTarget">
738 <arg type="s" name="name" direction="out"/>
739 </method>
740 <!-- <method name="PresetAllUnitFiles"> -->
741 <!-- <arg type="s" name="mode" direction="in"/> -->
742 <!-- <arg type="b" name="runtime" direction="in"/> -->
743 <!-- <arg type="b" name="force" direction="in"/> -->
744 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
745 <!-- </method> -->
746 <!-- <method name="AddDependencyUnitFiles"> -->
747 <!-- <arg type="as" name="files" direction="in"/> -->
748 <!-- <arg type="s" name="target" direction="in"/> -->
749 <!-- <arg type="s" name="type" direction="in"/> -->
750 <!-- <arg type="b" name="runtime" direction="in"/> -->
751 <!-- <arg type="b" name="force" direction="in"/> -->
752 <!-- <arg type="a(sss)" name="changes" direction="out"/> -->
753 <!-- </method> -->
754 <method name="GetUnitFileLinks">
755 <arg type="s" name="name" direction="in"/>
756 <arg type="b" name="runtime" direction="in"/>
757 <arg type="as" name="links" direction="out"/>
758 </method>
759 <method name="SetExitCode">
760 <arg type="y" name="number" direction="in"/>
761 </method>
762 <method name="LookupDynamicUserByName">
763 <arg type="s" name="name" direction="in"/>
764 <arg type="u" name="uid" direction="out"/>
765 </method>
766 <method name="LookupDynamicUserByUID">
767 <arg type="u" name="uid" direction="in"/>
768 <arg type="s" name="name" direction="out"/>
769 </method>
770 <!-- <method name="GetDynamicUsers"> -->
771 <!-- <arg type="a(us)" name="users" direction="out"/> -->
772 <!-- </method> -->
773 <!-- <method name="DumpUnitFileDescriptorStore"> -->
774 <!-- <arg type="s" name="name" direction="in"/> -->
775 <!-- <arg type="a(suuutuusu)" name="entries" direction="out"/> -->
776 <!-- </method> -->
777 <!-- <method name="StartAuxiliaryScope"> -->
778 <!-- <arg type="s" name="name" direction="in"/> -->
779 <!-- <arg type="ah" name="pidfds" direction="in"/> -->
780 <!-- <arg type="t" name="flags" direction="in"/> -->
781 <!-- <arg type="a(sv)" name="properties" direction="in"/> -->
782 <!-- <arg type="o" name="job" direction="out"/> -->
783 <!-- <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> -->
784 <!-- </method> -->
785 <signal name="UnitNew">
786 <arg type="s" name="id"/>
787 <arg type="o" name="unit"/>
788 </signal>
789 <signal name="UnitRemoved">
790 <arg type="s" name="id"/>
791 <arg type="o" name="unit"/>
792 </signal>
793 <signal name="JobNew">
794 <arg type="u" name="id"/>
795 <arg type="o" name="job"/>
796 <arg type="s" name="unit"/>
797 </signal>
798 <signal name="JobRemoved">
799 <arg type="u" name="id"/>
800 <arg type="o" name="job"/>
801 <arg type="s" name="unit"/>
802 <arg type="s" name="result"/>
803 </signal>
804 <signal name="StartupFinished">
805 <arg type="t" name="firmware"/>
806 <arg type="t" name="loader"/>
807 <arg type="t" name="kernel"/>
808 <arg type="t" name="initrd"/>
809 <arg type="t" name="userspace"/>
810 <arg type="t" name="total"/>
811 </signal>
812 <signal name="UnitFilesChanged">
813 </signal>
814 <signal name="Reloading">
815 <arg type="b" name="active"/>
816 </signal>
817 </interface>
818 <node name="unit"/>
819 <node name="job"/>
820</node>
821
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml
new file mode 100644
index 00000000..316dd080
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml
@@ -0,0 +1,1100 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
2"https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3<node>
4 <interface name="org.freedesktop.systemd1.Service">
5 <property name="Type" type="s" access="read">
6 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
7 </property>
8 <property name="ExitType" type="s" access="read">
9 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
10 </property>
11 <property name="Restart" type="s" access="read">
12 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
13 </property>
14 <property name="RestartMode" type="s" access="read">
15 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
16 </property>
17 <property name="PIDFile" type="s" access="read">
18 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
19 </property>
20 <property name="NotifyAccess" type="s" access="read">
21 </property>
22 <property name="RestartUSec" type="t" access="read">
23 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
24 </property>
25 <property name="RestartSteps" type="u" access="read">
26 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
27 </property>
28 <property name="RestartMaxDelayUSec" type="t" access="read">
29 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
30 </property>
31 <property name="RestartUSecNext" type="t" access="read">
32 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
33 </property>
34 <property name="TimeoutStartUSec" type="t" access="read">
35 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
36 </property>
37 <property name="TimeoutStopUSec" type="t" access="read">
38 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
39 </property>
40 <property name="TimeoutAbortUSec" type="t" access="read">
41 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
42 </property>
43 <property name="TimeoutStartFailureMode" type="s" access="read">
44 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
45 </property>
46 <property name="TimeoutStopFailureMode" type="s" access="read">
47 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
48 </property>
49 <property name="RuntimeMaxUSec" type="t" access="read">
50 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
51 </property>
52 <property name="RuntimeRandomizedExtraUSec" type="t" access="read">
53 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
54 </property>
55 <property name="WatchdogUSec" type="t" access="read">
56 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
57 </property>
58 <property name="WatchdogTimestamp" type="t" access="read">
59 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
60 </property>
61 <property name="WatchdogTimestampMonotonic" type="t" access="read">
62 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
63 </property>
64 <property name="RootDirectoryStartOnly" type="b" access="read">
65 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
66 </property>
67 <property name="RemainAfterExit" type="b" access="read">
68 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
69 </property>
70 <property name="GuessMainPID" type="b" access="read">
71 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
72 </property>
73 <!-- <property name="RestartPreventExitStatus" type="(aiai)" access="read"> -->
74 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
75 <!-- </property> -->
76 <!-- <property name="RestartForceExitStatus" type="(aiai)" access="read"> -->
77 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
78 <!-- </property> -->
79 <!-- <property name="SuccessExitStatus" type="(aiai)" access="read"> -->
80 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
81 <!-- </property> -->
82 <property name="MainPID" type="u" access="read">
83 </property>
84 <property name="ControlPID" type="u" access="read">
85 </property>
86 <property name="BusName" type="s" access="read">
87 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
88 </property>
89 <property name="FileDescriptorStoreMax" type="u" access="read">
90 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
91 </property>
92 <property name="NFileDescriptorStore" type="u" access="read">
93 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
94 </property>
95 <property name="FileDescriptorStorePreserve" type="s" access="read">
96 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
97 </property>
98 <property name="StatusText" type="s" access="read">
99 </property>
100 <property name="StatusErrno" type="i" access="read">
101 </property>
102 <property name="StatusBusError" type="s" access="read">
103 </property>
104 <property name="StatusVarlinkError" type="s" access="read">
105 </property>
106 <property name="Result" type="s" access="read">
107 </property>
108 <property name="ReloadResult" type="s" access="read">
109 </property>
110 <property name="CleanResult" type="s" access="read">
111 </property>
112 <property name="LiveMountResult" type="s" access="read">
113 </property>
114 <property name="USBFunctionDescriptors" type="s" access="read">
115 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
116 </property>
117 <property name="USBFunctionStrings" type="s" access="read">
118 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
119 </property>
120 <property name="UID" type="u" access="read">
121 </property>
122 <property name="GID" type="u" access="read">
123 </property>
124 <property name="NRestarts" type="u" access="read">
125 </property>
126 <property name="OOMPolicy" type="s" access="read">
127 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
128 </property>
129 <!-- <property name="OpenFile" type="a(sst)" access="read"> -->
130 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
131 <!-- </property> -->
132 <property name="ExtraFileDescriptorNames" type="as" access="read">
133 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
134 </property>
135 <property name="ReloadSignal" type="i" access="read">
136 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
137 </property>
138 <property name="RefreshOnReload" type="as" access="read">
139 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
140 </property>
141 <property name="ExecMainStartTimestamp" type="t" access="read">
142 </property>
143 <property name="ExecMainStartTimestampMonotonic" type="t" access="read">
144 </property>
145 <property name="ExecMainExitTimestamp" type="t" access="read">
146 </property>
147 <property name="ExecMainExitTimestampMonotonic" type="t" access="read">
148 </property>
149 <property name="ExecMainHandoffTimestamp" type="t" access="read">
150 </property>
151 <property name="ExecMainHandoffTimestampMonotonic" type="t" access="read">
152 </property>
153 <property name="ExecMainPID" type="u" access="read">
154 </property>
155 <property name="ExecMainCode" type="i" access="read">
156 </property>
157 <property name="ExecMainStatus" type="i" access="read">
158 </property>
159 <!-- <property name="ExecCondition" type="a(sasbttttuii)" access="read"> -->
160 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
161 <!-- </property> -->
162 <!-- <property name="ExecConditionEx" type="a(sasasttttuii)" access="read"> -->
163 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
164 <!-- </property> -->
165 <!-- <property name="ExecStartPre" type="a(sasbttttuii)" access="read"> -->
166 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
167 <!-- </property> -->
168 <!-- <property name="ExecStartPreEx" type="a(sasasttttuii)" access="read"> -->
169 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
170 <!-- </property> -->
171 <!-- <property name="ExecStart" type="a(sasbttttuii)" access="read"> -->
172 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
173 <!-- </property> -->
174 <!-- <property name="ExecStartEx" type="a(sasasttttuii)" access="read"> -->
175 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
176 <!-- </property> -->
177 <!-- <property name="ExecStartPost" type="a(sasbttttuii)" access="read"> -->
178 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
179 <!-- </property> -->
180 <!-- <property name="ExecStartPostEx" type="a(sasasttttuii)" access="read"> -->
181 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
182 <!-- </property> -->
183 <!-- <property name="ExecReload" type="a(sasbttttuii)" access="read"> -->
184 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
185 <!-- </property> -->
186 <!-- <property name="ExecReloadEx" type="a(sasasttttuii)" access="read"> -->
187 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
188 <!-- </property> -->
189 <!-- <property name="ExecReloadPost" type="a(sasbttttuii)" access="read"> -->
190 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
191 <!-- </property> -->
192 <!-- <property name="ExecReloadPostEx" type="a(sasasttttuii)" access="read"> -->
193 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
194 <!-- </property> -->
195 <!-- <property name="ExecStop" type="a(sasbttttuii)" access="read"> -->
196 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
197 <!-- </property> -->
198 <!-- <property name="ExecStopEx" type="a(sasasttttuii)" access="read"> -->
199 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
200 <!-- </property> -->
201 <!-- <property name="ExecStopPost" type="a(sasbttttuii)" access="read"> -->
202 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
203 <!-- </property> -->
204 <!-- <property name="ExecStopPostEx" type="a(sasasttttuii)" access="read"> -->
205 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
206 <!-- </property> -->
207 <method name="BindMount">
208 <arg type="s" name="source" direction="in"/>
209 <arg type="s" name="destination" direction="in"/>
210 <arg type="b" name="read_only" direction="in"/>
211 <arg type="b" name="mkdir" direction="in"/>
212 </method>
213 <!-- <method name="MountImage"> -->
214 <!-- <arg type="s" name="source" direction="in"/> -->
215 <!-- <arg type="s" name="destination" direction="in"/> -->
216 <!-- <arg type="b" name="read_only" direction="in"/> -->
217 <!-- <arg type="b" name="mkdir" direction="in"/> -->
218 <!-- <arg type="a(ss)" name="options" direction="in"/> -->
219 <!-- </method> -->
220 <!-- <method name="DumpFileDescriptorStore"> -->
221 <!-- <arg type="a(suuutuusu)" name="entries" direction="out"/> -->
222 <!-- </method> -->
223 <property name="Slice" type="s" access="read">
224 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
225 </property>
226 <property name="ControlGroup" type="s" access="read">
227 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
228 </property>
229 <property name="ControlGroupId" type="t" access="read">
230 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
231 </property>
232 <property name="MemoryCurrent" type="t" access="read">
233 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
234 </property>
235 <property name="MemoryPeak" type="t" access="read">
236 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
237 </property>
238 <property name="MemorySwapCurrent" type="t" access="read">
239 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
240 </property>
241 <property name="MemorySwapPeak" type="t" access="read">
242 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
243 </property>
244 <property name="MemoryZSwapCurrent" type="t" access="read">
245 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
246 </property>
247 <property name="MemoryAvailable" type="t" access="read">
248 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
249 </property>
250 <property name="EffectiveMemoryMax" type="t" access="read">
251 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
252 </property>
253 <property name="EffectiveMemoryHigh" type="t" access="read">
254 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
255 </property>
256 <property name="CPUUsageNSec" type="t" access="read">
257 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
258 </property>
259 <property name="EffectiveCPUs" type="ay" access="read">
260 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
261 </property>
262 <property name="EffectiveMemoryNodes" type="ay" access="read">
263 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
264 </property>
265 <property name="TasksCurrent" type="t" access="read">
266 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
267 </property>
268 <property name="EffectiveTasksMax" type="t" access="read">
269 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
270 </property>
271 <property name="IPIngressBytes" type="t" access="read">
272 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
273 </property>
274 <property name="IPIngressPackets" type="t" access="read">
275 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
276 </property>
277 <property name="IPEgressBytes" type="t" access="read">
278 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
279 </property>
280 <property name="IPEgressPackets" type="t" access="read">
281 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
282 </property>
283 <property name="IOReadBytes" type="t" access="read">
284 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
285 </property>
286 <property name="IOReadOperations" type="t" access="read">
287 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
288 </property>
289 <property name="IOWriteBytes" type="t" access="read">
290 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
291 </property>
292 <property name="IOWriteOperations" type="t" access="read">
293 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
294 </property>
295 <property name="OOMKills" type="t" access="read">
296 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
297 </property>
298 <property name="ManagedOOMKills" type="t" access="read">
299 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
300 </property>
301 <!-- <method name="GetProcesses"> -->
302 <!-- <arg type="a(sus)" name="processes" direction="out"/> -->
303 <!-- </method> -->
304 <!-- <method name="AttachProcesses"> -->
305 <!-- <arg type="s" name="subcgroup" direction="in"/> -->
306 <!-- <arg type="au" name="pids" direction="in"/> -->
307 <!-- </method> -->
308 <method name="RemoveSubgroup">
309 <arg type="s" name="subcgroup" direction="in"/>
310 <arg type="t" name="flags" direction="in"/>
311 </method>
312 <property name="Delegate" type="b" access="read">
313 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
314 </property>
315 <property name="DelegateControllers" type="as" access="read">
316 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
317 </property>
318 <property name="DelegateSubgroup" type="s" access="read">
319 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
320 </property>
321 <property name="CPUWeight" type="t" access="read">
322 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
323 </property>
324 <property name="StartupCPUWeight" type="t" access="read">
325 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
326 </property>
327 <property name="CPUQuotaPerSecUSec" type="t" access="read">
328 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
329 </property>
330 <property name="CPUQuotaPeriodUSec" type="t" access="read">
331 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
332 </property>
333 <property name="AllowedCPUs" type="ay" access="read">
334 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
335 </property>
336 <property name="StartupAllowedCPUs" type="ay" access="read">
337 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
338 </property>
339 <property name="AllowedMemoryNodes" type="ay" access="read">
340 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
341 </property>
342 <property name="StartupAllowedMemoryNodes" type="ay" access="read">
343 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
344 </property>
345 <property name="IOAccounting" type="b" access="read">
346 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
347 </property>
348 <property name="IOWeight" type="t" access="read">
349 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
350 </property>
351 <property name="StartupIOWeight" type="t" access="read">
352 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
353 </property>
354 <!-- <property name="IODeviceWeight" type="a(st)" access="read"> -->
355 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
356 <!-- </property> -->
357 <!-- <property name="IOReadBandwidthMax" type="a(st)" access="read"> -->
358 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
359 <!-- </property> -->
360 <!-- <property name="IOWriteBandwidthMax" type="a(st)" access="read"> -->
361 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
362 <!-- </property> -->
363 <!-- <property name="IOReadIOPSMax" type="a(st)" access="read"> -->
364 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
365 <!-- </property> -->
366 <!-- <property name="IOWriteIOPSMax" type="a(st)" access="read"> -->
367 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
368 <!-- </property> -->
369 <!-- <property name="IODeviceLatencyTargetUSec" type="a(st)" access="read"> -->
370 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
371 <!-- </property> -->
372 <property name="MemoryAccounting" type="b" access="read">
373 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
374 </property>
375 <property name="MemoryMin" type="t" access="read">
376 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
377 </property>
378 <property name="MemoryLow" type="t" access="read">
379 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
380 </property>
381 <property name="StartupMemoryLow" type="t" access="read">
382 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
383 </property>
384 <property name="MemoryHigh" type="t" access="read">
385 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
386 </property>
387 <property name="StartupMemoryHigh" type="t" access="read">
388 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
389 </property>
390 <property name="MemoryMax" type="t" access="read">
391 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
392 </property>
393 <property name="StartupMemoryMax" type="t" access="read">
394 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
395 </property>
396 <property name="MemorySwapMax" type="t" access="read">
397 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
398 </property>
399 <property name="StartupMemorySwapMax" type="t" access="read">
400 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
401 </property>
402 <property name="MemoryZSwapMax" type="t" access="read">
403 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
404 </property>
405 <property name="StartupMemoryZSwapMax" type="t" access="read">
406 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
407 </property>
408 <property name="MemoryZSwapWriteback" type="b" access="read">
409 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
410 </property>
411 <property name="DevicePolicy" type="s" access="read">
412 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
413 </property>
414 <!-- <property name="DeviceAllow" type="a(ss)" access="read"> -->
415 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
416 <!-- </property> -->
417 <property name="TasksAccounting" type="b" access="read">
418 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
419 </property>
420 <property name="TasksMax" type="t" access="read">
421 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
422 </property>
423 <property name="IPAccounting" type="b" access="read">
424 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
425 </property>
426 <!-- <property name="IPAddressAllow" type="a(iayu)" access="read"> -->
427 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
428 <!-- </property> -->
429 <!-- <property name="IPAddressDeny" type="a(iayu)" access="read"> -->
430 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
431 <!-- </property> -->
432 <property name="IPIngressFilterPath" type="as" access="read">
433 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
434 </property>
435 <property name="IPEgressFilterPath" type="as" access="read">
436 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
437 </property>
438 <property name="DisableControllers" type="as" access="read">
439 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
440 </property>
441 <property name="ManagedOOMSwap" type="s" access="read">
442 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
443 </property>
444 <property name="ManagedOOMMemoryPressure" type="s" access="read">
445 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
446 </property>
447 <property name="ManagedOOMMemoryPressureLimit" type="u" access="read">
448 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
449 </property>
450 <property name="ManagedOOMMemoryPressureDurationUSec" type="t" access="read">
451 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
452 </property>
453 <property name="ManagedOOMPreference" type="s" access="read">
454 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
455 </property>
456 <!-- <property name="BPFProgram" type="a(ss)" access="read"> -->
457 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
458 <!-- </property> -->
459 <!-- <property name="SocketBindAllow" type="a(iiqq)" access="read"> -->
460 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
461 <!-- </property> -->
462 <!-- <property name="SocketBindDeny" type="a(iiqq)" access="read"> -->
463 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
464 <!-- </property> -->
465 <!-- <property name="RestrictNetworkInterfaces" type="(bas)" access="read"> -->
466 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
467 <!-- </property> -->
468 <property name="BindNetworkInterface" type="s" access="read">
469 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
470 </property>
471 <property name="MemoryPressureWatch" type="s" access="read">
472 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
473 </property>
474 <property name="MemoryPressureThresholdUSec" type="t" access="read">
475 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
476 </property>
477 <!-- <property name="NFTSet" type="a(iiss)" access="read"> -->
478 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
479 <!-- </property> -->
480 <property name="CoredumpReceive" type="b" access="read">
481 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
482 </property>
483 <property name="Environment" type="as" access="read">
484 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
485 </property>
486 <!-- <property name="EnvironmentFiles" type="a(sb)" access="read"> -->
487 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
488 <!-- </property> -->
489 <property name="PassEnvironment" type="as" access="read">
490 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
491 </property>
492 <property name="UnsetEnvironment" type="as" access="read">
493 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
494 </property>
495 <property name="UMask" type="u" access="read">
496 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
497 </property>
498 <property name="LimitCPU" type="t" access="read">
499 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
500 </property>
501 <property name="LimitCPUSoft" type="t" access="read">
502 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
503 </property>
504 <property name="LimitFSIZE" type="t" access="read">
505 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
506 </property>
507 <property name="LimitFSIZESoft" type="t" access="read">
508 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
509 </property>
510 <property name="LimitDATA" type="t" access="read">
511 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
512 </property>
513 <property name="LimitDATASoft" type="t" access="read">
514 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
515 </property>
516 <property name="LimitSTACK" type="t" access="read">
517 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
518 </property>
519 <property name="LimitSTACKSoft" type="t" access="read">
520 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
521 </property>
522 <property name="LimitCORE" type="t" access="read">
523 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
524 </property>
525 <property name="LimitCORESoft" type="t" access="read">
526 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
527 </property>
528 <property name="LimitRSS" type="t" access="read">
529 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
530 </property>
531 <property name="LimitRSSSoft" type="t" access="read">
532 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
533 </property>
534 <property name="LimitNOFILE" type="t" access="read">
535 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
536 </property>
537 <property name="LimitNOFILESoft" type="t" access="read">
538 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
539 </property>
540 <property name="LimitAS" type="t" access="read">
541 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
542 </property>
543 <property name="LimitASSoft" type="t" access="read">
544 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
545 </property>
546 <property name="LimitNPROC" type="t" access="read">
547 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
548 </property>
549 <property name="LimitNPROCSoft" type="t" access="read">
550 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
551 </property>
552 <property name="LimitMEMLOCK" type="t" access="read">
553 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
554 </property>
555 <property name="LimitMEMLOCKSoft" type="t" access="read">
556 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
557 </property>
558 <property name="LimitLOCKS" type="t" access="read">
559 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
560 </property>
561 <property name="LimitLOCKSSoft" type="t" access="read">
562 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
563 </property>
564 <property name="LimitSIGPENDING" type="t" access="read">
565 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
566 </property>
567 <property name="LimitSIGPENDINGSoft" type="t" access="read">
568 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
569 </property>
570 <property name="LimitMSGQUEUE" type="t" access="read">
571 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
572 </property>
573 <property name="LimitMSGQUEUESoft" type="t" access="read">
574 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
575 </property>
576 <property name="LimitNICE" type="t" access="read">
577 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
578 </property>
579 <property name="LimitNICESoft" type="t" access="read">
580 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
581 </property>
582 <property name="LimitRTPRIO" type="t" access="read">
583 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
584 </property>
585 <property name="LimitRTPRIOSoft" type="t" access="read">
586 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
587 </property>
588 <property name="LimitRTTIME" type="t" access="read">
589 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
590 </property>
591 <property name="LimitRTTIMESoft" type="t" access="read">
592 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
593 </property>
594 <property name="WorkingDirectory" type="s" access="read">
595 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
596 </property>
597 <property name="RootDirectory" type="s" access="read">
598 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
599 </property>
600 <property name="RootImage" type="s" access="read">
601 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
602 </property>
603 <!-- <property name="RootImageOptions" type="a(ss)" access="read"> -->
604 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
605 <!-- </property> -->
606 <property name="RootHash" type="ay" access="read">
607 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
608 </property>
609 <property name="RootHashPath" type="s" access="read">
610 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
611 </property>
612 <property name="RootHashSignature" type="ay" access="read">
613 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
614 </property>
615 <property name="RootHashSignaturePath" type="s" access="read">
616 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
617 </property>
618 <property name="RootVerity" type="s" access="read">
619 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
620 </property>
621 <property name="RootEphemeral" type="b" access="read">
622 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
623 </property>
624 <property name="RootMStack" type="s" access="read">
625 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
626 </property>
627 <property name="ExtensionDirectories" type="as" access="read">
628 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
629 </property>
630 <!-- <property name="ExtensionImages" type="a(sba(ss))" access="read"> -->
631 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
632 <!-- </property> -->
633 <!-- <property name="MountImages" type="a(ssba(ss))" access="read"> -->
634 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
635 <!-- </property> -->
636 <property name="OOMScoreAdjust" type="i" access="read">
637 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
638 </property>
639 <property name="CoredumpFilter" type="t" access="read">
640 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
641 </property>
642 <property name="Nice" type="i" access="read">
643 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
644 </property>
645 <property name="IOSchedulingClass" type="i" access="read">
646 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
647 </property>
648 <property name="IOSchedulingPriority" type="i" access="read">
649 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
650 </property>
651 <property name="CPUSchedulingPolicy" type="i" access="read">
652 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
653 </property>
654 <property name="CPUSchedulingPriority" type="i" access="read">
655 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
656 </property>
657 <property name="CPUAffinity" type="ay" access="read">
658 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
659 </property>
660 <property name="CPUAffinityFromNUMA" type="b" access="read">
661 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
662 </property>
663 <property name="NUMAPolicy" type="i" access="read">
664 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
665 </property>
666 <property name="NUMAMask" type="ay" access="read">
667 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
668 </property>
669 <property name="TimerSlackNSec" type="t" access="read">
670 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
671 </property>
672 <property name="CPUSchedulingResetOnFork" type="b" access="read">
673 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
674 </property>
675 <property name="NonBlocking" type="b" access="read">
676 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
677 </property>
678 <property name="StandardInput" type="s" access="read">
679 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
680 </property>
681 <property name="StandardInputFileDescriptorName" type="s" access="read">
682 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
683 </property>
684 <property name="StandardInputData" type="ay" access="read">
685 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
686 </property>
687 <property name="StandardOutput" type="s" access="read">
688 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
689 </property>
690 <property name="StandardOutputFileDescriptorName" type="s" access="read">
691 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
692 </property>
693 <property name="StandardError" type="s" access="read">
694 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
695 </property>
696 <property name="StandardErrorFileDescriptorName" type="s" access="read">
697 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
698 </property>
699 <property name="TTYPath" type="s" access="read">
700 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
701 </property>
702 <property name="TTYReset" type="b" access="read">
703 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
704 </property>
705 <property name="TTYVHangup" type="b" access="read">
706 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
707 </property>
708 <property name="TTYVTDisallocate" type="b" access="read">
709 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
710 </property>
711 <property name="TTYRows" type="q" access="read">
712 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
713 </property>
714 <property name="TTYColumns" type="q" access="read">
715 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
716 </property>
717 <property name="SyslogPriority" type="i" access="read">
718 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
719 </property>
720 <property name="SyslogIdentifier" type="s" access="read">
721 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
722 </property>
723 <property name="SyslogLevelPrefix" type="b" access="read">
724 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
725 </property>
726 <property name="SyslogLevel" type="i" access="read">
727 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
728 </property>
729 <property name="SyslogFacility" type="i" access="read">
730 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
731 </property>
732 <property name="LogLevelMax" type="i" access="read">
733 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
734 </property>
735 <property name="LogRateLimitIntervalUSec" type="t" access="read">
736 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
737 </property>
738 <property name="LogRateLimitBurst" type="u" access="read">
739 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
740 </property>
741 <!-- <property name="LogExtraFields" type="aay" access="read"> -->
742 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
743 <!-- </property> -->
744 <!-- <property name="LogFilterPatterns" type="a(bs)" access="read"> -->
745 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
746 <!-- </property> -->
747 <property name="LogNamespace" type="s" access="read">
748 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
749 </property>
750 <property name="SecureBits" type="i" access="read">
751 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
752 </property>
753 <property name="CapabilityBoundingSet" type="t" access="read">
754 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
755 </property>
756 <property name="AmbientCapabilities" type="t" access="read">
757 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
758 </property>
759 <property name="User" type="s" access="read">
760 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
761 </property>
762 <property name="Group" type="s" access="read">
763 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
764 </property>
765 <property name="DynamicUser" type="b" access="read">
766 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
767 </property>
768 <property name="SetLoginEnvironment" type="b" access="read">
769 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
770 </property>
771 <property name="RemoveIPC" type="b" access="read">
772 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
773 </property>
774 <!-- <property name="SetCredential" type="a(say)" access="read"> -->
775 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
776 <!-- </property> -->
777 <!-- <property name="SetCredentialEncrypted" type="a(say)" access="read"> -->
778 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
779 <!-- </property> -->
780 <!-- <property name="LoadCredential" type="a(ss)" access="read"> -->
781 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
782 <!-- </property> -->
783 <!-- <property name="LoadCredentialEncrypted" type="a(ss)" access="read"> -->
784 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
785 <!-- </property> -->
786 <property name="ImportCredential" type="as" access="read">
787 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
788 </property>
789 <!-- <property name="ImportCredentialEx" type="a(ss)" access="read"> -->
790 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
791 <!-- </property> -->
792 <property name="SupplementaryGroups" type="as" access="read">
793 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
794 </property>
795 <property name="PAMName" type="s" access="read">
796 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
797 </property>
798 <property name="ReadWritePaths" type="as" access="read">
799 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
800 </property>
801 <property name="ReadOnlyPaths" type="as" access="read">
802 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
803 </property>
804 <property name="InaccessiblePaths" type="as" access="read">
805 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
806 </property>
807 <property name="ExecPaths" type="as" access="read">
808 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
809 </property>
810 <property name="NoExecPaths" type="as" access="read">
811 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
812 </property>
813 <property name="ExecSearchPath" type="as" access="read">
814 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
815 </property>
816 <property name="MountFlags" type="t" access="read">
817 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
818 </property>
819 <property name="PrivateTmp" type="b" access="read">
820 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
821 </property>
822 <property name="PrivateTmpEx" type="s" access="read">
823 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
824 </property>
825 <property name="PrivateDevices" type="b" access="read">
826 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
827 </property>
828 <property name="ProtectClock" type="b" access="read">
829 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
830 </property>
831 <property name="ProtectKernelTunables" type="b" access="read">
832 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
833 </property>
834 <property name="ProtectKernelModules" type="b" access="read">
835 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
836 </property>
837 <property name="ProtectKernelLogs" type="b" access="read">
838 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
839 </property>
840 <property name="ProtectControlGroups" type="b" access="read">
841 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
842 </property>
843 <property name="ProtectControlGroupsEx" type="s" access="read">
844 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
845 </property>
846 <property name="PrivateNetwork" type="b" access="read">
847 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
848 </property>
849 <property name="PrivateUsers" type="b" access="read">
850 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
851 </property>
852 <property name="PrivateUsersEx" type="s" access="read">
853 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
854 </property>
855 <property name="PrivateMounts" type="b" access="read">
856 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
857 </property>
858 <property name="PrivateIPC" type="b" access="read">
859 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
860 </property>
861 <property name="PrivatePIDs" type="s" access="read">
862 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
863 </property>
864 <property name="ProtectHome" type="s" access="read">
865 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
866 </property>
867 <property name="ProtectSystem" type="s" access="read">
868 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
869 </property>
870 <property name="SameProcessGroup" type="b" access="read">
871 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
872 </property>
873 <property name="UtmpIdentifier" type="s" access="read">
874 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
875 </property>
876 <property name="UtmpMode" type="s" access="read">
877 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
878 </property>
879 <!-- <property name="SELinuxContext" type="(bs)" access="read"> -->
880 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
881 <!-- </property> -->
882 <!-- <property name="AppArmorProfile" type="(bs)" access="read"> -->
883 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
884 <!-- </property> -->
885 <!-- <property name="SmackProcessLabel" type="(bs)" access="read"> -->
886 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
887 <!-- </property> -->
888 <property name="IgnoreSIGPIPE" type="b" access="read">
889 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
890 </property>
891 <property name="NoNewPrivileges" type="b" access="read">
892 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
893 </property>
894 <!-- <property name="SystemCallFilter" type="(bas)" access="read"> -->
895 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
896 <!-- </property> -->
897 <property name="SystemCallArchitectures" type="as" access="read">
898 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
899 </property>
900 <property name="SystemCallErrorNumber" type="i" access="read">
901 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
902 </property>
903 <!-- <property name="SystemCallLog" type="(bas)" access="read"> -->
904 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
905 <!-- </property> -->
906 <property name="Personality" type="s" access="read">
907 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
908 </property>
909 <property name="LockPersonality" type="b" access="read">
910 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
911 </property>
912 <!-- <property name="RestrictAddressFamilies" type="(bas)" access="read"> -->
913 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
914 <!-- </property> -->
915 <!-- <property name="RuntimeDirectorySymlink" type="a(sst)" access="read"> -->
916 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
917 <!-- </property> -->
918 <property name="RuntimeDirectoryPreserve" type="s" access="read">
919 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
920 </property>
921 <property name="RuntimeDirectoryMode" type="u" access="read">
922 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
923 </property>
924 <property name="RuntimeDirectory" type="as" access="read">
925 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
926 </property>
927 <!-- <property name="StateDirectorySymlink" type="a(sst)" access="read"> -->
928 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
929 <!-- </property> -->
930 <property name="StateDirectoryMode" type="u" access="read">
931 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
932 </property>
933 <property name="StateDirectoryAccounting" type="b" access="read">
934 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
935 </property>
936 <!-- <property name="StateDirectoryQuota" type="(tus)" access="read"> -->
937 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
938 <!-- </property> -->
939 <property name="StateDirectory" type="as" access="read">
940 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
941 </property>
942 <!-- <property name="CacheDirectorySymlink" type="a(sst)" access="read"> -->
943 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
944 <!-- </property> -->
945 <property name="CacheDirectoryMode" type="u" access="read">
946 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
947 </property>
948 <property name="CacheDirectoryAccounting" type="b" access="read">
949 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
950 </property>
951 <!-- <property name="CacheDirectoryQuota" type="(tus)" access="read"> -->
952 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
953 <!-- </property> -->
954 <property name="CacheDirectory" type="as" access="read">
955 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
956 </property>
957 <!-- <property name="LogsDirectorySymlink" type="a(sst)" access="read"> -->
958 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
959 <!-- </property> -->
960 <property name="LogsDirectoryMode" type="u" access="read">
961 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
962 </property>
963 <property name="LogsDirectoryAccounting" type="b" access="read">
964 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
965 </property>
966 <!-- <property name="LogsDirectoryQuota" type="(tus)" access="read"> -->
967 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
968 <!-- </property> -->
969 <property name="LogsDirectory" type="as" access="read">
970 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
971 </property>
972 <property name="ConfigurationDirectoryMode" type="u" access="read">
973 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
974 </property>
975 <property name="ConfigurationDirectory" type="as" access="read">
976 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
977 </property>
978 <property name="TimeoutCleanUSec" type="t" access="read">
979 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
980 </property>
981 <property name="MemoryDenyWriteExecute" type="b" access="read">
982 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
983 </property>
984 <property name="RestrictRealtime" type="b" access="read">
985 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
986 </property>
987 <property name="RestrictSUIDSGID" type="b" access="read">
988 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
989 </property>
990 <property name="RestrictNamespaces" type="t" access="read">
991 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
992 </property>
993 <property name="DelegateNamespaces" type="t" access="read">
994 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
995 </property>
996 <!-- <property name="RestrictFileSystems" type="(bas)" access="read"> -->
997 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
998 <!-- </property> -->
999 <!-- <property name="BindPaths" type="a(ssbt)" access="read"> -->
1000 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
1001 <!-- </property> -->
1002 <!-- <property name="BindReadOnlyPaths" type="a(ssbt)" access="read"> -->
1003 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
1004 <!-- </property> -->
1005 <!-- <property name="TemporaryFileSystem" type="a(ss)" access="read"> -->
1006 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
1007 <!-- </property> -->
1008 <property name="MountAPIVFS" type="b" access="read">
1009 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1010 </property>
1011 <property name="BindLogSockets" type="b" access="read">
1012 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1013 </property>
1014 <property name="KeyringMode" type="s" access="read">
1015 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1016 </property>
1017 <property name="ProtectProc" type="s" access="read">
1018 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1019 </property>
1020 <property name="ProcSubset" type="s" access="read">
1021 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1022 </property>
1023 <property name="ProtectHostname" type="b" access="read">
1024 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1025 </property>
1026 <!-- <property name="ProtectHostnameEx" type="(ss)" access="read"> -->
1027 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
1028 <!-- </property> -->
1029 <property name="PrivateBPF" type="s" access="read">
1030 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1031 </property>
1032 <property name="BPFDelegateCommands" type="s" access="read">
1033 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1034 </property>
1035 <property name="BPFDelegateMaps" type="s" access="read">
1036 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1037 </property>
1038 <property name="BPFDelegatePrograms" type="s" access="read">
1039 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1040 </property>
1041 <property name="BPFDelegateAttachments" type="s" access="read">
1042 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1043 </property>
1044 <property name="MemoryKSM" type="b" access="read">
1045 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1046 </property>
1047 <property name="MemoryTHP" type="s" access="read">
1048 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1049 </property>
1050 <property name="UserNamespacePath" type="s" access="read">
1051 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1052 </property>
1053 <property name="NetworkNamespacePath" type="s" access="read">
1054 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1055 </property>
1056 <property name="IPCNamespacePath" type="s" access="read">
1057 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1058 </property>
1059 <property name="RootImagePolicy" type="s" access="read">
1060 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1061 </property>
1062 <property name="MountImagePolicy" type="s" access="read">
1063 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1064 </property>
1065 <property name="ExtensionImagePolicy" type="s" access="read">
1066 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1067 </property>
1068 <!-- <property name="StateDirectoryQuotaUsage" type="(tt)" access="read"> -->
1069 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
1070 <!-- </property> -->
1071 <!-- <property name="CacheDirectoryQuotaUsage" type="(tt)" access="read"> -->
1072 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
1073 <!-- </property> -->
1074 <!-- <property name="LogsDirectoryQuotaUsage" type="(tt)" access="read"> -->
1075 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/> -->
1076 <!-- </property> -->
1077 <property name="KillMode" type="s" access="read">
1078 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1079 </property>
1080 <property name="KillSignal" type="i" access="read">
1081 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1082 </property>
1083 <property name="RestartKillSignal" type="i" access="read">
1084 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1085 </property>
1086 <property name="FinalKillSignal" type="i" access="read">
1087 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1088 </property>
1089 <property name="SendSIGKILL" type="b" access="read">
1090 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1091 </property>
1092 <property name="SendSIGHUP" type="b" access="read">
1093 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1094 </property>
1095 <property name="WatchdogSignal" type="i" access="read">
1096 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
1097 </property>
1098 </interface>
1099</node>
1100
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml
new file mode 100644
index 00000000..a554f513
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml
@@ -0,0 +1,359 @@
1<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
2"https://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3<node>
4 <interface name="org.freedesktop.systemd1.Unit">
5 <property name="Id" type="s" access="read">
6 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
7 </property>
8 <property name="Names" type="as" access="read">
9 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
10 </property>
11 <property name="Following" type="s" access="read">
12 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
13 </property>
14 <!-- <property name="Requires" type="as" access="read"> -->
15 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
16 <!-- </property> -->
17 <property name="Requisite" type="as" access="read">
18 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
19 </property>
20 <property name="Wants" type="as" access="read">
21 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
22 </property>
23 <property name="BindsTo" type="as" access="read">
24 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
25 </property>
26 <property name="PartOf" type="as" access="read">
27 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
28 </property>
29 <property name="Upholds" type="as" access="read">
30 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
31 </property>
32 <property name="RequiredBy" type="as" access="read">
33 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
34 </property>
35 <property name="RequisiteOf" type="as" access="read">
36 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
37 </property>
38 <property name="WantedBy" type="as" access="read">
39 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
40 </property>
41 <property name="BoundBy" type="as" access="read">
42 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
43 </property>
44 <property name="UpheldBy" type="as" access="read">
45 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
46 </property>
47 <property name="ConsistsOf" type="as" access="read">
48 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
49 </property>
50 <property name="Conflicts" type="as" access="read">
51 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
52 </property>
53 <property name="ConflictedBy" type="as" access="read">
54 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
55 </property>
56 <property name="Before" type="as" access="read">
57 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
58 </property>
59 <property name="After" type="as" access="read">
60 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
61 </property>
62 <property name="OnSuccess" type="as" access="read">
63 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
64 </property>
65 <property name="OnSuccessOf" type="as" access="read">
66 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
67 </property>
68 <property name="OnFailure" type="as" access="read">
69 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
70 </property>
71 <property name="OnFailureOf" type="as" access="read">
72 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
73 </property>
74 <property name="Triggers" type="as" access="read">
75 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
76 </property>
77 <property name="TriggeredBy" type="as" access="read">
78 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
79 </property>
80 <property name="PropagatesReloadTo" type="as" access="read">
81 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
82 </property>
83 <property name="ReloadPropagatedFrom" type="as" access="read">
84 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
85 </property>
86 <property name="PropagatesStopTo" type="as" access="read">
87 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
88 </property>
89 <property name="StopPropagatedFrom" type="as" access="read">
90 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
91 </property>
92 <property name="JoinsNamespaceOf" type="as" access="read">
93 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
94 </property>
95 <property name="SliceOf" type="as" access="read">
96 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
97 </property>
98 <property name="RequiresMountsFor" type="as" access="read">
99 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
100 </property>
101 <property name="WantsMountsFor" type="as" access="read">
102 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
103 </property>
104 <property name="Documentation" type="as" access="read">
105 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
106 </property>
107 <property name="Description" type="s" access="read">
108 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
109 </property>
110 <property name="AccessSELinuxContext" type="s" access="read">
111 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
112 </property>
113 <property name="LoadState" type="s" access="read">
114 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
115 </property>
116 <property name="ActiveState" type="s" access="read">
117 </property>
118 <property name="FreezerState" type="s" access="read">
119 </property>
120 <property name="SubState" type="s" access="read">
121 </property>
122 <property name="FragmentPath" type="s" access="read">
123 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
124 </property>
125 <property name="SourcePath" type="s" access="read">
126 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
127 </property>
128 <property name="DropInPaths" type="as" access="read">
129 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
130 </property>
131 <property name="UnitFileState" type="s" access="read">
132 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
133 </property>
134 <property name="UnitFilePreset" type="s" access="read">
135 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
136 </property>
137 <property name="StateChangeTimestamp" type="t" access="read">
138 </property>
139 <property name="StateChangeTimestampMonotonic" type="t" access="read">
140 </property>
141 <property name="InactiveExitTimestamp" type="t" access="read">
142 </property>
143 <property name="InactiveExitTimestampMonotonic" type="t" access="read">
144 </property>
145 <property name="ActiveEnterTimestamp" type="t" access="read">
146 </property>
147 <property name="ActiveEnterTimestampMonotonic" type="t" access="read">
148 </property>
149 <property name="ActiveExitTimestamp" type="t" access="read">
150 </property>
151 <property name="ActiveExitTimestampMonotonic" type="t" access="read">
152 </property>
153 <property name="InactiveEnterTimestamp" type="t" access="read">
154 </property>
155 <property name="InactiveEnterTimestampMonotonic" type="t" access="read">
156 </property>
157 <property name="CanStart" type="b" access="read">
158 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
159 </property>
160 <property name="CanStop" type="b" access="read">
161 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
162 </property>
163 <property name="CanReload" type="b" access="read">
164 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
165 </property>
166 <property name="CanIsolate" type="b" access="read">
167 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
168 </property>
169 <property name="CanClean" type="as" access="read">
170 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
171 </property>
172 <property name="CanFreeze" type="b" access="read">
173 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
174 </property>
175 <property name="CanLiveMount" type="b" access="read">
176 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
177 </property>
178 <!-- <property name="Job" type="(uo)" access="read"> -->
179 <!-- </property> -->
180 <property name="StopWhenUnneeded" type="b" access="read">
181 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
182 </property>
183 <property name="RefuseManualStart" type="b" access="read">
184 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
185 </property>
186 <property name="RefuseManualStop" type="b" access="read">
187 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
188 </property>
189 <property name="AllowIsolate" type="b" access="read">
190 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
191 </property>
192 <property name="DefaultDependencies" type="b" access="read">
193 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
194 </property>
195 <property name="SurviveFinalKillSignal" type="b" access="read">
196 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
197 </property>
198 <property name="OnSuccessJobMode" type="s" access="read">
199 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
200 </property>
201 <property name="OnFailureJobMode" type="s" access="read">
202 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
203 </property>
204 <property name="IgnoreOnIsolate" type="b" access="read">
205 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
206 </property>
207 <property name="NeedDaemonReload" type="b" access="read">
208 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
209 </property>
210 <property name="Markers" type="as" access="read">
211 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
212 </property>
213 <property name="JobTimeoutUSec" type="t" access="read">
214 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
215 </property>
216 <property name="JobRunningTimeoutUSec" type="t" access="read">
217 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
218 </property>
219 <property name="JobTimeoutAction" type="s" access="read">
220 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
221 </property>
222 <property name="JobTimeoutRebootArgument" type="s" access="read">
223 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
224 </property>
225 <property name="ConditionResult" type="b" access="read">
226 </property>
227 <property name="AssertResult" type="b" access="read">
228 </property>
229 <property name="ConditionTimestamp" type="t" access="read">
230 </property>
231 <property name="ConditionTimestampMonotonic" type="t" access="read">
232 </property>
233 <property name="AssertTimestamp" type="t" access="read">
234 </property>
235 <property name="AssertTimestampMonotonic" type="t" access="read">
236 </property>
237 <!-- <property name="Conditions" type="a(sbbsi)" access="read"> -->
238 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
239 <!-- </property> -->
240 <!-- <property name="Asserts" type="a(sbbsi)" access="read"> -->
241 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/> -->
242 <!-- </property> -->
243 <!-- <property name="LoadError" type="(ss)" access="read"> -->
244 <!-- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/> -->
245 <!-- </property> -->
246 <property name="Transient" type="b" access="read">
247 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
248 </property>
249 <property name="Perpetual" type="b" access="read">
250 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
251 </property>
252 <property name="StartLimitIntervalUSec" type="t" access="read">
253 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
254 </property>
255 <property name="StartLimitBurst" type="u" access="read">
256 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
257 </property>
258 <property name="StartLimitAction" type="s" access="read">
259 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
260 </property>
261 <property name="FailureAction" type="s" access="read">
262 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
263 </property>
264 <property name="FailureActionExitStatus" type="i" access="read">
265 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
266 </property>
267 <property name="SuccessAction" type="s" access="read">
268 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
269 </property>
270 <property name="SuccessActionExitStatus" type="i" access="read">
271 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
272 </property>
273 <property name="RebootArgument" type="s" access="read">
274 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
275 </property>
276 <property name="InvocationID" type="ay" access="read">
277 </property>
278 <property name="CollectMode" type="s" access="read">
279 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
280 </property>
281 <property name="Refs" type="as" access="read">
282 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
283 </property>
284 <!-- <property name="ActivationDetails" type="a(ss)" access="read"> -->
285 <!-- </property> -->
286 <property name="DebugInvocation" type="b" access="read">
287 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
288 </property>
289 <method name="Start">
290 <arg type="s" name="mode" direction="in"/>
291 <arg type="o" name="job" direction="out"/>
292 </method>
293 <method name="Stop">
294 <arg type="s" name="mode" direction="in"/>
295 <arg type="o" name="job" direction="out"/>
296 </method>
297 <method name="Reload">
298 <arg type="s" name="mode" direction="in"/>
299 <arg type="o" name="job" direction="out"/>
300 </method>
301 <method name="Restart">
302 <arg type="s" name="mode" direction="in"/>
303 <arg type="o" name="job" direction="out"/>
304 </method>
305 <method name="TryRestart">
306 <arg type="s" name="mode" direction="in"/>
307 <arg type="o" name="job" direction="out"/>
308 </method>
309 <method name="ReloadOrRestart">
310 <arg type="s" name="mode" direction="in"/>
311 <arg type="o" name="job" direction="out"/>
312 </method>
313 <method name="ReloadOrTryRestart">
314 <arg type="s" name="mode" direction="in"/>
315 <arg type="o" name="job" direction="out"/>
316 </method>
317 <!-- <method name="EnqueueJob"> -->
318 <!-- <arg type="s" name="job_type" direction="in"/> -->
319 <!-- <arg type="s" name="job_mode" direction="in"/> -->
320 <!-- <arg type="u" name="job_id" direction="out"/> -->
321 <!-- <arg type="o" name="job_path" direction="out"/> -->
322 <!-- <arg type="s" name="unit_id" direction="out"/> -->
323 <!-- <arg type="o" name="unit_path" direction="out"/> -->
324 <!-- <arg type="s" name="job_type" direction="out"/> -->
325 <!-- <arg type="a(uosos)" name="affected_jobs" direction="out"/> -->
326 <!-- </method> -->
327 <method name="Kill">
328 <arg type="s" name="whom" direction="in"/>
329 <arg type="i" name="signal" direction="in"/>
330 </method>
331 <method name="KillSubgroup">
332 <arg type="s" name="subgroup" direction="in"/>
333 <arg type="i" name="signal" direction="in"/>
334 </method>
335 <method name="QueueSignal">
336 <arg type="s" name="whom" direction="in"/>
337 <arg type="i" name="signal" direction="in"/>
338 <arg type="i" name="value" direction="in"/>
339 </method>
340 <method name="ResetFailed">
341 </method>
342 <!-- <method name="SetProperties"> -->
343 <!-- <arg type="b" name="runtime" direction="in"/> -->
344 <!-- <arg type="a(sv)" name="properties" direction="in"/> -->
345 <!-- </method> -->
346 <method name="Ref">
347 </method>
348 <method name="Unref">
349 </method>
350 <method name="Clean">
351 <arg type="as" name="mask" direction="in"/>
352 </method>
353 <method name="Freeze">
354 </method>
355 <method name="Thaw">
356 </method>
357 </interface>
358</node>
359
diff --git a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml
new file mode 100644
index 00000000..ac1cbf3a
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml
@@ -0,0 +1,172 @@
1import QtQuick
2import qs.Services
3import Quickshell
4import Quickshell.Widgets
5
6Item {
7 id: activeWindowDisplay
8
9 required property int maxWidth
10 required property var screen
11
12 property var activeWindow: {
13 let currWindowId = Array.from(NiriService.workspaces).find(ws => {
14 return ws.output === screen?.name && ws.is_active;
15 })?.active_window_id;
16
17 return currWindowId ? Array.from(NiriService.windows).find(win => win.id == currWindowId) : null;
18 }
19 property var windowEntry: activeWindow ? DesktopEntries.heuristicLookup(activeWindow.app_id) : null
20
21 anchors.verticalCenter: parent.verticalCenter
22 width: activeWindowDisplayContent.width
23 height: parent.height
24
25 WrapperMouseArea {
26 id: widgetMouseArea
27
28 anchors.fill: parent
29
30 hoverEnabled: true
31
32 Item {
33 anchors.fill: parent
34
35 Row {
36 id: activeWindowDisplayContent
37
38 width: childrenRect.width
39 height: parent.height
40 anchors.verticalCenter: parent.verticalCenter
41 spacing: 8
42
43 IconImage {
44 id: activeWindowIcon
45
46 implicitSize: 14
47
48 anchors.verticalCenter: parent.verticalCenter
49
50 source: {
51 let icon = activeWindowDisplay.windowEntry?.icon
52 if (typeof icon === 'string' || icon instanceof String) {
53 if (icon.includes("?path=")) {
54 const split = icon.split("?path=")
55 if (split.length !== 2)
56 return icon
57 const name = split[0]
58 const path = split[1]
59 const fileName = name.substring(
60 name.lastIndexOf("/") + 1)
61 return `file://${path}/${fileName}`
62 } else
63 icon = Quickshell.iconPath(icon);
64 return icon
65 }
66 return ""
67 }
68 asynchronous: true
69 smooth: true
70 mipmap: true
71 }
72
73 Text {
74 id: windowTitle
75
76 width: Math.min(implicitWidth, activeWindowDisplay.maxWidth - activeWindowIcon.width - activeWindowDisplayContent.spacing)
77
78 property var appAliases: { "Firefox": "Mozilla Firefox", "mpv Media Player": "mpv", "Thunderbird": "Mozilla Thunderbird", "Thunderbird (LMU)": "Mozilla Thunderbird" }
79
80 elide: Text.ElideRight
81 maximumLineCount: 1
82 color: "white"
83 anchors.verticalCenter: parent.verticalCenter
84 text: {
85 if (!activeWindowDisplay.activeWindow)
86 return "";
87
88 var title = activeWindowDisplay.activeWindow.title;
89 var appName = activeWindowDisplay.windowEntry?.name;
90 if (appAliases[appName])
91 appName = appAliases[appName];
92 if (appName && title.endsWith(appName)) {
93 const oldTitle = title;
94 title = title.substring(0, title.length - appName.length);
95 title = title.replace(/\s*(—|-)\s*$/, "");
96 if (!title)
97 title = oldTitle;
98 }
99 return title;
100 }
101 }
102 }
103 }
104 }
105
106 Loader {
107 id: tooltipLoader
108
109 active: false
110
111 Connections {
112 target: widgetMouseArea
113 function onContainsMouseChanged() {
114 if (widgetMouseArea.containsMouse)
115 tooltipLoader.active = true;
116 }
117 }
118
119 PopupWindow {
120 id: tooltip
121
122 property bool nextVisible: widgetMouseArea.containsMouse || tooltipMouseArea.containsMouse
123
124 anchor {
125 item: widgetMouseArea
126 edges: Edges.Bottom | Edges.Left
127 }
128 visible: false
129
130 onNextVisibleChanged: hangTimer.restart()
131
132 Timer {
133 id: hangTimer
134 interval: tooltip.visible ? 100 : 500
135 onTriggered: {
136 tooltip.visible = tooltip.nextVisible;
137 if (!tooltip.visible)
138 tooltipLoader.active = false;
139 }
140 }
141
142 implicitWidth: widgetTooltipText.contentWidth + 16
143 implicitHeight: widgetTooltipText.contentHeight + 16
144 color: "black"
145
146 WrapperMouseArea {
147 id: tooltipMouseArea
148
149 hoverEnabled: true
150 enabled: true
151
152 anchors.fill: parent
153
154 Item {
155 anchors.fill: parent
156
157 Text {
158 id: widgetTooltipText
159
160 anchors.centerIn: parent
161
162 font.pointSize: 10
163 font.family: "Fira Mono"
164 color: "white"
165
166 text: JSON.stringify(Object.assign({}, activeWindowDisplay.activeWindow), null, 2)
167 }
168 }
169 }
170 }
171 }
172}
diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml
new file mode 100644
index 00000000..33909884
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml
@@ -0,0 +1,142 @@
1import Quickshell
2import Quickshell.Wayland
3import QtQuick
4import qs.Services
5
6PanelWindow {
7 id: bar
8
9 WlrLayershell.namespace: "bar"
10
11 property bool haveMaximizedWindow: {
12 let currWindowId = Array.from(NiriService.workspaces).find(ws => {
13 return ws.output === bar.screen.name && ws.is_active;
14 })?.active_window_id;
15 let activeWindowTileSize = Array.from(NiriService.windows).find(win => win.id == currWindowId)?.layout?.tile_size;
16
17 if (!activeWindowTileSize)
18 return false;
19 return activeWindowTileSize[0] >= bar.screen.width && activeWindowTileSize[1] >= bar.screen.height - bar.height;
20 }
21
22 anchors {
23 top: true
24 left: true
25 right: true
26 }
27 margins {
28 left: bar.haveMaximizedWindow ? 0 : 26 + 8
29 right: bar.haveMaximizedWindow ? 0 : 26 + 8
30 }
31
32 implicitHeight: 21
33 color: "transparent"
34
35 property bool haveScreenshare: Array.from(NiriService.casts).some(cast => cast.target.Output?.name == bar.screen.name)
36
37 Rectangle {
38 color: {
39 if (bar.haveScreenshare)
40 return bar.haveMaximizedWindow ? Qt.rgba(0.2, 0, 0, 1) : Qt.rgba(0.2, 0, 0, 0.75);
41 return bar.haveMaximizedWindow ? "black" : Qt.rgba(0, 0, 0, 0.75);
42 }
43 anchors.fill: parent
44 // bottomLeftRadius: 8
45 // bottomRightRadius: 8
46 }
47
48 Row {
49 id: left
50
51 height: parent.height
52 width: childrenRect.width
53 anchors.left: parent.left
54 anchors.leftMargin: 8
55 anchors.verticalCenter: parent.verticalCenter
56 spacing: 8
57
58 WorkspaceSwitcher {
59 screen: bar.screen
60 }
61 }
62
63 Row {
64 id: center
65
66 height: parent.height
67 width: childrenRect.width
68 anchors.centerIn: parent
69 spacing: 5
70
71 ActiveWindowDisplay {
72 screen: bar.screen
73 maxWidth: bar.width - 2*Math.max(left.width, right.width) - 2*8
74 }
75 }
76
77 Row {
78 id: right
79
80 height: parent.height
81 width: childrenRect.width
82 anchors.right: parent.right
83 anchors.rightMargin: 8
84 anchors.verticalCenter: parent.verticalCenter
85 spacing: 0
86
87 WorktimeWidget {}
88
89 KeyboardLayout {}
90
91 Item {
92 visible: privacy.visible || ytDlp.visible
93 height: parent.height
94 width: 8 - 4
95 }
96
97 PrivacyWidget {
98 id: privacy
99 }
100
101 Item {
102 visible: privacy.visible && ytDlp.visible
103 height: parent.height
104 width: 8 - 4
105 }
106
107 YtDlpWidget {
108 id: ytDlp
109 }
110
111 Item {
112 visible: privacy.visible || ytDlp.visible
113 height: parent.height
114 width: 8 - 4
115 }
116
117 SystemTray {}
118
119 PipewireWidget {}
120
121 BrightnessWidget {}
122
123 BatteryWidget {}
124
125 LockscreenInhibitorWidget {}
126
127 WaylandInhibitorWidget {
128 window: bar
129 }
130
131 LidSwitchInhibitorWidget {}
132
133 NotificationInhibitorWidget {}
134
135 Item {
136 height: parent.height
137 width: 8 - 4
138 }
139
140 Clock {}
141 }
142} \ No newline at end of file
diff --git a/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml b/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml
new file mode 100644
index 00000000..f465fa20
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml
@@ -0,0 +1,139 @@
1import QtQuick
2import Quickshell
3import Quickshell.Widgets
4import Quickshell.Services.UPower
5
6Item {
7 id: root
8
9 height: parent.height
10 width: batteryIcon.width + 8
11 anchors.verticalCenter: parent.verticalCenter
12
13 property var batteryDevice: Array.from(UPower.devices.values).find(dev => dev.isLaptopBattery)
14
15 WrapperMouseArea {
16 id: widgetMouseArea
17
18 anchors.fill: parent
19
20 hoverEnabled: true
21
22 Item {
23 anchors.fill: parent
24
25 MaterialDesignIcon {
26 id: batteryIcon
27
28 implicitSize: 14
29 anchors.centerIn: parent
30
31 icon: {
32 if (!root.batteryDevice?.ready)
33 return "battery-unknown";
34
35 if (root.batteryDevice.state == UPowerDeviceState.FullyCharged)
36 return "power-plug-battery";
37
38 const perdec = 10 * Math.max(1, Math.ceil(root.batteryDevice.percentage * 10));
39 if (root.batteryDevice.state == UPowerDeviceState.Charging)
40 return `battery-charging-${perdec}`;
41 if (perdec == 100)
42 return "battery";
43 return `battery-${perdec}`;
44 }
45 color: {
46 if (!root.batteryDevice?.ready)
47 return "#555";
48
49 if (root.batteryDevice.state != UPowerDeviceState.FullyCharged && root.batteryDevice.state != UPowerDeviceState.Charging && root.batteryDevice.timeToEmpty < 20 * 60)
50 return "#f2201f";
51 if (root.batteryDevice.state != UPowerDeviceState.FullyCharged && root.batteryDevice.state != UPowerDeviceState.Charging && root.batteryDevice.timeToEmpty < 40 * 60)
52 return "#f28a21";
53 if (root.batteryDevice.state != UPowerDeviceState.FullyCharged)
54 return "#fff";
55 return "#555";
56 }
57 }
58 }
59 }
60
61 PopupWindow {
62 id: tooltip
63
64 property bool nextVisible: widgetMouseArea.containsMouse || tooltipMouseArea.containsMouse
65
66 anchor {
67 item: widgetMouseArea
68 edges: Edges.Bottom | Edges.Left
69 }
70 visible: false
71
72 onNextVisibleChanged: hangTimer.restart()
73
74 Timer {
75 id: hangTimer
76 interval: 100
77 onTriggered: tooltip.visible = tooltip.nextVisible
78 }
79
80 implicitWidth: widgetTooltipText.contentWidth + 16
81 implicitHeight: widgetTooltipText.contentHeight + 16
82 color: "black"
83
84 WrapperMouseArea {
85 id: tooltipMouseArea
86
87 hoverEnabled: true
88 enabled: true
89
90 anchors.fill: parent
91
92 Item {
93 anchors.fill: parent
94
95 Text {
96 id: widgetTooltipText
97
98 anchors.centerIn: parent
99
100 font.pointSize: 10
101 font.family: "Fira Sans"
102 color: "white"
103
104 text: {
105 if (!root.batteryDevice?.ready)
106 return "Not ready";
107
108 const stateStr = UPowerDeviceState.toString(root.batteryDevice.state);
109 var outStr = stateStr;
110 if (root.batteryDevice.state !== UPowerDeviceState.FullyCharged)
111 outStr += ` ${Math.round(root.batteryDevice.percentage * 100)}%`;
112
113 function formatTime(t) {
114 var res = "";
115 for (const unit of [{ "s": "h", "v": 3600 }, { "s": "m", "v": 60 }, { "s": "s", "v": 1 }]) {
116 if (t < unit.v)
117 continue;
118 res += Math.floor(t / unit.v) + unit.s;
119 t %= unit.v;
120 }
121 return res;
122 }
123 if (root.batteryDevice.timeToEmpty != 0) {
124 const tStr = formatTime(Math.floor(root.batteryDevice.timeToEmpty / 60) * 60);
125 if (tStr)
126 outStr += " " + tStr;
127 } else if (root.batteryDevice.timeToFull != 0) {
128 const tStr = formatTime(Math.ceil(root.batteryDevice.timeToFull / 60) * 60);
129 if (tStr)
130 outStr += " " + tStr;
131 }
132
133 return outStr;
134 }
135 }
136 }
137 }
138 }
139}
diff --git a/accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml b/accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml
new file mode 100644
index 00000000..a432179e
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml
@@ -0,0 +1,117 @@
1import QtQuick
2import QtQuick.Layouts
3import Quickshell
4import Quickshell.Widgets
5import qs.Services
6
7Scope {
8 id: root
9
10 property bool show: false
11 property bool inhibited: true
12
13 Connections {
14 target: Brightness
15
16 function onCurrBrightnessChanged() {
17 root.show = true;
18 hideTimer.restart();
19 }
20 }
21
22 onShowChanged: {
23 if (show)
24 hideTimer.restart();
25 }
26
27 Timer {
28 id: hideTimer
29 interval: 1000
30 onTriggered: root.show = false
31 }
32
33 Timer {
34 id: startInhibit
35 interval: 100
36 running: true
37 onTriggered: {
38 root.show = false;
39 root.inhibited = false;
40 }
41 }
42
43 LazyLoader {
44 active: root.show && !root.inhibited
45
46 Variants {
47 model: Quickshell.screens
48
49 delegate: Scope {
50 id: screenScope
51
52 required property var modelData
53
54 PanelWindow {
55 id: window
56
57 screen: screenScope.modelData
58
59 anchors.top: true
60 margins.top: screen.height / 2 - 50 + 3.5
61 exclusiveZone: 0
62 exclusionMode: ExclusionMode.Ignore
63
64 implicitWidth: 400
65 implicitHeight: 50
66
67 mask: Region {}
68
69 color: "transparent"
70
71 Rectangle {
72 anchors.fill: parent
73 color: Qt.rgba(0, 0, 0, 0.75)
74 }
75
76 RowLayout {
77 id: layout
78
79 anchors.centerIn: parent
80
81 height: 50 - 8*2
82 width: 400 - 8*2
83
84 MaterialDesignIcon {
85 id: volumeIcon
86
87 implicitWidth: parent.height
88 implicitHeight: parent.height
89
90 icon: `brightness-${Math.min(7, Math.floor(Brightness.currBrightness * 7) + 1)}`
91 }
92
93 Rectangle {
94 Layout.fillWidth: true
95
96 implicitHeight: 10
97
98 color: "#50ffffff"
99
100 Rectangle {
101 anchors {
102 left: parent.left
103 top: parent.top
104 bottom: parent.bottom
105 }
106
107 color: "white"
108
109 implicitWidth: parent.width * Brightness.currBrightness
110 }
111 }
112 }
113 }
114 }
115 }
116 }
117}
diff --git a/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml b/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml
new file mode 100644
index 00000000..3bb5a80e
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml
@@ -0,0 +1,84 @@
1import QtQuick
2import Quickshell
3import Quickshell.Widgets
4import qs.Services
5
6Item {
7 height: parent.height
8 width: brightnessIcon.width + 8
9 anchors.verticalCenter: parent.verticalCenter
10
11 WrapperMouseArea {
12 id: widgetMouseArea
13
14 anchors.fill: parent
15
16 hoverEnabled: true
17
18 property real sensitivity: (1 / 50) / 120
19 onWheel: event => Brightness.currBrightness += event.angleDelta.y * sensitivity
20
21 Item {
22 anchors.fill: parent
23
24 MaterialDesignIcon {
25 id: brightnessIcon
26
27 implicitSize: 14
28 anchors.centerIn: parent
29
30 icon: `brightness-${Math.min(7, Math.floor(Brightness.currBrightness * 7) + 1)}`
31 color: "#555"
32 }
33 }
34 }
35
36 PopupWindow {
37 id: tooltip
38
39 property bool nextVisible: widgetMouseArea.containsMouse || tooltipMouseArea.containsMouse
40
41 anchor {
42 item: widgetMouseArea
43 edges: Edges.Bottom | Edges.Left
44 }
45 visible: false
46
47 onNextVisibleChanged: hangTimer.restart()
48
49 Timer {
50 id: hangTimer
51 interval: 100
52 onTriggered: tooltip.visible = tooltip.nextVisible
53 }
54
55 implicitWidth: widgetTooltipText.contentWidth + 16
56 implicitHeight: widgetTooltipText.contentHeight + 16
57 color: "black"
58
59 WrapperMouseArea {
60 id: tooltipMouseArea
61
62 hoverEnabled: true
63 enabled: true
64
65 anchors.fill: parent
66
67 Item {
68 anchors.fill: parent
69
70 Text {
71 id: widgetTooltipText
72
73 anchors.centerIn: parent
74
75 font.pointSize: 10
76 font.family: "Fira Sans"
77 color: "white"
78
79 text: `${Math.round(Brightness.currBrightness * 100)}%`
80 }
81 }
82 }
83 }
84}
diff --git a/accounts/gkleen@sif/shell/quickshell/Clock.qml b/accounts/gkleen@sif/shell/quickshell/Clock.qml
new file mode 100644
index 00000000..58a80b8b
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Clock.qml
@@ -0,0 +1,295 @@
1import QtQml
2import QtQuick
3import Quickshell
4import Custom as Custom
5import QtQuick.Controls
6import QtQuick.Layouts
7import Quickshell.Widgets
8
9Item {
10 id: clockItem
11
12 property bool calendarPopup: true
13
14 width: clock.contentWidth
15 height: parent.height
16 anchors.verticalCenter: parent.verticalCenter
17
18 WrapperMouseArea {
19 id: clockMouseArea
20
21 anchors.fill: parent
22 hoverEnabled: true
23 enabled: clockItem.calendarPopup
24
25 Item {
26 anchors.fill: parent
27
28 Text {
29 id: clock
30 color: "white"
31
32 anchors.verticalCenter: parent.verticalCenter
33
34 Custom.Chrono {
35 id: chrono
36
37 onDateChanged: clock.text = format("W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}")
38 }
39
40 font.pointSize: 10
41 font.family: "Fira Sans"
42 font.features: { "tnum": 1 }
43 }
44 }
45 }
46
47 Loader {
48 id: tooltipLoader
49
50 active: false
51
52 Connections {
53 target: clockMouseArea
54 function onContainsMouseChanged() {
55 if (clockMouseArea.containsMouse)
56 tooltipLoader.active = true;
57 }
58 }
59
60 sourceComponent: PopupWindow {
61 id: tooltip
62
63 property bool nextVisible: clockMouseArea.containsMouse || tooltipMouseArea.containsMouse
64
65 anchor {
66 item: clockMouseArea
67 edges: Edges.Bottom | Edges.Left
68 }
69 visible: false
70
71 onNextVisibleChanged: hangTimer.restart()
72
73 Timer {
74 id: hangTimer
75 interval: 100
76 onTriggered: {
77 tooltip.visible = tooltip.nextVisible;
78 if (!tooltip.visible)
79 tooltipLoader.active = false;
80 }
81 }
82
83 implicitWidth: tooltipLayout.childrenRect.width + 16
84 implicitHeight: tooltipLayout.childrenRect.height + 16
85 color: "black"
86
87 onVisibleChanged: {
88 yearCalendar.year = chrono.date.getFullYear();
89 yearCalendar.angleRem = 0;
90 }
91
92 WrapperMouseArea {
93 id: tooltipMouseArea
94
95 hoverEnabled: true
96 enabled: true
97
98 onWheel: event => yearCalendar.scrollYear(event)
99
100 anchors.fill: parent
101
102 Item {
103 id: clockTooltipContent
104
105 anchors.fill: parent
106
107 ColumnLayout {
108 id: tooltipLayout
109
110 anchors {
111 left: parent.left
112 top: parent.top
113 leftMargin: 8
114 topMargin: 8
115 }
116
117 Text {
118 id: yearLabel
119
120 horizontalAlignment: Text.AlignHCenter
121
122 font.pointSize: 14
123 font.family: "Fira Sans"
124 font.features: { "tnum": 1 }
125 color: "white"
126
127 text: yearCalendar.year
128
129 Layout.fillWidth: true
130 Layout.bottomMargin: 8
131 }
132
133 GridLayout {
134 property int year: chrono.date.getFullYear()
135
136 id: yearCalendar
137
138 columns: 3
139 columnSpacing: 16
140 rowSpacing: 16
141
142 Layout.alignment: Qt.AlignHCenter
143 Layout.fillWidth: false
144
145 property real angleRem: 0
146 property real sensitivity: 1 / 120
147
148 function scrollYear(event) {
149 angleRem += event.angleDelta.y;
150 const d = Math.round(angleRem * sensitivity);
151 yearCalendar.year -= d;
152 angleRem -= d / sensitivity;
153 }
154
155 Connections {
156 target: clockMouseArea
157 function onWheel(event) { yearCalendar.scrollYear(event); }
158 }
159
160 Repeater {
161 model: 12
162
163 GridLayout {
164 columns: 2
165
166 required property int index
167 property int month: index
168
169 id: monthCalendar
170
171 Layout.alignment: Qt.AlignTop | Qt.AlignRight
172 Layout.fillWidth: false
173
174 Text {
175 Layout.column: 1
176 Layout.fillWidth: true
177
178 horizontalAlignment: Text.AlignHCenter
179
180 font.pointSize: 10
181 font.family: "Fira Sans"
182
183 text: new Date(yearCalendar.year, monthCalendar.month, 1).toLocaleString(Qt.locale("en_DK"), "MMMM")
184
185 color: "#ffead3"
186 }
187
188 DayOfWeekRow {
189 locale: grid.locale
190
191 Layout.row: 1
192 Layout.column: 1
193 Layout.fillWidth: true
194
195 delegate: WrapperItem {
196 required property string shortName
197
198 width: dowLabel.contentWidth + 6
199
200 Text {
201 id: dowLabel
202
203 anchors.fill: parent
204
205 font.pointSize: 10
206 font.family: "Fira Sans"
207
208 text: parent.shortName
209 color: "#ffcc66"
210
211 horizontalAlignment: Text.AlignHCenter
212 verticalAlignment: Text.AlignVCenter
213 }
214 }
215 }
216
217 WeekNumberColumn {
218 month: grid.month
219 year: grid.year
220 locale: grid.locale
221
222 Layout.fillHeight: true
223
224 delegate: Text {
225 required property int weekNumber
226
227 opacity: {
228 const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7);
229 const dayOfWeek = simple.getDay();
230 const isoWeekStart = simple;
231
232 isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1);
233 if (dayOfWeek > 4) {
234 isoWeekStart.setDate(isoWeekStart.getDate() + 7);
235 }
236
237 for (let i = 0; i < 7; i++) {
238 const dayInWeek = new Date(isoWeekStart);
239 dayInWeek.setDate(dayInWeek.getDate() + i);
240 if (dayInWeek.getMonth() == monthCalendar.month)
241 return 1;
242 }
243
244 return 0;
245 }
246
247 font.pointSize: 10
248 font.family: "Fira Sans"
249 font.features: { "tnum": 1 }
250
251 text: weekNumber
252 color: "#99ffdd"
253
254 horizontalAlignment: Text.AlignRight
255 verticalAlignment: Text.AlignVCenter
256 }
257 }
258
259 MonthGrid {
260 id: grid
261
262 year: yearCalendar.year
263 month: monthCalendar.month
264 locale: Qt.locale("en_DK")
265
266 Layout.fillWidth: true
267 Layout.fillHeight: true
268
269 delegate: Text {
270 required property var model
271
272 opacity: model.month === monthCalendar.month ? 1 : 0
273
274 font.pointSize: 10
275 font.family: "Fira Sans"
276 font.features: { "tnum": 1 }
277
278 property bool today: chrono.date.getFullYear() == model.year && chrono.date.getMonth() == model.month && chrono.date.getDate() == model.day
279
280 text: model.day
281 color: today ? "#ff6699" : "white"
282
283 horizontalAlignment: Text.AlignRight
284 verticalAlignment: Text.AlignVCenter
285 }
286 }
287 }
288 }
289 }
290 }
291 }
292 }
293 }
294 }
295}
diff --git a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml
new file mode 100644
index 00000000..46302e54
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml
@@ -0,0 +1,112 @@
1import Quickshell
2import QtQuick
3import qs.Services
4import Quickshell.Widgets
5
6Item {
7 width: kbdLabel.contentWidth + 8
8 height: parent.height
9 anchors.verticalCenter: parent.verticalCenter
10
11 WrapperMouseArea {
12 id: kbdMouseArea
13
14 anchors.fill: parent
15
16 hoverEnabled: true
17 cursorShape: Qt.PointingHandCursor
18 enabled: true
19 onClicked: {
20 NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": "Next" } } }, _ => {})
21 }
22 onWheel: event => {
23 NiriService.sendCommand({ "Action": { "SwitchLayout": { "layout": event.angleDelta > 0 ? "Next" : "Prev" } } }, _ => {})
24 }
25
26 Rectangle {
27 id: kbdWidget
28
29 property var keyboardAbbrev: { "English (programmer Dvorak)": "dvp", "English (US)": "us" }
30
31 anchors.fill: parent
32 color: {
33 if (kbdMouseArea.containsMouse) {
34 return "#33808080";
35 }
36 return "transparent";
37 }
38
39 Text {
40 id: kbdLabel
41
42 font.pointSize: 10
43 font.family: "Fira Sans"
44 color: {
45 if (NiriService.keyboardLayouts?.current_idx === 0)
46 return "#555";
47 return "white";
48 }
49 anchors.centerIn: parent
50
51 text: {
52 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx];
53 if (!currentLayout)
54 return "";
55 return kbdWidget.keyboardAbbrev[currentLayout] ? kbdWidget.keyboardAbbrev[currentLayout] : currentLayout;
56 }
57 }
58 }
59 }
60
61 PopupWindow {
62 id: tooltip
63
64 property bool nextVisible: kbdMouseArea.containsMouse || tooltipMouseArea.containsMouse
65
66 anchor {
67 item: kbdMouseArea
68 edges: Edges.Bottom | Edges.Left
69 }
70 visible: false
71
72 onNextVisibleChanged: hangTimer.restart()
73
74 Timer {
75 id: hangTimer
76 interval: 100
77 onTriggered: tooltip.visible = tooltip.nextVisible
78 }
79
80 implicitWidth: kbdTooltipText.contentWidth + 16
81 implicitHeight: kbdTooltipText.contentHeight + 16
82 color: "black"
83
84 WrapperMouseArea {
85 id: tooltipMouseArea
86
87 hoverEnabled: true
88 enabled: true
89
90 anchors.fill: parent
91
92 Item {
93 anchors.fill: parent
94
95 Text {
96 id: kbdTooltipText
97
98 anchors.centerIn: parent
99
100 font.pointSize: 10
101 font.family: "Fira Sans"
102 color: "white"
103
104 text: {
105 const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx];
106 return currentLayout || "";
107 }
108 }
109 }
110 }
111 }
112}
diff --git a/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml b/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml
new file mode 100644
index 00000000..8410dcda
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml
@@ -0,0 +1,47 @@
1import Quickshell
2import QtQuick
3import Quickshell.Widgets
4import qs.Services
5
6Item {
7 id: root
8
9 width: icon.width + 8
10 height: parent.height
11 anchors.verticalCenter: parent.verticalCenter
12
13 WrapperMouseArea {
14 id: widgetMouseArea
15
16 anchors.fill: parent
17
18 hoverEnabled: true
19 cursorShape: Qt.PointingHandCursor
20
21 onClicked: InhibitorState.lidSwitchInhibited = !InhibitorState.lidSwitchInhibited
22
23 Rectangle {
24 anchors.fill: parent
25 color: {
26 if (widgetMouseArea.containsMouse) {
27 return "#33808080";
28 }
29 return "transparent";
30 }
31
32 Item {
33 anchors.fill: parent
34
35 MaterialDesignIcon {
36 id: icon
37
38 implicitSize: 14
39 anchors.centerIn: parent
40
41 icon: InhibitorState.lidSwitchInhibited ? "laptop-off" : "laptop"
42 color: InhibitorState.lidSwitchInhibited ? "#f28a21" : "#555"
43 }
44 }
45 }
46 }
47}
diff --git a/accounts/gkleen@sif/shell/quickshell/LockSurface.qml b/accounts/gkleen@sif/shell/quickshell/LockSurface.qml
new file mode 100644
index 00000000..f4f8f0cd
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/LockSurface.qml
@@ -0,0 +1,227 @@
1import Quickshell.Widgets
2import QtQuick.Effects
3import QtQuick.Layouts
4import QtQuick
5import QtQuick.Controls
6import QtQuick.Controls.Fusion
7import qs.Services
8import QtQml
9
10Item {
11 id: lockSurface
12
13 property var screen
14 property list<var> messages: []
15 property bool responseRequired: false
16 property bool responseVisible: false
17 property string currentText: ""
18 property bool authRunning: false
19
20 signal response(string responseText)
21
22 anchors.fill: parent
23
24 Item {
25 id: background
26
27 anchors.fill: parent
28
29 property Img current: one
30 property string source: selector.selected
31
32 WallpaperSelector {
33 id: selector
34 seed: lockSurface.screen?.name || ""
35 }
36
37 onSourceChanged: {
38 if (!source)
39 current = null;
40 else if (current === one)
41 two.update()
42 else
43 one.update()
44 }
45
46 Img { id: one }
47 Img { id: two }
48
49 component Img: Item {
50 id: img
51
52 property string source
53
54 function update() {
55 source = background.source || ""
56 }
57
58 anchors.fill: parent
59
60 Image {
61 id: imageSource
62
63 source: img.source
64 sourceSize: Qt.size(parent.width, parent.height)
65 fillMode: Image.PreserveAspectCrop
66 smooth: true
67 visible: false
68 asynchronous: true
69 cache: false
70
71 onStatusChanged: {
72 if (status === Image.Ready) {
73 background.current = img
74 }
75 }
76 }
77
78 MultiEffect {
79 id: imageEffect
80
81 source: imageSource
82 anchors.fill: parent
83 blurEnabled: true
84 blur: 1
85 blurMax: 64
86 blurMultiplier: 2
87
88 opacity: 0
89
90 states: State {
91 name: "visible"
92 when: background.current === img
93
94 PropertyChanges {
95 imageEffect.opacity: 1
96 }
97 StateChangeScript {
98 name: "unloadOther"
99 script: {
100 if (img === one)
101 two.source = ""
102 if (img === two)
103 one.source = ""
104 }
105 }
106 }
107
108 transitions: Transition {
109 SequentialAnimation {
110 NumberAnimation {
111 target: imageEffect
112 properties: "opacity"
113 duration: {
114 if (img === one && two.source == "" || img === two && one.source == "")
115 return 0;
116 return 5000;
117 }
118 easing.type: Easing.OutCubic
119 }
120 ScriptAction {
121 scriptName: "unloadOther"
122 }
123 }
124 }
125 }
126 }
127 }
128
129 Item {
130 anchors {
131 top: lockSurface.top
132 left: lockSurface.left
133 right: lockSurface.right
134 }
135
136 implicitWidth: lockSurface.width
137 implicitHeight: 21
138
139 Rectangle {
140 anchors.fill: parent
141 color: Qt.rgba(0, 0, 0, 0.75)
142 }
143
144 Clock {
145 anchors.centerIn: parent
146 calendarPopup: false
147 }
148 }
149
150 WrapperRectangle {
151 id: unlockUi
152
153 Keys.onPressed: event => {
154 if (!lockSurface.authRunning) {
155 event.accepted = true;
156 lockSurface.authRunning = true;
157 }
158 }
159 focus: !passwordBox.visible
160
161 visible: lockSurface.authRunning
162
163 color: Qt.rgba(0, 0, 0, 0.75)
164 margin: 8
165
166 anchors.centerIn: parent
167
168 ColumnLayout {
169 spacing: 4
170
171 BusyIndicator {
172 visible: running
173 running: !Array.from(lockSurface.messages).length && !lockSurface.responseRequired
174 }
175
176 Repeater {
177 model: lockSurface.messages
178
179 Text {
180 required property var modelData
181
182 font.pointSize: 10
183 font.family: "Fira Sans"
184 color: modelData.error ? "#f28a21" : "#ffffff"
185
186 text: String(modelData.text).trim()
187
188 Layout.fillWidth: true
189 horizontalAlignment: Text.AlignHCenter
190 }
191 }
192
193 TextField {
194 id: passwordBox
195
196 visible: lockSurface.responseRequired
197 echoMode: lockSurface.responseVisible ? TextInput.Normal : TextInput.Password
198 inputMethodHints: Qt.ImhSensitiveData
199
200 onTextChanged: lockSurface.currentText = passwordBox.text
201 onAccepted: {
202 passwordBox.readOnly = true;
203 lockSurface.response(lockSurface.currentText);
204 }
205
206 Connections {
207 target: lockSurface
208 function onCurrentTextChanged() {
209 passwordBox.text = lockSurface.currentText
210 }
211 }
212 Connections {
213 target: lockSurface
214 function onResponseRequiredChanged() {
215 if (lockSurface.responseRequired)
216 passwordBox.readOnly = false;
217 passwordBox.focus = true;
218 passwordBox.selectAll();
219 }
220 }
221
222 Layout.topMargin: 4
223 Layout.fillWidth: true
224 }
225 }
226 }
227}
diff --git a/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml b/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml
new file mode 100644
index 00000000..0b4a68b2
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml
@@ -0,0 +1,128 @@
1import Quickshell
2import Quickshell.Wayland
3import Quickshell.Io
4import Quickshell.Services.Pam
5import Quickshell.Services.Mpris
6import Custom as Custom
7import qs.Services
8import QtQml
9
10Scope {
11 id: lockscreen
12
13 property string currentText: ""
14
15 PamContext {
16 id: pam
17
18 property list<var> messages: []
19
20 config: "quickshell"
21 onCompleted: result => {
22 if (result === PamResult.Success) {
23 lock.locked = false;
24 }
25 }
26 onPamMessage: {
27 messages = Array.from(messages).concat([{ "text": pam.message, "error": pam.messageIsError }])
28 }
29 onActiveChanged: {
30 messages = [];
31 }
32 }
33
34 Connections {
35 target: Custom.Systemd
36 function onSleep(before: bool) {
37 console.log(`received prepare for sleep ${before}`);
38 if (before) {
39 lock.locked = true;
40 if (pam.active)
41 pam.abort();
42 }
43 }
44 function onLock() { lock.locked = true; }
45 function onUnlock() { lock.locked = false; }
46 }
47
48 IdleMonitor {
49 id: idleMonitor
50 enabled: !lock.secure && !InhibitorState.lockscreenInhibited
51 timeout: 600
52 respectInhibitors: true
53
54 onIsIdleChanged: {
55 if (idleMonitor.isIdle)
56 lock.locked = true;
57 }
58 }
59
60 Custom.SystemdInhibitor {
61 enabled: !lock.secure
62
63 what: Custom.SystemdInhibitorParams.Sleep
64 who: "quickshell"
65 why: "Lock session"
66 mode: Custom.SystemdInhibitorParams.Delay
67 }
68
69 Binding {
70 target: NotificationManager
71 property: "lockscreenActive"
72 value: lock.locked
73 }
74
75 WlSessionLock {
76 id: lock
77
78 onLockStateChanged: {
79 if (!locked && pam.active)
80 pam.abort();
81
82 if (locked) {
83 NiriService.sendCommand({ "Action": { "PowerOffMonitors": {} } }, _ => {});
84 Custom.KeePassXC.lockAllDatabases();
85 Array.from(MprisProxy.players).forEach(player => {
86 if (player.canPause && player.isPlaying)
87 player.pause();
88 });
89 // Custom.Systemd.stopUserUnit("gpg-agent.service", "replace");
90 GpgAgent.reloadAgent();
91 }
92 }
93 Component.onCompleted: { (_ => {})(MprisProxy.players); }
94
95 onSecureStateChanged: Custom.Systemd.lockedHint = lock.secure
96
97 WlSessionLockSurface {
98 id: lockSurface
99
100 color: "black"
101
102 LockSurface {
103 id: surfaceContent
104
105 onResponse: responseText => pam.respond(responseText)
106 onAuthRunningChanged: {
107 if (authRunning)
108 pam.start();
109 }
110 Connections {
111 target: pam
112 function onMessagesChanged() { surfaceContent.messages = pam.messages; }
113 function onResponseRequiredChanged() { surfaceContent.responseRequired = pam.responseRequired; }
114 function onActiveChanged() { surfaceContent.authRunning = pam.active; }
115 }
116 onCurrentTextChanged: lockscreen.currentText = currentText
117 Connections {
118 target: lockscreen
119 function onCurrentTextChanged() { surfaceContent.currentText = lockscreen.currentText; }
120 }
121 Connections {
122 target: lockSurface
123 function onScreenChanged() { surfaceContent.screen = lockSurface.screen; }
124 }
125 }
126 }
127 }
128}
diff --git a/accounts/gkleen@sif/shell/quickshell/LockscreenInhibitorWidget.qml b/accounts/gkleen@sif/shell/quickshell/LockscreenInhibitorWidget.qml
new file mode 100644
index 00000000..1cbf3f16
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/LockscreenInhibitorWidget.qml
@@ -0,0 +1,48 @@
1import Quickshell
2import QtQuick
3import Quickshell.Widgets
4import qs.Services
5
6Item {
7 id: root
8
9 width: icon.width + 8
10 height: parent.height
11 anchors.verticalCenter: parent.verticalCenter
12
13 WrapperMouseArea {
14 id: widgetMouseArea
15
16 anchors.fill: parent
17
18 // enabled: InhibitorState.lockscreenInhibited || !InhibitorState.waylandIdleInhibited
19 hoverEnabled: true
20 cursorShape: widgetMouseArea.enabled ? Qt.PointingHandCursor : undefined
21
22 onClicked: InhibitorState.lockscreenInhibited = !InhibitorState.lockscreenInhibited
23
24 Rectangle {
25 anchors.fill: parent
26 color: {
27 if (widgetMouseArea.containsMouse) {
28 return "#33808080";
29 }
30 return "transparent";
31 }
32
33 Item {
34 anchors.fill: parent
35
36 MaterialDesignIcon {
37 id: icon
38
39 implicitSize: 14
40 anchors.centerIn: parent
41
42 icon: InhibitorState.lockscreenInhibited || InhibitorState.waylandIdleInhibited ? "lock-off" : "lock"
43 color: InhibitorState.lockscreenInhibited ? "#f28a21" : "#555"
44 }
45 }
46 }
47 }
48}
diff --git a/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml b/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml
new file mode 100644
index 00000000..155a009e
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml
@@ -0,0 +1,35 @@
1import QtQuick
2import QtQuick.Effects
3
4Item {
5 id: root
6
7 required property string icon
8 property color color: "white"
9
10 property real implicitSize: 0
11
12 readonly property real actualSize: Math.min(root.width, root.height)
13
14 implicitWidth: root.implicitSize
15 implicitHeight: root.implicitSize
16
17 Image {
18 id: sourceImage
19 source: "file://" + @mdi@ + "/svg/" + root.icon + ".svg"
20 anchors.fill: parent
21 fillMode: Image.PreserveAspectFit
22
23 sourceSize.width: root.actualSize
24 sourceSize.height: root.actualSize
25
26 layer.enabled: true
27 layer.effect: MultiEffect {
28 id: effect
29
30 brightness: 1
31 colorization: 1
32 colorizationColor: root.color
33 }
34 }
35}
diff --git a/accounts/gkleen@sif/shell/quickshell/NiriIdle.qml b/accounts/gkleen@sif/shell/quickshell/NiriIdle.qml
new file mode 100644
index 00000000..beff205c
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/NiriIdle.qml
@@ -0,0 +1,30 @@
1import QtQml
2import Quickshell
3import Quickshell.Wayland
4import qs.Services
5import Custom as Custom
6
7Scope {
8 IdleMonitor {
9 id: idleMonitor30
10 timeout: 30
11
12 onIsIdleChanged: Custom.Systemd.setIdleHint(idleMonitor30.isIdle)
13 }
14 IdleMonitor {
15 id: idleMonitor540
16 timeout: 540
17
18 onIsIdleChanged: {
19 if (idleMonitor540.isIdle)
20 NiriService.sendCommand({ "Action": { "PowerOffMonitors": {} } }, _ => {});
21 }
22 }
23 Connections {
24 target: Custom.Systemd
25 function onSleep(before: bool) {
26 if (!before)
27 NiriService.sendCommand({ "Action": { "PowerOnMonitors": {} } }, _ => {});
28 }
29 }
30}
diff --git a/accounts/gkleen@sif/shell/quickshell/NotificationDisplay.qml b/accounts/gkleen@sif/shell/quickshell/NotificationDisplay.qml
new file mode 100644
index 00000000..cc0e49b1
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/NotificationDisplay.qml
@@ -0,0 +1,340 @@
1import QtQml
2import QtQml.Models
3import QtQuick
4import Quickshell
5import Quickshell.Widgets
6import Quickshell.Wayland
7import qs.Services
8import QtQuick.Layouts
9import Quickshell.Services.Notifications
10
11Scope {
12 id: root
13
14 property var activeScreen: Array.from(Quickshell.screens).find(screen => screen.name === Array.from(NiriService.workspaces).find(ws => ws.is_focused)?.output) ?? null
15
16 Instantiator {
17 id: notifsRepeater
18
19 model: ScriptModel {
20 values: NotificationManager.groups
21 }
22
23 delegate: PanelWindow {
24 id: notifWindow
25
26 visible: NotificationManager.active
27
28 screen: root.activeScreen
29
30 WlrLayershell.namespace: "notifications"
31
32 required property var modelData
33 required property var index
34
35 property int activeIx: modelData.length - 1
36 onModelDataChanged: {
37 notifWindow.activeIx = modelData.length - 1;
38 }
39
40 property color textColor: {
41 if (notifWindow.modelData?.[notifWindow.activeIx]?.urgency == NotificationUrgency.Low)
42 return "#ff999999";
43 return "white";
44 }
45 property color backgroundColor: {
46 if (notifWindow.modelData?.[notifWindow.activeIx]?.urgency == NotificationUrgency.Critical)
47 return "#dd900000";
48 return "black";
49 }
50
51 anchors {
52 right: true
53 top: true
54 }
55
56 readonly property real spaceAbove: {
57 var res = 0;
58 for (let i = 0; i < notifWindow.index; i++) {
59 (_ => {})(notifsRepeater.objectAt(i).modelData);
60 res += notifsRepeater.objectAt(i).height + 8;
61 }
62 return res;
63 }
64
65 margins {
66 right: 26 + 8
67 top: 8 + spaceAbove
68 }
69
70 color: "transparent"
71
72 implicitHeight: Math.max(notifCount.visible ? notifCount.contentHeight : 0, notifSummary.contentHeight) + (notifBody.visible ? 8 + notifBody.contentHeight : 0) + (notifActions.visible ? 8 + notifActions.height : 0) + (notifTime.visible ? 8 + notifTime.contentHeight : 0) + 16
73 implicitWidth: 400
74
75 WrapperMouseArea {
76 enabled: true
77
78 anchors.fill: parent
79
80 cursorShape: Qt.PointingHandCursor
81
82 onClicked: {
83 for (const notif of notifWindow.modelData)
84 notif.dismiss();
85 }
86
87 property real angleRem: 0
88 property real sensitivity: 1 / 120
89 onWheel: event => {
90 angleRem += event.angleDelta.y;
91 const d = Math.round(angleRem * sensitivity);
92 angleRem -= d / sensitivity;
93 notifWindow.activeIx = ((notifWindow.modelData?.length ?? 1) + notifWindow.activeIx - d) % (notifWindow.modelData?.length ?? 1);
94 }
95
96 Rectangle {
97 color: notifWindow.backgroundColor
98 anchors.fill: parent
99 border {
100 color: Qt.hsla(195/360, 1, 0.45, 1)
101 width: 2
102 }
103
104 GridLayout {
105 id: notifLayout
106
107 width: 400 - 16
108 anchors.fill: parent
109 anchors.margins: 8
110 columnSpacing: 8
111 rowSpacing: 8
112
113 columns: notifImage.visible ? 3 : 2
114 rows: {
115 var res = 1;
116 if (notifBody.visible)
117 res += 1;
118 if (notifActions.visible)
119 res += 1;
120 if (notifTime.visible)
121 res += 1;
122 return res;
123 }
124
125 Text {
126 id: notifCount
127
128 visible: notifWindow.modelData?.length > 1 ?? false
129 text: `${notifWindow.activeIx + 1}/${notifWindow.modelData?.length ?? ""}`
130
131 font.pointSize: 10
132 font.family: "Fira Sans"
133 font.bold: true
134 font.features: { "tnum": 1 }
135 color: notifWindow.textColor
136 maximumLineCount: 1
137
138 Layout.fillWidth: false
139 Layout.row: 0
140 Layout.column: notifImage.visible ? 1 : 0
141 }
142
143 Text {
144 id: notifSummary
145
146 text: notifWindow.modelData?.[notifWindow.activeIx]?.summary ?? ""
147
148 font.pointSize: 10
149 font.family: "Fira Sans"
150 font.italic: true
151 color: notifWindow.textColor
152 maximumLineCount: 1
153 elide: Text.ElideRight
154
155 Layout.fillWidth: true
156 Layout.row: 0
157 Layout.column: (notifCount.visible ? 1 : 0) + (notifImage.visible ? 1 : 0)
158 Layout.columnSpan: notifCount.visible ? 1 : 2
159 }
160
161 Image {
162 id: notifImage
163
164 visible: (notifWindow.modelData?.[notifWindow.activeIx]?.image || notifWindow.modelData?.[notifWindow.activeIx]?.appIcon) ?? false
165
166 onStatusChanged: {
167 if (notifImage.status == Image.Error)
168 notifImage.visible = false;
169 }
170
171 source: (notifWindow.modelData?.[notifWindow.activeIx]?.image || notifWindow.modelData?.[notifWindow.activeIx]?.appIcon) ?? ""
172 fillMode: Image.PreserveAspectFit
173 asynchronous: true
174 smooth: true
175 mipmap: true
176
177 Layout.maximumWidth: 50
178 Layout.column: 0
179 Layout.row: 0
180 Layout.fillHeight: true
181 Layout.rowSpan: 1 + (notifBody.visible ? 1 : 0) + (notifTime.visible ? 1 : 0)
182 }
183
184 Text {
185 id: notifBody
186
187 visible: notifWindow.modelData?.[notifWindow.activeIx]?.body ?? false
188 text: notifWindow.modelData?.[notifWindow.activeIx]?.body ?? ""
189 textFormat: Text.RichText
190 wrapMode: Text.Wrap
191
192 font.pointSize: 10
193 font.family: "Fira Sans"
194 color: notifWindow.textColor
195
196 Layout.fillWidth: true
197 Layout.row: 1
198 Layout.column: notifImage.visible ? 1 : 0
199 Layout.columnSpan: notifCount.visible ? 2 : 1
200 }
201
202 Text {
203 id: notifTime
204
205 Connections {
206 target: NotificationManager.clock
207 function onDateChanged() {
208 notifTime.text = NotificationManager.formatTime(notifWindow.modelData?.[notifWindow.activeIx]?.receivedTime);
209 }
210 }
211
212 visible: notifTime.text && notifTime.text !== "now"
213 text: NotificationManager.formatTime(notifWindow.modelData?.[notifWindow.activeIx]?.receivedTime)
214
215 font.pointSize: 8
216 font.family: "Fira Sans"
217 font.italic: true
218 color: "#555"
219 maximumLineCount: 1
220 horizontalAlignment: Text.AlignRight
221
222 Layout.fillWidth: true
223 Layout.row: notifBody.visible ? 2 : 1
224 Layout.column: notifImage.visible ? 1 : 0
225 Layout.columnSpan: 2
226 }
227
228 RowLayout {
229 id: notifActions
230
231 visible: notifWindow.modelData?.[notifWindow.activeIx]?.actions.length > 0 ?? false
232
233 spacing: 8
234 uniformCellSizes: true
235
236 width: 400 - 16
237 Layout.row: 1 + (notifBody.visible ? 1 : 0) + (notifTime.visible ? 1 : 0)
238 Layout.column: 0
239 Layout.columnSpan: 2 + (notifImage.visible ? 1 : 0)
240
241 Repeater {
242 model: ScriptModel {
243 values: notifWindow.modelData?.[notifWindow.activeIx]?.actions
244 }
245
246 delegate: WrapperMouseArea {
247 id: actionMouseArea
248
249 required property var modelData
250
251 height: actionLabelWrapper.implicitHeight
252 Layout.fillWidth: true
253 Layout.horizontalStretchFactor: 1
254
255 hoverEnabled: true
256 cursorShape: Qt.PointingHandCursor
257
258 onClicked: actionMouseArea.modelData?.invoke()
259
260 Rectangle {
261 anchors.fill: parent
262
263 color: actionMouseArea.containsMouse ? "#20ffffff" : "transparent"
264
265 border {
266 width: 2
267 color: "#20ffffff"
268 }
269
270 WrapperItem {
271 id: actionLabelWrapper
272
273 margin: 8
274 anchors.centerIn: parent
275
276 RowLayout {
277 id: actionLabelLayout
278
279 spacing: 8
280
281 IconImage {
282 id: actionIcon
283
284 visible: notifWindow.modelData?.[notifWindow.activeIx]?.hasActionIcons
285
286 onStatusChanged: {
287 if (actionIcon.status == Image.Error)
288 actionIcon.visible = false;
289 }
290
291 implicitSize: 16
292 source: {
293 if (!actionIcon.visible)
294 return "";
295
296 let icon = actionMouseArea.modelData?.identifier ?? ""
297 if (icon.includes("?path=")) {
298 const split = icon.split("?path=")
299 if (split.length !== 2)
300 return icon
301 const name = split[0]
302 const path = split[1]
303 const fileName = name.substring(
304 name.lastIndexOf("/") + 1)
305 return `file://${path}/${fileName}`
306 }
307 return icon
308 }
309 asynchronous: true
310 smooth: true
311 mipmap: true
312
313 Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
314 }
315
316 Text {
317 id: actionLabel
318
319 visible: actionMouseArea.modelData?.text ?? false
320
321 text: actionMouseArea.modelData?.text ?? ""
322
323 font.pointSize: 10
324 font.family: "Fira Sans"
325 color: notifWindow.textColor
326 maximumLineCount: 1
327 elide: Text.ElideRight
328 }
329 }
330 }
331 }
332 }
333 }
334 }
335 }
336 }
337 }
338 }
339 }
340}
diff --git a/accounts/gkleen@sif/shell/quickshell/NotificationInhibitorWidget.qml b/accounts/gkleen@sif/shell/quickshell/NotificationInhibitorWidget.qml
new file mode 100644
index 00000000..80cbba19
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/NotificationInhibitorWidget.qml
@@ -0,0 +1,266 @@
1import Quickshell
2import QtQuick
3import Quickshell.Widgets
4import qs.Services
5import QtQuick.Controls
6import QtQuick.Layouts
7import QtQuick.Shapes
8
9Item {
10 id: root
11
12 width: icon.width + 8
13 height: parent.height
14 anchors.verticalCenter: parent.verticalCenter
15
16 WrapperMouseArea {
17 id: widgetMouseArea
18
19 anchors.fill: parent
20
21 hoverEnabled: true
22 cursorShape: Qt.PointingHandCursor
23
24 onClicked: NotificationManager.displayInhibited = !NotificationManager.displayInhibited
25
26 Rectangle {
27 anchors.fill: parent
28 color: {
29 if (widgetMouseArea.containsMouse) {
30 return "#33808080";
31 }
32 return "transparent";
33 }
34
35 Item {
36 anchors.fill: parent
37
38 MaterialDesignIcon {
39 id: icon
40
41 implicitSize: 14
42 anchors.centerIn: parent
43
44 icon: NotificationManager.active ? "message" : "message-off"
45 color: {
46 if (!NotificationManager.active && !NotificationManager.displayInhibited)
47 return "#f28a21";
48 if (NotificationManager.displayInhibited)
49 return "white";
50 return "#555";
51 }
52 }
53 }
54 }
55 }
56
57 Loader {
58 id: tooltipLoader
59
60 active: false
61
62 Connections {
63 target: widgetMouseArea
64 function onContainsMouseChanged() {
65 if (widgetMouseArea.containsMouse)
66 tooltipLoader.active = true;
67 }
68 }
69
70 sourceComponent: PopupWindow {
71 id: tooltip
72
73 property bool nextVisible: NotificationManager.active && NotificationManager.history.length > 0 && (widgetMouseArea.containsMouse || tooltipMouseArea.containsMouse)
74
75 anchor {
76 item: widgetMouseArea
77 edges: Edges.Bottom | Edges.Left
78 }
79 visible: false
80
81 onNextVisibleChanged: hangTimer.restart()
82
83 Timer {
84 id: hangTimer
85 interval: tooltip.visible ? 100 : 500
86 onTriggered: {
87 tooltip.visible = tooltip.nextVisible;
88 if (!tooltip.visible)
89 tooltipLoader.active = false;
90 }
91 }
92
93 implicitWidth: 400
94 implicitHeight: Math.min(tooltip.screen.height * 0.66, Math.max(100, scroll.contentHeight + 16))
95 color: "black"
96
97 WrapperMouseArea {
98 id: tooltipMouseArea
99
100 hoverEnabled: true
101 enabled: true
102
103 anchors.fill: parent
104
105 WrapperItem {
106 margin: 8
107
108 ScrollView {
109 id: scroll
110
111 contentWidth: availableWidth
112 // ScrollBar.vertical.policy: ScrollBar.AlwaysOn
113
114 ColumnLayout {
115 id: historyLayout
116 anchors {
117 left: parent.left
118 right: parent.right
119 }
120
121 spacing: 8
122
123 Repeater {
124 model: ScriptModel {
125 values: [...NotificationManager.history].reverse().map(o => o.notification)
126 }
127
128 delegate: GridLayout {
129 id: notif
130
131 Layout.fillWidth: true
132 Layout.preferredHeight: notifSummary.contentHeight + (notifBody.visible ? notifBody.contentHeight + 8 : 0) + (notifSep.visible ? notifSep.height + 8 : 0) + notifTime.contentHeight + 8
133
134 required property var modelData
135 required property int index
136
137 columnSpacing: 8
138 rowSpacing: 8
139
140 columns: notifImage.visible ? 2 : 1
141 rows: {
142 var res = 2;
143 if (notifBody.visible)
144 res += 1;
145 if (notifSep.visible)
146 res += 1;
147 return res;
148 }
149
150 Shape {
151 id: notifSep
152
153 visible: notif.index != 0
154
155 height: 2
156 width: 400 - 32
157
158 ShapePath {
159 strokeWidth: 2
160 strokeColor: "#20ffffff"
161 startX: 0; startY: 0;
162 PathLine { x: 400 - 32; y: 0; }
163 }
164
165 Layout.row: 0
166 Layout.column: 0
167 Layout.columnSpan: notifImage.visible ? 2 : 1
168 Layout.alignment: Qt.AlignHCenter
169 }
170
171 Text {
172 id: notifSummary
173
174 text: notif.modelData?.summary ?? ""
175
176 font.pointSize: 10
177 font.family: "Fira Sans"
178 font.italic: true
179 color: "white"
180 maximumLineCount: 1
181 elide: Text.ElideRight
182
183 Layout.fillWidth: true
184 Layout.row: notifSep.visible ? 1 : 0
185 Layout.column: notifImage.visible ? 1 : 0
186 }
187
188 Image {
189 id: notifImage
190
191 visible: (notif.modelData?.image || notif.modelData?.appIcon) ?? false
192
193 onStatusChanged: {
194 if (notifImage.status == Image.Error)
195 notifImage.visible = false;
196 }
197
198 source: (notif.modelData?.image || notif.modelData?.appIcon) ?? ""
199 fillMode: Image.PreserveAspectFit
200 asynchronous: true
201 smooth: true
202 mipmap: true
203
204 Layout.maximumWidth: 50
205 Layout.column: 0
206 Layout.row: notifSep.visible ? 1 : 0
207 Layout.fillHeight: true
208 Layout.rowSpan: notifBody.visible ? 3 : 2
209 }
210
211 Text {
212 id: notifBody
213
214 visible: notif.modelData?.body ?? false
215 text: notif.modelData?.body ?? ""
216 textFormat: Text.RichText
217 wrapMode: Text.Wrap
218
219 font.pointSize: 10
220 font.family: "Fira Sans"
221 color: "white"
222
223 Layout.fillWidth: true
224 Layout.row: notifSep.visible ? 2 : 1
225 Layout.column: notifImage.visible ? 1 : 0
226 }
227
228 Text {
229 id: notifTime
230
231 Connections {
232 target: NotificationManager.clock
233 function onDateChanged() {
234 notifTime.text = NotificationManager.formatTime(notif.modelData?.receivedTime);
235 }
236 }
237
238 text: NotificationManager.formatTime(notif.modelData?.receivedTime)
239
240 font.pointSize: 8
241 font.family: "Fira Sans"
242 font.italic: true
243 color: "#555"
244 maximumLineCount: 1
245 horizontalAlignment: Text.AlignRight
246
247 Layout.fillWidth: true
248 Layout.row: {
249 var res = 1;
250 if (notifSep.visible)
251 res += 1;
252 if (notifBody.visible)
253 res += 1;
254 return res;
255 }
256 Layout.column: notifImage.visible ? 1 : 0
257 }
258 }
259 }
260 }
261 }
262 }
263 }
264 }
265 }
266}
diff --git a/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml b/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml
new file mode 100644
index 00000000..9c6b65a4
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml
@@ -0,0 +1,483 @@
1import QtQuick
2import QtQuick.Layouts
3import QtQuick.Controls.Fusion
4import Quickshell
5import Quickshell.Services.Pipewire
6import Quickshell.Widgets
7
8Item {
9 height: parent.height
10 width: volumeIcon.width + 8
11 anchors.verticalCenter: parent.verticalCenter
12
13 PwObjectTracker {
14 objects: [Pipewire.defaultAudioSink]
15 }
16
17 WrapperMouseArea {
18 id: widgetMouseArea
19
20 anchors.fill: parent
21 hoverEnabled: true
22 cursorShape: Qt.PointingHandCursor
23
24 onClicked: {
25 if (!Pipewire.defaultAudioSink)
26 return;
27 Pipewire.defaultAudioSink.audio.muted = !Pipewire.defaultAudioSink.audio.muted;
28 }
29
30 property real sensitivity: (1 / 40) / 120
31 onWheel: event => {
32 if (!Pipewire.defaultAudioSink)
33 return;
34 Pipewire.defaultAudioSink.audio.volume += event.angleDelta.y * sensitivity;
35 }
36
37 Rectangle {
38 id: volumeWidget
39
40 anchors.fill: parent
41 color: {
42 if (widgetMouseArea.containsMouse)
43 return "#33808080";
44 return "transparent";
45 }
46
47 Item {
48 anchors.fill: parent
49
50 MaterialDesignIcon {
51 id: volumeIcon
52
53 implicitSize: 14
54 anchors.centerIn: parent
55
56 icon: {
57 if (!Pipewire.defaultAudioSink || Pipewire.defaultAudioSink.audio.muted)
58 return "volume-off";
59 if (Pipewire.defaultAudioSink.audio.volume <= 0.33)
60 return "volume-low";
61 if (Pipewire.defaultAudioSink.audio.volume <= 0.67)
62 return "volume-medium";
63 return "volume-high";
64 }
65 color: "#555"
66 }
67 }
68 }
69 }
70
71 Loader {
72 id: tooltipLoader
73
74 active: false
75
76 Connections {
77 target: widgetMouseArea
78 function onContainsMouseChanged() {
79 if (widgetMouseArea.containsMouse)
80 tooltipLoader.active = true;
81 }
82 }
83
84 PwObjectTracker {
85 objects: Pipewire.devices
86 }
87 PwObjectTracker {
88 objects: Pipewire.nodes
89 }
90
91 sourceComponent: PopupWindow {
92 id: tooltip
93
94 property bool openPopup: false
95 property bool nextVisible: widgetMouseArea.containsMouse || tooltipMouseArea.containsMouse || openPopup
96
97 anchor {
98 item: widgetMouseArea
99 edges: Edges.Bottom | Edges.Left
100 }
101 visible: false
102
103 onNextVisibleChanged: hangTimer.restart()
104
105 Timer {
106 id: hangTimer
107 interval: 100
108 onTriggered: {
109 tooltip.visible = tooltip.nextVisible;
110 if (!tooltip.visible)
111 tooltipLoader.active = false;
112 }
113 }
114
115 implicitWidth: tooltipContent.width
116 implicitHeight: tooltipContent.height
117 color: "transparent"
118
119 Rectangle {
120 width: tooltip.width
121 height: tooltipLayout.childrenRect.height + 16
122 color: "black"
123 }
124
125 WrapperItem {
126 id: tooltipContent
127
128 bottomMargin: Math.max(0, 200 - tooltipLayout.implicitHeight)
129
130 WrapperMouseArea {
131 id: tooltipMouseArea
132
133 hoverEnabled: true
134 enabled: true
135
136 WrapperItem {
137 margin: 8
138 bottomMargin: 8
139
140 GridLayout {
141 id: tooltipLayout
142
143 columns: 4
144
145 Repeater {
146 model: Array.from(Pipewire.devices.values).filter(dev => dev.type == "Audio/Device")
147
148 Item {
149 id: descItem
150
151 required property var modelData
152 required property int index
153
154 Layout.column: 0
155 Layout.row: index
156
157 implicitWidth: descText.contentWidth
158 implicitHeight: descText.contentHeight
159
160 Text {
161 id: descText
162
163 color: "white"
164 font.pointSize: 10
165 font.family: "Fira Sans"
166
167 text: descItem.modelData.description
168 }
169 }
170 }
171
172 Repeater {
173 id: defaultSinkRepeater
174
175 model: {
176 Array.from(Pipewire.devices.values)
177 .filter(dev => dev.type == "Audio/Device")
178 .map(device => Array.from(Pipewire.nodes.values).find(node => node.type == PwNodeType.AudioSink && node.device?.id == device.id ));
179 }
180
181 Item {
182 id: defaultSinkItem
183
184 required property var modelData
185 required property int index
186
187 visible: Boolean(modelData)
188
189 PwObjectTracker {
190 objects: [defaultSinkItem.modelData]
191 }
192
193 Layout.column: 1
194 Layout.row: index
195
196 Layout.fillHeight: true
197
198 implicitWidth: 16 + 8
199
200 WrapperMouseArea {
201 id: defaultSinkMouseArea
202
203 anchors.fill: parent
204 hoverEnabled: true
205 cursorShape: Qt.PointingHandCursor
206
207 onClicked: {
208 Pipewire.preferredDefaultAudioSink = defaultSinkItem.modelData
209 }
210
211 onWheel: event => scrollVolume(event);
212 property real sensitivity: (1 / 40) / 120
213 function scrollVolume(event) {
214 defaultSinkItem.modelData.audio.volume += event.angleDelta.y * sensitivity;
215 }
216
217 Rectangle {
218 id: defaultSinkWidget
219
220 anchors.fill: parent
221 color: {
222 if (defaultSinkMouseArea.containsMouse)
223 return "#33808080";
224 return "transparent";
225 }
226
227 MaterialDesignIcon {
228 width: 16
229 height: 16
230 anchors.centerIn: parent
231
232 icon: {
233 if (defaultSinkItem.modelData?.id == Pipewire.defaultAudioSink?.id)
234 return "speaker";
235 return "speaker-off";
236 }
237 color: icon == "speaker" ? "white" : "#555"
238 }
239 }
240 }
241
242 PopupWindow {
243 id: volumeTooltip
244
245 property bool nextVisible: defaultSinkMouseArea.containsMouse || volumeTooltipMouseArea.containsMouse
246
247 anchor {
248 item: defaultSinkMouseArea
249 edges: Edges.Bottom | Edges.Left
250 }
251 visible: false
252
253 onNextVisibleChanged: volumeHangTimer.restart()
254
255 onVisibleChanged: tooltip.openPopup = volumeTooltip.visible
256
257 Timer {
258 id: volumeHangTimer
259 interval: 100
260 onTriggered: volumeTooltip.visible = volumeTooltip.nextVisible
261 }
262
263 implicitWidth: volumeTooltipText.contentWidth + 16
264 implicitHeight: volumeTooltipText.contentHeight + 16
265 color: "black"
266
267 WrapperMouseArea {
268 id: volumeTooltipMouseArea
269
270 hoverEnabled: true
271 enabled: true
272
273 onWheel: event => defaultSinkMouseArea.scrollVolume(event);
274
275 anchors.fill: parent
276
277 Item {
278 anchors.fill: parent
279
280 Text {
281 id: volumeTooltipText
282
283 anchors.centerIn: parent
284
285 font.pointSize: 10
286 font.family: "Fira Sans"
287 color: "white"
288
289 text: `${Math.round(defaultSinkItem.modelData?.audio?.volume * 100)}%`
290 }
291 }
292 }
293 }
294 }
295 }
296
297 Repeater {
298 id: defaultSourceRepeater
299
300 model: {
301 Array.from(Pipewire.devices.values)
302 .filter(dev => dev.type == "Audio/Device")
303 .map(device => Array.from(Pipewire.nodes.values).find(node => node.type == PwNodeType.AudioSource && node.device?.id == device.id ));
304 }
305
306 Item {
307 id: defaultSourceItem
308
309 required property var modelData
310 required property int index
311
312 visible: Boolean(modelData)
313
314 PwObjectTracker {
315 objects: [defaultSourceItem.modelData]
316 }
317
318 Layout.column: 2
319 Layout.row: index
320
321 Layout.fillHeight: true
322
323 implicitWidth: 16 + 8
324
325 WrapperMouseArea {
326 id: defaultSourceMouseArea
327
328 anchors.fill: parent
329 hoverEnabled: true
330 cursorShape: Qt.PointingHandCursor
331
332 onClicked: {
333 Pipewire.preferredDefaultAudioSource = defaultSourceItem.modelData
334 }
335
336 onWheel: event => scrollVolume(event);
337 property real sensitivity: (1 / 40) / 120
338 function scrollVolume(event) {
339 defaultSourceItem.modelData.audio.volume += event.angleDelta.y * sensitivity;
340 }
341
342 Rectangle {
343 id: defaultSourceWidget
344
345 anchors.fill: parent
346 color: {
347 if (defaultSourceMouseArea.containsMouse)
348 return "#33808080";
349 return "transparent";
350 }
351
352 MaterialDesignIcon {
353 width: 16
354 height: 16
355 anchors.centerIn: parent
356
357 icon: {
358 if (defaultSourceItem.modelData?.id == Pipewire.defaultAudioSource?.id)
359 return "microphone";
360 return "microphone-off";
361 }
362 color: icon == "microphone" ? "white" : "#555"
363 }
364 }
365 }
366
367 PopupWindow {
368 id: volumeTooltip
369
370 property bool nextVisible: defaultSourceMouseArea.containsMouse || volumeTooltipMouseArea.containsMouse
371
372 anchor {
373 item: defaultSourceMouseArea
374 edges: Edges.Bottom | Edges.Left
375 }
376 visible: false
377
378 onNextVisibleChanged: volumeHangTimer.restart()
379
380 onVisibleChanged: tooltip.openPopup = volumeTooltip.visible
381
382 Timer {
383 id: volumeHangTimer
384 interval: 100
385 onTriggered: volumeTooltip.visible = volumeTooltip.nextVisible
386 }
387
388 implicitWidth: volumeTooltipText.contentWidth + 16
389 implicitHeight: volumeTooltipText.contentHeight + 16
390 color: "black"
391
392 WrapperMouseArea {
393 id: volumeTooltipMouseArea
394
395 hoverEnabled: true
396 enabled: true
397
398 onWheel: event => defaultSourceMouseArea.scrollVolume(event);
399
400 anchors.fill: parent
401
402 Item {
403 anchors.fill: parent
404
405 Text {
406 id: volumeTooltipText
407
408 anchors.centerIn: parent
409
410 font.pointSize: 10
411 font.family: "Fira Sans"
412 color: "white"
413
414 text: `${Math.round(defaultSourceItem.modelData?.audio?.volume * 100)}%`
415 }
416 }
417 }
418 }
419 }
420 }
421
422 Repeater {
423 id: profileRepeater
424
425 model: Array.from(Pipewire.devices.values).filter(dev => dev.type == "Audio/Device")
426
427 Item {
428 id: profileItem
429
430 required property var modelData
431 required property int index
432
433 PwObjectTracker {
434 objects: [profileItem.modelData]
435 }
436
437 Layout.column: 3
438 Layout.row: index
439
440 Layout.fillWidth: true
441
442 implicitWidth: Math.max(profileBox.implicitWidth, 300)
443 implicitHeight: profileBox.height
444
445 ComboBox {
446 id: profileBox
447
448 model: profileItem.modelData.profiles
449
450 textRole: "description"
451 valueRole: "index"
452 onActivated: profileItem.modelData.setProfile(currentValue)
453
454 anchors.fill: parent
455
456 implicitContentWidthPolicy: ComboBox.WidestText
457
458 Connections {
459 target: profileItem.modelData
460 function onCurrentProfileChanged() {
461 profileBox.currentIndex = Array.from(profileItem.modelData.profiles).findIndex(profile => profile.index == profileItem.modelData.currentProfile);
462 }
463 }
464 Component.onCompleted: {
465 profileBox.currentIndex = Array.from(profileItem.modelData.profiles).findIndex(profile => profile.index == profileItem.modelData.currentProfile);
466 }
467
468 Connections {
469 target: profileBox.popup
470 function onVisibleChanged() {
471 tooltip.openPopup = profileBox.popup.visible
472 }
473 }
474 }
475 }
476 }
477 }
478 }
479 }
480 }
481 }
482 }
483}
diff --git a/accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml b/accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml
new file mode 100644
index 00000000..d7ffadfe
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml
@@ -0,0 +1,49 @@
1import QtQuick
2import QtQuick.Layouts
3import Quickshell
4import Quickshell.Widgets
5import qs.Services
6
7Item {
8 height: parent.height
9 width: layout.childrenRect.width
10 anchors.verticalCenter: parent.verticalCenter
11
12 visible: Array.from(Privacy.activeItems).length > 0
13
14 RowLayout {
15 id: layout
16
17 anchors.fill: parent
18
19 spacing: 8
20
21 Repeater {
22 model: Privacy.activeItems
23
24 Item {
25 id: privacyItem
26
27 required property var modelData;
28
29 height: parent.height
30 width: icon.width
31
32 MaterialDesignIcon {
33 id: icon
34
35 implicitSize: 14
36 anchors.centerIn: parent
37
38 icon: {
39 if (privacyItem.modelData == Privacy.Item.Microphone)
40 return "microphone";
41 if (privacyItem.modelData == Privacy.Item.Screensharing)
42 return "monitor-share";
43 }
44 color: "#f2201f"
45 }
46 }
47 }
48 }
49}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml b/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml
new file mode 100644
index 00000000..f3ae6804
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml
@@ -0,0 +1,107 @@
1pragma Singleton
2
3import QtQml
4import Quickshell
5import Quickshell.Io
6import Custom as Custom
7import qs.Services
8
9Singleton {
10 id: root
11
12 property string subsystem: "backlight"
13 property string device: "intel_backlight"
14
15 property real currBrightness
16 property real exponent: 4
17
18 function calcCurrBrightness() {
19 if (!currFile.loaded || !maxFile.loaded)
20 return undefined;
21 const curr = Number(currFile.text());
22 const max = Number(maxFile.text());
23 const val = Math.pow(curr / max, 1 / root.exponent);
24 return val;
25 }
26
27 Connections {
28 target: currFile
29 function onLoaded() {
30 const b = root.calcCurrBrightness();
31 if (typeof b !== 'undefined')
32 root.currBrightness = b;
33 }
34 }
35 Connections {
36 target: maxFile
37 function onLoaded() {
38 const b = root.calcCurrBrightness();
39 if (typeof b !== 'undefined')
40 root.currBrightness = b;
41 }
42 }
43
44 onCurrBrightnessChanged: {
45 root.currBrightness = Math.max(0, Math.min(1, root.currBrightness));
46
47 const prev = root.calcCurrBrightness();
48 if (typeof prev === 'undefined' || Math.abs(root.currBrightness - prev) < 0.01)
49 return;
50
51 const max = Number(maxFile.text());
52 const actual = Number(currFile.text());
53 let curr = Math.max(0, Math.min(max, Math.pow(root.currBrightness, root.exponent) * max));
54 if (Math.round(curr) == actual && curr < actual)
55 curr = Math.max(0, actual - 1);
56 else if (Math.round(curr) == actual && curr > actual)
57 curr = Math.min(max, actual + 1);
58 // root.currBrightness = Math.pow(curr / max, 1 / root.exponent);
59 Custom.Systemd.setBrightness(root.subsystem, root.device, Math.round(curr));
60 }
61
62 FileView {
63 id: currFile
64 path: `/sys/class/${root.subsystem}/${root.device}/brightness`
65 blockAllReads: true
66 watchChanges: true
67 onFileChanged: reload()
68 }
69 FileView {
70 id: maxFile
71 path: `/sys/class/${root.subsystem}/${root.device}/max_brightness`
72 blockAllReads: true
73 watchChanges: true
74 onFileChanged: reload()
75 }
76
77
78 Timer {
79 id: startupDelay
80 interval: 500
81 running: true
82 repeat: false
83 }
84 property bool onlyInternal: true
85 Connections {
86 target: NiriService
87 function onOutputsChanged() {
88 root.onlyInternal = Object.keys(NiriService.outputs).every(oname => oname == "eDP-1");
89 }
90 }
91 onOnlyInternalChanged: {
92 if (startupDelay.running)
93 return;
94
95 if (!root.onlyInternal)
96 root.currBrightness = 1
97 }
98
99
100 IpcHandler {
101 target: "Brightness"
102
103 function set(brightness: real): void {
104 root.currBrightness = brightness;
105 }
106 }
107}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/GpgAgent.qml b/accounts/gkleen@sif/shell/quickshell/Services/GpgAgent.qml
new file mode 100644
index 00000000..3de69535
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/GpgAgent.qml
@@ -0,0 +1,18 @@
1pragma Singleton
2
3import Quickshell
4import Quickshell.Io
5
6Singleton {
7 id: root
8
9 Socket {
10 id: agentSocket
11 connected: true
12 path: `${Quickshell.env("XDG_RUNTIME_DIR")}/gnupg/S.gpg-agent`
13 }
14
15 function reloadAgent() {
16 agentSocket.write("RELOADAGENT\n")
17 }
18}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml b/accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml
new file mode 100644
index 00000000..60202a29
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/InhibitorState.qml
@@ -0,0 +1,23 @@
1pragma Singleton
2
3import Quickshell
4import Custom as Custom
5
6Singleton {
7 id: inhibitorState
8
9 property bool waylandIdleInhibited: false
10 property alias lidSwitchInhibited: lidSwitchInhibitor.enabled
11 property bool lockscreenInhibited: false
12
13 Custom.SystemdInhibitor {
14 id: lidSwitchInhibitor
15
16 enabled: false
17
18 what: Custom.SystemdInhibitorParams.HandleLidSwitch
19 who: "quickshell"
20 why: "User request"
21 mode: Custom.SystemdInhibitorParams.BlockWeak
22 }
23}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml b/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml
new file mode 100644
index 00000000..e3ab9755
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml
@@ -0,0 +1,8 @@
1pragma Singleton
2
3import Quickshell
4import Quickshell.Services.Mpris
5
6Scope {
7 property list<var> players: Mpris.players.values
8}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml b/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml
new file mode 100644
index 00000000..e9e86f95
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/NiriService.qml
@@ -0,0 +1,217 @@
1pragma Singleton
2
3import Quickshell
4import Quickshell.Io
5import QtQuick
6
7Singleton {
8 id: root
9
10 property var workspaces: []
11 property var outputs: {}
12 property var keyboardLayouts: {}
13 property var windows: []
14 property var casts: []
15 readonly property string socketPath: Quickshell.env("NIRI_SOCKET")
16
17 function refreshOutputs() {
18 commandSocket.sendCommand("Outputs", data => {
19 outputs = data.Ok.Outputs;
20 });
21 }
22
23 function sendCommand(command, callback) {
24 commandSocket.sendCommand(command, callback);
25 }
26
27 Socket {
28 id: eventStreamSocket
29 path: root.socketPath
30 connected: true
31
32 property bool acked: false
33
34 onConnectionStateChanged: {
35 if (connected) {
36 acked = false;
37 write('"EventStream"\n');
38 }
39 }
40
41 parser: SplitParser {
42 onRead: line => {
43 try {
44 const event = JSON.parse(line)
45
46 // console.log(JSON.stringify(event))
47
48 if (event.WorkspacesChanged) {
49 root.workspaces = event.WorkspacesChanged.workspaces
50 root.refreshOutputs();
51 } else if (event.WorkspaceActivated)
52 eventWorkspaceActivated(event.WorkspaceActivated);
53 else if (event.WorkspaceUrgencyChanged)
54 eventWorkspaceUrgencyChanged(event.WorkspaceUrgencyChanged);
55 else if (event.WorkspaceActiveWindowChanged)
56 eventWorkspaceActiveWindowChanged(event.WorkspaceActiveWindowChanged);
57 else if (event.KeyboardLayoutsChanged)
58 root.keyboardLayouts = event.KeyboardLayoutsChanged.keyboard_layouts;
59 else if (event.KeyboardLayoutSwitched)
60 root.keyboardLayouts = Object.assign({}, root.keyboardLayouts, {"current_idx": event.KeyboardLayoutSwitched.idx });
61 else if (event.WindowsChanged)
62 root.windows = event.WindowsChanged.windows
63 else if (event.WindowOpenedOrChanged)
64 eventWindowOpenedOrChanged(event.WindowOpenedOrChanged);
65 else if (event.WindowClosed)
66 eventWindowClosed(event.WindowClosed);
67 else if (event.WindowFocusChanged)
68 eventWindowFocusChanged(event.WindowFocusChanged);
69 else if (event.WindowUrgencyChanged)
70 eventWindowUrgencyChanged(event.WindowUrgencyChanged);
71 else if (event.WindowLayoutsChanged)
72 eventWindowLayoutsChanged(event.WindowLayoutsChanged);
73 else if (event.WindowFocusTimestampChanged)
74 eventWindowFocusTimestampChanged(event.WindowFocusTimestampChanged);
75 else if (event.CastsChanged)
76 root.casts = event.CastsChanged.casts
77 else if (event.CastStartedOrChanged)
78 eventCastStartedOrChanged(event.CastStartedOrChanged);
79 else if (event.CastStopped)
80 eventCastStopped(event.CastStopped);
81 else if (event.Ok && !eventStreamSocket.acked) { eventStreamSocket.acked = true; }
82 else if (event.OverviewOpenedOrClosed) {}
83 else if (event.ScreenshotCaptured) {}
84 else if (event.ConfigLoaded) {}
85 else
86 console.log(JSON.stringify(event));
87 } catch (e) {
88 console.warn("NiriService: Failed to parse event:", line, e)
89 }
90 }
91 }
92 }
93
94 Socket {
95 id: commandSocket
96 path: root.socketPath
97 connected: true
98
99 property var awaitingAnswer: null
100 property var cmdQueue: []
101
102 parser: SplitParser {
103 onRead: line => {
104 if (commandSocket.awaitingAnswer === null)
105 return;
106
107 try {
108 const response = JSON.parse(line);
109 commandSocket.awaitingAnswer.callback(response);
110 commandSocket.awaitingAnswer = null;
111 } catch (e) {
112 console.warn("NiriService: Failed to parse response:", line, e)
113 }
114 commandSocket._handleQueue();
115 }
116 }
117
118 onCmdQueueChanged: {
119 _handleQueue();
120 }
121 onAwaitingAnswerChanged: {
122 _handleQueue();
123 }
124
125 function _handleQueue() {
126 if (cmdQueue.length <= 0 || awaitingAnswer !== null)
127 return;
128
129 let localQueue = Array.from(cmdQueue);
130 awaitingAnswer = localQueue.shift();
131 cmdQueue = localQueue;
132 write(JSON.stringify(awaitingAnswer.command) + '\n');
133 }
134
135 function sendCommand(command, callback) {
136 cmdQueue = Array.from(cmdQueue).concat([{ "command": command, "callback": callback }])
137 }
138 }
139
140 function eventWorkspaceActivated(data) {
141 let relevant_output = null;
142 Array.from(root.workspaces).forEach(ws => {
143 if (data.id === ws.id)
144 relevant_output = ws.output;
145 });
146 root.workspaces = Array.from(root.workspaces).map(ws => {
147 if (data.focused)
148 ws.is_focused = false;
149 if (ws.output === relevant_output)
150 ws.is_active = false;
151 if (data.id === ws.id) {
152 ws.is_active = true;
153 ws.is_focused = data.focused;
154 }
155 return ws;
156 });
157 }
158 function eventWorkspaceUrgencyChanged(data) {
159 root.workspaces = Array.from(root.workspaces).map(ws => {
160 if (data.id == ws.id)
161 ws.is_urgent = data.urgent;
162 return ws;
163 });
164 }
165 function eventWorkspaceActiveWindowChanged(data) {
166 root.workspaces = Array.from(root.workspaces).map(ws => {
167 if (data.workspace_id === ws.id)
168 ws.active_window_id = data.active_window_id;
169 return ws;
170 });
171 }
172 function eventWindowOpenedOrChanged(data) {
173 root.windows = Array.from(root.windows).map(win => {
174 if (data.window.is_focused)
175 win.is_focused = false;
176 return win;
177 }).filter(win => win.id !== data.window.id).concat([data.window]);
178 }
179 function eventWindowClosed(data) {
180 root.windows = Array.from(root.windows).filter(win => win.id !== data.id);
181 }
182 function eventWindowFocusChanged(data) {
183 root.windows = Array.from(root.windows).map(win => {
184 win.is_focused = win.id === data.id;
185 return win;
186 });
187 }
188 function eventWindowUrgencyChanged(data) {
189 root.windows = Array.from(root.windows).map(win => {
190 if (win.id === data.id)
191 win.is_urgent = data.urgent;
192 return win;
193 });
194 }
195 function eventWindowLayoutsChanged(data) {
196 root.windows = Array.from(root.windows).map(win => {
197 Array.from(data.changes).forEach(change => {
198 if (win.id === change[0])
199 win.layout = change[1];
200 });
201 return win;
202 });
203 }
204 function eventWindowFocusTimestampChanged(data) {
205 root.windows = Array.from(root.windows).map(win => {
206 if (win.id === data.id)
207 win.focus_timestamp = data.focus_timestamp;
208 return win;
209 });
210 }
211 function eventCastStartedOrChanged(data) {
212 root.casts = [...Array.from(root.casts).filter(cast => cast.stream_id !== data.cast.stream_id), data.cast];
213 }
214 function eventCastStopped(data) {
215 root.casts = Array.from(root.casts).filter(cast => cast.stream_id !== data.stream_id);
216 }
217}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml b/accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml
new file mode 100644
index 00000000..5f8ff419
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/NotificationManager.qml
@@ -0,0 +1,162 @@
1pragma Singleton
2
3import QtQml
4import Quickshell
5import Quickshell.Services.Notifications
6
7Singleton {
8 id: root
9
10 readonly property bool active: !root.lockscreenActive && !root.displayInhibited
11 property bool lockscreenActive: false
12 property bool displayInhibited: false
13 property alias trackedNotifications: server.trackedNotifications
14 readonly property var groups: {
15 function matchesGroupKey(notif, groupKey) {
16 var matches = true;
17 for (const prop in groupKey.test) {
18 if (notif[prop] !== groupKey.test[prop]) {
19 matches = false;
20 break;
21 }
22 }
23 return matches;
24 }
25
26 var groups = new Map();
27 var notifs = new Array();
28 for (const [ix, notif] of server.trackedNotifications.values.entries()) {
29 var didGroup = false;
30 for (const groupKey of root.groupKeys) {
31 if (!matchesGroupKey(notif, groupKey))
32 continue;
33
34 const key = JSON.stringify({
35 "key": groupKey,
36 "values": Object.assign({}, ...(Array.from(groupKey["group-by"]).map(prop => {
37 var res = {};
38 res[prop] = notif[prop];
39 return res;
40 })))
41 });
42 if (!groups.has(key))
43 groups.set(key, new Array());
44 groups.get(key).push({ "ix": ix, "notif": notif });
45 didGroup = true;
46 break;
47 }
48
49 if (!didGroup)
50 notifs.push([{ "ix": ix, "notif": notif }]);
51 }
52 notifs.push(...groups.values());
53 notifs.sort((as, bs) => Math.min(...(as.map(o => o.ix))) - Math.min(...(bs.map(o => o.ix))));
54 return notifs.map(ns => ns.map(n => n.notif));
55 }
56
57 property var groupKeys: [
58 { "test": { "appName": "Element" }, "group-by": [ "summary" ] }
59 ];
60
61 property int historyLimit: 100
62 property var history: []
63
64 Component {
65 id: expirationTimer
66
67 QtObject {
68 id: timer
69
70 required property QtObject parent
71 required property int expirationTime
72
73 property list<QtObject> data: [
74 Timer {
75 running: root.active && !timer.expired
76 interval: timer.expirationTime
77 onTriggered: {
78 timer.parent.expirationTimer.destroy();
79 timer.parent.expirationTimer = null;
80 timer.parent.expire();
81 }
82 }
83 ]
84 }
85 }
86
87 Component {
88 id: notificationLock
89
90 RetainableLock {}
91 }
92
93 readonly property SystemClock clock: SystemClock {
94 precision: SystemClock.Minutes
95 }
96
97 function formatTime(time) {
98 const now = root.clock.date;
99 const diff = now - time;
100 const minutes = Math.ceil(diff / 60000);
101 const hours = Math.floor(minutes / 60);
102
103 if (hours < 1) {
104 if (minutes < 1)
105 return "now";
106 if (minutes == 1)
107 return "1 minute";
108 return `${minutes} minutes`;
109 }
110
111 const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
112 const timeDate = new Date(time.getFullYear(), time.getMonth(), time.getDate())
113 const days = Math.floor((nowDate - timeDate) / (1000 * 86400))
114
115 const timeStr = time.toLocaleTimeString(Qt.locale(), "HH:mm");
116
117 if (days === 0)
118 return timeStr;
119 if (days === 1)
120 return `yesterday ${timeStr}`;
121
122 const dateStr = time.toLocaleDateString(Qt.locale(), "YYYY-MM-DD");
123 return `${dateStr} ${timeStr}`;
124 }
125
126 NotificationServer {
127 id: server
128
129 bodySupported: true
130 actionsSupported: true
131 actionIconsSupported: true
132 imageSupported: true
133 bodyMarkupSupported: true
134 bodyImagesSupported: true
135
136 onNotification: notification => {
137 var timeout = notification.expireTimeout * 1000;
138 if (notification.appName == "poweralertd")
139 timeout = 2000;
140 if (timeout > 0) {
141 Object.defineProperty(notification, "expirationTimer", { configurable: true, enumerable: true, writable: true });
142 notification.expirationTimer = expirationTimer.createObject(notification, { parent: notification, expirationTime: timeout });
143 }
144 Object.defineProperty(notification, "receivedTime", { configurable: true, enumerable: true, writable: true });
145 notification.receivedTime = root.clock.date;
146 notification.closed.connect((reason) => server.onNotificationClosed(notification, reason));
147 notification.tracked = true;
148 }
149
150 function onNotificationClosed(notification, reason) {
151 while (root.history.length >= root.historyLimit) {
152 root.history[0].lock.locked = false;
153 root.history.shift();
154 }
155
156 root.history.push({
157 lock: notificationLock.createObject(root, { locked: true, object: notification }),
158 notification: notification
159 });
160 }
161 }
162}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml b/accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml
new file mode 100644
index 00000000..9c813e49
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml
@@ -0,0 +1,63 @@
1pragma Singleton
2
3import QtQml
4import Quickshell
5import Quickshell.Services.Pipewire
6
7Singleton {
8 id: root
9
10 PwObjectTracker {
11 objects: Pipewire.nodes.values
12 }
13
14 enum Item {
15 Microphone,
16 Screensharing
17 }
18
19 readonly property list<var> activeItems: {
20 var items = [];
21 if (microphoneActive)
22 items.push(Privacy.Item.Microphone);
23 if (screensharingActive)
24 items.push(Privacy.Item.Screensharing);
25 return items;
26 }
27
28 readonly property bool microphoneActive: {
29 if (!Pipewire.ready || !Pipewire.nodes?.values) {
30 return false
31 }
32
33 for (const node of Pipewire.nodes.values) {
34 if (!node || (node.type & PwNodeType.AudioInStream) != PwNodeType.AudioInStream)
35 continue;
36
37 if (node.properties?.["stream.monitor"] === "true")
38 continue;
39
40 if (node.audio?.muted)
41 continue;
42
43 return true;
44 }
45
46 return false;
47 }
48
49 readonly property bool screensharingActive: {
50 if (!Pipewire.ready || !Pipewire.nodes?.values) {
51 return false
52 }
53
54 for (const node of Pipewire.nodes.values) {
55 if (!node || (node.type & PwNodeType.VideoInStream) != PwNodeType.VideoInStream)
56 continue;
57
58 return true;
59 }
60
61 return false;
62 }
63}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/ScreenRecord.qml b/accounts/gkleen@sif/shell/quickshell/Services/ScreenRecord.qml
new file mode 100644
index 00000000..eb415452
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/ScreenRecord.qml
@@ -0,0 +1,63 @@
1pragma Singleton
2
3import Quickshell
4import Quickshell.Io
5
6Singleton {
7 id: root
8 property bool active: false
9 property bool slurpSuccess: false
10
11 onActiveChanged: {
12 if (!active) {
13 slurp.running = false;
14 screenRecorder.running = false;
15 }
16 if (active)
17 slurp.running = true;
18 }
19
20 Process {
21 id: screenRecorder
22 running: false
23 onRunningChanged: {
24 console.log("wf-recorder running: ", screenRecorder.running);
25
26 if (!screenRecorder.running && !slurp.running)
27 root.active = false;
28 }
29 stderr: SplitParser {
30 onRead: line => console.log("wf-recorder stderr: ", line)
31 }
32 stdout: SplitParser {
33 onRead: line => console.log("wf-recorder stdout: ", line)
34 }
35 }
36
37 Process {
38 id: slurp
39 running: false
40 command: [ @slurp@, "-o", "-d" ]
41 stdout: StdioCollector {}
42 stderr: SplitParser {
43 onRead: line => console.log("slurp stderr: ", line)
44 }
45 onExited: exitCode => {
46 if (exitCode !== 0) {
47 console.log("slurp failed: ", exitCode);
48 root.active = false;
49 return;
50 }
51 console.log("slurp succeeded: ", slurp.stdout.text);
52
53 const nowDate = new Date();
54
55 screenRecorder.command = [
56 @wf-recorder@,
57 "-g", slurp.stdout.text,
58 "-f", `${Quickshell.env("HOME")}/screenshots/${nowDate.toLocaleString(Qt.locale(), "yyyy-MM-ddThh:mm:ss")}.mkv`,
59 ];
60 screenRecorder.running = true;
61 }
62 }
63}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/WallpaperSelector.qml b/accounts/gkleen@sif/shell/quickshell/Services/WallpaperSelector.qml
new file mode 100644
index 00000000..c71a9cca
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/WallpaperSelector.qml
@@ -0,0 +1,8 @@
1import Custom as Custom
2
3Custom.FileSelector {
4 id: root
5
6 directory: @wallpapers@
7 epoch: 79200000
8}
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/Worktime.qml b/accounts/gkleen@sif/shell/quickshell/Services/Worktime.qml
new file mode 100644
index 00000000..d98378f1
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/Services/Worktime.qml
@@ -0,0 +1,84 @@
1pragma Singleton
2
3import QtQuick
4import Quickshell
5import Quickshell.Io
6import QtQml
7
8Singleton {
9 id: root
10
11 property alias time: timeState
12 property alias today: todayState
13
14 CommandState {
15 id: timeState
16 command: "time"
17 }
18 CommandState {
19 id: todayState
20 command: "today"
21 }
22
23 IpcHandler {
24 target: "Worktime"
25
26 function refresh(): void {
27 time.running = true;
28 today.running = true;
29 }
30 }
31
32 component CommandState : Scope {
33 id: commandState
34
35 required property string command
36 property var state: null
37
38 property bool strikeout: !strikeoutTimer.running
39 property alias running: process.running
40 property alias updating: updateTimer.running
41
42 Process {
43 id: process
44 running: true
45 command: [ @worktime@, commandState.command, "--waybar" ]
46 stdout: StdioCollector {
47 id: processCollector
48 onStreamFinished: {
49 try {
50 commandState.state = JSON.parse(processCollector.text);
51 strikeoutTimer.restart();
52 } catch (e) {
53 console.warn("Worktime: Failed to parse output:", processCollector.text, e);
54 }
55 }
56 }
57 }
58
59 Timer {
60 id: updateTimer
61 running: commandState.state?.class == "running" || commandState.state?.class == "over"
62 interval: 60000
63 repeat: true
64 onTriggered: process.running = true
65 }
66
67 Timer {
68 id: strikeoutTimer
69 running: false
70 interval: 5 * updateTimer.interval
71 repeat: false
72 }
73 }
74
75 Timer {
76 running: Boolean(timeState.state) && Boolean(todayState.state) && timeState.strikeout && todayState.strikeout
77 interval: 1000
78 repeat: false
79 onTriggered: {
80 timeState.state = null;
81 todayState.state = null;
82 }
83 }
84}
diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml
new file mode 100644
index 00000000..f0c50632
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml
@@ -0,0 +1,201 @@
1import QtQuick
2import QtQuick.Effects
3import Quickshell
4import Quickshell.Widgets
5import Quickshell.Services.SystemTray
6
7Item {
8 anchors.verticalCenter: parent.verticalCenter
9 width: systemTrayRow.childrenRect.width
10 height: parent.height
11 clip: true
12
13 Row {
14 id: systemTrayRow
15 anchors.centerIn: parent
16 width: childrenRect.width
17 height: parent.height
18 spacing: 0
19
20 Repeater {
21 model: ScriptModel {
22 values: {
23 var trayItems = Array.from(SystemTray.items.values).filter(item => item.status !== Status.Passive && !(["Fcitx"].includes(item.id)));
24 trayItems.sort((a, b) => a.category !== b.category ? b.category - a.category : a.id.localeCompare(b.id))
25 return trayItems;
26 }
27 }
28
29 delegate: Item {
30 id: trayItemWrapper
31
32 required property var modelData
33 required property int index
34
35 property var trayItem: modelData
36 property string iconSource: {
37 let icon = trayItem && trayItem.icon
38 if (typeof icon === 'string' || icon instanceof String) {
39 if (icon.includes("?path=")) {
40 const split = icon.split("?path=")
41 if (split.length !== 2)
42 return icon
43 const name = split[0]
44 const path = split[1]
45 const fileName = name.substring(
46 name.lastIndexOf("/") + 1)
47 return `file://${path}/${fileName}`
48 }
49 return icon
50 }
51 return ""
52 }
53
54 width: icon.width + 6
55 height: parent.height
56 anchors.verticalCenter: parent.verticalCenter
57
58 WrapperMouseArea {
59 id: trayItemArea
60
61 anchors.fill: parent
62 acceptedButtons: Qt.LeftButton | Qt.RightButton
63 hoverEnabled: true
64 cursorShape: trayItem.onlyMenu ? Qt.ArrowCursor : Qt.PointingHandCursor
65 onClicked: mouse => {
66 if (!trayItem)
67 return
68
69 if (mouse.button === Qt.LeftButton
70 && !trayItem.onlyMenu) {
71 trayItem.activate()
72 return
73 }
74
75 if (trayItem.hasMenu) {
76 var globalPos = mapToGlobal(0, 0)
77 var currentScreen = screen || Screen
78 var screenX = currentScreen.x || 0
79 var relativeX = globalPos.x - screenX
80 menuAnchor.menu = trayItem.menu
81 menuAnchor.anchor.window = bar
82 menuAnchor.anchor.rect = Qt.rect(
83 relativeX,
84 21,
85 parent.width, 1)
86 menuAnchor.open()
87 }
88 }
89
90 Rectangle {
91 anchors.fill: parent
92 color: {
93 if (trayItemArea.containsMouse)
94 return "#33808080";
95 return "transparent";
96 }
97
98 Item {
99 anchors.fill: parent
100
101 layer.enabled: true
102 layer.effect: MultiEffect {
103 colorization: 1
104 colorizationColor: "#555"
105 }
106
107 IconImage {
108 id: icon
109
110 anchors.centerIn: parent
111 implicitSize: 16
112 source: trayItemWrapper.iconSource
113 asynchronous: true
114 smooth: true
115 mipmap: true
116
117 layer.enabled: true
118 layer.effect: MultiEffect {
119 id: effect
120
121 brightness: 1
122 }
123 }
124 }
125 }
126 }
127
128 PopupWindow {
129 id: tooltip
130
131 property bool nextVisible: (trayItem.tooltipTitle || trayItem.tooltipDescription) && (trayItemArea.containsMouse || tooltipMouseArea.containsMouse) && !menuAnchor.visible
132
133 anchor {
134 item: trayItemArea
135 edges: Edges.Bottom
136 }
137
138 visible: false
139 onNextVisibleChanged: hangTimer.restart()
140
141 Timer {
142 id: hangTimer
143 interval: 100
144 onTriggered: tooltip.visible = tooltip.nextVisible
145 }
146
147 color: "black"
148
149 implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16
150 implicitHeight: (trayItem.tooltipTitle ? tooltipTitle.contentHeight : 0) + (trayItem.tooltipDescription ? tooltipDescription.contentHeight : 0) + 16
151
152 WrapperMouseArea {
153 id: tooltipMouseArea
154
155 hoverEnabled: true
156 enabled: true
157
158 margin: 4
159
160 anchors.fill: parent
161
162 Item {
163 anchors.fill: parent
164
165 Column {
166 anchors.centerIn: parent
167 Text {
168 id: tooltipTitle
169
170 enabled: trayItem.tooltipTitle
171
172 font.pointSize: 10
173 font.family: "Fira Sans"
174 font.bold: true
175 color: "white"
176
177 text: trayItem.tooltipTitle
178 }
179
180 Text {
181 id: tooltipDescription
182
183 enabled: trayItem.tooltipDescription
184
185 font.pointSize: 10
186 font.family: "Fira Sans"
187 color: "white"
188
189 text: trayItem.tooltipDescription
190 }
191 }
192 }
193 }
194 }
195 }
196 }
197 }
198 QsMenuAnchor {
199 id: menuAnchor
200 }
201}
diff --git a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml
new file mode 100644
index 00000000..3d950031
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml
@@ -0,0 +1,106 @@
1import Quickshell
2import Quickshell.Io
3import Quickshell.Services.Pipewire
4import Quickshell.Services.Mpris
5import qs.Services
6import Custom as Custom
7import QtQml
8
9Scope {
10 id: root
11
12 SocketServer {
13 active: true
14 path: `${Quickshell.env("XDG_RUNTIME_DIR")}/shell.sock`
15 handler: Socket {
16 parser: SplitParser {
17 onRead: line => {
18 const command = (() => {
19 try {
20 return JSON.parse(line);
21 } catch (e) {
22 console.warn("UnixIPC: Failed to parse command:", line, e);
23 }
24 })();
25 if (!command)
26 return;
27
28 if (command.Volume)
29 root.onCommandVolume(command.Volume);
30 else if (command.Brightness)
31 root.onCommandBrightness(command.Brightness);
32 else if (command.LockSession)
33 Custom.Systemd.lockSession();
34 else if (command.Suspend)
35 Custom.Systemd.suspend();
36 else if (command.Hibernate)
37 Custom.Systemd.hibernate();
38 else if (command.Mpris)
39 root.onCommandMpris(command.Mpris);
40 else if (command.Notifications)
41 root.onCommandNotifications(command.Notifications);
42 else if (command.ScreenRecord)
43 root.onCommandScreenRecord(command.ScreenRecord);
44 else
45 console.warn("UnixIPC: Command not handled:", JSON.stringify(command));
46 }
47 }
48
49 onError: e => {
50 if (e == 1)
51 return;
52 console.warn("QLocalSocket::LocalSocketError", e);
53 }
54 }
55 }
56
57 PwObjectTracker {
58 objects: [ Pipewire.defaultAudioSink, Pipewire.defaultAudioSource ]
59 }
60 function onCommandVolume(command) {
61 if (command.muted === "toggle")
62 Pipewire.defaultAudioSink.audio.muted = !Pipewire.defaultAudioSink.audio.muted;
63 if (command.volume === "up")
64 Pipewire.defaultAudioSink.audio.volume += 0.02;
65 if (command.volume === "down")
66 Pipewire.defaultAudioSink.audio.volume -= 0.02;
67
68 if (command["mic-muted"] === "toggle")
69 Pipewire.defaultAudioSource.audio.muted = !Pipewire.defaultAudioSource.audio.muted;
70 }
71
72 function onCommandBrightness(command) {
73 if (command === "up")
74 Brightness.currBrightness += 0.02
75 if (command === "down")
76 Brightness.currBrightness -= 0.02
77 }
78
79 function onCommandMpris(command) {
80 if (command.PauseAll)
81 Array.from(MprisProxy.players).forEach(player => {
82 if (player.canPause && player.isPlaying)
83 player.pause();
84 });
85 }
86 Component.onCompleted: { (_ => {})(MprisProxy.players); }
87
88 function onCommandNotifications(command) {
89 if (command.DismissGroup && NotificationManager.active) {
90 if (NotificationManager.groups.length > 0)
91 for (const notif of [...NotificationManager.groups[0]])
92 notif.dismiss();
93 }
94 if (command.DismissAll && NotificationManager.active) {
95 for (const notif of [...NotificationManager.trackedNotifications.values])
96 notif.dismiss();
97 }
98 }
99
100 function onCommandScreenRecord(command) {
101 if (command.Toggle)
102 ScreenRecord.active = !ScreenRecord.active;
103 else
104 console.warn("UnixIPC.ScreenRecord: Command not handled:", JSON.stringify(command));
105 }
106}
diff --git a/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml b/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml
new file mode 100644
index 00000000..91dc9591
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml
@@ -0,0 +1,163 @@
1import QtQuick
2import QtQuick.Layouts
3import Quickshell
4import Quickshell.Services.Pipewire
5import Quickshell.Widgets
6
7Scope {
8 id: root
9
10 property string show: ""
11 property bool inhibited: true
12
13 PwObjectTracker {
14 objects: [ Pipewire.defaultAudioSink, Pipewire.defaultAudioSource ]
15 }
16
17 Connections {
18 enabled: Pipewire.defaultAudioSink
19 target: Pipewire.defaultAudioSink?.audio || null
20
21 function onVolumeChanged() {
22 root.show = "sink";
23 hideTimer.restart();
24 }
25 function onMutedChanged() {
26 root.show = "sink";
27 hideTimer.restart();
28 }
29 }
30
31 Connections {
32 enabled: Pipewire.defaultAudioSource
33 target: Pipewire.defaultAudioSource?.audio || null
34
35 function onVolumeChanged() {
36 root.show = "source";
37 hideTimer.restart();
38 }
39 function onMutedChanged() {
40 root.show = "source";
41 hideTimer.restart();
42 }
43 }
44
45 onShowChanged: {
46 if (show)
47 hideTimer.restart();
48 }
49
50 Timer {
51 id: hideTimer
52 interval: 1000
53 onTriggered: root.show = ""
54 }
55
56 Timer {
57 id: startInhibit
58 interval: 100
59 running: true
60 onTriggered: {
61 root.show = "";
62 root.inhibited = false;
63 }
64 }
65
66 LazyLoader {
67 active: root.show && !root.inhibited
68
69 Variants {
70 model: Quickshell.screens
71
72 delegate: Scope {
73 id: screenScope
74
75 required property var modelData
76
77 PanelWindow {
78 id: window
79
80 screen: screenScope.modelData
81
82 anchors.top: true
83 margins.top: screen.height / 2 - 50 + 3.5
84 exclusiveZone: 0
85 exclusionMode: ExclusionMode.Ignore
86
87 implicitWidth: 400
88 implicitHeight: 50
89
90 mask: Region {}
91
92 color: "transparent"
93
94 Rectangle {
95 anchors.fill: parent
96 color: Qt.rgba(0, 0, 0, 0.75)
97 }
98
99 RowLayout {
100 id: layout
101
102 anchors.centerIn: parent
103
104 height: 50 - 8*2
105 width: 400 - 8*2
106
107 MaterialDesignIcon {
108 id: volumeIcon
109
110 implicitWidth: parent.height
111 implicitHeight: parent.height
112
113 icon: {
114 if (root.show == "sink") {
115 if (!Pipewire.defaultAudioSink || Pipewire.defaultAudioSink.audio.muted)
116 return "volume-off";
117 if (Pipewire.defaultAudioSink.audio.volume <= 0.33)
118 return "volume-low";
119 if (Pipewire.defaultAudioSink.audio.volume <= 0.67)
120 return "volume-medium";
121 return "volume-high";
122 } else if (root.show == "source") {
123 if (!Pipewire.defaultAudioSource || Pipewire.defaultAudioSource.audio.muted)
124 return "microphone-off";
125 if (Pipewire.defaultAudioSource.audio.volume > 1)
126 return "microphone-plus";
127 return "microphone";
128 }
129 return "volume-high";
130 }
131 }
132
133 Rectangle {
134 Layout.fillWidth: true
135
136 implicitHeight: 10
137
138 color: "#50ffffff"
139
140 Rectangle {
141 anchors {
142 left: parent.left
143 top: parent.top
144 bottom: parent.bottom
145 }
146
147 color: Pipewire.defaultAudioSink?.audio.muted ? "#70ffffff" : "white"
148
149 implicitWidth: {
150 if (root.show == "sink")
151 return parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0);
152 else if (root.show == "source")
153 return parent.width * Math.min(1, (Pipewire.defaultAudioSource?.audio.volume ?? 0));
154 return 0;
155 }
156 }
157 }
158 }
159 }
160 }
161 }
162 }
163}
diff --git a/accounts/gkleen@sif/shell/quickshell/WallpaperBackground.qml b/accounts/gkleen@sif/shell/quickshell/WallpaperBackground.qml
new file mode 100644
index 00000000..4f85a900
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/WallpaperBackground.qml
@@ -0,0 +1,89 @@
1import QtQuick
2import Quickshell
3import qs.Services
4
5Item {
6 id: root
7
8 anchors.fill: parent
9
10 required property string screen
11
12 property Img current: one
13 property string source: selector.selected
14
15 WallpaperSelector {
16 id: selector
17 seed: screen
18 }
19
20 onSourceChanged: {
21 if (!source)
22 current = null;
23 else if (current === one)
24 two.update()
25 else
26 one.update()
27 }
28
29 Img { id: one }
30 Img { id: two }
31
32 component Img: Image {
33 id: img
34
35 function update() {
36 source = root.source || ""
37 }
38
39 anchors.fill: parent
40 fillMode: Image.PreserveAspectCrop
41 smooth: true
42 asynchronous: true
43 cache: false
44
45 opacity: 0
46
47 onStatusChanged: {
48 if (status === Image.Ready) {
49 root.current = this
50 }
51 }
52
53 states: State {
54 name: "visible"
55 when: root.current === img
56
57 PropertyChanges {
58 img.opacity: 1
59 }
60 StateChangeScript {
61 name: "unloadOther"
62 script: {
63 if (img === one)
64 two.source = ""
65 if (img === two)
66 one.source = ""
67 }
68 }
69 }
70
71 transitions: Transition {
72 SequentialAnimation {
73 NumberAnimation {
74 target: img
75 properties: "opacity"
76 duration: {
77 if (img === one && two.source == "" || img === two && one.source == "")
78 return 0;
79 return 5000;
80 }
81 easing.type: Easing.OutCubic
82 }
83 ScriptAction {
84 scriptName: "unloadOther"
85 }
86 }
87 }
88 }
89}
diff --git a/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml b/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml
new file mode 100644
index 00000000..0512ff51
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml
@@ -0,0 +1,56 @@
1import Quickshell
2import QtQuick
3import Quickshell.Widgets
4import Quickshell.Wayland
5import qs.Services
6
7Item {
8 id: root
9
10 required property var window
11
12 width: icon.width + 8
13 height: parent.height
14 anchors.verticalCenter: parent.verticalCenter
15
16 IdleInhibitor {
17 id: inhibitor
18 enabled: InhibitorState.waylandIdleInhibited
19 window: root.window
20 }
21
22 WrapperMouseArea {
23 id: widgetMouseArea
24
25 anchors.fill: parent
26
27 hoverEnabled: true
28 cursorShape: Qt.PointingHandCursor
29
30 onClicked: InhibitorState.waylandIdleInhibited = !InhibitorState.waylandIdleInhibited
31
32 Rectangle {
33 anchors.fill: parent
34 color: {
35 if (widgetMouseArea.containsMouse) {
36 return "#33808080";
37 }
38 return "transparent";
39 }
40
41 Item {
42 anchors.fill: parent
43
44 MaterialDesignIcon {
45 id: icon
46
47 implicitSize: 14
48 anchors.centerIn: parent
49
50 icon: inhibitor.enabled ? "eye" : "eye-off"
51 color: inhibitor.enabled ? "white" : "#555"
52 }
53 }
54 }
55 }
56}
diff --git a/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml b/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml
new file mode 100644
index 00000000..d0595b3d
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml
@@ -0,0 +1,204 @@
1import Quickshell
2import QtQuick
3import qs.Services
4import Quickshell.Widgets
5import QtQuick.Layouts
6
7Row {
8 id: workspaces
9
10 required property var screen
11
12 property var ignoreWorkspaces: @ignore_workspaces@
13
14 height: parent.height
15 anchors.verticalCenter: parent.verticalCenter
16 spacing: 0
17
18 Repeater {
19 model: ScriptModel {
20 values: {
21 let currWorkspaces = NiriService.workspaces;
22 const ignoreWorkspaces = Array.from(workspaces.ignoreWorkspaces);
23 currWorkspaces = currWorkspaces.filter(ws => ws.output == workspaces.screen?.name).filter(ws => ws.is_active || ignoreWorkspaces.every(iws => iws !== ws.name));
24 currWorkspaces.sort((a, b) => {
25 if (NiriService.outputs?.[a.output]?.logical?.x !== NiriService.outputs?.[b.output]?.logical?.x)
26 return NiriService.outputs?.[a.output]?.logical?.x - NiriService.outputs?.[b.output]?.logical?.x
27 if (NiriService.outputs?.[a.output]?.logical?.y !== NiriService.outputs?.[b.output]?.logical?.y)
28 return NiriService.outputs?.[a.output]?.logical?.y - NiriService.outputs?.[b.output]?.logical?.y
29 return a.idx - b.idx;
30 });
31 return currWorkspaces;
32 }
33 }
34
35 Item {
36 id: wsItem
37
38 property var workspaceData: modelData
39
40 width: wsLabel.contentWidth + 8
41 height: parent.height
42 anchors.verticalCenter: parent.verticalCenter
43
44 WrapperMouseArea {
45 id: mouseArea
46
47 anchors.fill: parent
48
49 hoverEnabled: true
50 cursorShape: Qt.PointingHandCursor
51 enabled: true
52 onClicked: {
53 NiriService.sendCommand({ "Action": { "FocusWorkspace": { "reference": { "Id": workspaceData.id } } } }, _ => {});
54 }
55
56 Rectangle {
57 anchors.fill: parent
58
59 color: {
60 if (mouseArea.containsMouse) {
61 return "#33808080";
62 }
63 return "transparent";
64 }
65
66 Text {
67 id: wsLabel
68
69 anchors.centerIn: parent
70
71 font.pointSize: 10
72 font.family: "Fira Sans"
73 color: {
74 if (workspaceData.is_active)
75 return "#23fd00";
76 if (workspaceData.active_window_id === null)
77 return "#555";
78 return "white";
79 }
80
81 text: workspaceData.name ? workspaceData.name : workspaceData.idx
82 }
83 }
84 }
85
86 PopupWindow {
87 id: tooltip
88
89 property bool nextVisible: (mouseArea.containsMouse || tooltipMouseArea.containsMouse) && [...windowsModel.values].length > 0
90
91 anchor {
92 item: mouseArea
93 edges: Edges.Bottom | Edges.Left
94 }
95 visible: false
96
97 onNextVisibleChanged: hangTimer.restart()
98
99 Timer {
100 id: hangTimer
101 interval: 100
102 onTriggered: tooltip.visible = tooltip.nextVisible
103 }
104
105 implicitWidth: tooltipContent.implicitWidth
106 implicitHeight: tooltipContent.implicitHeight
107 color: "black"
108
109 WrapperMouseArea {
110 id: tooltipMouseArea
111
112 hoverEnabled: true
113 enabled: true
114
115 anchors.fill: parent
116
117 WrapperItem {
118 id: tooltipContent
119
120 margin: 0
121
122 ColumnLayout {
123 spacing: 0
124
125 Repeater {
126 model: ScriptModel {
127 id: windowsModel
128
129 values: {
130 let currWindows = Array.from(NiriService.windows).filter(win => win.workspace_id == wsItem.workspaceData.id);
131 currWindows.sort((a, b) => {
132 if (a.is_floating !== b.is_floating)
133 return b.is_floating - a.is_floating;
134 if (a.layout.tile_pos_in_workspace_view?.[0] !== b.layout.tile_pos_in_workspace_view?.[0])
135 return a.layout.tile_pos_in_workspace_view?.[0] - b.layout.tile_pos_in_workspace_view?.[0]
136 if (a.layout.tile_pos_in_workspace_view?.[1] !== b.layout.tile_pos_in_workspace_view?.[1])
137 return a.layout.tile_pos_in_workspace_view?.[1] - b.layout.tile_pos_in_workspace_view?.[1]
138 if (a.layout.pos_in_scrolling_layout?.[0] !== b.layout.pos_in_scrolling_layout?.[0])
139 return a.layout.pos_in_scrolling_layout?.[0] - b.layout.pos_in_scrolling_layout?.[0]
140 if (a.layout.pos_in_scrolling_layout?.[1] !== b.layout.pos_in_scrolling_layout?.[1])
141 return a.layout.pos_in_scrolling_layout?.[1] - b.layout.pos_in_scrolling_layout?.[1]
142 if (a.app_id !== b.app_id)
143 return a.app_id?.localeCompare(b.app_id);
144
145 return a.title.localeCompare(b.title);
146 });
147 return currWindows;
148 }
149 }
150
151 WrapperMouseArea {
152 id: windowMouseArea
153
154 required property int index
155 required property var modelData
156 property var windowData: modelData
157
158 hoverEnabled: true
159 cursorShape: Qt.PointingHandCursor
160 enabled: true
161
162 Layout.fillWidth: true
163
164 onClicked: {
165 NiriService.sendCommand({ "Action": { "FocusWindow": { "id": windowData.id } } }, _ => {})
166 }
167
168 WrapperRectangle {
169 color: windowMouseArea.containsMouse ? "#33808080" : "transparent";
170
171 WrapperItem {
172 rightMargin: 8
173 leftMargin: 8
174 topMargin: windowMouseArea.index == 0 ? 8 : 4
175 bottomMargin: windowMouseArea.index == windowsModel.values.length - 1 ? 8 : 4
176
177 Text {
178 id: windowLabel
179
180 font.pointSize: 10
181 font.family: "Fira Sans"
182 color: {
183 if (windowData.is_focused)
184 return "#23fd00";
185 if (NiriService.workspaces.find(ws => ws.id == windowData.workspace_id)?.active_window_id == windowData.id)
186 return "white";
187 return "#555";
188 }
189
190 text: windowData.title
191
192 horizontalAlignment: Text.AlignLeft
193 }
194 }
195 }
196 }
197 }
198 }
199 }
200 }
201 }
202 }
203 }
204}
diff --git a/accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml b/accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml
new file mode 100644
index 00000000..b7baee34
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml
@@ -0,0 +1,212 @@
1import QtQml
2import Quickshell
3import QtQuick
4import Quickshell.Widgets
5import qs.Services
6
7Item {
8 id: root
9
10 height: parent.height
11 width: (timeWidget.visible ? timeWidget.label.contentWidth + 8 : 0) + (todayWidget.visible ? todayWidget.label.contentWidth + 8 : 0) + (icon.visible ? icon.implicitWidth + 8 : 0)
12 anchors.verticalCenter: parent.verticalCenter
13
14 component TextWidget : Item {
15 id: textWidget
16
17 visible: textWidget.state.state?.text ?? false
18
19 required property var state
20 property alias label: label
21 property alias mouseArea: mouseArea
22
23 anchors.verticalCenter: parent.verticalCenter
24 implicitWidth: label.contentWidth + 8
25 height: parent.height
26
27 WrapperMouseArea {
28 id: mouseArea
29
30 anchors.fill: parent
31
32 enabled: true
33 hoverEnabled: true
34 acceptedButtons: Qt.NoButton
35 cursorShape: Qt.PointingHandCursor
36
37 Item {
38 anchors.fill: parent
39
40 Text {
41 id: label
42
43 anchors.centerIn: parent
44
45 text: textWidget.state.state?.text ?? ""
46
47 font.pointSize: 10
48 font.family: "Fira Sans"
49 font.strikeout: textWidget.state.strikeout
50 color: {
51 if (textWidget.state.state?.class == "running")
52 return "white";
53 if (textWidget.state.state?.class == "over")
54 return "#f28a21";
55 return "#555";
56 }
57 }
58 }
59 }
60 }
61
62 WrapperMouseArea {
63 id: mouseArea
64
65 anchors.fill: parent
66 hoverEnabled: true
67
68 cursorShape: Qt.PointingHandCursor
69 onClicked: {
70 Worktime.time.running = true;
71 Worktime.today.running = true;
72 }
73
74 Rectangle {
75 anchors.fill: parent
76 color: {
77 if (mouseArea.containsMouse)
78 return "#33808080";
79 return "transparent";
80 }
81
82 Row {
83 height: parent.height
84 anchors.centerIn: parent
85 spacing: 0
86
87 TextWidget {
88 id: timeWidget
89 state: Worktime.time
90 }
91
92 TextWidget {
93 id: todayWidget
94 state: Worktime.today
95 }
96
97 MaterialDesignIcon {
98 id: icon
99
100 anchors.verticalCenter: parent.verticalCenter
101
102 implicitSize: 14
103
104 visible: !timeWidget.visible && !todayWidget.visible
105
106 icon: (Worktime.time.running || Worktime.today.running) ? "update" : "timer-off"
107 color: "#555"
108 }
109 }
110 }
111 }
112
113 component WorktimePopup : PopupWindow {
114 id: tooltip
115
116 required property var state
117 required property var mouseArea
118
119 property bool iconVisible: tooltip.state.running || !tooltip.state.updating
120 property bool tooltipVisible: tooltip.state.state?.tooltip ?? false
121
122 property bool nextVisible: (tooltip.tooltipVisible || tooltip.iconVisible) && (tooltip.mouseArea.containsMouse || tooltipMouseArea.containsMouse)
123
124 anchor {
125 item: tooltip.mouseArea
126 edges: Edges.Bottom | Edges.Left
127 }
128 visible: false
129
130 onNextVisibleChanged: hangTimer.restart()
131
132 Timer {
133 id: hangTimer
134 interval: 100
135 onTriggered: tooltip.visible = tooltip.nextVisible
136 }
137
138 implicitWidth: (tooltipIcon.visible ? tooltipIcon.implicitWidth : 0) + (tooltipIcon.visible && tooltipText.visible ? 8 : 0) + (tooltipText.visible ? tooltipText.implicitWidth : 0) + 16
139 implicitHeight: tooltipText.implicitHeight + 16
140 color: "black"
141
142 WrapperMouseArea {
143 id: tooltipMouseArea
144
145 enabled: true
146 hoverEnabled: true
147
148 anchors.fill: parent
149
150 Item {
151 anchors.fill: parent
152
153 Row {
154 id: tooltipLayout
155
156 anchors {
157 left: parent.left
158 top: parent.top
159 leftMargin: 8
160 topMargin: 8
161 verticalCenter: parent.verticalCenter
162 }
163
164 height: parent.height
165 width: childrenRect.width
166
167 spacing: 0
168
169 MaterialDesignIcon {
170 id: tooltipIcon
171
172 implicitSize: 14
173 anchors.verticalCenter: parent.verticalCenter
174
175 visible: tooltip.iconVisible
176
177 icon: tooltip.state.running ? "update" : "timer-off"
178 }
179
180 Item {
181 visible: tooltipIcon.visible && tooltipText.visible
182 height: parent.height
183 width: 8
184 }
185
186 Text {
187 id: tooltipText
188
189 visible: tooltip.tooltipVisible
190
191 anchors.verticalCenter: parent.verticalCenter
192
193 font.pointSize: 10
194 font.family: "Fira Sans"
195 color: "white"
196
197 text: tooltip.state.state?.tooltip ?? ""
198 }
199 }
200 }
201 }
202 }
203
204 WorktimePopup {
205 state: Worktime.time
206 mouseArea: timeWidget.mouseArea
207 }
208 WorktimePopup {
209 state: Worktime.today
210 mouseArea: todayWidget.mouseArea
211 }
212}
diff --git a/accounts/gkleen@sif/shell/quickshell/YtDlpWidget.qml b/accounts/gkleen@sif/shell/quickshell/YtDlpWidget.qml
new file mode 100644
index 00000000..ff338d49
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/YtDlpWidget.qml
@@ -0,0 +1,190 @@
1import QtQml.Models
2import QtQuick
3import QtQuick.Layouts
4import QtQuick.Controls.Material
5import Quickshell
6import Quickshell.Io
7import Quickshell.Widgets
8import Custom as Custom
9
10Item {
11 id: root
12
13 height: parent.height
14 width: icon.width
15 anchors.verticalCenter: parent.verticalCenter
16
17 visible: Boolean(unitsModel.values.length)
18
19 WrapperMouseArea {
20 id: widgetMouseArea
21
22 anchors.fill: parent
23 hoverEnabled: true
24
25 Item {
26 anchors.fill: parent
27
28 MaterialDesignIcon {
29 id: icon
30
31 implicitSize: 14
32 anchors.centerIn: parent
33
34 icon: "tray-arrow-down"
35 color: "white"
36 }
37 }
38 }
39
40 PopupWindow {
41 id: tooltip
42
43 property bool openPopup: false
44 property bool nextVisible: widgetMouseArea.containsMouse || tooltipMouseArea.containsMouse || openPopup
45
46 anchor {
47 item: widgetMouseArea
48 edges: Edges.Bottom | Edges.Left
49 }
50 visible: false
51
52 onNextVisibleChanged: hangTimer.restart()
53
54 Timer {
55 id: hangTimer
56 interval: 100
57 onTriggered: tooltip.visible = tooltip.nextVisible
58 }
59
60 implicitWidth: tooltipContent.width
61 implicitHeight: tooltipContent.height
62 color: "transparent"
63
64 Rectangle {
65 width: tooltip.width
66 height: tooltipLayout.childrenRect.height + 16
67 color: "black"
68 }
69
70 WrapperItem {
71 id: tooltipContent
72
73 WrapperMouseArea {
74 id: tooltipMouseArea
75
76 hoverEnabled: true
77 enabled: true
78
79 WrapperItem {
80 margin: 8
81
82 child: GridLayout {
83 id: tooltipLayout
84
85 columns: 2
86 }
87
88 Repeater {
89 model: ScriptModel {
90 id: unitsModel
91
92 values: [...Custom.Systemd.userUnits.values].filter(unit => unit.id.match(/^yt-dlp@.+\.service$/) && unit.activeState === "active" && unit.runtimeDirectory)
93 }
94
95 Item {
96 id: unitDelegate
97
98 Component.onCompleted: {
99 while (children.length) { children[0].parent = tooltipLayout; }
100 }
101
102 required property var modelData
103 required property int index
104
105 property var state: null
106
107 Socket {
108 id: socket
109
110 path: Quickshell.env("XDG_RUNTIME_DIR") + "/" + unitDelegate.modelData.runtimeDirectory[0] + "/status.sock"
111 connected: true
112 onError: e => {
113 console.warn("YtDlpWidget: Error in Socket:", socket.path, e);
114 }
115 parser: SplitParser {
116 onRead: line => {
117 try {
118 unitDelegate.state = JSON.parse(line)
119 } catch (e) {
120 console.warn("YtDlpWidget: Failed to parse state:", line, e)
121 }
122 }
123 }
124 }
125
126 WrapperItem {
127 Layout.column: 0
128 Layout.row: unitDelegate.index
129
130 implicitWidth: descText.contentWidth
131 implicitHeight: descText.contentHeight
132
133 Text {
134 id: descText
135
136 color: "white"
137 font.pointSize: 10
138 font.family: "Fira Sans"
139
140 text: unitDelegate.state?.title || unitDelegate.modelData.id
141 }
142 }
143
144 /*
145 WrapperItem {
146 Layout.column: 1
147 Layout.row: unitDelegate.index
148
149 implicitWidth: fragText.contentWidth
150 implicitHeight: fragText.contentHeight
151
152 visible: Boolean(unitDelegate.state)
153
154 Text {
155 id: fragText
156
157 color: "white"
158 font.pointSize: 10
159 font.family: "Fira Sans"
160
161 text: `${unitDelegate.state?.fragment_index}/${unitDelegate.state?.fragment_count}`
162 }
163 }
164 */
165
166 WrapperItem {
167 Layout.column: 1
168 Layout.row: unitDelegate.index
169
170 visible: Boolean(unitDelegate.state)
171
172 ProgressBar {
173 id: progress
174
175 Material.background: "black"
176 Material.accent: "white"
177
178 from: 0
179 to: unitDelegate.state?.total_bytes || unitDelegate.state?.total_bytes_estimate || 0
180 value: unitDelegate.state?.downloaded_bytes || 0
181 indeterminate: !Boolean(unitDelegate.state?.total_bytes || unitDelegate.state?.total_bytes_estimate) || unitDelegate.state?.status !== "downloading"
182 }
183 }
184 }
185 }
186 }
187 }
188 }
189 }
190}
diff --git a/accounts/gkleen@sif/shell/quickshell/displaymanager.qml b/accounts/gkleen@sif/shell/quickshell/displaymanager.qml
new file mode 100644
index 00000000..b452c03d
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/displaymanager.qml
@@ -0,0 +1,115 @@
1//@ pragma UseQApplication
2
3import Quickshell
4import Quickshell.Wayland
5import Quickshell.Io
6import Quickshell.Services.Greetd
7import QtQml
8
9
10ShellRoot {
11 id: displaymanager
12
13 settings.watchFiles: false
14
15 property string currentText: ""
16 property string username: @username@
17 property list<string> command: @niri_session@
18 property list<var> messages: []
19 property bool responseRequired: false
20 property bool responseVisible: false
21
22 signal startAuth()
23
24 onStartAuth: {
25 if (Greetd.state !== GreetdState.Inactive)
26 Greetd.cancelSession();
27 displaymanager.messages = [];
28 Greetd.createSession(displaymanager.username);
29 }
30
31 Connections {
32 target: Greetd
33 function onStateChanged() {
34 console.log("greetd state: ", GreetdState.toString(Greetd.state));
35 if (Greetd.state === GreetdState.ReadyToLaunch)
36 Greetd.launch(displaymanager.command);
37 }
38 function onAuthMessage(message: string, error: bool, responseRequired: bool, echoResponse: bool) {
39 displaymanager.responseVisible = echoResponse;
40 displaymanager.responseRequired = responseRequired;
41 displaymanager.messages = Array.from(displaymanager.messages).concat([{ "text": message, "error": error }]);
42 }
43 function onAuthFailure(message: string) {
44 displaymanager.responseRequired = false;
45 displaymanager.messages = Array.from(displaymanager.messages).concat([{ "text": message, "error": true }]);
46 }
47 }
48
49 Component.onCompleted: {
50 if (Greetd.state !== GreetdState.Inactive)
51 Greetd.cancelSession();
52 }
53
54 Variants {
55 model: Quickshell.screens
56
57 delegate: Scope {
58 id: screenScope
59
60 required property var modelData
61
62 PanelWindow {
63 color: "black"
64
65 screen: screenScope.modelData
66
67 WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
68
69 anchors.top: true
70 anchors.bottom: true
71 anchors.left: true
72 anchors.right: true
73
74 LockSurface {
75 id: surfaceContent
76
77 screen: screenScope.modelData
78
79 onCurrentTextChanged: displaymanager.currentText = currentText
80 Connections {
81 target: displaymanager
82 function onCurrentTextChanged() { surfaceContent.currentText = displaymanager.currentText; }
83 function onMessagesChanged() { surfaceContent.messages = Array.from(displaymanager.messages); }
84 function onResponseRequiredChanged() { surfaceContent.responseRequired = displaymanager.responseRequired; }
85 function onResponseVisibleChanged() { surfaceContent.responseVisible = displaymanager.responseVisible; }
86 }
87
88 onResponse: responseText => Greetd.respond(responseText);
89 Connections {
90 target: Greetd
91 function onStateChanged() {
92 if (Greetd.state === GreetdState.Authenticating) {
93 surfaceContent.authRunning = true;
94 } else {
95 surfaceContent.authRunning = false;
96 }
97 }
98 }
99
100 onAuthRunningChanged: {
101 if (surfaceContent.authRunning && Greetd.state !== GreetdState.Authenticating)
102 displaymanager.startAuth();
103 }
104 Component.onCompleted: {
105 surfaceContent.authRunning = Greetd.state === GreetdState.Authenticating
106 surfaceContent.messages = Array.from(displaymanager.messages);
107 surfaceContent.responseVisible = displaymanager.responseVisible;
108 surfaceContent.responseRequired = displaymanager.responseRequired;
109 surfaceContent.currentText = displaymanager.currentText;
110 }
111 }
112 }
113 }
114 }
115}
diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml
new file mode 100644
index 00000000..1a5875f0
--- /dev/null
+++ b/accounts/gkleen@sif/shell/quickshell/shell.qml
@@ -0,0 +1,53 @@
1//@ pragma UseQApplication
2
3import Quickshell
4import Quickshell.Wayland
5
6ShellRoot {
7 settings.watchFiles: false
8
9 Variants {
10 model: Quickshell.screens
11
12 delegate: Scope {
13 id: screenScope
14
15 required property var modelData
16
17 PanelWindow {
18 id: bgWindow
19
20 screen: screenScope.modelData
21
22 WlrLayershell.layer: WlrLayer.Background
23 WlrLayershell.namespace: "background"
24 exclusionMode: ExclusionMode.Ignore
25
26 anchors.top: true
27 anchors.bottom: true
28 anchors.left: true
29 anchors.right: true
30
31 color: "black"
32
33 WallpaperBackground {
34 screen: bgWindow.screen.name
35 }
36 }
37
38 Bar {
39 screen: screenScope.modelData
40 }
41 }
42 }
43
44 Lockscreen {}
45 NiriIdle {}
46
47 VolumeOSD {}
48 BrightnessOSD {}
49
50 NotificationDisplay {}
51
52 UnixIPC {}
53}