From 509f0c9a8a83e10a8a2a677980612fadbf4009f2 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 21 Mar 2022 18:29:41 +0100 Subject: [PATCH] IPC is now a socket --- README.md | 1 - hyprctl/main.cpp | 116 +++++++++++++++++++-------------- src/debug/HyprCtl.cpp | 79 +++++++++++++++------- src/debug/HyprCtl.hpp | 1 + src/managers/ThreadManager.cpp | 4 +- 5 files changed, 126 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index ef0f7e93..bec0e909 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ Nevertheless, REPORT any you find! Make an issue! - Fix electron rendering issues - Fix sloppy dragging of windows - Optimization - - IPC done correctly with a socket - Fix weird scroll on XWayland - Become sane - STABILITY diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 12cac2ce..41c4e27b 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -1,11 +1,17 @@ #include +#include +#include #include #include +#include +#include +#include +#include #include -#include #include -#include +#include +#include #include const std::string USAGE = R"#( @@ -16,64 +22,76 @@ usage: hyprctl [command] [(opt)args] clients )#"; -void readReply() { - std::ifstream ifs; +void request(std::string arg) { + const auto SERVERSOCKET = socket(AF_INET, SOCK_STREAM, 0); - while (1) { - usleep(1000 * 25); - - ifs.open("/tmp/hypr/.hyprlandrq"); - - if (ifs.good()) { - std::string reply = ""; - std::getline(ifs, reply); - - if (reply.find("RPLY:") != std::string::npos) { - reply = ""; - std::string temp = ""; - while (std::getline(ifs, temp)) - reply += temp + '\n'; - - std::cout << reply; - - unlink("/tmp/hypr/.hyprlandrq"); // cleanup - break; - } - } + if (SERVERSOCKET < 0) { + std::cout << "Couldn't open a socket (1)"; + return; } -} -void requestMonitors() { - std::ofstream ofs; - ofs.open("/tmp/hypr/.hyprlandrq", std::ios::trunc); + const auto SERVER = gethostbyname("localhost"); - ofs << "R>monitors"; + if (!SERVER) { + std::cout << "Couldn't get host (2)"; + return; + } - ofs.close(); + sockaddr_in serverAddress = {0}; + serverAddress.sin_family = AF_INET; + bcopy((char*)SERVER->h_addr, (char*)&serverAddress.sin_addr.s_addr, SERVER->h_length); - readReply(); -} + std::ifstream socketPortStream; + socketPortStream.open("/tmp/hypr/.socket"); + + if (!socketPortStream.good()) { + std::cout << "No socket port file (2a)"; + return; + } -void requestClients() { - std::ofstream ofs; - ofs.open("/tmp/hypr/.hyprlandrq", std::ios::trunc); + std::string port = ""; + std::getline(socketPortStream, port); + socketPortStream.close(); - ofs << "R>clients"; + int portInt = 0; + try { + portInt = std::stoi(port.c_str()); + } catch (...) { + std::cout << "Port not an int?! (2b)"; + return; + } - ofs.close(); + if (portInt == 0) { + std::cout << "Port not an int?! (2c)"; + return; + } + + serverAddress.sin_port = portInt; - readReply(); -} + if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) { + std::cout << "Couldn't connect to port " << port << " (3) Is Hyprland running?"; + return; + } -void requestWorkspaces() { - std::ofstream ofs; - ofs.open("/tmp/hypr/.hyprlandrq", std::ios::trunc); + auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length()); - ofs << "R>workspaces"; + if (sizeWritten < 0) { + std::cout << "Couldn't write (4)"; + return; + } - ofs.close(); + char buffer[8192] = {0}; - readReply(); + sizeWritten = read(SERVERSOCKET,buffer, 8192); + + if (sizeWritten < 0) { + std::cout << "Couldn't read (5)"; + return; + } + + close(SERVERSOCKET); + + std::cout << std::string(buffer); } int main(int argc, char** argv) { @@ -84,9 +102,9 @@ int main(int argc, char** argv) { return 1; } - if (!strcmp(argv[1], "monitors")) requestMonitors(); - else if (!strcmp(argv[1], "clients")) requestClients(); - else if (!strcmp(argv[1], "workspaces")) requestWorkspaces(); + if (!strcmp(argv[1], "monitors")) request("R>monitors"); + else if (!strcmp(argv[1], "clients")) request("R>clients"); + else if (!strcmp(argv[1], "workspaces")) request("R>workspaces"); else { printf(USAGE.c_str()); return 1; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 1b06617a..56319e53 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1,6 +1,12 @@ #include "HyprCtl.hpp" +#include +#include +#include +#include +#include #include +#include #include #include @@ -46,31 +52,58 @@ std::string workspacesRequest() { return result; } -void HyprCtl::tickHyprCtl() { - struct stat buf; +void HyprCtl::startHyprCtlSocket() { + int port = 9187; - if (stat("/tmp/hypr/.hyprlandrq", &buf) == 0) { - // file exists, let's open it + std::thread([&]() { + const auto SOCKET = socket(AF_INET, SOCK_STREAM, 0); - requestStream.open("/tmp/hypr/.hyprlandrq"); - - std::string request = ""; - std::getline(requestStream, request); - - requestStream.close(); - - std::string reply = ""; - if (request == "R>monitors") reply = monitorsRequest(); - if (request == "R>workspaces") reply = workspacesRequest(); - if (request == "R>clients") reply = clientsRequest(); - - if (reply != "") { - std::ofstream ofs; - ofs.open("/tmp/hypr/.hyprlandrq", std::ios::trunc); - ofs << "RPLY:\n" << reply; - ofs.close(); + if (SOCKET < 0) { + Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work."); + return; } - // the hyprctl app deletes the file when done. - } + const sockaddr_in SERVERADDRESS = {.sin_family = AF_INET, .sin_port = port, .sin_addr = (in_addr)INADDR_ANY}; + + if (bind(SOCKET, (sockaddr*)&SERVERADDRESS, sizeof(SERVERADDRESS)) < 0) { + Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work."); + return; + } + + // 10 max queued. + listen(SOCKET, 10); + + sockaddr_in clientAddress; + socklen_t clientSize = sizeof(clientAddress); + + char readBuffer[1024] = {0}; + + Debug::log(LOG, "Hypr socket started on port %i", SERVERADDRESS.sin_port); + + std::string cmd = "rm -f /tmp/hypr/.socket && echo \"" + std::to_string(SERVERADDRESS.sin_port) + "\" > /tmp/hypr/.socket"; + system(cmd.c_str()); // forgive me for using system() but it works and it doesnt matter here that much + + while(1) { + const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize); + + if (ACCEPTEDCONNECTION < 0) { + Debug::log(ERR, "Couldn't listen on the Hyprland Socket. (3) IPC will not work."); + break; + } + + auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024); + readBuffer[messageSize == 1024 ? 1024 : messageSize] = '\0'; + + std::string request(readBuffer); + + std::string reply = ""; + if (request == "R>monitors") reply = monitorsRequest(); + if (request == "R>workspaces") reply = workspacesRequest(); + if (request == "R>clients") reply = clientsRequest(); + + write(ACCEPTEDCONNECTION, reply.c_str(), reply.length()); + + close(ACCEPTEDCONNECTION); + } + }).detach(); } \ No newline at end of file diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 41303364..1a8851c7 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -4,6 +4,7 @@ #include namespace HyprCtl { + void startHyprCtlSocket(); void tickHyprCtl(); inline std::ifstream requestStream; diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp index 6ad6339b..fa3d0d4e 100644 --- a/src/managers/ThreadManager.cpp +++ b/src/managers/ThreadManager.cpp @@ -20,6 +20,8 @@ void CThreadManager::handle() { g_pConfigManager->init(); + HyprCtl::startHyprCtlSocket(); + while (3.1415f) { slowUpdate++; if (slowUpdate >= g_pConfigManager->getInt("general:max_fps")){ @@ -27,8 +29,6 @@ void CThreadManager::handle() { slowUpdate = 0; } - HyprCtl::tickHyprCtl(); - std::this_thread::sleep_for(std::chrono::microseconds(1000000 / g_pConfigManager->getInt("general:max_fps"))); } } \ No newline at end of file