fix(hooks): run session power hooks before fallback actions

This commit is contained in:
Ly-sec
2026-05-07 20:04:28 +02:00
parent 1faa2f98a4
commit cc50c4f2e4
4 changed files with 42 additions and 6 deletions
+25 -3
View File
@@ -402,6 +402,8 @@ void Application::initServices() {
m_configService.addReloadCallback([this]() { m_idleManager.reload(m_configService.config().idle); });
m_hookManager.setCommandRunner([this](const std::string& command) { return runUserCommand(command); });
m_hookManager.setBlockingCommandRunner(
[this](const std::string& command) { return runUserCommandBlocking(command); });
m_hookManager.reload(m_configService.config().hooks);
m_configService.addReloadCallback([this]() { m_hookManager.reload(m_configService.config().hooks); });
m_nightLightManager.reload(m_configService.config().nightlight);
@@ -756,9 +758,9 @@ void Application::initUi() {
m_lockScreen.setSessionHooks([this]() { m_hookManager.fire(HookKind::SessionLocked); },
[this]() { m_hookManager.fire(HookKind::SessionUnlocked); });
m_sessionActionHooks.onLogout = [this]() { m_hookManager.fire(HookKind::LoggingOut); };
m_sessionActionHooks.onReboot = [this]() { m_hookManager.fire(HookKind::Rebooting); };
m_sessionActionHooks.onShutdown = [this]() { m_hookManager.fire(HookKind::ShuttingDown); };
m_sessionActionHooks.onLogout = [this]() { m_hookManager.fireBlocking(HookKind::LoggingOut); };
m_sessionActionHooks.onReboot = [this]() { m_hookManager.fireBlocking(HookKind::Rebooting); };
m_sessionActionHooks.onShutdown = [this]() { m_hookManager.fireBlocking(HookKind::ShuttingDown); };
m_wayland.setPointerEventCallback([this](const PointerEvent& event) {
if (m_lockScreen.isActive()) {
@@ -1160,6 +1162,26 @@ bool Application::runUserCommand(const std::string& command) {
return true;
}
bool Application::runUserCommandBlocking(const std::string& command) {
constexpr std::string_view prefix = "noctalia:";
if (command.rfind(prefix, 0) == 0) {
const std::string response = m_ipcService.execute(command.substr(prefix.size()));
if (response.rfind("error:", 0) == 0) {
kLog.warn("IPC command '{}' failed: {}", command, response.substr(0, response.find('\n')));
return false;
}
return true;
}
const auto result = process::runSync(command);
if (!result) {
kLog.warn("command failed: {} exit_code={} stderr={}", command, result.exitCode, result.err);
return false;
}
return true;
}
bool Application::runIdleCommand(const std::string& command) { return runUserCommand(command); }
void Application::onIconThemeChanged() {
+1
View File
@@ -110,6 +110,7 @@ private:
void syncNotificationDaemon();
void syncPolkitAgent();
bool runUserCommand(const std::string& command);
bool runUserCommandBlocking(const std::string& command);
bool runIdleCommand(const std::string& command);
void onIconThemeChanged();
void onUpowerStateChangedForHooks();
+11 -3
View File
@@ -12,10 +12,18 @@ namespace {
void HookManager::setCommandRunner(CommandRunner runner) { m_runner = std::move(runner); }
void HookManager::setBlockingCommandRunner(CommandRunner runner) { m_blockingRunner = std::move(runner); }
void HookManager::reload(const HooksConfig& config) { m_config = config; }
void HookManager::fire(HookKind kind) const {
if (kind == HookKind::Count || !m_runner) {
void HookManager::fire(HookKind kind) const { fireWithRunner(kind, m_runner); }
void HookManager::fireBlocking(HookKind kind) const {
fireWithRunner(kind, m_blockingRunner ? m_blockingRunner : m_runner);
}
void HookManager::fireWithRunner(HookKind kind, const CommandRunner& runner) const {
if (kind == HookKind::Count || !runner) {
return;
}
const auto& cmds = m_config.commands[static_cast<std::size_t>(kind)];
@@ -25,7 +33,7 @@ void HookManager::fire(HookKind kind) const {
const std::string_view name = hookKindKey(kind);
kLog.debug("hook '{}' running {} command(s)", name, cmds.size());
for (const auto& cmd : cmds) {
if (!m_runner(cmd)) {
if (!runner(cmd)) {
kLog.warn("hook '{}' command failed: {}", name, cmd);
}
}
+5
View File
@@ -13,13 +13,18 @@ public:
using EnvVar = std::pair<const char*, std::string>;
void setCommandRunner(CommandRunner runner);
void setBlockingCommandRunner(CommandRunner runner);
void reload(const HooksConfig& config);
void fire(HookKind kind) const;
void fireBlocking(HookKind kind) const;
void fire(HookKind kind, std::initializer_list<EnvVar> env) const;
[[nodiscard]] const HooksConfig& config() const noexcept { return m_config; }
private:
void fireWithRunner(HookKind kind, const CommandRunner& runner) const;
HooksConfig m_config;
CommandRunner m_runner;
CommandRunner m_blockingRunner;
};