From 29d98e7d7676d5331c11b983b58324c4bf622e8f Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 31 Jan 2025 17:58:18 -0800 Subject: [PATCH 1/3] Revert "core: Add InstanceLock to make sure that only one hyprsunset is running. (#14)" This reverts commit 7a2f65dfe929f267f253198b7ea81729b87439d2. --- CMakeLists.txt | 2 +- src/IPCSemaphore.cpp | 32 -------- src/IPCSemaphore.hpp | 26 ------- src/InstanceLock.cpp | 138 ---------------------------------- src/InstanceLock.hpp | 45 ----------- src/helpers/GetRuntimeDir.cpp | 47 ------------ src/helpers/GetRuntimeDir.hpp | 5 -- src/helpers/Log.hpp | 5 +- src/main.cpp | 9 --- 9 files changed, 2 insertions(+), 307 deletions(-) delete mode 100644 src/IPCSemaphore.cpp delete mode 100644 src/IPCSemaphore.hpp delete mode 100644 src/InstanceLock.cpp delete mode 100644 src/InstanceLock.hpp delete mode 100644 src/helpers/GetRuntimeDir.cpp delete mode 100644 src/helpers/GetRuntimeDir.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bd498ed..2b0d37f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ execute_process( # include_directories(.) -set(CMAKE_CXX_STANDARD 26) +set(CMAKE_CXX_STANDARD 23) add_compile_options( -Wall -Wextra diff --git a/src/IPCSemaphore.cpp b/src/IPCSemaphore.cpp deleted file mode 100644 index 1e69f94..0000000 --- a/src/IPCSemaphore.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include "helpers/Log.hpp" -#include "IPCSemaphore.hpp" - -CIPCSemaphore::CIPCSemaphore(const char* semName) : pSemaphore(sem_open(semName, O_CREAT, 0666)) { - if (pSemaphore == SEM_FAILED) { - Debug::log(ERR, "✖ Failed to open semaphore"); - pSemaphore = nullptr; - } -} - -CIPCSemaphore::~CIPCSemaphore() noexcept { - sem_close(pSemaphore); -} - -CIPCSemaphore::Lock CIPCSemaphore::getLock() noexcept { - return Lock{pSemaphore}; -} - -CIPCSemaphore::Lock::Lock(sem_t* semaphore) : pSemaphore(semaphore) { - if (!semaphore) { - Debug::log(ERR, "✖ Lock failed null semaphore"); - return; - } - sem_wait(semaphore); -} - -CIPCSemaphore::Lock::~Lock() noexcept { - if (pSemaphore) - sem_post(pSemaphore); -} diff --git a/src/IPCSemaphore.hpp b/src/IPCSemaphore.hpp deleted file mode 100644 index 3c19da1..0000000 --- a/src/IPCSemaphore.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -class CIPCSemaphore { - public: - class Lock { - public: - explicit Lock(sem_t* semaphore); - ~Lock() noexcept; - - private: - sem_t* pSemaphore = nullptr; - }; - - public: - CIPCSemaphore(const char* semName); - - ~CIPCSemaphore() noexcept; - - Lock getLock() noexcept; - - private: - sem_t* pSemaphore = nullptr; -}; diff --git a/src/InstanceLock.cpp b/src/InstanceLock.cpp deleted file mode 100644 index 4be7639..0000000 --- a/src/InstanceLock.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "InstanceLock.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "helpers/Log.hpp" -#include "helpers/GetRuntimeDir.hpp" - -#include "IPCSemaphore.hpp" - -CInstanceLock::CInstanceLock() : pLockFolder(getHyprsunsetFolder()) { - static constexpr const char* SEM_NAME = "/hyprsunsetsemaphore"; - CIPCSemaphore fileSem{SEM_NAME}; - auto fileLock = fileSem.getLock(); - - if (!lock()) { - Debug::log(NONE, "✖ Failed to set instance lock {}", pLockFolder.c_str()); - return; - } - - isOnlyInstance = true; -} - -CInstanceLock::~CInstanceLock() { - unlock(); -} - -bool CInstanceLock::lock() { - auto ids = readLocks(); - - auto sameEnvIt = findSameEnv(ids); - - if (sameEnvIt != ids.end()) { - pid_t oldPid = sameEnvIt->pid; - - if (!killOld(oldPid)) - return false; - } - - writeLock(); - - return true; -} - -void CInstanceLock::unlock() { - std::filesystem::remove(getLockFile(pIdentifer.pid)); -} - -void CInstanceLock::writeLock() { - std::ofstream f{getLockFile(pIdentifer.pid), std::fstream::out | std::fstream::trunc}; - f << pIdentifer.toString(); -} - -std::vector CInstanceLock::readLocks() { - std::vector ids; - - for (const auto& file : std::filesystem::recursive_directory_iterator(pLockFolder)) { - ids.emplace_back(readFile(file).value_or(CInstanceLock::SInstanceIdentifier{})); - } - - return ids; -} - -std::optional CInstanceLock::readFile(const std::filesystem::directory_entry& file) { - if (!file.is_regular_file()) - return std::nullopt; - - pid_t pid = 0; - std::string waylandEnv; - - std::ifstream f{file.path(), std::fstream::in}; - f >> pid >> waylandEnv; - - return CInstanceLock::SInstanceIdentifier{pid, std::move(waylandEnv)}; -} - -bool CInstanceLock::killOld(pid_t oldPid) { - if (oldPid <= 0) - return false; - - if (kill(oldPid, SIGTERM) == -1) { - Debug::log(NONE, "✖ Failed to to kill the other running instance: {}", strerror(errno)); - return false; - } - - while (isProcessAlive(oldPid)) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - - return true; -} - -bool CInstanceLock::isProcessAlive(pid_t pid) { - return kill(pid, 0) == 0 || errno != ESRCH; -} - -std::vector::iterator CInstanceLock::findSameEnv(std::vector& ids) { - return std::ranges::find_if(std::views::all(ids), [this](const CInstanceLock::SInstanceIdentifier& id) { return id.waylandEnv == pIdentifer.waylandEnv; }); -} - -std::vector::iterator CInstanceLock::findUs(std::vector& ids) { - return std::ranges::find_if(std::views::all(ids), [this](const CInstanceLock::SInstanceIdentifier& id) { return id == pIdentifer; }); -} - -std::filesystem::path CInstanceLock::getLockFile(pid_t pid) { - return pLockFolder.string() + '/' + std::to_string(pid); -} - -CInstanceLock::CInstanceLock::SInstanceIdentifier CInstanceLock::getInstanceIdentifier() { - int pid = getpid(); - if (pid == -1) { - Debug::log(NONE, "✖ Failed to get proccess id. How could it happen...: {}", strerror(errno)); - return {-1, {}}; - } - - const char* display = getenv("WAYLAND_DISPLAY"); - if (!display) { - Debug::log(NONE, "✖ Failed to get the current wayland display. Is a wayland compositor running?"); - return {-1, {}}; - } - - return {pid, display}; -} - -std::string CInstanceLock::CInstanceLock::SInstanceIdentifier::toString() const { - return std::format("{}\n{}\n", pid, waylandEnv); -} - -bool CInstanceLock::CInstanceLock::SInstanceIdentifier::operator==(const SInstanceIdentifier& other) const { - return pid == other.pid && waylandEnv == other.waylandEnv; -} diff --git a/src/InstanceLock.hpp b/src/InstanceLock.hpp deleted file mode 100644 index 4775dda..0000000 --- a/src/InstanceLock.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -class CInstanceLock { - public: - CInstanceLock(); - ~CInstanceLock(); - - bool isOnlyInstance = false; - - private: - struct SInstanceIdentifier { - pid_t pid = -1; - std::string waylandEnv; - - SInstanceIdentifier() = default; - SInstanceIdentifier(pid_t pid, std::string&& display) : pid(pid), waylandEnv(std::move(display)) {} - - std::string toString() const; - - bool operator==(const SInstanceIdentifier& other) const; - }; - - private: - std::filesystem::path pLockFolder; - SInstanceIdentifier pIdentifer{getInstanceIdentifier()}; - - private: - bool lock(); - void unlock(); - std::vector readLocks(); - void writeLock(); - std::optional readFile(const std::filesystem::directory_entry& file); - static bool killOld(pid_t oldPid); - static bool isProcessAlive(pid_t pid); - std::vector::iterator findSameEnv(std::vector& ids); - std::vector::iterator findUs(std::vector& ids); - std::filesystem::path getLockFile(pid_t pid); - static SInstanceIdentifier getInstanceIdentifier(); -}; diff --git a/src/helpers/GetRuntimeDir.cpp b/src/helpers/GetRuntimeDir.cpp deleted file mode 100644 index 87823a3..0000000 --- a/src/helpers/GetRuntimeDir.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include -#include - -#include "Log.hpp" -#include "GetRuntimeDir.hpp" - -// taken from Hyprland/hyprctl/main.cpp -static unsigned getUID() { - const auto UID = getuid(); - const auto PWUID = getpwuid(UID); - return PWUID ? PWUID->pw_uid : UID; -} - -static std::filesystem::path getRuntimeDir() { - const auto XDG = getenv("XDG_RUNTIME_DIR"); - - if (!XDG) { - const auto USERID = std::to_string(getUID()); - return "/run/user/" + USERID + "/hypr"; - } - - return std::string{XDG} + "/hypr"; -} - -std::filesystem::path getHyprsunsetFolder() { - std::filesystem::path lockFolder = getRuntimeDir(); - lockFolder += "/hyprsunset"; - - std::error_code errexists; - if (!std::filesystem::exists(lockFolder, errexists)) { - if (errexists) { - Debug::log(NONE, "✖ Failed to check if {} exists: {}", lockFolder.string(), errexists.message()); - return {}; - } else { - std::error_code errcreate; - std::filesystem::create_directory(lockFolder, errcreate); - if (errcreate) { - Debug::log(NONE, "✖ Failed to create {} folder: {}", lockFolder.string(), errcreate.message()); - return {}; - } - } - } - - return lockFolder; -} diff --git a/src/helpers/GetRuntimeDir.hpp b/src/helpers/GetRuntimeDir.hpp deleted file mode 100644 index 8811773..0000000 --- a/src/helpers/GetRuntimeDir.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -std::filesystem::path getHyprsunsetFolder(); diff --git a/src/helpers/Log.hpp b/src/helpers/Log.hpp index e006b67..f802025 100644 --- a/src/helpers/Log.hpp +++ b/src/helpers/Log.hpp @@ -1,9 +1,6 @@ -#pragma once - #include #include #include -#include enum LogLevel { NONE = -1, @@ -30,4 +27,4 @@ namespace Debug { std::cout << std::vformat(fmt.get(), std::make_format_args(args...)) << std::endl; // flush cuz systemd etc } -}; // namespace Debug +}; // namespace Debug \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 183e10f..0877935 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,8 +9,6 @@ #include "helpers/Log.hpp" -#include "InstanceLock.hpp" - #include #include using namespace Hyprutils::Math; @@ -53,7 +51,6 @@ struct { std::vector> outputs; bool initialized = false; Mat3x3 ctm; - CInstanceLock instLock; } state; void sigHandler(int sig) { @@ -87,11 +84,6 @@ static void printHelp() { int main(int argc, char** argv, char** envp) { Debug::log(NONE, "┏ hyprsunset v{} ━━╸\n┃", HYPRSUNSET_VERSION); - if (!state.instLock.isOnlyInstance) { - Debug::log(NONE, "✖ Another instance of hyprsunset is running"); - return 1; - } - float GAMMA = 1.0f; // default unsigned long long KELVIN = 6000; // default bool kelvinSet = false, identity = false; @@ -170,7 +162,6 @@ int main(int argc, char** argv, char** envp) { return 1; } - signal(SIGINT, sigHandler); signal(SIGTERM, sigHandler); state.pRegistry = makeShared((wl_proxy*)wl_display_get_registry(state.wlDisplay)); From 9c0b80729c24f78ea3fedfdba3d4f8613b915b27 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 31 Jan 2025 18:09:22 -0800 Subject: [PATCH 2/3] core: support hyprland_ctm_control_manager_v1.blocked() --- src/main.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0877935..c760e8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,9 +169,18 @@ int main(int argc, char** argv, char** envp) { const std::string IFACE = interface; if (IFACE == hyprland_ctm_control_manager_v1_interface.name) { - Debug::log(NONE, "┣ Found hyprland-ctm-control-v1 supported with version {}, binding to v1", version); + auto targetVersion = std::min(version, 2u); + + Debug::log(NONE, "┣ Found hyprland-ctm-control-v1 supported with version {}, binding to v{}", version, targetVersion); state.pCTMMgr = makeShared( - (wl_proxy*)wl_registry_bind((wl_registry*)state.pRegistry->resource(), name, &hyprland_ctm_control_manager_v1_interface, 1)); + (wl_proxy*)wl_registry_bind((wl_registry*)state.pRegistry->resource(), name, &hyprland_ctm_control_manager_v1_interface, targetVersion)); + + if (targetVersion >= 2) { + state.pCTMMgr->setBlocked([](CCHyprlandCtmControlManagerV1*) { + Debug::log(NONE, "✖ A CTM manager is already running on the current compositor."); + exit(1); + }); + } } else if (IFACE == wl_output_interface.name) { if (std::find_if(state.outputs.begin(), state.outputs.end(), [name](const auto& el) { return el->id == name; }) != state.outputs.end()) From acb5c54464a132b16a3a34675f910e7469717474 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 2 Feb 2025 00:22:24 -0800 Subject: [PATCH 3/3] bump h-p and nix --- CMakeLists.txt | 2 +- flake.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b0d37f..ada466c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ endfunction() protocolwayland() -pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.4.0) +pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.6.2) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") diff --git a/flake.lock b/flake.lock index 6744567..27e4ec7 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ ] }, "locked": { - "lastModified": 1737556638, - "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", + "lastModified": 1738422629, + "narHash": "sha256-5v+bv75wJWvahyM2xcMTSNNxmV8a7hb01Eey5zYnBJw=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", + "rev": "755aef8dab49d0fc4663c715fa4ad221b2aedaed", "type": "github" }, "original": { @@ -33,11 +33,11 @@ ] }, "locked": { - "lastModified": 1737632363, - "narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=", + "lastModified": 1737978343, + "narHash": "sha256-TfFS0HCEJh63Kahrkp1h9hVDMdLU8a37Zz+IFucxyfA=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "006620eb29d54ea9086538891404c78563d1bae1", + "rev": "6a8bc9d2a4451df12f5179dc0b1d2d46518a90ab", "type": "github" }, "original": { @@ -71,11 +71,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737469691, - "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=", + "lastModified": 1738410390, + "narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab", + "rev": "3a228057f5b619feb3186e986dbe76278d707b6e", "type": "github" }, "original": {