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
This commit is contained in:
trianta 2024-09-07 14:54:33 -05:00 committed by GitHub
parent 5ca4823128
commit 70add904c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 51 additions and 0 deletions

View file

@ -91,6 +91,7 @@ class CCompositor {
bool m_bNextIsUnsafe = false; bool m_bNextIsUnsafe = false;
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
bool m_bIsShuttingDown = false; bool m_bIsShuttingDown = false;
bool m_bFinalRequests = false;
bool m_bDesktopEnvSet = false; bool m_bDesktopEnvSet = false;
bool m_bEnableXwayland = true; bool m_bEnableXwayland = true;

View file

@ -141,6 +141,18 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) {
return result; 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) { static Hyprlang::CParseResult handleMonitor(const char* c, const char* v) {
const std::string VALUE = v; const std::string VALUE = v;
const std::string COMMAND = c; const std::string COMMAND = c;
@ -609,6 +621,7 @@ CConfigManager::CConfigManager() {
// keywords // keywords
m_pConfig->registerHandler(&::handleRawExec, "exec", {false}); m_pConfig->registerHandler(&::handleRawExec, "exec", {false});
m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false}); m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false});
m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false});
m_pConfig->registerHandler(&::handleMonitor, "monitor", {false}); m_pConfig->registerHandler(&::handleMonitor, "monitor", {false});
m_pConfig->registerHandler(&::handleBind, "bind", {true}); m_pConfig->registerHandler(&::handleBind, "bind", {true});
m_pConfig->registerHandler(&::handleUnbind, "unbind", {false}); m_pConfig->registerHandler(&::handleUnbind, "unbind", {false});
@ -801,6 +814,7 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
m_vDeclaredPlugins.clear(); m_vDeclaredPlugins.clear();
m_dLayerRules.clear(); m_dLayerRules.clear();
m_vFailedPluginConfigValues.clear(); m_vFailedPluginConfigValues.clear();
finalExecRequests.clear();
// paths // paths
configPaths.clear(); configPaths.clear();
@ -1398,6 +1412,24 @@ void CConfigManager::dispatchExecOnce() {
g_pCompositor->performUserChecks(); 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) { void CConfigManager::appendMonitorRule(const SMonitorRule& r) {
m_dMonitorRules.emplace_back(r); m_dMonitorRules.emplace_back(r);
} }
@ -1700,6 +1732,16 @@ std::optional<std::string> CConfigManager::handleExecOnce(const std::string& com
return {}; 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) { static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
auto args = CVarList(modeline, 0, 's'); auto args = CVarList(modeline, 0, 's');

View file

@ -192,6 +192,7 @@ class CConfigManager {
// no-op when done. // no-op when done.
void dispatchExecOnce(); void dispatchExecOnce();
void dispatchExecShutdown();
void performMonitorReload(); void performMonitorReload();
void appendMonitorRule(const SMonitorRule&); void appendMonitorRule(const SMonitorRule&);
@ -213,6 +214,7 @@ class CConfigManager {
// keywords // keywords
std::optional<std::string> handleRawExec(const std::string&, const std::string&); 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> 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> handleMonitor(const std::string&, const std::string&);
std::optional<std::string> handleBind(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&); std::optional<std::string> handleUnbind(const std::string&, const std::string&);
@ -289,6 +291,7 @@ class CConfigManager {
bool firstExecDispatched = false; bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false; bool m_bManualCrashInitiated = false;
std::deque<std::string> firstExecRequests; 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::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::string m_szConfigErrors = ""; std::string m_szConfigErrors = "";

View file

@ -1781,6 +1781,11 @@ SDispatchResult CKeybindManager::renameWorkspace(std::string args) {
} }
SDispatchResult CKeybindManager::exitHyprland(std::string argz) { SDispatchResult CKeybindManager::exitHyprland(std::string argz) {
g_pConfigManager->dispatchExecShutdown();
if (g_pCompositor->m_bFinalRequests)
return {}; // Exiting deferred until requests complete
g_pCompositor->stopCompositor(); g_pCompositor->stopCompositor();
return {}; return {};
} }