mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-04-10 06:11:54 +10:00
Some checks failed
Build / Nix (push) Has been cancelled
Build / Nix-1 (push) Has been cancelled
Build / Nix-2 (push) Has been cancelled
Build / Nix-3 (push) Has been cancelled
Build / Nix-4 (push) Has been cancelled
Build / Nix-5 (push) Has been cancelled
Build / Nix-6 (push) Has been cancelled
Build / Nix-7 (push) Has been cancelled
Build / Nix-8 (push) Has been cancelled
Build / Nix-9 (push) Has been cancelled
Build / Nix-10 (push) Has been cancelled
Build / Nix-11 (push) Has been cancelled
Build / Nix-12 (push) Has been cancelled
Build / Nix-13 (push) Has been cancelled
Build / Nix-14 (push) Has been cancelled
Build / Nix-15 (push) Has been cancelled
Build / Nix-16 (push) Has been cancelled
Build / Nix-17 (push) Has been cancelled
Build / Nix-18 (push) Has been cancelled
Build / Nix-19 (push) Has been cancelled
Build / Nix-20 (push) Has been cancelled
Build / Nix-21 (push) Has been cancelled
Build / Nix-22 (push) Has been cancelled
Build / Nix-23 (push) Has been cancelled
Build / Nix-24 (push) Has been cancelled
Build / Nix-25 (push) Has been cancelled
Build / Nix-26 (push) Has been cancelled
Build / Nix-27 (push) Has been cancelled
Build / Nix-28 (push) Has been cancelled
Build / Nix-29 (push) Has been cancelled
Build / Nix-30 (push) Has been cancelled
Build / Nix-31 (push) Has been cancelled
Build / Nix-32 (push) Has been cancelled
Build / Nix-33 (push) Has been cancelled
Build / Archlinux (push) Has been cancelled
Lint / Lint (push) Has been cancelled
133 lines
3.7 KiB
C++
133 lines
3.7 KiB
C++
#include "ipc.hpp"
|
|
#include <functional>
|
|
#include <variant>
|
|
|
|
#include <qbuffer.h>
|
|
#include <qlocalserver.h>
|
|
#include <qlocalsocket.h>
|
|
#include <qlogging.h>
|
|
#include <qloggingcategory.h>
|
|
#include <qobject.h>
|
|
|
|
#include "../core/generation.hpp"
|
|
#include "../core/logcat.hpp"
|
|
#include "../core/paths.hpp"
|
|
#include "ipccommand.hpp"
|
|
|
|
namespace qs::ipc {
|
|
|
|
QS_LOGGING_CATEGORY(logIpc, "quickshell.ipc", QtWarningMsg);
|
|
|
|
IpcServer::IpcServer(const QString& path) {
|
|
QObject::connect(&this->server, &QLocalServer::newConnection, this, &IpcServer::onNewConnection);
|
|
|
|
QLocalServer::removeServer(path);
|
|
|
|
if (!this->server.listen(path)) {
|
|
qCCritical(logIpc) << "Failed to start IPC server on path" << path;
|
|
return;
|
|
}
|
|
|
|
qCInfo(logIpc) << "Started IPC server on path" << path;
|
|
}
|
|
|
|
void IpcServer::start() {
|
|
if (auto* run = QsPaths::instance()->instanceRunDir()) {
|
|
auto path = run->filePath("ipc.sock");
|
|
new IpcServer(path);
|
|
} else {
|
|
qCCritical(
|
|
logIpc
|
|
) << "Could not start IPC server as the instance runtime path could not be created.";
|
|
}
|
|
}
|
|
|
|
void IpcServer::onNewConnection() {
|
|
while (auto* connection = this->server.nextPendingConnection()) {
|
|
new IpcServerConnection(connection, this);
|
|
}
|
|
}
|
|
|
|
IpcServerConnection::IpcServerConnection(QLocalSocket* socket, IpcServer* server)
|
|
: QObject(server)
|
|
, socket(socket) {
|
|
socket->setParent(this);
|
|
this->stream.setDevice(socket);
|
|
QObject::connect(socket, &QLocalSocket::disconnected, this, &IpcServerConnection::onDisconnected);
|
|
QObject::connect(socket, &QLocalSocket::readyRead, this, &IpcServerConnection::onReadyRead);
|
|
|
|
qCInfo(logIpc) << "New IPC connection" << this;
|
|
}
|
|
|
|
void IpcServerConnection::onDisconnected() {
|
|
qCInfo(logIpc) << "IPC connection disconnected" << this;
|
|
this->deleteLater();
|
|
}
|
|
|
|
void IpcServerConnection::onReadyRead() {
|
|
this->stream.startTransaction();
|
|
|
|
this->stream.startTransaction();
|
|
IpcCommand command;
|
|
this->stream >> command;
|
|
if (!this->stream.commitTransaction()) return;
|
|
|
|
std::visit(
|
|
[this]<typename Command>(Command& command) {
|
|
if constexpr (std::is_same_v<std::monostate, Command>) {
|
|
qCCritical(logIpc) << "Received invalid IPC command from" << this;
|
|
this->socket->disconnectFromServer();
|
|
} else {
|
|
command.exec(this);
|
|
}
|
|
},
|
|
command
|
|
);
|
|
|
|
if (!this->stream.commitTransaction()) return;
|
|
|
|
// async connections reparent
|
|
if (dynamic_cast<IpcServer*>(this->parent()) != nullptr) {
|
|
this->deleteLater();
|
|
}
|
|
}
|
|
|
|
IpcClient::IpcClient(const QString& path) {
|
|
QObject::connect(&this->socket, &QLocalSocket::connected, this, &IpcClient::connected);
|
|
QObject::connect(&this->socket, &QLocalSocket::disconnected, this, &IpcClient::disconnected);
|
|
QObject::connect(&this->socket, &QLocalSocket::errorOccurred, this, &IpcClient::onError);
|
|
|
|
this->socket.connectToServer(path);
|
|
this->stream.setDevice(&this->socket);
|
|
}
|
|
|
|
bool IpcClient::isConnected() const { return this->socket.isValid(); }
|
|
|
|
void IpcClient::waitForConnected() { this->socket.waitForConnected(); }
|
|
void IpcClient::waitForDisconnected() { this->socket.waitForDisconnected(); }
|
|
|
|
void IpcClient::kill() { this->sendMessage(IpcCommand(IpcKillCommand())); }
|
|
|
|
void IpcClient::onError(QLocalSocket::LocalSocketError error) {
|
|
qCCritical(logIpc) << "Socket Error" << error;
|
|
}
|
|
|
|
int IpcClient::connect(const QString& id, const std::function<void(IpcClient& client)>& callback) {
|
|
auto path = QsPaths::ipcPath(id);
|
|
auto client = IpcClient(path);
|
|
qCDebug(logIpc) << "Connecting to instance" << id << "at" << path;
|
|
|
|
client.waitForConnected();
|
|
if (!client.isConnected()) return -1;
|
|
qCDebug(logIpc) << "Connected.";
|
|
|
|
callback(client);
|
|
return 0;
|
|
}
|
|
|
|
void IpcKillCommand::exec(IpcServerConnection* /*unused*/) {
|
|
qInfo() << "Exiting due to IPC request.";
|
|
EngineGeneration::currentGeneration()->quit();
|
|
}
|
|
|
|
} // namespace qs::ipc
|