feat: Inhibit screensaver during backup operations
Adds logic to prevent the screensaver or screen lock from activating while a backup is in progress. - Uses a D-Bus call to `org.freedesktop.ScreenSaver.Inhibit` to request a lock. - The lock is activated when a backup starts. - The lock is reliably released when the backup finishes, fails, or is cancelled.
This commit is contained in:
@@ -28,6 +28,59 @@ class BackupManager:
|
||||
self.is_system_process = False
|
||||
self.app = app
|
||||
self.encryption_manager = EncryptionManager(logger, app)
|
||||
self.inhibit_cookie = None
|
||||
|
||||
def _inhibit_screensaver(self):
|
||||
"""Prevents the screensaver and auto-suspend during a backup."""
|
||||
if not shutil.which("gdbus"):
|
||||
self.logger.log("gdbus command not found, cannot inhibit screensaver.")
|
||||
return
|
||||
|
||||
try:
|
||||
self.logger.log("Attempting to inhibit screensaver and power management.")
|
||||
command = [
|
||||
"gdbus", "call", "--session", "--dest", "org.freedesktop.ScreenSaver",
|
||||
"--object-path", "/org/freedesktop/ScreenSaver",
|
||||
"--method", "org.freedesktop.ScreenSaver.Inhibit",
|
||||
"Py-Backup", "Backup in progress"
|
||||
]
|
||||
result = subprocess.run(command, capture_output=True, text=True, check=True)
|
||||
# Output is like "(uint32 12345,)", we need to extract the number.
|
||||
match = re.search(r'uint32\s+(\d+)', result.stdout)
|
||||
if match:
|
||||
self.inhibit_cookie = int(match.group(1))
|
||||
self.logger.log(f"Successfully inhibited screensaver with cookie {self.inhibit_cookie}")
|
||||
else:
|
||||
self.logger.log(f"Could not parse inhibit cookie from gdbus output: {result.stdout}")
|
||||
except FileNotFoundError:
|
||||
self.logger.log("gdbus command not found, cannot inhibit screensaver.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.logger.log(f"Failed to inhibit screensaver. D-Bus call failed: {e.stderr}")
|
||||
except Exception as e:
|
||||
self.logger.log(f"An unexpected error occurred while inhibiting screensaver: {e}")
|
||||
|
||||
def _uninhibit_screensaver(self):
|
||||
"""Releases the screensaver and auto-suspend lock."""
|
||||
if self.inhibit_cookie is None:
|
||||
return
|
||||
if not shutil.which("gdbus"):
|
||||
self.logger.log("gdbus command not found, cannot uninhibit screensaver.")
|
||||
return
|
||||
|
||||
try:
|
||||
self.logger.log(f"Attempting to uninhibit screensaver with cookie {self.inhibit_cookie}")
|
||||
command = [
|
||||
"gdbus", "call", "--session", "--dest", "org.freedesktop.ScreenSaver",
|
||||
"--object-path", "/org/freedesktop/ScreenSaver",
|
||||
"--method", "org.freedesktop.ScreenSaver.UnInhibit",
|
||||
str(self.inhibit_cookie)
|
||||
]
|
||||
subprocess.run(command, capture_output=True, text=True, check=True)
|
||||
self.logger.log("Successfully uninhibited screensaver.")
|
||||
except Exception as e:
|
||||
self.logger.log(f"Failed to uninhibit screensaver: {e}")
|
||||
finally:
|
||||
self.inhibit_cookie = None
|
||||
|
||||
def cancel_and_delete_privileged_backup(self, delete_path: str):
|
||||
"""Cancels a running system backup and deletes the target directory in one atomic pkexec call."""
|
||||
@@ -169,6 +222,7 @@ rm -f '{info_file_path}'
|
||||
|
||||
def start_backup(self, queue, source_path: str, dest_path: str, is_system: bool, is_dry_run: bool = False, exclude_files: Optional[List[Path]] = None, source_size: int = 0, is_compressed: bool = False, is_encrypted: bool = False, mode: str = "incremental", password: Optional[str] = None, key_file: Optional[str] = None):
|
||||
self.is_system_process = is_system
|
||||
self._inhibit_screensaver()
|
||||
thread = threading.Thread(target=self._run_backup_path, args=(
|
||||
queue, source_path, dest_path, is_system, is_dry_run, exclude_files, source_size, is_compressed, is_encrypted, mode, password, key_file))
|
||||
thread.daemon = True
|
||||
@@ -370,6 +424,7 @@ set -e
|
||||
finally:
|
||||
if is_encrypted and mount_point:
|
||||
self.encryption_manager.cleanup_encrypted_backup(base_dest_path)
|
||||
self._uninhibit_screensaver()
|
||||
self.process = None
|
||||
|
||||
def _create_info_file(self, pybackup_dir: str, backup_name: str, source_size: int, is_encrypted: bool):
|
||||
|
||||
Reference in New Issue
Block a user