aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorvaxerski <[email protected]>2023-08-08 16:16:34 +0200
committervaxerski <[email protected]>2023-08-08 16:16:40 +0200
commitc748f36939cdac74332dde3afb866ad35bea1825 (patch)
tree1ef2c1593bdfd8a42520e0b891aac9c9fade3b16
parentad3b8dddf993736fe2d716e4cdc5c079e511da2e (diff)
downloadHyprland-c748f36939cdac74332dde3afb866ad35bea1825.tar.gz
Hyprland-c748f36939cdac74332dde3afb866ad35bea1825.zip
internal: add lock files and hyprctl instances
-rw-r--r--hyprctl/main.cpp92
-rw-r--r--src/Compositor.cpp21
-rw-r--r--src/Compositor.hpp5
3 files changed, 116 insertions, 2 deletions
diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp
index 31efcd16..76d26e23 100644
--- a/hyprctl/main.cpp
+++ b/hyprctl/main.cpp
@@ -11,12 +11,16 @@
#include <unistd.h>
#include <ranges>
#include <algorithm>
+#include <signal.h>
#include <iostream>
#include <string>
#include <fstream>
#include <string>
+#include <vector>
#include <deque>
+#include <filesystem>
+#include <stdarg.h>
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
@@ -45,6 +49,7 @@ commands:
plugin
notify
globalshortcuts
+ instances
flags:
-j -> output in JSON
@@ -53,6 +58,20 @@ flags:
#define PAD
+std::string getFormat(const char* fmt, ...) {
+ char* outputStr = nullptr;
+
+ va_list args;
+ va_start(args, fmt);
+ vasprintf(&outputStr, fmt, args);
+ va_end(args);
+
+ std::string output = std::string(outputStr);
+ free(outputStr);
+
+ return output;
+}
+
void request(std::string arg, int minArgs = 0) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -260,6 +279,75 @@ void batchRequest(std::string arg) {
request(rq);
}
+void instancesRequest(bool json) {
+ std::string result = "";
+
+ struct SInstanceData {
+ std::string id;
+ uint64_t time;
+ uint64_t pid;
+ std::string wlSocket;
+ bool valid = true;
+ };
+
+ // gather instance data
+ std::vector<SInstanceData> instances;
+
+ for (const auto& el : std::filesystem::directory_iterator("/tmp/hypr")) {
+ if (el.is_directory())
+ continue;
+
+ // read lock
+ SInstanceData* data = &instances.emplace_back();
+ data->id = el.path().string();
+ data->id = data->id.substr(data->id.find_last_of('/') + 1, data->id.find(".lock") - data->id.find_last_of('/') - 1);
+
+ data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
+
+ // read file
+ std::ifstream ifs(el.path().string());
+
+ int i = 0;
+ for (std::string line; std::getline(ifs, line); ++i) {
+ if (i == 0) {
+ data->pid = std::stoull(line);
+ } else if (i == 1) {
+ data->wlSocket = line;
+ } else
+ break;
+ }
+
+ ifs.close();
+ }
+
+ std::erase_if(instances, [&](const auto& el) { return kill(el.pid, 0) != 0 && errno == ESRCH; });
+
+ std::sort(instances.begin(), instances.end(), [&](const auto& a, const auto& b) { return a.time < b.time; });
+
+ if (!json) {
+ for (auto& el : instances) {
+ result += getFormat("instance %s:\n\ttime: %llu\n\tpid: %llu\n\twl socket: %s\n\n", el.id.c_str(), el.time, el.pid, el.wlSocket.c_str());
+ }
+ } else {
+ result += '[';
+ for (auto& el : instances) {
+ result += getFormat(R"#(
+{
+ "instance": "%s",
+ "time": %llu,
+ "pid": %llu,
+ "wl_socket": "%s"
+},)#",
+ el.id.c_str(), el.time, el.pid, el.wlSocket.c_str());
+ }
+
+ result.pop_back();
+ result += "\n]";
+ }
+
+ std::cout << result << "\n";
+}
+
std::deque<std::string> splitArgs(int argc, char** argv) {
std::deque<std::string> result;
@@ -287,6 +375,7 @@ int main(int argc, char** argv) {
std::string fullRequest = "";
std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv);
+ bool json = false;
for (auto i = 0; i < ARGS.size(); ++i) {
if (ARGS[i] == "--") {
@@ -298,6 +387,7 @@ int main(int argc, char** argv) {
// parse
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
fullArgs += "j";
+ json = true;
} else if (ARGS[i] == "--batch") {
fullRequest = "--batch ";
} else {
@@ -356,6 +446,8 @@ int main(int argc, char** argv) {
request(fullRequest);
else if (fullRequest.contains("/globalshortcuts"))
request(fullRequest);
+ else if (fullRequest.contains("/instances"))
+ instancesRequest(json);
else if (fullRequest.contains("/switchxkblayout"))
request(fullRequest, 2);
else if (fullRequest.contains("/seterror"))
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index d1124bc1..ec70bb68 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -312,6 +312,8 @@ void CCompositor::cleanup() {
if (!m_sWLDisplay || m_bIsShuttingDown)
return;
+ removeLockFile();
+
m_bIsShuttingDown = true;
#ifdef USES_SYSTEMD
@@ -416,6 +418,23 @@ void CCompositor::initManagers(eManagersInitStage stage) {
}
}
+void CCompositor::createLockFile() {
+ const auto PATH = "/tmp/hypr/" + m_szInstanceSignature + ".lock";
+
+ std::ofstream ofs(PATH, std::ios::trunc);
+
+ ofs << m_iHyprlandPID << "\n" << m_szWLDisplaySocket << "\n";
+
+ ofs.close();
+}
+
+void CCompositor::removeLockFile() {
+ const auto PATH = "/tmp/hypr/" + m_szInstanceSignature + ".lock";
+
+ if (std::filesystem::exists(PATH))
+ std::filesystem::remove(PATH);
+}
+
void CCompositor::startCompositor() {
initAllSignals();
@@ -477,6 +496,8 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!");
#endif
+ createLockFile();
+
// This blocks until we are done.
Debug::log(LOG, "Hyprland is ready, running the event loop!");
wl_display_run(m_sWLDisplay);
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 1be02e62..971b0fa2 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -28,8 +28,7 @@
#include "hyprerror/HyprError.hpp"
#include "plugins/PluginSystem.hpp"
-enum eManagersInitStage
-{
+enum eManagersInitStage {
STAGE_PRIORITY = 0,
STAGE_LATE
};
@@ -107,6 +106,8 @@ class CCompositor {
void initServer();
void startCompositor();
void cleanup();
+ void createLockFile();
+ void removeLockFile();
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;