internal: add lock files and hyprctl instances

This commit is contained in:
Vaxry 2023-08-08 16:16:34 +02:00
parent ad3b8dddf9
commit c748f36939
3 changed files with 116 additions and 2 deletions

View file

@ -11,12 +11,16 @@
#include <unistd.h> #include <unistd.h>
#include <ranges> #include <ranges>
#include <algorithm> #include <algorithm>
#include <signal.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <vector>
#include <deque> #include <deque>
#include <filesystem>
#include <stdarg.h>
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args] const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
@ -45,6 +49,7 @@ commands:
plugin plugin
notify notify
globalshortcuts globalshortcuts
instances
flags: flags:
-j -> output in JSON -j -> output in JSON
@ -53,6 +58,20 @@ flags:
#define PAD #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) { void request(std::string arg, int minArgs = 0) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0); const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@ -260,6 +279,75 @@ void batchRequest(std::string arg) {
request(rq); 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> splitArgs(int argc, char** argv) {
std::deque<std::string> result; std::deque<std::string> result;
@ -287,6 +375,7 @@ int main(int argc, char** argv) {
std::string fullRequest = ""; std::string fullRequest = "";
std::string fullArgs = ""; std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv); const auto ARGS = splitArgs(argc, argv);
bool json = false;
for (auto i = 0; i < ARGS.size(); ++i) { for (auto i = 0; i < ARGS.size(); ++i) {
if (ARGS[i] == "--") { if (ARGS[i] == "--") {
@ -298,6 +387,7 @@ int main(int argc, char** argv) {
// parse // parse
if (ARGS[i] == "-j" && !fullArgs.contains("j")) { if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
fullArgs += "j"; fullArgs += "j";
json = true;
} else if (ARGS[i] == "--batch") { } else if (ARGS[i] == "--batch") {
fullRequest = "--batch "; fullRequest = "--batch ";
} else { } else {
@ -356,6 +446,8 @@ int main(int argc, char** argv) {
request(fullRequest); request(fullRequest);
else if (fullRequest.contains("/globalshortcuts")) else if (fullRequest.contains("/globalshortcuts"))
request(fullRequest); request(fullRequest);
else if (fullRequest.contains("/instances"))
instancesRequest(json);
else if (fullRequest.contains("/switchxkblayout")) else if (fullRequest.contains("/switchxkblayout"))
request(fullRequest, 2); request(fullRequest, 2);
else if (fullRequest.contains("/seterror")) else if (fullRequest.contains("/seterror"))

View file

@ -312,6 +312,8 @@ void CCompositor::cleanup() {
if (!m_sWLDisplay || m_bIsShuttingDown) if (!m_sWLDisplay || m_bIsShuttingDown)
return; return;
removeLockFile();
m_bIsShuttingDown = true; m_bIsShuttingDown = true;
#ifdef USES_SYSTEMD #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() { void CCompositor::startCompositor() {
initAllSignals(); initAllSignals();
@ -477,6 +496,8 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!"); Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!");
#endif #endif
createLockFile();
// This blocks until we are done. // This blocks until we are done.
Debug::log(LOG, "Hyprland is ready, running the event loop!"); Debug::log(LOG, "Hyprland is ready, running the event loop!");
wl_display_run(m_sWLDisplay); wl_display_run(m_sWLDisplay);

View file

@ -28,8 +28,7 @@
#include "hyprerror/HyprError.hpp" #include "hyprerror/HyprError.hpp"
#include "plugins/PluginSystem.hpp" #include "plugins/PluginSystem.hpp"
enum eManagersInitStage enum eManagersInitStage {
{
STAGE_PRIORITY = 0, STAGE_PRIORITY = 0,
STAGE_LATE STAGE_LATE
}; };
@ -107,6 +106,8 @@ class CCompositor {
void initServer(); void initServer();
void startCompositor(); void startCompositor();
void cleanup(); void cleanup();
void createLockFile();
void removeLockFile();
wlr_surface* m_pLastFocus = nullptr; wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr; CWindow* m_pLastWindow = nullptr;