diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 373abcb..7cfd459 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -1,9 +1,18 @@ #include "Hyprpaper.hpp" +#include +#include +#include +#include CHyprpaper::CHyprpaper() = default; void CHyprpaper::init() { + if (!lockSingleInstance()) { + Debug::log(CRIT, "Cannot launch multiple instances of Hyprpaper at once!"); + exit(1); + } + removeOldHyprpaperImages(); g_pConfigManager = std::make_unique(); @@ -29,6 +38,8 @@ void CHyprpaper::init() { std::lock_guard lg(m_mtTickMutex); tick(true); } + + unlockSingleInstance(); } void CHyprpaper::tick(bool force) { @@ -552,3 +563,38 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { } } } + +bool CHyprpaper::lockSingleInstance() { + const std::string XDG_RUNTIME_DIR = getenv("XDG_RUNTIME_DIR"); + + const auto LOCKFILE = XDG_RUNTIME_DIR + "/hyprpaper.lock"; + + if (std::filesystem::exists(LOCKFILE)) { + std::ifstream ifs(LOCKFILE); + std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + + try { + kill(std::stoull(content), 0); + + if (errno != ESRCH) + return false; + } catch (std::exception& e) { + ; + } + } + + // create lockfile + std::ofstream ofs(LOCKFILE, std::ios::trunc); + + ofs << std::to_string(getpid()); + + ofs.close(); + + return true; +} + +void CHyprpaper::unlockSingleInstance() { + const std::string XDG_RUNTIME_DIR = getenv("XDG_RUNTIME_DIR"); + const auto LOCKFILE = XDG_RUNTIME_DIR + "/hyprpaper.lock"; + unlink(LOCKFILE.c_str()); +} \ No newline at end of file diff --git a/src/Hyprpaper.hpp b/src/Hyprpaper.hpp index 9d6287c..16a173d 100644 --- a/src/Hyprpaper.hpp +++ b/src/Hyprpaper.hpp @@ -59,6 +59,8 @@ public: SPoolBuffer* getPoolBuffer(SMonitor*, CWallpaperTarget*); void unloadWallpaper(const std::string&); void createSeat(wl_seat*); + bool lockSingleInstance(); // fails on multi-instance + void unlockSingleInstance(); std::mutex m_mtTickMutex;