aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authortrianta <[email protected]>2024-09-07 14:54:33 -0500
committerGitHub <[email protected]>2024-09-07 20:54:33 +0100
commit70add904c40924a761059e4009a8c0f1e43d76a3 (patch)
tree0c359796ef48aefc9b6cff3a19110909406a21b4 /src
parent5ca48231287d67e75a3f21dbdbc47d6dc65752c4 (diff)
downloadHyprland-70add904c40924a761059e4009a8c0f1e43d76a3.tar.gz
Hyprland-70add904c40924a761059e4009a8c0f1e43d76a3.zip
config: add exec-shutdown for running commands on shutdown (#7683)
* config: add exec-shutdown for running commands on shutdown * compositor: delay stopping until after exec-shutdown
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.hpp1
-rw-r--r--src/config/ConfigManager.cpp42
-rw-r--r--src/config/ConfigManager.hpp3
-rw-r--r--src/managers/KeybindManager.cpp5
4 files changed, 51 insertions, 0 deletions
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index f17d86e5..a57450f1 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -91,6 +91,7 @@ class CCompositor {
bool m_bNextIsUnsafe = false;
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
bool m_bIsShuttingDown = false;
+ bool m_bFinalRequests = false;
bool m_bDesktopEnvSet = false;
bool m_bEnableXwayland = true;
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index b16b7747..852994a7 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -141,6 +141,18 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) {
return result;
}
+static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) {
+ const std::string VALUE = v;
+ const std::string COMMAND = c;
+
+ const auto RESULT = g_pConfigManager->handleExecShutdown(COMMAND, VALUE);
+
+ Hyprlang::CParseResult result;
+ if (RESULT.has_value())
+ result.setError(RESULT.value().c_str());
+ return result;
+}
+
static Hyprlang::CParseResult handleMonitor(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
@@ -609,6 +621,7 @@ CConfigManager::CConfigManager() {
// keywords
m_pConfig->registerHandler(&::handleRawExec, "exec", {false});
m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false});
+ m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false});
m_pConfig->registerHandler(&::handleMonitor, "monitor", {false});
m_pConfig->registerHandler(&::handleBind, "bind", {true});
m_pConfig->registerHandler(&::handleUnbind, "unbind", {false});
@@ -801,6 +814,7 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
m_vDeclaredPlugins.clear();
m_dLayerRules.clear();
m_vFailedPluginConfigValues.clear();
+ finalExecRequests.clear();
// paths
configPaths.clear();
@@ -1398,6 +1412,24 @@ void CConfigManager::dispatchExecOnce() {
g_pCompositor->performUserChecks();
}
+void CConfigManager::dispatchExecShutdown() {
+ if (finalExecRequests.empty()) {
+ g_pCompositor->m_bFinalRequests = false;
+ return;
+ }
+
+ g_pCompositor->m_bFinalRequests = true;
+
+ for (auto const& c : finalExecRequests) {
+ handleExecShutdown("", c);
+ }
+
+ finalExecRequests.clear();
+
+ // Actually exit now
+ handleExecShutdown("", "hyprctl dispatch exit");
+}
+
void CConfigManager::appendMonitorRule(const SMonitorRule& r) {
m_dMonitorRules.emplace_back(r);
}
@@ -1700,6 +1732,16 @@ std::optional<std::string> CConfigManager::handleExecOnce(const std::string& com
return {};
}
+std::optional<std::string> CConfigManager::handleExecShutdown(const std::string& command, const std::string& args) {
+ if (g_pCompositor->m_bFinalRequests) {
+ g_pKeybindManager->spawn(args);
+ return {};
+ }
+
+ finalExecRequests.push_back(args);
+ return {};
+}
+
static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
auto args = CVarList(modeline, 0, 's');
diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp
index 4d087753..da450e39 100644
--- a/src/config/ConfigManager.hpp
+++ b/src/config/ConfigManager.hpp
@@ -192,6 +192,7 @@ class CConfigManager {
// no-op when done.
void dispatchExecOnce();
+ void dispatchExecShutdown();
void performMonitorReload();
void appendMonitorRule(const SMonitorRule&);
@@ -213,6 +214,7 @@ class CConfigManager {
// keywords
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
+ std::optional<std::string> handleExecShutdown(const std::string&, const std::string&);
std::optional<std::string> handleMonitor(const std::string&, const std::string&);
std::optional<std::string> handleBind(const std::string&, const std::string&);
std::optional<std::string> handleUnbind(const std::string&, const std::string&);
@@ -289,6 +291,7 @@ class CConfigManager {
bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false;
std::deque<std::string> firstExecRequests;
+ std::deque<std::string> finalExecRequests;
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::string m_szConfigErrors = "";
diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp
index 2db9f375..2f593d74 100644
--- a/src/managers/KeybindManager.cpp
+++ b/src/managers/KeybindManager.cpp
@@ -1781,6 +1781,11 @@ SDispatchResult CKeybindManager::renameWorkspace(std::string args) {
}
SDispatchResult CKeybindManager::exitHyprland(std::string argz) {
+ g_pConfigManager->dispatchExecShutdown();
+
+ if (g_pCompositor->m_bFinalRequests)
+ return {}; // Exiting deferred until requests complete
+
g_pCompositor->stopCompositor();
return {};
}