From a3f14e815c267226773beb444c3dad694a815828 Mon Sep 17 00:00:00 2001 From: Lenoch <81lennoch@gmail.com> Date: Mon, 16 Dec 2024 23:46:55 +0100 Subject: [PATCH] Add support for "kill a task" button for Linux - Added support for killing tasks on Linux using `killall -ignore-case` - Moved task killing logic to a dedicated taskkill.py file - Updated commands.py to use the new kill function - Updated commands.json to include OS-specific arguments for task killing - Updated translations to include OS-specific argument names for task killing --- app/buttons/commands.py | 18 +----------- app/buttons/system/__init__.py | 1 + app/buttons/system/taskkill.py | 49 +++++++++++++++++++++++++++++++++ webdeck/commands.json | 8 +++++- webdeck/translations/de_DE.lang | 3 +- webdeck/translations/en_US.lang | 3 +- webdeck/translations/fr_FR.lang | 3 +- webdeck/translations/ko_KR.lang | 3 +- webdeck/translations/ru_RU.lang | 3 +- 9 files changed, 68 insertions(+), 23 deletions(-) create mode 100644 app/buttons/system/taskkill.py diff --git a/app/buttons/commands.py b/app/buttons/commands.py index c3ccb40..ab032e5 100644 --- a/app/buttons/commands.py +++ b/app/buttons/commands.py @@ -95,23 +95,7 @@ def handle_command(message=None): window.close(hwnd) elif message.startswith(("/kill", "/taskill", "/taskkill", "/forceclose")): - window_name = ( - message.replace("/kill", "") - .replace("/taskill", "") - .replace("/taskkill", "") - .replace("/forceclose", "") - ) - hwnd = window.get_by_name(window_name) - if hwnd: - log.debug(f"Window '{window_name}' found with handle : {hwnd}") - else: - log.debug(f"Window '{window_name}' not found") - try: - window.close(hwnd) - except: - if not "." in window_name: - window_name += ".exe" - subprocess.Popen(f"taskkill /f /im {window_name}", shell=True) + system.kill(message) elif message.startswith("/restart"): exe = message.replace("/restart", "") diff --git a/app/buttons/system/__init__.py b/app/buttons/system/__init__.py index 4281f36..8bd3019 100644 --- a/app/buttons/system/__init__.py +++ b/app/buttons/system/__init__.py @@ -1,3 +1,4 @@ from .command_handler import handle_command from .screensaver import handle_command as screensaver from .lock_session import lock_session +from .taskkill import kill diff --git a/app/buttons/system/taskkill.py b/app/buttons/system/taskkill.py new file mode 100644 index 0000000..7a982bb --- /dev/null +++ b/app/buttons/system/taskkill.py @@ -0,0 +1,49 @@ +from app.utils.platform import is_windows, is_linux + +import os +import subprocess +import pyautogui +from app.utils.logger import log +from .. import window + +def kill(message): + process = ( + message.replace("/kill", "") + .replace("/taskill", "") + .replace("/taskkill", "") + .replace("/forceclose", "") + ).strip() + + if is_windows: + if process.endswith(".exe"): + subprocess.Popen(f"taskkill /f /im {process}", shell=True) + else: + window_name = process + hwnd = window.get_by_name(window_name) + if hwnd: + log.debug(f"Window '{window_name}' found with handle : {hwnd}") + try: + window.close(hwnd) + except: + subprocess.Popen(f"taskkill /f /im {window_name}.exe", shell=True) + else: + log.debug(f"Window '{window_name}' not found") + subprocess.Popen(f"taskkill /f /im {window_name}.exe", shell=True) + + elif is_linux: + log.debug(f"Killing process '{process}'") + if subprocess.run(f"killall --ignore-case {process}", shell=True).returncode == 0: + log.success(f"Process '{process}' killed successfully") + else: + log.error(f"Process '{process}' not found") + raise RuntimeError(f"Process '{process}' not found") + + else: + raise NotImplementedError("Screensaver is not implemented for this platform.") + + +def screensaver_off(): + pyautogui.press("CTRL") + if is_linux: + os.system("gnome-screensaver-command -d") + \ No newline at end of file diff --git a/webdeck/commands.json b/webdeck/commands.json index b6a9d0a..ff1d3d4 100644 --- a/webdeck/commands.json +++ b/webdeck/commands.json @@ -517,7 +517,13 @@ "command": "/forceclose", "args": [ { - "TYPE": "input filetype['.exe']" + "TYPE": "input filetype['.exe']", + "os": "windows" + }, + { + "TYPE": "input text", + "placeholder": "killall process_name", + "os": "linux" } ], "style": {} diff --git a/webdeck/translations/de_DE.lang b/webdeck/translations/de_DE.lang index ba92179..cf22475 100644 --- a/webdeck/translations/de_DE.lang +++ b/webdeck/translations/de_DE.lang @@ -456,7 +456,8 @@ SYSTEM_superaltf4__btn_description=Force close the foreground window SYSTEM_kill_a_task__btn_name=Kill a task SYSTEM_kill_a_task__btn_default_display_name=Kill task SYSTEM_kill_a_task__btn_description= -SYSTEM_kill_a_task__arg_1_name=Task (app.exe) +SYSTEM_kill_a_task__arg_1_name__windows=Task (app.exe) +SYSTEM_kill_a_task__arg_1_name__linux=Process name (as shown in 'ps -A') SYSTEM_restart_a_task__btn_name=Restart a task SYSTEM_restart_a_task__btn_default_display_name=Restart task diff --git a/webdeck/translations/en_US.lang b/webdeck/translations/en_US.lang index 4b01b8c..0d8a85c 100644 --- a/webdeck/translations/en_US.lang +++ b/webdeck/translations/en_US.lang @@ -456,7 +456,8 @@ SYSTEM_superaltf4__btn_description=Force close the foreground window SYSTEM_kill_a_task__btn_name=Kill a task SYSTEM_kill_a_task__btn_default_display_name=Kill task SYSTEM_kill_a_task__btn_description= -SYSTEM_kill_a_task__arg_1_name=Task (app.exe) +SYSTEM_kill_a_task__arg_1_name__windows=Task (app.exe) +SYSTEM_kill_a_task__arg_1_name__linux=Process name (as shown in 'ps -A') SYSTEM_restart_a_task__btn_name=Restart a task SYSTEM_restart_a_task__btn_default_display_name=Restart task diff --git a/webdeck/translations/fr_FR.lang b/webdeck/translations/fr_FR.lang index c154f75..4bce869 100644 --- a/webdeck/translations/fr_FR.lang +++ b/webdeck/translations/fr_FR.lang @@ -456,7 +456,8 @@ SYSTEM_superaltf4__btn_description=Ferme de force la fenêtre au premier plan SYSTEM_kill_a_task__btn_name=Tuer une tâche SYSTEM_kill_a_task__btn_default_display_name=Tuer la tâche SYSTEM_kill_a_task__btn_description= -SYSTEM_kill_a_task__arg_1_name=Tache (app.exe) +SYSTEM_kill_a_task__arg_1_name__windows=Tache (app.exe) +SYSTEM_kill_a_task__arg_1_name__linux=Nom du processus (tel qu'affiché dans 'ps -A') SYSTEM_restart_a_task__btn_name=Redémarrer une application SYSTEM_restart_a_task__btn_default_display_name=Redémarrer l'application diff --git a/webdeck/translations/ko_KR.lang b/webdeck/translations/ko_KR.lang index 7b7c81b..11892d9 100644 --- a/webdeck/translations/ko_KR.lang +++ b/webdeck/translations/ko_KR.lang @@ -456,7 +456,8 @@ SYSTEM_superaltf4__btn_description=현재 창을 강제로 종료합니다. SYSTEM_kill_a_task__btn_name=프로그램 종료 SYSTEM_kill_a_task__btn_default_display_name= SYSTEM_kill_a_task__btn_description= -SYSTEM_kill_a_task__arg_1_name=프로그램 (app.exe) +SYSTEM_kill_a_task__arg_1_name__windows=프로그램 (app.exe) +SYSTEM_kill_a_task__arg_1_name__linux=프로세스 이름 ('ps -A' 에 표시된 대로) SYSTEM_restart_a_task__btn_name=프로그램 재시작 SYSTEM_restart_a_task__btn_default_display_name= diff --git a/webdeck/translations/ru_RU.lang b/webdeck/translations/ru_RU.lang index 935823d..5301bec 100644 --- a/webdeck/translations/ru_RU.lang +++ b/webdeck/translations/ru_RU.lang @@ -456,7 +456,8 @@ SYSTEM_superaltf4__btn_description=Force close the foreground window SYSTEM_kill_a_task__btn_name=Kill a task SYSTEM_kill_a_task__btn_default_display_name=Kill task SYSTEM_kill_a_task__btn_description= -SYSTEM_kill_a_task__arg_1_name=Task (app.exe) +SYSTEM_kill_a_task__arg_1_name__windows=Task (app.exe) +SYSTEM_kill_a_task__arg_1_name__linux=Process name (as shown in 'ps -A') SYSTEM_restart_a_task__btn_name=Restart a task SYSTEM_restart_a_task__btn_default_display_name=Restart task