plugin: add hypr extras (#690)
* move machine * works * prevent duplicate refreshes * use instead of hyprctl proc
This commit is contained in:
parent
17509aa2d9
commit
57e3989185
10 changed files with 445 additions and 62 deletions
|
|
@ -5,7 +5,6 @@ import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
import Caelestia
|
import Caelestia
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
|
|
@ -16,13 +15,10 @@ MouseArea {
|
||||||
required property LazyLoader loader
|
required property LazyLoader loader
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
|
|
||||||
property int borderWidth
|
|
||||||
property int rounding
|
|
||||||
|
|
||||||
property bool onClient
|
property bool onClient
|
||||||
|
|
||||||
property real realBorderWidth: onClient ? borderWidth : 2
|
property real realBorderWidth: onClient ? (Hypr.options["general:border_size"] ?? 1) : 2
|
||||||
property real realRounding: onClient ? rounding : 0
|
property real realRounding: onClient ? (Hypr.options["decoration:rounding"] ?? 0) : 0
|
||||||
|
|
||||||
property real ssx
|
property real ssx
|
||||||
property real ssy
|
property real ssy
|
||||||
|
|
@ -89,6 +85,8 @@ MouseArea {
|
||||||
cursorShape: Qt.CrossCursor
|
cursorShape: Qt.CrossCursor
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
Hypr.extras.refreshOptions();
|
||||||
|
|
||||||
// Break binding if frozen
|
// Break binding if frozen
|
||||||
if (loader.freeze)
|
if (loader.freeze)
|
||||||
clients = clients;
|
clients = clients;
|
||||||
|
|
@ -186,22 +184,6 @@ MouseArea {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
running: true
|
|
||||||
command: ["hyprctl", "-j", "getoption", "general:border_size"]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: root.borderWidth = JSON.parse(text).int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
running: true
|
|
||||||
command: ["hyprctl", "-j", "getoption", "decoration:rounding"]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: root.rounding = JSON.parse(text).int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: screencopy
|
id: screencopy
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,6 @@ ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Switch layout")
|
text: qsTr("Switch layout")
|
||||||
onClicked: Quickshell.execDetached(["hyprctl", "switchxkblayout", "all", "next"])
|
onClicked: Hypr.message("switchxkblayout all next")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core Qml Gui Quick Concurrent Sql)
|
find_package(Qt6 REQUIRED COMPONENTS Core Qml Gui Quick Concurrent Sql Network)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(Qalculate IMPORTED_TARGET libqalculate REQUIRED)
|
pkg_check_modules(Qalculate IMPORTED_TARGET libqalculate REQUIRED)
|
||||||
pkg_check_modules(Pipewire IMPORTED_TARGET libpipewire-0.3 REQUIRED)
|
pkg_check_modules(Pipewire IMPORTED_TARGET libpipewire-0.3 REQUIRED)
|
||||||
|
|
@ -49,6 +49,7 @@ qml_module(caelestia
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
|
Qt::Concurrent
|
||||||
Qt::Sql
|
Qt::Sql
|
||||||
PkgConfig::Qalculate
|
PkgConfig::Qalculate
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@ qml_module(caelestia-internal
|
||||||
SOURCES
|
SOURCES
|
||||||
cachingimagemanager.hpp cachingimagemanager.cpp
|
cachingimagemanager.hpp cachingimagemanager.cpp
|
||||||
circularindicatormanager.hpp circularindicatormanager.cpp
|
circularindicatormanager.hpp circularindicatormanager.cpp
|
||||||
|
hyprdevices.hpp hyprdevices.cpp
|
||||||
|
hyprextras.hpp hyprextras.cpp
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
Qt::Concurrent
|
Qt::Concurrent
|
||||||
|
Qt::Network
|
||||||
)
|
)
|
||||||
|
|
|
||||||
129
plugin/src/Caelestia/Internal/hyprdevices.cpp
Normal file
129
plugin/src/Caelestia/Internal/hyprdevices.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
#include "hyprdevices.hpp"
|
||||||
|
|
||||||
|
#include <qjsonarray.h>
|
||||||
|
|
||||||
|
namespace caelestia::internal::hypr {
|
||||||
|
|
||||||
|
HyprKeyboard::HyprKeyboard(QJsonObject ipcObject, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_lastIpcObject(ipcObject) {}
|
||||||
|
|
||||||
|
QVariantHash HyprKeyboard::lastIpcObject() const {
|
||||||
|
return m_lastIpcObject.toVariantHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HyprKeyboard::address() const {
|
||||||
|
return m_lastIpcObject.value("address").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HyprKeyboard::name() const {
|
||||||
|
return m_lastIpcObject.value("name").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HyprKeyboard::layout() const {
|
||||||
|
return m_lastIpcObject.value("layout").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HyprKeyboard::activeKeymap() const {
|
||||||
|
return m_lastIpcObject.value("active_keymap").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HyprKeyboard::capsLock() const {
|
||||||
|
return m_lastIpcObject.value("capsLock").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HyprKeyboard::numLock() const {
|
||||||
|
return m_lastIpcObject.value("numLock").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HyprKeyboard::main() const {
|
||||||
|
return m_lastIpcObject.value("main").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HyprKeyboard::updateLastIpcObject(const QJsonObject& object) {
|
||||||
|
if (m_lastIpcObject == object) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto last = m_lastIpcObject;
|
||||||
|
|
||||||
|
m_lastIpcObject = object;
|
||||||
|
emit lastIpcObjectChanged();
|
||||||
|
|
||||||
|
bool dirty = false;
|
||||||
|
if (last.value("address") != object.value("address")) {
|
||||||
|
dirty = true;
|
||||||
|
emit addressChanged();
|
||||||
|
}
|
||||||
|
if (last.value("name") != object.value("name")) {
|
||||||
|
dirty = true;
|
||||||
|
emit nameChanged();
|
||||||
|
}
|
||||||
|
if (last.value("layout") != object.value("layout")) {
|
||||||
|
dirty = true;
|
||||||
|
emit layoutChanged();
|
||||||
|
}
|
||||||
|
if (last.value("active_keymap") != object.value("active_keymap")) {
|
||||||
|
dirty = true;
|
||||||
|
emit activeKeymapChanged();
|
||||||
|
}
|
||||||
|
if (last.value("capsLock") != object.value("capsLock")) {
|
||||||
|
dirty = true;
|
||||||
|
emit capsLockChanged();
|
||||||
|
}
|
||||||
|
if (last.value("numLock") != object.value("numLock")) {
|
||||||
|
dirty = true;
|
||||||
|
emit numLockChanged();
|
||||||
|
}
|
||||||
|
if (last.value("main") != object.value("main")) {
|
||||||
|
dirty = true;
|
||||||
|
emit mainChanged();
|
||||||
|
}
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprDevices::HyprDevices(QObject* parent)
|
||||||
|
: QObject(parent) {}
|
||||||
|
|
||||||
|
QList<HyprKeyboard*> HyprDevices::keyboards() const {
|
||||||
|
return m_keyboards;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HyprDevices::updateLastIpcObject(const QJsonObject& object) {
|
||||||
|
const auto val = object.value("keyboards").toArray();
|
||||||
|
bool dirty = false;
|
||||||
|
|
||||||
|
for (const auto& keyboard : std::as_const(m_keyboards)) {
|
||||||
|
if (std::find_if(val.begin(), val.end(), [keyboard](const QJsonValue& object) {
|
||||||
|
return object.toObject().value("address").toString() == keyboard->address();
|
||||||
|
}) == val.end()) {
|
||||||
|
dirty = true;
|
||||||
|
m_keyboards.removeAll(keyboard);
|
||||||
|
keyboard->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& o : val) {
|
||||||
|
const auto obj = o.toObject();
|
||||||
|
const auto addr = obj.value("address").toString();
|
||||||
|
|
||||||
|
auto it = std::find_if(m_keyboards.begin(), m_keyboards.end(), [addr](const HyprKeyboard* keyboard) {
|
||||||
|
return keyboard->address() == addr;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != m_keyboards.end()) {
|
||||||
|
dirty |= (*it)->updateLastIpcObject(obj);
|
||||||
|
} else {
|
||||||
|
dirty = true;
|
||||||
|
m_keyboards << new HyprKeyboard(obj, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty) {
|
||||||
|
emit keyboardsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace caelestia::internal::hypr
|
||||||
72
plugin/src/Caelestia/Internal/hyprdevices.hpp
Normal file
72
plugin/src/Caelestia/Internal/hyprdevices.hpp
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qjsonobject.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
|
||||||
|
namespace caelestia::internal::hypr {
|
||||||
|
|
||||||
|
class HyprKeyboard : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
QML_UNCREATABLE("HyprKeyboard instances can only be retrieved from a HyprDevices")
|
||||||
|
|
||||||
|
Q_PROPERTY(QVariantHash lastIpcObject READ lastIpcObject NOTIFY lastIpcObjectChanged)
|
||||||
|
Q_PROPERTY(QString address READ address NOTIFY addressChanged)
|
||||||
|
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||||
|
Q_PROPERTY(QString layout READ layout NOTIFY layoutChanged)
|
||||||
|
Q_PROPERTY(QString activeKeymap READ activeKeymap NOTIFY activeKeymapChanged)
|
||||||
|
Q_PROPERTY(bool capsLock READ capsLock NOTIFY capsLockChanged)
|
||||||
|
Q_PROPERTY(bool numLock READ numLock NOTIFY numLockChanged)
|
||||||
|
Q_PROPERTY(bool main READ main NOTIFY mainChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit HyprKeyboard(QJsonObject ipcObject, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] QVariantHash lastIpcObject() const;
|
||||||
|
[[nodiscard]] QString address() const;
|
||||||
|
[[nodiscard]] QString name() const;
|
||||||
|
[[nodiscard]] QString layout() const;
|
||||||
|
[[nodiscard]] QString activeKeymap() const;
|
||||||
|
[[nodiscard]] bool capsLock() const;
|
||||||
|
[[nodiscard]] bool numLock() const;
|
||||||
|
[[nodiscard]] bool main() const;
|
||||||
|
|
||||||
|
bool updateLastIpcObject(const QJsonObject& object);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void lastIpcObjectChanged();
|
||||||
|
void addressChanged();
|
||||||
|
void nameChanged();
|
||||||
|
void layoutChanged();
|
||||||
|
void activeKeymapChanged();
|
||||||
|
void capsLockChanged();
|
||||||
|
void numLockChanged();
|
||||||
|
void mainChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QJsonObject m_lastIpcObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HyprDevices : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
QML_UNCREATABLE("HyprDevices instances can only be retrieved from a HyprExtras")
|
||||||
|
|
||||||
|
Q_PROPERTY(QList<HyprKeyboard*> keyboards READ keyboards NOTIFY keyboardsChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit HyprDevices(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] QList<HyprKeyboard*> keyboards() const;
|
||||||
|
|
||||||
|
bool updateLastIpcObject(const QJsonObject& object);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void keyboardsChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<HyprKeyboard*> m_keyboards;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace caelestia::internal::hypr
|
||||||
158
plugin/src/Caelestia/Internal/hyprextras.cpp
Normal file
158
plugin/src/Caelestia/Internal/hyprextras.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
#include "hyprextras.hpp"
|
||||||
|
|
||||||
|
#include <qdir.h>
|
||||||
|
#include <qjsonarray.h>
|
||||||
|
#include <qlocalsocket.h>
|
||||||
|
#include <qvariant.h>
|
||||||
|
|
||||||
|
namespace caelestia::internal::hypr {
|
||||||
|
|
||||||
|
HyprExtras::HyprExtras(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_requestSocket("")
|
||||||
|
, m_eventSocket("")
|
||||||
|
, m_socket(nullptr)
|
||||||
|
, m_devices(new HyprDevices(this)) {
|
||||||
|
const auto his = qEnvironmentVariable("HYPRLAND_INSTANCE_SIGNATURE");
|
||||||
|
if (his.isEmpty()) {
|
||||||
|
qWarning()
|
||||||
|
<< "HyprExtras::HyprExtras: $HYPRLAND_INSTANCE_SIGNATURE is unset. Unable to connect to Hyprland socket.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hyprDir = QString("%1/hypr/%2").arg(qEnvironmentVariable("XDG_RUNTIME_DIR"), his);
|
||||||
|
if (!QDir(hyprDir).exists()) {
|
||||||
|
hyprDir = "/tmp/hypr/" + his;
|
||||||
|
|
||||||
|
if (!QDir(hyprDir).exists()) {
|
||||||
|
qWarning() << "HyprExtras::HyprExtras: Hyprland socket directory does not exist. Unable to connect to "
|
||||||
|
"Hyprland socket.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_requestSocket = hyprDir + "/.socket.sock";
|
||||||
|
m_eventSocket = hyprDir + "/.event.sock";
|
||||||
|
|
||||||
|
refreshOptions();
|
||||||
|
refreshDevices();
|
||||||
|
|
||||||
|
m_socket = new QLocalSocket(this);
|
||||||
|
QObject::connect(m_socket, &QLocalSocket::readyRead, this, &HyprExtras::readEvent);
|
||||||
|
m_socket->connectToServer(m_eventSocket);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantHash HyprExtras::options() const {
|
||||||
|
return m_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprDevices* HyprExtras::devices() const {
|
||||||
|
return m_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HyprExtras::message(const QString& message) {
|
||||||
|
makeRequest(message, [](bool, const QByteArray&) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void HyprExtras::refreshOptions() {
|
||||||
|
if (!m_optionsRefresh.isNull()) {
|
||||||
|
m_optionsRefresh->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_optionsRefresh = makeRequestJson("descriptions", [this](bool success, const QJsonDocument& response) {
|
||||||
|
m_optionsRefresh.reset();
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto options = response.array();
|
||||||
|
bool dirty = false;
|
||||||
|
|
||||||
|
for (const auto& o : std::as_const(options)) {
|
||||||
|
const auto obj = o.toObject();
|
||||||
|
const auto key = obj.value("value").toString();
|
||||||
|
const auto value = obj.value("data").toObject().value("current").toVariant();
|
||||||
|
if (m_options.value(key) != value) {
|
||||||
|
dirty = true;
|
||||||
|
m_options.insert(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty) {
|
||||||
|
emit optionsChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void HyprExtras::refreshDevices() {
|
||||||
|
if (!m_devicesRefresh.isNull()) {
|
||||||
|
m_devicesRefresh->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_devicesRefresh = makeRequestJson("devices", [this](bool success, const QJsonDocument& response) {
|
||||||
|
m_devicesRefresh.reset();
|
||||||
|
if (success) {
|
||||||
|
m_devices->updateLastIpcObject(response.object());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void HyprExtras::readEvent() {
|
||||||
|
while (true) {
|
||||||
|
auto rawEvent = m_socket->readLine();
|
||||||
|
if (rawEvent.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rawEvent.truncate(rawEvent.length() - 1); // Remove trailing \n
|
||||||
|
const auto event = QByteArrayView(rawEvent.data(), rawEvent.indexOf(">>"));
|
||||||
|
handleEvent(QString::fromUtf8(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HyprExtras::handleEvent(const QString& event) {
|
||||||
|
if (event == "configreloaded") {
|
||||||
|
refreshOptions();
|
||||||
|
} else if (event == "activelayout") {
|
||||||
|
refreshDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprExtras::SocketPtr HyprExtras::makeRequestJson(
|
||||||
|
const QString& request, const std::function<void(bool, QJsonDocument)>& callback) {
|
||||||
|
return makeRequest("j/" + request, [callback](bool success, const QByteArray& response) {
|
||||||
|
callback(success, QJsonDocument::fromJson(response));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprExtras::SocketPtr HyprExtras::makeRequest(
|
||||||
|
const QString& request, const std::function<void(bool, QByteArray)>& callback) {
|
||||||
|
if (m_requestSocket.isEmpty()) {
|
||||||
|
return SocketPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto socket = SocketPtr::create(this);
|
||||||
|
|
||||||
|
QObject::connect(socket.data(), &QLocalSocket::connected, this, [=, this]() {
|
||||||
|
QObject::connect(socket.data(), &QLocalSocket::readyRead, this, [socket, callback]() {
|
||||||
|
const auto response = socket->readAll();
|
||||||
|
callback(true, std::move(response));
|
||||||
|
socket->close();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket->write(request.toUtf8());
|
||||||
|
socket->flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
QObject::connect(socket.data(), &QLocalSocket::errorOccurred, this, [=](QLocalSocket::LocalSocketError err) {
|
||||||
|
qWarning() << "HyprExtras::makeRequest: error making request:" << err << "| request:" << request;
|
||||||
|
callback(false, {});
|
||||||
|
socket->close();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket->connectToServer(m_requestSocket);
|
||||||
|
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace caelestia::internal::hypr
|
||||||
51
plugin/src/Caelestia/Internal/hyprextras.hpp
Normal file
51
plugin/src/Caelestia/Internal/hyprextras.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hyprdevices.hpp"
|
||||||
|
#include <qlocalsocket.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
|
||||||
|
namespace caelestia::internal::hypr {
|
||||||
|
|
||||||
|
class HyprExtras : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
Q_PROPERTY(QVariantHash options READ options NOTIFY optionsChanged)
|
||||||
|
Q_PROPERTY(HyprDevices* devices READ devices CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit HyprExtras(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] QVariantHash options() const;
|
||||||
|
[[nodiscard]] HyprDevices* devices() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void message(const QString& message);
|
||||||
|
|
||||||
|
Q_INVOKABLE void refreshOptions();
|
||||||
|
Q_INVOKABLE void refreshDevices();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void optionsChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
using SocketPtr = QSharedPointer<QLocalSocket>;
|
||||||
|
|
||||||
|
QString m_requestSocket;
|
||||||
|
QString m_eventSocket;
|
||||||
|
QLocalSocket* m_socket;
|
||||||
|
|
||||||
|
QVariantHash m_options;
|
||||||
|
HyprDevices* const m_devices;
|
||||||
|
|
||||||
|
SocketPtr m_optionsRefresh;
|
||||||
|
SocketPtr m_devicesRefresh;
|
||||||
|
|
||||||
|
void readEvent();
|
||||||
|
void handleEvent(const QString& event);
|
||||||
|
|
||||||
|
SocketPtr makeRequestJson(const QString& request, const std::function<void(bool, QJsonDocument)>& callback);
|
||||||
|
SocketPtr makeRequest(const QString& request, const std::function<void(bool, QByteArray)>& callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace caelestia::internal::hypr
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
import Caelestia
|
import Caelestia
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
|
@ -12,7 +13,7 @@ Singleton {
|
||||||
property alias enabled: props.enabled
|
property alias enabled: props.enabled
|
||||||
|
|
||||||
function setDynamicConfs(): void {
|
function setDynamicConfs(): void {
|
||||||
Quickshell.execDetached(["hyprctl", "--batch", "keyword animations:enabled 0;keyword decoration:shadow:enabled 0;keyword decoration:blur:enabled 0;keyword general:gaps_in 0;keyword general:gaps_out 0;keyword general:border_size 1;keyword decoration:rounding 0;keyword general:allow_tearing 1"]);
|
Hypr.message("[[BATCH]]keyword animations:enabled 0;keyword decoration:shadow:enabled 0;keyword decoration:blur:enabled 0;keyword general:gaps_in 0;keyword general:gaps_out 0;keyword general:border_size 1;keyword decoration:rounding 0;keyword general:allow_tearing 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnabledChanged: {
|
onEnabledChanged: {
|
||||||
|
|
@ -21,7 +22,7 @@ Singleton {
|
||||||
if (Config.utilities.toasts.gameModeChanged)
|
if (Config.utilities.toasts.gameModeChanged)
|
||||||
Toaster.toast(qsTr("Game mode enabled"), qsTr("Disabled Hyprland animations, blur, gaps and shadows"), "gamepad");
|
Toaster.toast(qsTr("Game mode enabled"), qsTr("Disabled Hyprland animations, blur, gaps and shadows"), "gamepad");
|
||||||
} else {
|
} else {
|
||||||
Quickshell.execDetached(["hyprctl", "reload"]);
|
Hypr.message("reload");
|
||||||
if (Config.utilities.toasts.gameModeChanged)
|
if (Config.utilities.toasts.gameModeChanged)
|
||||||
Toaster.toast(qsTr("Game mode disabled"), qsTr("Hyprland settings restored"), "gamepad");
|
Toaster.toast(qsTr("Game mode disabled"), qsTr("Hyprland settings restored"), "gamepad");
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +31,7 @@ Singleton {
|
||||||
PersistentProperties {
|
PersistentProperties {
|
||||||
id: props
|
id: props
|
||||||
|
|
||||||
property bool enabled
|
property bool enabled: Hypr.options["animations:enabled"] === 0
|
||||||
|
|
||||||
reloadableId: "gameMode"
|
reloadableId: "gameMode"
|
||||||
}
|
}
|
||||||
|
|
@ -44,14 +45,6 @@ Singleton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
running: true
|
|
||||||
command: ["hyprctl", "getoption", "animations:enabled", "-j"]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: props.enabled = JSON.parse(text).int === 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
target: "gameMode"
|
target: "gameMode"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ pragma Singleton
|
||||||
import qs.components.misc
|
import qs.components.misc
|
||||||
import qs.config
|
import qs.config
|
||||||
import Caelestia
|
import Caelestia
|
||||||
|
import Caelestia.Internal
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
|
@ -20,16 +21,24 @@ Singleton {
|
||||||
readonly property HyprlandMonitor focusedMonitor: Hyprland.focusedMonitor
|
readonly property HyprlandMonitor focusedMonitor: Hyprland.focusedMonitor
|
||||||
readonly property int activeWsId: focusedWorkspace?.id ?? 1
|
readonly property int activeWsId: focusedWorkspace?.id ?? 1
|
||||||
|
|
||||||
property var keyboard
|
readonly property HyprKeyboard keyboard: extras.devices.keyboards.find(kb => kb.main) ?? null
|
||||||
readonly property bool capsLock: keyboard?.capsLock ?? false
|
readonly property bool capsLock: keyboard?.capsLock ?? false
|
||||||
readonly property bool numLock: keyboard?.numLock ?? false
|
readonly property bool numLock: keyboard?.numLock ?? false
|
||||||
readonly property string defaultKbLayout: keyboard?.layout.split(",")[0] ?? "??"
|
readonly property string defaultKbLayout: keyboard?.layout.split(",")[0] ?? "??"
|
||||||
readonly property string kbLayoutFull: keyboard?.active_keymap ?? "Unknown"
|
readonly property string kbLayoutFull: keyboard?.activeKeymap ?? "Unknown"
|
||||||
readonly property string kbLayout: kbMap.get(kbLayoutFull) ?? "??"
|
readonly property string kbLayout: kbMap.get(kbLayoutFull) ?? "??"
|
||||||
readonly property var kbMap: new Map()
|
readonly property var kbMap: new Map()
|
||||||
|
|
||||||
|
readonly property alias extras: extras
|
||||||
|
readonly property alias options: extras.options
|
||||||
|
readonly property alias devices: extras.devices
|
||||||
|
|
||||||
signal configReloaded
|
signal configReloaded
|
||||||
|
|
||||||
|
function message(message: string): void {
|
||||||
|
extras.message(message);
|
||||||
|
}
|
||||||
|
|
||||||
function dispatch(request: string): void {
|
function dispatch(request: string): void {
|
||||||
Hyprland.dispatch(request);
|
Hyprland.dispatch(request);
|
||||||
}
|
}
|
||||||
|
|
@ -68,9 +77,7 @@ Singleton {
|
||||||
|
|
||||||
if (n === "configreloaded") {
|
if (n === "configreloaded") {
|
||||||
root.configReloaded();
|
root.configReloaded();
|
||||||
setDynamicConfsProc.running = true;
|
extras.message("[[BATCH]]keyword bindln ,Caps_Lock,global,caelestia:refreshDevices;keyword bindln ,Num_Lock,global,caelestia:refreshDevices");
|
||||||
} else if (n === "activelayout") {
|
|
||||||
devicesProc.running = true;
|
|
||||||
} else if (["workspace", "moveworkspace", "activespecial", "focusedmon"].includes(n)) {
|
} else if (["workspace", "moveworkspace", "activespecial", "focusedmon"].includes(n)) {
|
||||||
Hyprland.refreshWorkspaces();
|
Hyprland.refreshWorkspaces();
|
||||||
Hyprland.refreshMonitors();
|
Hyprland.refreshMonitors();
|
||||||
|
|
@ -104,35 +111,22 @@ Singleton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
id: devicesProc
|
|
||||||
|
|
||||||
running: true
|
|
||||||
command: ["hyprctl", "-j", "devices"]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: root.keyboard = JSON.parse(text).keyboards.find(k => k.main)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: setDynamicConfsProc
|
|
||||||
|
|
||||||
running: true
|
|
||||||
command: ["hyprctl", "--batch", "keyword bindln ,Caps_Lock,global,caelestia:reloadDevices;keyword bindln ,Num_Lock,global,caelestia:reloadDevices"]
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
target: "hypr"
|
target: "hypr"
|
||||||
|
|
||||||
function reloadDevices(): void {
|
function refreshDevices(): void {
|
||||||
devicesProc.running = true;
|
extras.refreshDevices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomShortcut {
|
CustomShortcut {
|
||||||
name: "reloadDevices"
|
name: "refreshDevices"
|
||||||
description: "Reload devices"
|
description: "Reload devices"
|
||||||
onPressed: devicesProc.running = true
|
onPressed: extras.refreshDevices()
|
||||||
onReleased: devicesProc.running = true
|
onReleased: extras.refreshDevices()
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprExtras {
|
||||||
|
id: extras
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue