mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-22 19:05:59 +01:00
internal: add lock files and hyprctl instances
This commit is contained in:
parent
ad3b8dddf9
commit
c748f36939
3 changed files with 116 additions and 2 deletions
|
@ -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"))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue