diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json
index 957819178..f5756f516 100644
--- a/Assets/Translations/de.json
+++ b/Assets/Translations/de.json
@@ -1642,6 +1642,16 @@
"description": "Befehl, der ausgeführt wird, wenn sich das Hintergrundbild ändert.",
"label": "Hintergrundbild geändert",
"placeholder": "z.B. notify-send \"Hintergrundbild\" \"Geändert\""
+ },
+ "screen-lock": {
+ "description": "Befehl, der ausgeführt wird, wenn der Bildschirm gesperrt wird.",
+ "label": "Bildschirm gesperrt",
+ "placeholder": "z.B. notify-send \"Bildschirm\" \"Gesperrt\""
+ },
+ "screen-unlock": {
+ "description": "Befehl, der ausgeführt wird, wenn der Bildschirm entsperrt wird.",
+ "label": "Bildschirm entsperrt",
+ "placeholder": "z.B. notify-send \"Bildschirm\" \"Entsperrt\""
}
},
"launcher": {
diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json
index e63fc6afc..3b5ecd4c6 100644
--- a/Assets/Translations/en.json
+++ b/Assets/Translations/en.json
@@ -1618,7 +1618,7 @@
"label": "Hook command information"
},
"parameters": {
- "description": "• Wallpaper hook: $1 = wallpaper path, $2 = screen name
• Theme toggle hook: $1 = true/false (Dark Mode state)",
+ "description": "• Wallpaper hook: $1 = wallpaper path, $2 = screen name
• Theme toggle hook: $1 = true/false (Dark Mode state)
• Screen lock/unlock hooks: No parameters",
"label": "Available parameters"
}
},
@@ -1642,6 +1642,16 @@
"description": "Command to be executed when wallpaper changes.",
"label": "Wallpaper changed",
"placeholder": "e.g., notify-send \"Wallpaper\" \"Changed\""
+ },
+ "screen-lock": {
+ "description": "Command to be executed when the screen is locked.",
+ "label": "Screen locked",
+ "placeholder": "e.g., notify-send \"Screen\" \"Locked\""
+ },
+ "screen-unlock": {
+ "description": "Command to be executed when the lock screen is unlocked.",
+ "label": "Screen unlocked",
+ "placeholder": "e.g., notify-send \"Screen\" \"Unlocked\""
}
},
"launcher": {
diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json
index ddaaeed9a..ed5e1036c 100644
--- a/Assets/Translations/es.json
+++ b/Assets/Translations/es.json
@@ -1642,6 +1642,16 @@
"description": "Comando a ejecutar cuando cambia el fondo de pantalla.",
"label": "Fondo de pantalla cambiado",
"placeholder": "ej., notify-send \"Fondo de pantalla\" \"Cambiado\""
+ },
+ "screen-lock": {
+ "description": "Comando a ejecutar cuando se bloquea la pantalla.",
+ "label": "Pantalla bloqueada",
+ "placeholder": "ej., notify-send \"Pantalla\" \"Bloqueada\""
+ },
+ "screen-unlock": {
+ "description": "Comando a ejecutar cuando se desbloquea la pantalla.",
+ "label": "Pantalla desbloqueada",
+ "placeholder": "ej., notify-send \"Pantalla\" \"Desbloqueada\""
}
},
"launcher": {
diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json
index 546d7f329..3dfccf7c9 100644
--- a/Assets/Translations/fr.json
+++ b/Assets/Translations/fr.json
@@ -1642,6 +1642,16 @@
"description": "Commande à exécuter lorsque le fond d'écran change.",
"label": "Fond d'écran changé",
"placeholder": "ex: notify-send \"Fond d'écran\" \"Changé\""
+ },
+ "screen-lock": {
+ "description": "Commande à exécuter lorsque l'écran est verrouillé.",
+ "label": "Écran verrouillé",
+ "placeholder": "ex: notify-send \"Écran\" \"Verrouillé\""
+ },
+ "screen-unlock": {
+ "description": "Commande à exécuter lorsque l'écran est déverrouillé.",
+ "label": "Écran déverrouillé",
+ "placeholder": "ex: notify-send \"Écran\" \"Déverrouillé\""
}
},
"launcher": {
diff --git a/Assets/Translations/ja.json b/Assets/Translations/ja.json
index 1dd46e8e1..c52820282 100644
--- a/Assets/Translations/ja.json
+++ b/Assets/Translations/ja.json
@@ -1642,6 +1642,16 @@
"description": "壁紙が変更された際に実行されるコマンド。",
"label": "壁紙変更時",
"placeholder": "例: notify-send \"Wallpaper\" \"Changed\""
+ },
+ "screen-lock": {
+ "description": "画面がロックされた際に実行されるコマンド。",
+ "label": "画面ロック時",
+ "placeholder": "例: notify-send \"Screen\" \"Locked\""
+ },
+ "screen-unlock": {
+ "description": "ロック画面が解除された際に実行されるコマンド。",
+ "label": "画面ロック解除時",
+ "placeholder": "例: notify-send \"Screen\" \"Unlocked\""
}
},
"launcher": {
diff --git a/Assets/Translations/nl.json b/Assets/Translations/nl.json
index d5e001cf8..520f4a42f 100644
--- a/Assets/Translations/nl.json
+++ b/Assets/Translations/nl.json
@@ -1642,6 +1642,16 @@
"description": "Commando dat wordt uitgevoerd wanneer de achtergrond verandert.",
"label": "Achtergrond gewijzigd",
"placeholder": "bijv. notify-send \"Achtergrond\" \"Gewijzigd\""
+ },
+ "screen-lock": {
+ "description": "Commando dat wordt uitgevoerd wanneer het scherm wordt vergrendeld.",
+ "label": "Scherm vergrendeld",
+ "placeholder": "bijv. notify-send \"Scherm\" \"Vergrendeld\""
+ },
+ "screen-unlock": {
+ "description": "Commando dat wordt uitgevoerd wanneer het scherm wordt ontgrendeld.",
+ "label": "Scherm ontgrendeld",
+ "placeholder": "bijv. notify-send \"Scherm\" \"Ontgrendeld\""
}
},
"launcher": {
diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json
index 824c00ba8..90ad25276 100644
--- a/Assets/Translations/pt.json
+++ b/Assets/Translations/pt.json
@@ -1642,6 +1642,16 @@
"description": "Comando a ser executado quando o papel de parede muda.",
"label": "Papel de parede alterado",
"placeholder": "ex., notify-send \"Papel de parede\" \"Alterado\""
+ },
+ "screen-lock": {
+ "description": "Comando a ser executado quando a tela é bloqueada.",
+ "label": "Tela bloqueada",
+ "placeholder": "ex., notify-send \"Tela\" \"Bloqueada\""
+ },
+ "screen-unlock": {
+ "description": "Comando a ser executado quando a tela é desbloqueada.",
+ "label": "Tela desbloqueada",
+ "placeholder": "ex., notify-send \"Tela\" \"Desbloqueada\""
}
},
"launcher": {
diff --git a/Assets/Translations/ru.json b/Assets/Translations/ru.json
index 46d24b19f..69e662f1d 100644
--- a/Assets/Translations/ru.json
+++ b/Assets/Translations/ru.json
@@ -1642,6 +1642,16 @@
"description": "Команда для выполнения при смене обоев.",
"label": "Обои изменены",
"placeholder": "например, notify-send \"Wallpaper\" \"Changed\""
+ },
+ "screen-lock": {
+ "description": "Команда для выполнения при блокировке экрана.",
+ "label": "Экран заблокирован",
+ "placeholder": "например, notify-send \"Экран\" \"Заблокирован\""
+ },
+ "screen-unlock": {
+ "description": "Команда для выполнения при разблокировке экрана.",
+ "label": "Экран разблокирован",
+ "placeholder": "например, notify-send \"Экран\" \"Разблокирован\""
}
},
"launcher": {
diff --git a/Assets/Translations/tr.json b/Assets/Translations/tr.json
index 053ddc1fe..b994257bc 100644
--- a/Assets/Translations/tr.json
+++ b/Assets/Translations/tr.json
@@ -1642,6 +1642,16 @@
"description": "Duvar kâğıdı değiştiğinde çalıştırılacak komut.",
"label": "Duvar kâğıdı değişti",
"placeholder": "örn., notify-send \"Duvar Kâğıdı\" \"Değişti\""
+ },
+ "screen-lock": {
+ "description": "Ekran kilitlendiğinde çalıştırılacak komut.",
+ "label": "Ekran kilitlendi",
+ "placeholder": "örn., notify-send \"Ekran\" \"Kilitlendi\""
+ },
+ "screen-unlock": {
+ "description": "Ekran kilidi açıldığında çalıştırılacak komut.",
+ "label": "Ekran kilidi açıldı",
+ "placeholder": "örn., notify-send \"Ekran\" \"Açıldı\""
}
},
"launcher": {
diff --git a/Assets/Translations/uk-UA.json b/Assets/Translations/uk-UA.json
index a8f4e7645..ccd1b2786 100644
--- a/Assets/Translations/uk-UA.json
+++ b/Assets/Translations/uk-UA.json
@@ -1642,6 +1642,16 @@
"description": "Команда для виконання при зміні шпалер.",
"label": "Шпалери змінено",
"placeholder": "напр., notify-send \"Шпалери\" \"Змінено\""
+ },
+ "screen-lock": {
+ "description": "Команда для виконання при блокуванні екрана.",
+ "label": "Екран заблоковано",
+ "placeholder": "напр., notify-send \"Екран\" \"Заблоковано\""
+ },
+ "screen-unlock": {
+ "description": "Команда для виконання при розблокуванні екрана.",
+ "label": "Екран розблоковано",
+ "placeholder": "напр., notify-send \"Екран\" \"Розблоковано\""
}
},
"launcher": {
diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json
index 10b480b27..1abacf5eb 100644
--- a/Assets/Translations/zh-CN.json
+++ b/Assets/Translations/zh-CN.json
@@ -1642,6 +1642,16 @@
"description": "壁纸更改时执行的命令。",
"label": "壁纸已更改",
"placeholder": "例如:notify-send \"壁纸\" \"已更改\""
+ },
+ "screen-lock": {
+ "description": "屏幕锁定时执行的命令。",
+ "label": "屏幕已锁定",
+ "placeholder": "例如:notify-send \"屏幕\" \"已锁定\""
+ },
+ "screen-unlock": {
+ "description": "屏幕解锁时执行的命令。",
+ "label": "屏幕已解锁",
+ "placeholder": "例如:notify-send \"屏幕\" \"已解锁\""
}
},
"launcher": {
diff --git a/Assets/settings-default.json b/Assets/settings-default.json
index 52928de0b..b525cbab8 100644
--- a/Assets/settings-default.json
+++ b/Assets/settings-default.json
@@ -400,7 +400,9 @@
"hooks": {
"enabled": false,
"wallpaperChange": "",
- "darkModeChange": ""
+ "darkModeChange": "",
+ "screenLock": "",
+ "screenUnlock": ""
},
"desktopWidgets": {
"enabled": false,
diff --git a/Commons/Settings.qml b/Commons/Settings.qml
index ad2fac0b1..7cc5fd152 100644
--- a/Commons/Settings.qml
+++ b/Commons/Settings.qml
@@ -611,6 +611,8 @@ Singleton {
property bool enabled: false
property string wallpaperChange: ""
property string darkModeChange: ""
+ property string screenLock: ""
+ property string screenUnlock: ""
}
// desktop widgets
diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml
index dba8ea77d..1c9b8c2f5 100644
--- a/Modules/LockScreen/LockScreen.qml
+++ b/Modules/LockScreen/LockScreen.qml
@@ -24,6 +24,9 @@ Loader {
id: root
active: false
+ // Expose lockContext for hooks
+ readonly property var lockContext: item ? item.lockContext : null
+
Component.onCompleted: {
// Register with panel service
PanelService.lockScreen = this;
diff --git a/Modules/Panels/Settings/Tabs/HooksTab.qml b/Modules/Panels/Settings/Tabs/HooksTab.qml
index a808227d6..6c661250f 100644
--- a/Modules/Panels/Settings/Tabs/HooksTab.qml
+++ b/Modules/Panels/Settings/Tabs/HooksTab.qml
@@ -77,6 +77,50 @@ ColumnLayout {
Layout.fillWidth: true
}
+ // Screen Lock Hook Section
+ NInputAction {
+ id: screenLockHookInput
+ label: I18n.tr("settings.hooks.screen-lock.label")
+ description: I18n.tr("settings.hooks.screen-lock.description")
+ placeholderText: I18n.tr("settings.hooks.screen-lock.placeholder")
+ text: Settings.data.hooks.screenLock
+ onEditingFinished: {
+ Settings.data.hooks.screenLock = screenLockHookInput.text;
+ }
+ onActionClicked: {
+ if (screenLockHookInput.text) {
+ HooksService.executeLockHook();
+ }
+ }
+ Layout.fillWidth: true
+ }
+
+ NDivider {
+ Layout.fillWidth: true
+ }
+
+ // Screen Unlock Hook Section
+ NInputAction {
+ id: screenUnlockHookInput
+ label: I18n.tr("settings.hooks.screen-unlock.label")
+ description: I18n.tr("settings.hooks.screen-unlock.description")
+ placeholderText: I18n.tr("settings.hooks.screen-unlock.placeholder")
+ text: Settings.data.hooks.screenUnlock
+ onEditingFinished: {
+ Settings.data.hooks.screenUnlock = screenUnlockHookInput.text;
+ }
+ onActionClicked: {
+ if (screenUnlockHookInput.text) {
+ HooksService.executeUnlockHook();
+ }
+ }
+ Layout.fillWidth: true
+ }
+
+ NDivider {
+ Layout.fillWidth: true
+ }
+
// Info section
ColumnLayout {
spacing: Style.marginM
diff --git a/Services/Control/HooksService.qml b/Services/Control/HooksService.qml
index 9f2274317..c76ac1d51 100644
--- a/Services/Control/HooksService.qml
+++ b/Services/Control/HooksService.qml
@@ -23,6 +23,34 @@ Singleton {
}
}
+ // Track lock screen state for unlock hook
+ property bool wasLocked: false
+
+ Connections {
+ target: PanelService
+ function onLockScreenChanged() {
+ if (PanelService.lockScreen) {
+ lockScreenActiveConnection.target = PanelService.lockScreen;
+ }
+ }
+ }
+
+ Connections {
+ id: lockScreenActiveConnection
+ target: PanelService.lockScreen
+ function onActiveChanged() {
+ // Detect lock: was unlocked, now locked
+ if (!wasLocked && PanelService.lockScreen.active) {
+ executeLockHook();
+ }
+ // Detect unlock: was locked, now not locked
+ if (wasLocked && !PanelService.lockScreen.active) {
+ executeUnlockHook();
+ }
+ wasLocked = PanelService.lockScreen.active;
+ }
+ }
+
// Execute wallpaper change hook
function executeWallpaperHook(wallpaperPath, screenName) {
if (!Settings.data.hooks?.enabled) {
@@ -64,8 +92,53 @@ Singleton {
}
}
+ // Execute screen lock hook
+ function executeLockHook() {
+ if (!Settings.data.hooks?.enabled) {
+ return;
+ }
+
+ const script = Settings.data.hooks?.screenLock;
+ if (!script || script === "") {
+ return;
+ }
+
+ try {
+ Quickshell.execDetached(["sh", "-c", script]);
+ Logger.d("HooksService", `Executed screen lock hook: ${script}`);
+ } catch (e) {
+ Logger.e("HooksService", `Failed to execute screen lock hook: ${e}`);
+ }
+ }
+
+ // Execute screen unlock hook
+ function executeUnlockHook() {
+ if (!Settings.data.hooks?.enabled) {
+ return;
+ }
+
+ const script = Settings.data.hooks?.screenUnlock;
+ if (!script || script === "") {
+ return;
+ }
+
+ try {
+ Quickshell.execDetached(["sh", "-c", script]);
+ Logger.d("HooksService", `Executed screen unlock hook: ${script}`);
+ } catch (e) {
+ Logger.e("HooksService", `Failed to execute screen unlock hook: ${e}`);
+ }
+ }
+
// Initialize the service
function init() {
Logger.i("HooksService", "Service started");
+ // Initialize lock screen state tracking
+ Qt.callLater(() => {
+ if (PanelService.lockScreen) {
+ wasLocked = PanelService.lockScreen.active;
+ lockScreenActiveConnection.target = PanelService.lockScreen;
+ }
+ });
}
}