Read a list of applications that should always be started in sleep mode from sleep.toml.
This commit is contained in:
@@ -286,6 +286,7 @@ class ScriptManager:
|
|||||||
try:
|
try:
|
||||||
from . import sleep_mode_manager
|
from . import sleep_mode_manager
|
||||||
sleepModeManager = sleep_mode_manager.getManager()
|
sleepModeManager = sleep_mode_manager.getManager()
|
||||||
|
sleepModeManager.refreshAutoSleepConfig()
|
||||||
if sleepModeManager and sleepModeManager.isActiveForApp(app):
|
if sleepModeManager and sleepModeManager.isActiveForApp(app):
|
||||||
return self.get_or_create_sleep_mode_script(app)
|
return self.get_or_create_sleep_mode_script(app)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
|||||||
@@ -214,6 +214,25 @@ class SettingsManager(object):
|
|||||||
if not os.path.exists(userCustomFile):
|
if not os.path.exists(userCustomFile):
|
||||||
os.close(os.open(userCustomFile, os.O_CREAT, 0o700))
|
os.close(os.open(userCustomFile, os.O_CREAT, 0o700))
|
||||||
|
|
||||||
|
sleepConfigFile = os.path.join(cthulhuDir, "sleep.toml")
|
||||||
|
if not os.path.exists(sleepConfigFile):
|
||||||
|
sleepTemplate = (
|
||||||
|
"# Cthulhu auto-sleep apps\n"
|
||||||
|
"#\n"
|
||||||
|
"# List current app names with:\n"
|
||||||
|
"# cthulhu --list-apps\n"
|
||||||
|
"# Use the middle app-name column from that output.\n"
|
||||||
|
"#\n"
|
||||||
|
"# Add app names to auto-enable sleep mode:\n"
|
||||||
|
"# apps = [\"qemu\"]\n"
|
||||||
|
"#\n"
|
||||||
|
"# Or use a section:\n"
|
||||||
|
"# [sleep]\n"
|
||||||
|
"# apps = [\"qemu\"]\n"
|
||||||
|
)
|
||||||
|
with open(sleepConfigFile, "w", encoding="utf-8") as configFile:
|
||||||
|
configFile.write(sleepTemplate)
|
||||||
|
|
||||||
if self.isFirstStart() and self._backend:
|
if self.isFirstStart() and self._backend:
|
||||||
self._backend.saveDefaultSettings(self.defaultGeneral,
|
self._backend.saveDefaultSettings(self.defaultGeneral,
|
||||||
self.defaultPronunciations,
|
self.defaultPronunciations,
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ __copyright__ = "Copyright (c) 2024 Stormux"
|
|||||||
__license__ = "LGPL"
|
__license__ = "LGPL"
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
|
from tomlkit import parse
|
||||||
import cthulhu.braille as braille
|
import cthulhu.braille as braille
|
||||||
import cthulhu.cmdnames as cmdnames
|
import cthulhu.cmdnames as cmdnames
|
||||||
import cthulhu.debug as debug
|
import cthulhu.debug as debug
|
||||||
@@ -47,7 +49,12 @@ class SleepModeManager:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._handlers = self.getHandlers(True)
|
self._handlers = self.getHandlers(True)
|
||||||
self._bindings = keybindings.KeyBindings()
|
self._bindings = keybindings.KeyBindings()
|
||||||
self._apps = []
|
self._apps = set()
|
||||||
|
self._disabledAutoSleepApps = set()
|
||||||
|
self._autoSleepAppNames = set()
|
||||||
|
self._autoSleepPath = self._getAutoSleepPath()
|
||||||
|
self._autoSleepConfigMTime = None
|
||||||
|
self._loadAutoSleepConfig()
|
||||||
self._lastToggleTime = 0
|
self._lastToggleTime = 0
|
||||||
self._toggleDebounceDelay = 0.1 # 100ms debounce (reduced for better responsiveness)
|
self._toggleDebounceDelay = 0.1 # 100ms debounce (reduced for better responsiveness)
|
||||||
|
|
||||||
@@ -76,12 +83,106 @@ class SleepModeManager:
|
|||||||
def isActiveForApp(self, app):
|
def isActiveForApp(self, app):
|
||||||
"""Returns True if sleep mode is active for app."""
|
"""Returns True if sleep mode is active for app."""
|
||||||
|
|
||||||
result = bool(app and hash(app) in self._apps)
|
if not app:
|
||||||
|
return False
|
||||||
|
|
||||||
|
appHash = hash(app)
|
||||||
|
result = appHash in self._apps
|
||||||
|
if not result and self._isAutoSleepConfiguredForApp(app):
|
||||||
|
result = appHash not in self._disabledAutoSleepApps
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
tokens = ["SLEEP MODE MANAGER: Is active for", app]
|
tokens = ["SLEEP MODE MANAGER: Is active for", app]
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _getAutoSleepPath(self):
|
||||||
|
prefsDir = os.path.join(GLib.get_user_data_dir(), "cthulhu")
|
||||||
|
try:
|
||||||
|
from . import cthulhu
|
||||||
|
app = cthulhu.cthulhuApp
|
||||||
|
if app and app.settingsManager:
|
||||||
|
configuredDir = app.settingsManager.getPrefsDir()
|
||||||
|
if configuredDir:
|
||||||
|
prefsDir = configuredDir
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return os.path.join(prefsDir, "sleep.toml")
|
||||||
|
|
||||||
|
def _refreshAutoSleepPath(self):
|
||||||
|
latestPath = self._getAutoSleepPath()
|
||||||
|
if latestPath != self._autoSleepPath:
|
||||||
|
self._autoSleepPath = latestPath
|
||||||
|
self._autoSleepConfigMTime = None
|
||||||
|
self._loadAutoSleepConfig()
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
latestMTime = os.path.getmtime(self._autoSleepPath)
|
||||||
|
except OSError:
|
||||||
|
latestMTime = None
|
||||||
|
|
||||||
|
if latestMTime != self._autoSleepConfigMTime:
|
||||||
|
self._loadAutoSleepConfig()
|
||||||
|
|
||||||
|
def refreshAutoSleepConfig(self):
|
||||||
|
"""Refresh auto-sleep config if prefs directory has changed."""
|
||||||
|
|
||||||
|
self._refreshAutoSleepPath()
|
||||||
|
|
||||||
|
def _loadAutoSleepConfig(self):
|
||||||
|
self._autoSleepAppNames = set()
|
||||||
|
self._autoSleepConfigMTime = None
|
||||||
|
|
||||||
|
if not os.path.isfile(self._autoSleepPath):
|
||||||
|
msg = f"SLEEP MODE MANAGER: No sleep config at {self._autoSleepPath}"
|
||||||
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._autoSleepConfigMTime = os.path.getmtime(self._autoSleepPath)
|
||||||
|
except OSError:
|
||||||
|
self._autoSleepConfigMTime = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(self._autoSleepPath, "r", encoding="utf-8") as configFile:
|
||||||
|
config = parse(configFile.read() or "")
|
||||||
|
except Exception as error:
|
||||||
|
tokens = ["SLEEP MODE MANAGER: Failed to parse", self._autoSleepPath, ":", error]
|
||||||
|
debug.printTokens(debug.LEVEL_WARNING, tokens, True)
|
||||||
|
return
|
||||||
|
|
||||||
|
appNames = []
|
||||||
|
topLevelApps = config.get("apps", [])
|
||||||
|
if isinstance(topLevelApps, list):
|
||||||
|
appNames.extend(topLevelApps)
|
||||||
|
|
||||||
|
sleepSection = config.get("sleep", {})
|
||||||
|
if isinstance(sleepSection, dict):
|
||||||
|
sectionApps = sleepSection.get("apps", [])
|
||||||
|
if isinstance(sectionApps, list):
|
||||||
|
appNames.extend(sectionApps)
|
||||||
|
|
||||||
|
for appName in appNames:
|
||||||
|
if not isinstance(appName, str):
|
||||||
|
continue
|
||||||
|
normalizedName = appName.strip().lower()
|
||||||
|
if normalizedName:
|
||||||
|
self._autoSleepAppNames.add(normalizedName)
|
||||||
|
|
||||||
|
msg = f"SLEEP MODE MANAGER: Loaded {len(self._autoSleepAppNames)} auto-sleep apps from {self._autoSleepPath}"
|
||||||
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
|
|
||||||
|
def _isAutoSleepConfiguredForApp(self, app):
|
||||||
|
if not app:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self._autoSleepAppNames:
|
||||||
|
return False
|
||||||
|
|
||||||
|
appName = (AXObject.get_name(app) or "").strip().lower()
|
||||||
|
return bool(appName and appName in self._autoSleepAppNames)
|
||||||
|
|
||||||
def _setupHandlers(self):
|
def _setupHandlers(self):
|
||||||
"""Sets up and returns the sleep-mode-manager input event handlers."""
|
"""Sets up and returns the sleep-mode-manager input event handlers."""
|
||||||
|
|
||||||
@@ -132,12 +233,16 @@ class SleepModeManager:
|
|||||||
if not (script and script.app):
|
if not (script and script.app):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
from . import cthulhu_state
|
self.refreshAutoSleepConfig()
|
||||||
|
|
||||||
scriptManager = script_manager.get_manager()
|
scriptManager = script_manager.get_manager()
|
||||||
|
|
||||||
if self.isActiveForApp(script.app):
|
if self.isActiveForApp(script.app):
|
||||||
# Turning OFF sleep mode
|
# Turning OFF sleep mode
|
||||||
self._apps.remove(hash(script.app))
|
appHash = hash(script.app)
|
||||||
|
self._apps.discard(appHash)
|
||||||
|
if self._isAutoSleepConfiguredForApp(script.app):
|
||||||
|
self._disabledAutoSleepApps.add(appHash)
|
||||||
newScript = scriptManager.get_script(script.app)
|
newScript = scriptManager.get_script(script.app)
|
||||||
if notifyUser:
|
if notifyUser:
|
||||||
newScript.presentMessage(
|
newScript.presentMessage(
|
||||||
@@ -177,7 +282,9 @@ class SleepModeManager:
|
|||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Active script set successfully", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Active script set successfully", True)
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Adding app to sleep list", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Adding app to sleep list", True)
|
||||||
self._apps.append(hash(script.app))
|
appHash = hash(script.app)
|
||||||
|
self._disabledAutoSleepApps.discard(appHash)
|
||||||
|
self._apps.add(appHash)
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Enabled for {AXObject.get_name(script.app)} (delayed)", True)
|
debug.printMessage(debug.LEVEL_INFO, f"SLEEP MODE: Enabled for {AXObject.get_name(script.app)} (delayed)", True)
|
||||||
# Reset debounce timer after successful toggle
|
# Reset debounce timer after successful toggle
|
||||||
self._lastToggleTime = 0
|
self._lastToggleTime = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user