mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
notif: send proper wifi on/off and bt on/off notif without a need for hooks, make Hooks documentation a bit more generic.
This commit is contained in:
@@ -487,6 +487,12 @@
|
||||
},
|
||||
"internal": {
|
||||
"dbus-disabled": "DBus notifications disabled",
|
||||
"network": "Network",
|
||||
"wifi-enabled": "Wi-Fi is on",
|
||||
"wifi-disabled": "Wi-Fi is off",
|
||||
"bluetooth": "Bluetooth",
|
||||
"bluetooth-enabled": "Bluetooth is on",
|
||||
"bluetooth-disabled": "Bluetooth is off",
|
||||
"session-bus-unavailable": "Session bus unavailable",
|
||||
"mpris-disabled": "MPRIS disabled"
|
||||
}
|
||||
|
||||
+2
-2
@@ -143,7 +143,7 @@ Idle behaviors are named entries under `[idle.behavior.*]`. When no `config.toml
|
||||
```toml
|
||||
[idle.behavior.lock]
|
||||
timeout = 660
|
||||
command = "noctalia:lock"
|
||||
command = "noctalia:screen-lock"
|
||||
enabled = false # explicitly disabled in the default config
|
||||
|
||||
[idle.behavior.screen-off]
|
||||
@@ -166,7 +166,7 @@ command = "notify-send 'Idle' 'Going idle'"
|
||||
The `noctalia:` prefix runs the rest of the string through the IPC command registry — the same as `noctalia msg <subcommand>`. Examples:
|
||||
|
||||
```
|
||||
noctalia:lock
|
||||
noctalia:screen-lock
|
||||
noctalia:dpms-off
|
||||
noctalia:dpms-on
|
||||
noctalia:enable-idle-inhibitor
|
||||
|
||||
+39
-15
@@ -99,7 +99,13 @@ Each action accepts a single string chord or an array of chords.
|
||||
|
||||
## Hooks
|
||||
|
||||
Optional shell hooks run commands when specific events happen. Define them under `[hooks]` in `config.toml`. Each event is a string (one command) or an array of strings (run in order). The same `noctalia:` prefix rules apply as in [idle behaviors](services.md#idle).
|
||||
Optional shell hooks run extra commands when specific events happen. Define them under `[hooks]` in `config.toml`.
|
||||
Each event is a string (one command) or an array of strings (run in order). The same `noctalia:` prefix rules apply as
|
||||
in [idle behaviors](services.md#idle).
|
||||
|
||||
Hooks do not replace Noctalia's built-in behavior. For example, Wi-Fi and Bluetooth power changes still create internal
|
||||
Noctalia notifications even when `wifi_*` / `bluetooth_*` hooks are not configured. `notify-send` can be useful while
|
||||
testing that a hook fires, but it is not required for Noctalia's own notifications.
|
||||
|
||||
| Key | When it fires |
|
||||
|-----|---------------|
|
||||
@@ -122,24 +128,42 @@ Optional shell hooks run commands when specific events happen. Define them under
|
||||
|
||||
```toml
|
||||
[hooks]
|
||||
started = "notify-send 'Noctalia' 'Shell started'"
|
||||
wallpaper_changed = ["touch /tmp/noctalia-wallpaper"]
|
||||
colors_changed = "notify-send 'Theme' 'Palette updated'"
|
||||
# Start a user unit after Noctalia IPC is ready.
|
||||
started = "systemctl --user start noctalia-ready.target"
|
||||
|
||||
session_locked = "notify-send 'Session' 'Locked'"
|
||||
session_unlocked = "notify-send 'Session' 'Unlocked'"
|
||||
# Reload tools that consume generated wallpaper/theme files.
|
||||
wallpaper_changed = "systemctl --user restart wallpaper-sync.service"
|
||||
colors_changed = [
|
||||
"systemctl --user reload foot-server.service",
|
||||
"logger -t noctalia-hooks 'theme colors changed'",
|
||||
]
|
||||
|
||||
logging_out = "echo logging out >> /tmp/noctalia-hooks.log"
|
||||
rebooting = "notify-send 'System' 'Rebooting'"
|
||||
shutting_down = "notify-send 'System' 'Shutting down'"
|
||||
# Combine normal shell commands with Noctalia IPC commands.
|
||||
session_locked = [
|
||||
"playerctl pause",
|
||||
"noctalia:bar-hide",
|
||||
]
|
||||
session_unlocked = [
|
||||
"noctalia:bar-show",
|
||||
"noctalia:dpms-on",
|
||||
]
|
||||
|
||||
wifi_enabled = "notify-send 'Network' 'Wi-Fi on'"
|
||||
wifi_disabled = "notify-send 'Network' 'Wi-Fi off'"
|
||||
logging_out = "logger -t noctalia-hooks 'logout requested'"
|
||||
rebooting = "systemctl --user stop backup-sync.service"
|
||||
shutting_down = "systemctl --user stop backup-sync.service"
|
||||
|
||||
bluetooth_enabled = "notify-send 'BT' 'Bluetooth on'"
|
||||
bluetooth_disabled = "notify-send 'BT' 'Bluetooth off'"
|
||||
# Wi-Fi/Bluetooth internal notifications are emitted without these hooks;
|
||||
# use hooks only for extra side effects.
|
||||
wifi_enabled = "logger -t noctalia-hooks 'Wi-Fi radio enabled'"
|
||||
wifi_disabled = "logger -t noctalia-hooks 'Wi-Fi radio disabled'"
|
||||
|
||||
bluetooth_enabled = "logger -t noctalia-hooks 'Bluetooth powered on'"
|
||||
bluetooth_disabled = "logger -t noctalia-hooks 'Bluetooth powered off'"
|
||||
|
||||
battery_low_percent_threshold = 15
|
||||
battery_state_changed = "notify-send 'Power' \"Battery: $NOCTALIA_BATTERY_STATE\""
|
||||
battery_under_threshold = "notify-send 'Power' \"Battery at ${NOCTALIA_BATTERY_PERCENT}%\""
|
||||
battery_state_changed = "logger -t noctalia-hooks \"Battery: $NOCTALIA_BATTERY_STATE\""
|
||||
battery_under_threshold = "systemctl --user start battery-low.target"
|
||||
|
||||
# Quick test while developing a hook; not needed for Noctalia's own notifications.
|
||||
# started = "notify-send 'Noctalia hook' 'started fired'"
|
||||
```
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ temperature_night = 4000 # Kelvin
|
||||
|
||||
[idle.behavior.lock]
|
||||
timeout = 660
|
||||
command = "noctalia:lock"
|
||||
command = "noctalia:screen-lock"
|
||||
enabled = false
|
||||
|
||||
# [idle.behavior.screen-off]
|
||||
|
||||
+22
-12
@@ -474,8 +474,9 @@ void Application::initServices() {
|
||||
|
||||
try {
|
||||
m_networkService = std::make_unique<NetworkService>(*m_systemBus);
|
||||
m_prevWirelessEnabledForEvents = m_networkService->state().wirelessEnabled;
|
||||
m_networkService->setChangeCallback([this, shouldRefreshControlCenter](const NetworkState& state) {
|
||||
onNetworkStateChangedForHooks(state);
|
||||
onNetworkStateChangedForEvents(state);
|
||||
m_bar.refresh();
|
||||
if (shouldRefreshControlCenter()) {
|
||||
m_panelManager.refresh();
|
||||
@@ -498,6 +499,7 @@ void Application::initServices() {
|
||||
|
||||
try {
|
||||
m_bluetoothService = std::make_unique<BluetoothService>(*m_systemBus);
|
||||
m_prevBluetoothPoweredForEvents = m_bluetoothService->state().powered;
|
||||
auto refreshBluetoothUi = [this, shouldRefreshControlCenter]() {
|
||||
m_bar.refresh();
|
||||
if (shouldRefreshControlCenter()) {
|
||||
@@ -505,7 +507,7 @@ void Application::initServices() {
|
||||
}
|
||||
};
|
||||
m_bluetoothService->setStateCallback([this, refreshBluetoothUi](const BluetoothState& state) {
|
||||
onBluetoothStateChangedForHooks(state);
|
||||
onBluetoothStateChangedForEvents(state);
|
||||
refreshBluetoothUi();
|
||||
});
|
||||
m_bluetoothService->setDevicesCallback(
|
||||
@@ -1112,36 +1114,44 @@ void Application::onUpowerStateChangedForHooks() {
|
||||
m_prevUpowerForHooks = next;
|
||||
}
|
||||
|
||||
void Application::onNetworkStateChangedForHooks(const NetworkState& state) {
|
||||
if (!m_prevWirelessEnabledForHooks.has_value()) {
|
||||
m_prevWirelessEnabledForHooks = state.wirelessEnabled;
|
||||
void Application::onNetworkStateChangedForEvents(const NetworkState& state) {
|
||||
if (!m_prevWirelessEnabledForEvents.has_value()) {
|
||||
m_prevWirelessEnabledForEvents = state.wirelessEnabled;
|
||||
return;
|
||||
}
|
||||
const bool prev = *m_prevWirelessEnabledForHooks;
|
||||
const bool prev = *m_prevWirelessEnabledForEvents;
|
||||
if (prev != state.wirelessEnabled) {
|
||||
if (state.wirelessEnabled) {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.network"),
|
||||
i18n::tr("notifications.internal.wifi-enabled"), "");
|
||||
m_hookManager.fire(HookKind::WifiEnabled);
|
||||
} else {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.network"),
|
||||
i18n::tr("notifications.internal.wifi-disabled"), "");
|
||||
m_hookManager.fire(HookKind::WifiDisabled);
|
||||
}
|
||||
}
|
||||
m_prevWirelessEnabledForHooks = state.wirelessEnabled;
|
||||
m_prevWirelessEnabledForEvents = state.wirelessEnabled;
|
||||
}
|
||||
|
||||
void Application::onBluetoothStateChangedForHooks(const BluetoothState& state) {
|
||||
if (!m_prevBluetoothPoweredForHooks.has_value()) {
|
||||
m_prevBluetoothPoweredForHooks = state.powered;
|
||||
void Application::onBluetoothStateChangedForEvents(const BluetoothState& state) {
|
||||
if (!m_prevBluetoothPoweredForEvents.has_value()) {
|
||||
m_prevBluetoothPoweredForEvents = state.powered;
|
||||
return;
|
||||
}
|
||||
const bool prev = *m_prevBluetoothPoweredForHooks;
|
||||
const bool prev = *m_prevBluetoothPoweredForEvents;
|
||||
if (prev != state.powered) {
|
||||
if (state.powered) {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.bluetooth"),
|
||||
i18n::tr("notifications.internal.bluetooth-enabled"), "");
|
||||
m_hookManager.fire(HookKind::BluetoothEnabled);
|
||||
} else {
|
||||
m_notificationManager.addInternal(i18n::tr("notifications.internal.bluetooth"),
|
||||
i18n::tr("notifications.internal.bluetooth-disabled"), "");
|
||||
m_hookManager.fire(HookKind::BluetoothDisabled);
|
||||
}
|
||||
}
|
||||
m_prevBluetoothPoweredForHooks = state.powered;
|
||||
m_prevBluetoothPoweredForEvents = state.powered;
|
||||
}
|
||||
|
||||
std::vector<PollSource*> Application::currentPollSources() {
|
||||
|
||||
@@ -106,8 +106,8 @@ private:
|
||||
bool runIdleCommand(const std::string& command);
|
||||
void onIconThemeChanged();
|
||||
void onUpowerStateChangedForHooks();
|
||||
void onNetworkStateChangedForHooks(const NetworkState& state);
|
||||
void onBluetoothStateChangedForHooks(const BluetoothState& state);
|
||||
void onNetworkStateChangedForEvents(const NetworkState& state);
|
||||
void onBluetoothStateChangedForEvents(const BluetoothState& state);
|
||||
[[nodiscard]] std::vector<PollSource*> currentPollSources();
|
||||
[[nodiscard]] std::vector<PollSource*> buildPollSources();
|
||||
|
||||
@@ -137,8 +137,8 @@ private:
|
||||
std::unique_ptr<PolkitAgent> m_polkitAgent;
|
||||
std::unique_ptr<UPowerService> m_upowerService;
|
||||
std::optional<UPowerState> m_prevUpowerForHooks;
|
||||
std::optional<bool> m_prevWirelessEnabledForHooks;
|
||||
std::optional<bool> m_prevBluetoothPoweredForHooks;
|
||||
std::optional<bool> m_prevWirelessEnabledForEvents;
|
||||
std::optional<bool> m_prevBluetoothPoweredForEvents;
|
||||
SessionActionHooks m_sessionActionHooks;
|
||||
std::unique_ptr<BrightnessService> m_brightnessService;
|
||||
std::unique_ptr<TrayService> m_trayService;
|
||||
|
||||
@@ -642,7 +642,7 @@ void ConfigService::loadAll() {
|
||||
.name = "lock",
|
||||
.enabled = false,
|
||||
.timeoutSeconds = 660,
|
||||
.command = "noctalia:lock",
|
||||
.command = "noctalia:screen-lock",
|
||||
});
|
||||
m_config.bars.push_back(BarConfig{});
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user