diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 8069d414ee1..c2fbe9d48c4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -557,7 +557,7 @@ void logSystemInfo() { Debug::log(NONE, "{}", NFsUtils::readFileAsString("/etc/os-release").value_or("error")); } -int64_t getPPIDof(int64_t pid) { +pid_t getPPIDof(pid_t pid) { #if defined(KERN_PROC_PID) int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, @@ -606,6 +606,97 @@ int64_t getPPIDof(int64_t pid) { #endif } +std::vector getAllPIDOf(const std::string& name) { + std::vector results; + +#if defined(KERN_PROC_ALL) + int mib[] = {CTL_KERN, + KERN_PROC, + KERN_PROC_ALL, +#if defined(__NetBSD__) || defined(__OpenBSD__) + 0, + sizeof(KINFO_PROC), + 0 +#endif + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + + size_t size = 0; + if (sysctl(mib, miblen, NULL, &size, NULL, 0) == -1) + return results; + + std::vector kprocList(size / sizeof(KINFO_PROC)); + + if (sysctl(mib, miblen, kprocList.data(), &size, NULL, 0) != -1) { + for (auto& kproc : kprocList) { +#if defined(__DragonFly__) + if (name == std::string(kproc.kp_comm)) + results.push_back(kproc.kp_pid); +#elif defined(__FreeBSD__) + if (name == std::string(kproc.ki_comm)) + results.push_back(kproc.ki_pid); +#else + if (name == std::string(kproc.p_comm)) + results.push_back(kproc.p_pid); +#endif + } + } +#else + std::error_code ec; + for (const auto& entry : std::filesystem::directory_iterator("/proc", ec)) { + if (!entry.is_directory()) + continue; + + const auto& dirname = entry.path().filename().string(); + if (!isNumber(dirname)) + continue; + + const auto pid = std::stoll(dirname); + std::string procName = binaryNameForPid(pid).value_or(""); + + if (procName == name) + results.push_back(pid); + } +#endif + + return results; +} + +std::expected binaryNameForPid(pid_t pid) { + if (pid <= 0) + return std::unexpected("No pid for client"); + +#if defined(KERN_PROC_PATHNAME) + int mib[] = { + CTL_KERN, +#if defined(__NetBSD__) + KERN_PROC_ARGS, + pid, + KERN_PROC_PATHNAME, +#else + KERN_PROC, + KERN_PROC_PATHNAME, + pid, +#endif + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + char exe[PATH_MAX] = "/nonexistent"; + size_t sz = sizeof(exe); + sysctl(mib, miblen, &exe, &sz, NULL, 0); + std::string path = exe; +#else + std::string path = std::format("/proc/{}/exe", (uint64_t)pid); +#endif + std::error_code ec; + + std::string fullPath = std::filesystem::canonical(path, ec); + + if (ec) + return std::unexpected("canonical failed"); + + return fullPath; +} + std::expected configStringToInt(const std::string& VALUE) { auto parseHex = [](const std::string& value) -> std::expected { try { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index f361313bc12..16130cc09ec 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -19,27 +19,29 @@ struct SWorkspaceIDName { std::string name; }; -std::string absolutePath(const std::string&, const std::string&); -std::string escapeJSONStrings(const std::string& str); -bool isDirection(const std::string&); -bool isDirection(const char&); -SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); -std::optional cleanCmdForWorkspace(const std::string&, std::string); -float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); -void logSystemInfo(); -std::string execAndGet(const char*); -int64_t getPPIDof(int64_t pid); -std::expected configStringToInt(const std::string&); -Vector2D configStringToVector2D(const std::string&); -std::optional getPlusMinusKeywordResult(std::string in, float relative); -double normalizeAngleRad(double ang); -std::vector getBacktrace(); -void throwError(const std::string& err); -bool envEnabled(const std::string& env); -Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len); -bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr); -float stringToPercentage(const std::string& VALUE, const float REL); -bool isNvidiaDriverVersionAtLeast(int threshold); +std::string absolutePath(const std::string&, const std::string&); +std::string escapeJSONStrings(const std::string& str); +bool isDirection(const std::string&); +bool isDirection(const char&); +SWorkspaceIDName getWorkspaceIDNameFromString(const std::string&); +std::optional cleanCmdForWorkspace(const std::string&, std::string); +float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); +void logSystemInfo(); +std::string execAndGet(const char*); +pid_t getPPIDof(pid_t pid); +std::expected binaryNameForPid(pid_t pid); +std::vector getAllPIDOf(const std::string& name); +std::expected configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); +std::optional getPlusMinusKeywordResult(std::string in, float relative); +double normalizeAngleRad(double ang); +std::vector getBacktrace(); +void throwError(const std::string& err); +bool envEnabled(const std::string& env); +Hyprutils::OS::CFileDescriptor allocateSHMFile(size_t len); +bool allocateSHMFilePair(size_t size, Hyprutils::OS::CFileDescriptor& rw_fd_ptr, Hyprutils::OS::CFileDescriptor& ro_fd_ptr); +float stringToPercentage(const std::string& VALUE, const float REL); +bool isNvidiaDriverVersionAtLeast(int threshold); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 43558d9d66f..97b6d31a390 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -19,6 +19,7 @@ #include "../render/Renderer.hpp" #include "../hyprerror/HyprError.hpp" #include "../config/ConfigManager.hpp" +#include "../helpers/MiscFunctions.hpp" #include #include @@ -921,11 +922,11 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { // Dispatchers SDispatchResult CKeybindManager::spawn(std::string args) { - const uint64_t PROC = spawnWithRules(args, nullptr); + const pid_t PROC = spawnWithRules(args, nullptr); return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; } -uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) { +pid_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) { args = trim(args); @@ -937,13 +938,25 @@ uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitial args = args.substr(args.find_first_of(']') + 1); } - const uint64_t PROC = spawnRawProc(args, pInitialWorkspace); + const pid_t PROC = spawnRawProc(args, pInitialWorkspace); if (!RULES.empty()) { const auto RULESLIST = CVarList(RULES, 0, ';'); + auto global = false; for (auto const& r : RULESLIST) { - g_pConfigManager->addExecRule({r, (unsigned long)PROC}); + Debug::log(CRIT, "PROC = {}", PROC); + Debug::log(CRIT, "getProcNameOf(PROC) = {}", *binaryNameForPid(PROC)); + Debug::log(CRIT, "getAllPIDOf(getProcNameOf(PROC)) = {}", getAllPIDOf(*binaryNameForPid(PROC))); + if (r == "global") + global = true; + else { + if (global) + for (const auto& pid : getAllPIDOf(*binaryNameForPid(PROC))) + g_pConfigManager->addExecRule({r, (unsigned long)pid}); + else + g_pConfigManager->addExecRule({r, (unsigned long)PROC}); + } } Debug::log(LOG, "Applied {} rule arguments for exec.", RULESLIST.size()); @@ -953,11 +966,11 @@ uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitial } SDispatchResult CKeybindManager::spawnRaw(std::string args) { - const uint64_t PROC = spawnRawProc(args, nullptr); + const pid_t PROC = spawnRawProc(args, nullptr); return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)}; } -uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWorkspace) { +pid_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWorkspace) { Debug::log(LOG, "Executing {}", args); const auto HLENV = getHyprlandLaunchEnv(pInitialWorkspace); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index be2d114b57e..e6c1d7d78ad 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -154,8 +154,8 @@ class CKeybindManager { static void moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir = ""); static void moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection); static void switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory = false); - static uint64_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace); - static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); + static pid_t spawnRawProc(std::string, PHLWORKSPACE pInitialWorkspace); + static pid_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); // -------------- Dispatchers -------------- // static SDispatchResult closeActive(std::string); diff --git a/src/managers/permissions/DynamicPermissionManager.cpp b/src/managers/permissions/DynamicPermissionManager.cpp index c015adfed8e..f402edfc597 100644 --- a/src/managers/permissions/DynamicPermissionManager.cpp +++ b/src/managers/permissions/DynamicPermissionManager.cpp @@ -6,6 +6,7 @@ #include #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" +#include "../../helpers/MiscFunctions.hpp" #include using namespace Hyprutils::String; @@ -69,41 +70,6 @@ static const char* permissionToHumanString(eDynamicPermissionType type) { return "error"; } -static std::expected binaryNameForPid(pid_t pid) { - if (pid <= 0) - return std::unexpected("No pid for client"); - -#if defined(KERN_PROC_PATHNAME) - int mib[] = { - CTL_KERN, -#if defined(__NetBSD__) - KERN_PROC_ARGS, - pid, - KERN_PROC_PATHNAME, -#else - KERN_PROC, - KERN_PROC_PATHNAME, - pid, -#endif - }; - u_int miblen = sizeof(mib) / sizeof(mib[0]); - char exe[PATH_MAX] = "/nonexistent"; - size_t sz = sizeof(exe); - sysctl(mib, miblen, &exe, &sz, NULL, 0); - std::string path = exe; -#else - std::string path = std::format("/proc/{}/exe", (uint64_t)pid); -#endif - std::error_code ec; - - std::string fullPath = std::filesystem::canonical(path, ec); - - if (ec) - return std::unexpected("canonical failed"); - - return fullPath; -} - static std::expected binaryNameForWlClient(wl_client* client) { pid_t pid = 0; wl_client_get_credentials(client, &pid, nullptr, nullptr); diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols index 3a5c2bda1c1..755aef8dab4 160000 --- a/subprojects/hyprland-protocols +++ b/subprojects/hyprland-protocols @@ -1 +1 @@ -Subproject commit 3a5c2bda1c1a4e55cc1330c782547695a93f05b2 +Subproject commit 755aef8dab49d0fc4663c715fa4ad221b2aedaed