21 Commits

Author SHA1 Message Date
zach 82518006c3 revert toaster enum 2026-06-05 19:45:43 +02:00
zach 9cefdf509c cmake build hotfix 2026-06-05 12:31:37 +02:00
zach 27924aca37 disable incompatible-type for qmllint in clock 2026-06-04 23:22:28 +02:00
zach b4716d25c0 nodiscard 2026-06-04 22:57:45 +02:00
zach d8f047dbc9 nodiscard 2026-06-04 22:38:17 +02:00
zach 91b50b312d open launcher with gesture from bottom border 2026-06-04 19:01:02 +02:00
zach 3e933a8b78 remove logging 2026-06-04 18:56:42 +02:00
zach e127928126 Merge pull request 'Rewrite the manager responsible for handling automatic hyprsunset temperature activation as a qml plugin' (#117) from hyprsunset-manager-rewrite into main
Reviewed-on: #117
2026-06-04 15:05:45 +02:00
zach 94f2cf076c fix applying end() on init
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 23s
Python / test (pull_request) Successful in 49s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m3s
2026-06-04 15:05:18 +02:00
zach 9168b6e893 Merge branch 'main' into hyprsunset-manager-rewrite
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 24s
Python / test (pull_request) Successful in 42s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m3s
2026-06-04 14:56:53 +02:00
zach a477fb2e22 fix namespaces and logging names 2026-06-04 14:56:20 +02:00
zach 6586cc2788 do not use apply() in initializer
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 48s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m4s
2026-06-03 23:21:07 +02:00
zach 0be98a64ac Merge branch 'main' into hyprsunset-manager-rewrite
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 15s
Python / lint-format (pull_request) Successful in 23s
Python / test (pull_request) Successful in 54s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m4s
2026-06-03 18:02:27 +02:00
zach b6e7ee7a54 Merge pull request 'lid behavior watcher to lock session' (#115) from lid-switch-behavior into main
Reviewed-on: #115
2026-06-03 18:02:21 +02:00
AramJonghu 59789ab8d3 unused imports in shell.qml
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 21s
Python / test (pull_request) Successful in 51s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m4s
2026-06-03 18:01:10 +02:00
AramJonghu a128c0fa40 removal reduntant config option and settings, unused lines in Lock.qml
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 21s
Python / test (pull_request) Successful in 52s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m4s
2026-06-03 17:59:03 +02:00
AramJonghu 6f856e2162 fix typo
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 18s
Python / test (pull_request) Successful in 44s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m5s
2026-06-03 17:47:12 +02:00
AramJonghu a19701222b forgotton import and removal LidService
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 26s
Python / test (pull_request) Successful in 41s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m4s
2026-06-03 17:43:58 +02:00
AramJonghu 0d8f558f66 Took caelestia lid logic (prepare to sleep) instead
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 12s
Python / lint-format (pull_request) Successful in 19s
Python / test (pull_request) Successful in 45s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m3s
2026-06-03 17:41:29 +02:00
AramJonghu ed28d8b56a Took caelestia lid logic (prepare to sleep) instead 2026-06-03 17:41:17 +02:00
zach d246ba1800 rewrite the manager responsible for handling automatic hyprsunset temperature activation as a qml plugin
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 13s
Python / lint-format (pull_request) Successful in 19s
Python / test (pull_request) Successful in 50s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m2s
2026-06-02 16:09:48 +02:00
45 changed files with 670 additions and 617 deletions
-1
View File
@@ -253,7 +253,6 @@ Singleton {
return {
recolorLogo: lock.recolorLogo,
enableFprint: lock.enableFprint,
lidWatch: lock.lidWatch,
showNotifContent: lock.showNotifContent,
showNotifIcon: lock.showNotifIcon,
maxFprintTries: lock.maxFprintTries,
-1
View File
@@ -4,7 +4,6 @@ JsonObject {
property int blurAmount: 40
property bool enableFprint: true
property int maxFprintTries: 3
property bool lidWatch: false
property bool recolorLogo: false
property bool showNotifContent: false
property bool showNotifIcon: true
-18
View File
@@ -1,18 +0,0 @@
import Quickshell
import ZShell
import QtQuick
Scope {
id: root
signal requestLock
Connections {
function onStateChanged(): void {
if (LidWatcher.state === LidWatcher.Closed)
root.requestLock();
}
target: LidWatcher
}
}
+6 -3
View File
@@ -69,14 +69,17 @@ Item {
root.singleGestureTriggered = false;
}
onCentroidChanged: {
if (root.singleGestureTriggered)
return;
const x = centroid.position.x;
const y = centroid.position.y;
const dragX = x - centroid.pressPosition.x;
const dragY = y - centroid.pressPosition.y;
if (centroid.pressPosition.y >= root.screen.height - Config.barConfig.border && dragY < -200)
root.visibilities.launcher = true;
if (root.singleGestureTriggered)
return;
if (centroid.pressPosition.y < root.bar.implicitHeight) {
if (dragY > 20) {
root.visibilities.settings = true;
+11 -59
View File
@@ -2,12 +2,13 @@ pragma Singleton
import Quickshell
import QtQuick
import ZShell.Services
import qs.Config
Singleton {
id: root
property bool enabled
readonly property bool enabled: service.enabled
readonly property int end: Config.general.color.scheduleHyprsunsetEnd
property bool manualToggle: false
readonly property int start: Config.general.color.scheduleHyprsunsetStart
@@ -17,69 +18,20 @@ Singleton {
if (!Config.general.color.scheduleHyprsunset)
return;
var now = new Date();
if (now.getHours() >= root.start || now.getHours() < root.end) {
root.startNightLight(root.temp);
} else {
root.stopNightLight();
}
}
function startNightLight(temp: int): void {
Quickshell.execDetached(["hyprctl", "hyprsunset", "temperature", `${temp}`]);
root.enabled = true;
}
function stopNightLight(): void {
Quickshell.execDetached(["hyprctl", "hyprsunset", "identity"]);
root.enabled = false;
service.apply();
}
function toggleNightLight(): void {
if (enabled)
stopNightLight();
else
startNightLight(temp);
service.manualToggle = true;
service.toggle();
}
onManualToggleChanged: {
if (root.manualToggle)
manualTimer.start();
}
HyprsunsetManager {
id: service
Timer {
id: manualTimer
interval: 60000 * 60
repeat: false
running: false
onTriggered: {
root.manualToggle = false;
}
}
Timer {
interval: 5000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
if (!Config.general.color.scheduleHyprsunset)
return;
if (root.manualToggle)
return;
var now = new Date();
if (now.getHours() >= root.start || now.getHours() < root.end) {
if (!root.enabled)
root.startNightLight(root.temp);
} else {
if (root.enabled)
root.stopNightLight();
}
}
activeAuto: Config.general.color.scheduleHyprsunset
endTime: root.end
startTime: root.start
temp: root.temp
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ CustomRect {
anchors.centerIn: parent
color: root.visibilities.dashboard ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
font: Appearance.font.family.mono
font: Appearance.font.family.mono // qmllint disable incompatible-type
text: Time.dateStr
Behavior on color {
+5
View File
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Wayland
import ZShell.Internal
import qs.Config
import qs.Helpers
@@ -29,6 +30,10 @@ Scope {
Quickshell.execDetached(action);
}
LidWatcher {
onAboutToSleep: root.lock.lock.locked = true
}
Variants {
model: Config.general.idle.timeouts
-11
View File
@@ -9,7 +9,6 @@ import qs.Components
Scope {
id: root
required property var lid
property alias lock: lock
property int seenOnce: 0
@@ -19,16 +18,6 @@ Scope {
signal requestLock
signal unlock
onRequestLock: lock.locked = true
onUnlock: lock.locked = false
Connections {
target: root.lid
function onRequestLock(): void {
lock.locked = true
}
}
LockSurface {
id: lockSurface
@@ -60,17 +60,6 @@ SettingsPage {
Separator {
}
SettingSwitch {
name: "Laptop lid watch to lock session"
object: Config.lock
setting: "lidWatch"
shouldBeActive: Battery.isLaptop
}
Separator {
shouldBeActive: Battery.isLaptop
}
SettingSpinBox {
min: 0
name: "Blur amount"
-2
View File
@@ -28,8 +28,6 @@ Item {
spacing: 1
Component.onCompleted: console.log(Battery.isLaptop)
CustomRect {
id: track
+4 -4
View File
@@ -18,13 +18,13 @@ public:
explicit BlobGroup(QObject* parent = nullptr);
~BlobGroup() override;
qreal smoothing() const {
[[nodiscard]] qreal smoothing() const {
return m_smoothing;
}
void setSmoothing(qreal s);
QColor color() const {
[[nodiscard]] QColor color() const {
return m_color;
}
@@ -36,11 +36,11 @@ void removeShape(BlobShape* shape);
void setInvertedRect(BlobInvertedRect* rect);
void clearInvertedRect(BlobInvertedRect* rect);
const QList<BlobShape*>& shapes() const {
[[nodiscard]] const QList<BlobShape*>& shapes() const {
return m_shapes;
}
BlobInvertedRect* invertedRect() const {
[[nodiscard]] BlobInvertedRect* invertedRect() const {
return m_invertedRect;
}
+5 -5
View File
@@ -16,25 +16,25 @@ public:
explicit BlobInvertedRect(QQuickItem* parent = nullptr);
~BlobInvertedRect() override;
qreal borderLeft() const {
[[nodiscard]] qreal borderLeft() const {
return m_borderLeft;
}
void setBorderLeft(qreal v);
qreal borderRight() const {
[[nodiscard]] qreal borderRight() const {
return m_borderRight;
}
void setBorderRight(qreal v);
qreal borderTop() const {
[[nodiscard]] qreal borderTop() const {
return m_borderTop;
}
void setBorderTop(qreal v);
qreal borderBottom() const {
[[nodiscard]] qreal borderBottom() const {
return m_borderBottom;
}
@@ -47,7 +47,7 @@ void borderTopChanged();
void borderBottomChanged();
protected:
bool isInvertedRect() const override {
[[nodiscard]] bool isInvertedRect() const override {
return true;
}
+2 -2
View File
@@ -21,8 +21,8 @@ struct BlobRectData {
class BlobMaterial : public QSGMaterial {
public:
QSGMaterialType* type() const override;
QSGMaterialShader* createShader(QSGRendererInterface::RenderMode) const override;
[[nodiscard]] QSGMaterialType* type() const override;
[[nodiscard]] QSGMaterialShader* createShader(QSGRendererInterface::RenderMode) const override;
int compare(const QSGMaterial* other) const override;
float m_paddedX = 0;
+7 -7
View File
@@ -24,7 +24,7 @@ public:
explicit BlobRect(QQuickItem* parent = nullptr);
~BlobRect() override;
qreal stiffness() const {
[[nodiscard]] qreal stiffness() const {
return m_stiffness;
}
@@ -35,7 +35,7 @@ void setStiffness(qreal s) {
}
}
qreal damping() const {
[[nodiscard]] qreal damping() const {
return m_damping;
}
@@ -46,7 +46,7 @@ void setDamping(qreal d) {
}
}
qreal deformScale() const {
[[nodiscard]] qreal deformScale() const {
return m_deformScale;
}
@@ -62,25 +62,25 @@ QQmlListProperty<BlobRect> exclude();
bool isExcluded(const BlobShape* other) const override;
void cornerRadii(float out[4]) const override;
qreal topLeftRadius() const {
[[nodiscard]] qreal topLeftRadius() const {
return m_topLeftRadius;
}
void setTopLeftRadius(qreal r);
qreal topRightRadius() const {
[[nodiscard]] qreal topRightRadius() const {
return m_topRightRadius;
}
void setTopRightRadius(qreal r);
qreal bottomLeftRadius() const {
[[nodiscard]] qreal bottomLeftRadius() const {
return m_bottomLeftRadius;
}
void setBottomLeftRadius(qreal r);
qreal bottomRightRadius() const {
[[nodiscard]] qreal bottomRightRadius() const {
return m_bottomRightRadius;
}
+6 -7
View File
@@ -21,23 +21,23 @@ public:
explicit BlobShape(QQuickItem* parent = nullptr);
~BlobShape() override = default;
BlobGroup* group() const {
[[nodiscard]] BlobGroup* group() const {
return m_group;
}
void setGroup(BlobGroup* g);
qreal radius() const {
[[nodiscard]] qreal radius() const {
return m_radius;
}
void setRadius(qreal r);
QMatrix4x4 deformMatrix() const {
[[nodiscard]] QMatrix4x4 deformMatrix() const {
return m_centeredDeformMatrix;
}
QMatrix4x4 rawDeformMatrix() const {
[[nodiscard]] QMatrix4x4 rawDeformMatrix() const {
return m_deformMatrix;
}
@@ -53,7 +53,7 @@ void geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) overri
void updatePolish() override;
QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) override;
virtual bool isInvertedRect() const {
[[nodiscard]] virtual bool isInvertedRect() const {
return false;
}
@@ -72,10 +72,9 @@ void updateCenteredDeformMatrix();
BlobGroup* m_group = nullptr;
qreal m_radius = 0;
QMatrix4x4 m_deformMatrix; // identity by default
QMatrix4x4 m_deformMatrix;
QMatrix4x4 m_centeredDeformMatrix;
// Cached data from updatePolish
float m_cachedPaddedX = 0;
float m_cachedPaddedY = 0;
float m_cachedPaddedW = 0;
-1
View File
@@ -45,7 +45,6 @@ qml_module(ZShell
requests.hpp requests.cpp
toaster.hpp toaster.cpp
qalculator.hpp qalculator.cpp
lidwatcher.hpp lidwatcher.cpp
LIBRARIES
Qt::Gui
Qt::Quick
+1
View File
@@ -9,6 +9,7 @@ qml_module(ZShell-internal
sparklineitem.hpp sparklineitem.cpp
arcgauge.hpp arcgauge.cpp
wallpaperimage.hpp wallpaperimage.cpp
lidwatcher.hpp lidwatcher.cpp
LIBRARIES
Qt::Gui
Qt::Quick
+1 -1
View File
@@ -58,4 +58,4 @@ qreal m_sweepAngle = 1.5 * M_PI;
qreal m_lineWidth = 10.0;
};
} // namespace ZShell::internal
} // namespace ZShell::Internal
@@ -19,7 +19,8 @@ class CachingImageManager : public QObject {
public:
explicit CachingImageManager(QObject* parent = nullptr)
: QObject(parent)
, m_item(nullptr) {}
, m_item(nullptr) {
}
[[nodiscard]] QQuickItem* item() const;
void setItem(QQuickItem* item);
+2 -2
View File
@@ -2,7 +2,7 @@
#include <algorithm>
namespace caelestia::internal {
namespace ZShell::internal {
CircularBuffer::CircularBuffer(QObject* parent)
: QObject(parent) {
@@ -92,4 +92,4 @@ qreal CircularBuffer::at(int index) const {
return m_data[actualIndex];
}
} // namespace caelestia::internal
} // namespace ZShell::internal
+2 -2
View File
@@ -4,7 +4,7 @@
#include <qqmlintegration.h>
#include <qvector.h>
namespace caelestia::internal {
namespace ZShell::internal {
class CircularBuffer : public QObject {
Q_OBJECT
@@ -41,4 +41,4 @@ int m_count = 0;
int m_capacity = 0;
};
} // namespace caelestia::internal
} // namespace ZShell::internal
@@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <qeasingcurve.h>
#include <qobject.h>
#include <qqmlintegration.h>
+86
View File
@@ -0,0 +1,86 @@
#include "lidwatcher.hpp"
#include <QtDBus/qdbusconnection.h>
#include <QtDBus/qdbuserror.h>
#include <QtDBus/qdbusinterface.h>
#include <QtDBus/qdbusreply.h>
#include <qloggingcategory.h>
Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.internal.logindmanager", QtInfoMsg)
namespace ZShell::internal {
LidWatcher::LidWatcher(QObject* parent) : QObject(parent) {
auto bus = QDBusConnection::systemBus();
if (!bus.isConnected()) {
qCWarning(lcLidWatcher)
<< "Failed to connect to system bus:" << bus.lastError().message();
return;
}
bool ok = bus.connect("org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"PrepareForSleep",
this,
SLOT(handlePrepareForSleep(bool)));
if (!ok) {
qCWarning(lcLidWatcher)
<< "Failed to connect to PrepareForSleep signal:"
<< bus.lastError().message();
}
QDBusInterface login1("org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
bus);
const QDBusReply<QDBusObjectPath> reply = login1.call("GetSession", "auto");
if (!reply.isValid()) {
qCWarning(lcLidWatcher) << "Failed to get session path";
return;
}
const auto sessionPath = reply.value().path();
ok = bus.connect("org.freedesktop.login1",
sessionPath,
"org.freedesktop.login1.Session",
"Lock",
this,
SLOT(handleLockRequested()));
if (!ok) {
qCWarning(lcLidWatcher)
<< "Failed to connect to Lock signal:" << bus.lastError().message();
}
ok = bus.connect("org.freedesktop.login1",
sessionPath,
"org.freedesktop.login1.Session",
"Unlock",
this,
SLOT(handleUnlockRequested()));
if (!ok) {
qCWarning(lcLidWatcher) << "Failed to connect to Unlock signal:"
<< bus.lastError().message();
}
}
void LidWatcher::handlePrepareForSleep(bool sleep) {
if (sleep) {
emit aboutToSleep();
} else {
emit resumed();
}
}
void LidWatcher::handleLockRequested() {
emit lockRequested();
}
void LidWatcher::handleUnlockRequested() {
emit unlockRequested();
}
} // namespace ZShell::internal
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <qobject.h>
#include <qqmlintegration.h>
namespace ZShell::internal {
class LidWatcher : public QObject {
Q_OBJECT
QML_ELEMENT
public:
explicit LidWatcher(QObject* parent = nullptr);
signals:
void aboutToSleep();
void resumed();
void lockRequested();
void unlockRequested();
private slots:
void handlePrepareForSleep(bool sleep);
void handleLockRequested();
void handleUnlockRequested();
};
} // namespace ZShell::internal
+2 -2
View File
@@ -4,7 +4,7 @@
#include <qpainterpath.h>
#include <qpen.h>
namespace caelestia::internal {
namespace ZShell::internal {
SparklineItem::SparklineItem(QQuickItem* parent)
: QQuickPaintedItem(parent) {
@@ -212,4 +212,4 @@ void SparklineItem::setLineWidth(qreal width) {
update();
}
} // namespace caelestia::internal
} // namespace ZShell::internal
+2 -2
View File
@@ -7,7 +7,7 @@
#include "circularbuffer.hpp"
namespace caelestia::internal {
namespace ZShell::internal {
class SparklineItem : public QQuickPaintedItem {
Q_OBJECT
@@ -87,4 +87,4 @@ int m_historyLength = 30;
qreal m_lineWidth = 2.0;
};
} // namespace caelestia::internal
} // namespace ZShell::internal
+4 -3
View File
@@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <qabstractitemmodel.h>
#include <qdir.h>
#include <qfilesystemwatcher.h>
@@ -85,9 +86,9 @@ public:
explicit FileSystemModel(QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
[[nodiscard]] int rowCount(const QModelIndex& parent = QModelIndex()) const override;
[[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
[[nodiscard]] QString path() const;
void setPath(const QString& path);
+1
View File
@@ -9,6 +9,7 @@ qml_module(ZShell-services
cavaprovider.hpp cavaprovider.cpp
desktopmodel.hpp desktopmodel.cpp
desktopstatemanager.hpp desktopstatemanager.cpp
hyprsunsetmanager.hpp hyprsunsetmanager.cpp
LIBRARIES
Qt6::Core
Qt6::Qml
+1 -1
View File
@@ -59,7 +59,7 @@ quint32 readChunk(double* out, quint32 count = 0);
private:
explicit AudioCollector(QObject* parent = nullptr);
~AudioCollector();
~AudioCollector() override;
std::jthread m_thread;
std::vector<float> m_buffer1;
+2 -3
View File
@@ -11,11 +11,10 @@ Q_OBJECT
public:
explicit AudioProcessor(QObject* parent = nullptr);
~AudioProcessor();
~AudioProcessor() override;
void init();
public slots:
void start();
void stop();
@@ -31,7 +30,7 @@ Q_OBJECT
public:
explicit AudioProvider(QObject* parent = nullptr);
~AudioProvider();
~AudioProvider() override;
protected:
AudioProcessor* m_processor;
+1 -1
View File
@@ -11,7 +11,7 @@ Q_OBJECT
public:
explicit BeatProcessor(QObject* parent = nullptr);
~BeatProcessor();
~BeatProcessor() override;
signals:
void beat(smpl_t bpm);
+1 -1
View File
@@ -11,7 +11,7 @@ Q_OBJECT
public:
explicit CavaProcessor(QObject* parent = nullptr);
~CavaProcessor();
~CavaProcessor() override;
void setBars(int bars);
+5 -4
View File
@@ -4,6 +4,7 @@
#include <QList>
#include <QString>
#include <QQmlEngine>
#include <cstdint>
namespace ZShell::services {
@@ -30,9 +31,9 @@ enum DesktopRoles {
explicit DesktopModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void loadDirectory(const QString &path);
Q_INVOKABLE void moveIcon(int index, int newX, int newY);
@@ -43,4 +44,4 @@ QList<DesktopItem> m_items;
void saveCurrentLayout();
};
} // namespace ZShell::services
} // namespace ZShell::Services
@@ -18,7 +18,7 @@ Q_INVOKABLE void saveLayout(const QVariantMap& layout);
Q_INVOKABLE QVariantMap getLayout();
private:
QString getConfigFilePath() const;
[[nodiscard]] QString getConfigFilePath() const;
};
} // namespace ZShell::services
@@ -0,0 +1,147 @@
#include "hyprsunsetmanager.hpp"
#include <qlogging.h>
#include <qobject.h>
#include <qprocess.h>
#include <qtimer.h>
namespace ZShell::services {
HyprsunsetManager::HyprsunsetManager(QObject* parent) : QObject(parent) {
connect(&m_timer, &QTimer::timeout, this, &HyprsunsetManager::apply);
connect(&m_manualTimer, &QTimer::timeout, this, [this] {
m_manualToggle = false;
emit manualToggleChanged();
apply();
});
connect(&m_startCooldown, &QTimer::timeout, this, [this] {
m_startAllowed = true;
apply();
});
m_startCooldown.start(2000);
m_manualTimer.setSingleShot(true);
m_timer.start(60000);
m_process.setStandardInputFile(QProcess::nullDevice());
m_process.setStandardOutputFile(QProcess::nullDevice());
}
int HyprsunsetManager::startTime() const {
return m_startTime;
}
int HyprsunsetManager::endTime() const {
return m_endTime;
}
bool HyprsunsetManager::manualToggle() const {
return m_manualToggle;
}
bool HyprsunsetManager::enabled() const {
return m_enabled;
}
bool HyprsunsetManager::activeAuto() const {
return m_activeAuto;
}
int HyprsunsetManager::temp() const {
return m_temp;
}
void HyprsunsetManager::setActiveAuto(bool activeAuto) {
if (activeAuto == m_activeAuto)
return;
m_activeAuto = activeAuto;
emit activeAutoChanged();
}
void HyprsunsetManager::setManualToggle(bool toggle) {
if (toggle == m_manualToggle)
return;
m_manualToggle = toggle;
emit manualToggleChanged();
m_manualTimer.start(60 * 60 * 1000);
}
void HyprsunsetManager::setEndTime(const int& time) {
if (time == m_endTime)
return;
m_endTime = time;
emit endTimeChanged();
apply();
}
void HyprsunsetManager::setStartTime(const int& time) {
if (time == m_startTime)
return;
m_startTime = time;
emit startTimeChanged();
apply();
}
void HyprsunsetManager::setTemp(const int& temp) {
if (temp == m_temp)
return;
m_temp = temp;
emit tempChanged();
apply();
}
void HyprsunsetManager::toggle() {
if (m_enabled) {
end();
} else {
start();
}
}
void HyprsunsetManager::start() {
if (m_enabled && m_initialized)
return;
m_initialized = true;
m_enabled = true;
emit enabledChanged();
m_process.setProgram("hyprctl");
m_process.setArguments({"hyprsunset", "temperature", QString::number(m_temp)});
m_process.startDetached();
}
void HyprsunsetManager::end() {
if (!m_enabled && m_initialized)
return;
m_initialized = true;
m_enabled = false;
emit enabledChanged();
m_process.setProgram("hyprctl");
m_process.setArguments({"hyprsunset", "identity"});
m_process.startDetached();
}
void HyprsunsetManager::apply() {
if (m_manualToggle || !m_activeAuto || !m_startAllowed)
return;
const auto current = QTime::currentTime().hour();
if (current >= m_startTime || current < m_endTime) {
start();
} else {
end();
}
}
};
@@ -0,0 +1,66 @@
#pragma once
#include <QObject>
#include <QTime>
#include <QProcess>
#include <QTimer>
#include <qqmlintegration.h>
#include <qtmetamacros.h>
namespace ZShell::services {
class HyprsunsetManager : public QObject {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
Q_PROPERTY(int endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
Q_PROPERTY(int temp READ temp WRITE setTemp NOTIFY tempChanged)
Q_PROPERTY(bool activeAuto READ activeAuto WRITE setActiveAuto NOTIFY activeAutoChanged)
Q_PROPERTY(bool manualToggle READ manualToggle WRITE setManualToggle NOTIFY manualToggleChanged)
public:
explicit HyprsunsetManager(QObject* parent = nullptr);
[[nodiscard]] int startTime() const;
[[nodiscard]] int endTime() const;
[[nodiscard]] bool enabled() const;
[[nodiscard]] int temp() const;
[[nodiscard]] bool activeAuto() const;
[[nodiscard]] bool manualToggle() const;
Q_INVOKABLE void toggle();
Q_INVOKABLE void apply();
void setStartTime(const int& time);
void setEndTime(const int& time);
void setTemp(const int& temp);
void setActiveAuto(bool activeAuto);
void setManualToggle(bool toggle);
signals:
void enabledChanged();
void startTimeChanged();
void activeAutoChanged();
void endTimeChanged();
void tempChanged();
void manualToggleChanged();
private:
int m_startTime;
int m_endTime;
bool m_enabled = false;
bool m_manualToggle = false;
bool m_activeAuto;
bool m_startAllowed = false;
bool m_initialized = false;
QTimer m_startCooldown;
int m_temp;
QProcess m_process;
QTimer m_timer;
QTimer m_manualTimer;
void start();
void end();
};
};
-121
View File
@@ -1,121 +0,0 @@
#include "lidwatcher.hpp"
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
#include <QtDBus/QDBusServiceWatcher>
#include <QLoggingCategory>
#include <QTimer>
Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.lidwatcher", QtInfoMsg)
namespace ZShell {
static constexpr auto kLogin1Service = "org.freedesktop.login1";
static constexpr auto kLogin1Path = "/org/freedesktop/login1";
static constexpr auto kLogin1Interface = "org.freedesktop.login1.Manager";
static constexpr auto kDBusPropertiesInterface =
"org.freedesktop.DBus.Properties";
LidWatcher::LidWatcher(QObject* parent)
: QObject(parent)
, m_watcher(nullptr)
, m_pollTimer(nullptr)
, m_available(false)
{
QDBusConnection bus = QDBusConnection::systemBus();
if (!bus.isConnected()) {
qCWarning(lcLidWatcher) << "system bus unavailable";
emit availableChanged();
return;
}
m_pollTimer = new QTimer(this);
m_pollTimer->setInterval(5000);
connect(m_pollTimer, &QTimer::timeout, this, &LidWatcher::queryLidState);
m_watcher = new QDBusServiceWatcher(
kLogin1Service,
bus,
QDBusServiceWatcher::WatchForRegistration,
this);
connect(m_watcher, &QDBusServiceWatcher::serviceRegistered,
this, &LidWatcher::tryConnect);
tryConnect();
}
bool LidWatcher::available() const {
return m_available;
}
LidWatcher::LidState LidWatcher::state() const {
return m_state;
}
void LidWatcher::tryConnect() {
QDBusConnection bus = QDBusConnection::systemBus();
const auto connected = bus.connect(
QString(),
kLogin1Path,
kDBusPropertiesInterface,
"PropertiesChanged",
this,
SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)));
queryLidState();
if (connected) {
m_pollTimer->stop();
qCInfo(lcLidWatcher) << "login1 PropertiesChanged connected";
} else {
qCWarning(lcLidWatcher)
<< "login1 PropertiesChanged unavailable, polling";
if (!m_pollTimer->isActive()) {
m_pollTimer->start();
}
}
if (!m_available) {
m_available = true;
emit availableChanged();
}
}
void LidWatcher::queryLidState() {
auto msg = QDBusMessage::createMethodCall(kLogin1Service,
kLogin1Path,
kDBusPropertiesInterface,
"Get");
msg << kLogin1Interface << "LidClosed";
const QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(msg);
if (!reply.isValid()) {
qCWarning(lcLidWatcher)
<< "cannot query LidClosed:" << reply.error().message();
return;
}
const auto newState = reply.value().toBool() ? Closed : Opened;
if (m_state != newState) {
m_state = newState;
emit stateChanged();
}
}
void LidWatcher::onPropertiesChanged(const QString& interface,
const QVariantMap& changed,
const QStringList& ) {
if (interface != kLogin1Interface) {
return;
}
if (!changed.contains("LidClosed")) {
return;
}
const auto newState = changed.value("LidClosed").toBool() ? Closed : Opened;
if (m_state != newState) {
m_state = newState;
emit stateChanged();
}
}
} // namespace ZShell
-50
View File
@@ -1,50 +0,0 @@
#pragma once
#include <QObject>
#include <QStringList>
#include <QVariantMap>
#include <cstdint>
#include <qqmlintegration.h>
class QDBusServiceWatcher;
class QTimer;
namespace ZShell {
class LidWatcher : public QObject {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
Q_PROPERTY(LidState state READ state NOTIFY stateChanged)
public:
enum LidState : std::uint8_t{ Opened, Closed };
Q_ENUM(LidState)
explicit LidWatcher(QObject* parent = nullptr);
[[nodiscard]] bool available() const;
[[nodiscard]] LidState state() const;
private:
void tryConnect();
void queryLidState();
QDBusServiceWatcher* m_watcher;
QTimer* m_pollTimer;
bool m_available;
LidState m_state = Opened;
private Q_SLOTS:
void onPropertiesChanged(const QString& interface,
const QVariantMap& changed,
const QStringList& invalidated);
Q_SIGNALS:
void availableChanged();
void stateChanged();
};
} // namespace ZShell
+1 -1
View File
@@ -13,7 +13,7 @@ QML_SINGLETON
public:
explicit Qalculator(QObject* parent = nullptr);
Q_INVOKABLE QString eval(const QString& expr, bool printExpr = true) const;
Q_INVOKABLE [[nodiscard]] QString eval(const QString& expr, bool printExpr = true) const;
};
} // namespace ZShell
+3 -3
View File
@@ -29,9 +29,9 @@ Q_INVOKABLE void cacheImage(const QUrl& source, const QString& cacheDir, QJSValu
Q_INVOKABLE void cacheImage(const QUrl& source, const QString& cacheDir, QJSValue onSaved, QJSValue onFailed);
// clang-format on
Q_INVOKABLE bool copyFile(const QUrl& source, const QUrl& target, bool overwrite = true) const;
Q_INVOKABLE bool deleteFile(const QUrl& path) const;
Q_INVOKABLE QString toLocalFile(const QUrl& url) const;
Q_INVOKABLE [[nodiscard]] bool copyFile(const QUrl& source, const QUrl& target, bool overwrite = true) const;
Q_INVOKABLE [[nodiscard]] bool deleteFile(const QUrl& path) const;
Q_INVOKABLE [[nodiscard]] QString toLocalFile(const QUrl& url) const;
private:
bool loadSourceImage(const QUrl& source, QImage& image) const;
-7
View File
@@ -326,13 +326,6 @@ export const settingsIndex = [
section: "Lockscreen",
keywords: ["notification", "hide", "icon"],
},
{
name: "Laptop lid watch to lock session",
category: "lockscreen",
categoryName: "Lockscreen",
section: "Lockscreen",
keywords: ["lid", "lock", "watch", "session", "laptop"],
},
{
name: "Blur amount",
category: "lockscreen",
-14
View File
@@ -7,13 +7,11 @@
//@ pragma DropExpensiveFonts
import Quickshell
import Quickshell.Services.UPower
import QtQuick
import qs.Modules
import qs.Modules.Wallpaper
import qs.Modules.Lock
import qs.Drawers
import qs.Helpers
import qs.Config
import qs.Modules.Polkit
import qs.Daemons
@@ -35,8 +33,6 @@ ShellRoot {
Lock {
id: lock
lid: lid
}
Shortcuts {
@@ -49,16 +45,6 @@ ShellRoot {
Polkit {
}
LazyLoader {
id: lid
activeAsync: Config.lock.lidWatch && Battery.isLaptop
component: LidService {
onRequestLock: lock.lock.requestLock()
}
}
LazyLoader {
activeAsync: root.laptop