From 059395c3d39541cc1f5bb30e0ba4e41ebcd74ca5 Mon Sep 17 00:00:00 2001 From: Sho Date: Sun, 2 Aug 2026 14:49:02 +0900 Subject: [PATCH] perf: eliminate recursive disk globs and ensure instant process detaching to prevent lag after game exits --- .../services/python/active_window_service.py | 46 +++++++++++++------ quickshell/services/python/launch_app.py | 17 +++---- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/quickshell/services/python/active_window_service.py b/quickshell/services/python/active_window_service.py index 4cfe82c..224437b 100755 --- a/quickshell/services/python/active_window_service.py +++ b/quickshell/services/python/active_window_service.py @@ -236,6 +236,19 @@ def resolve_game_info(app_lower): return None +_desktop_file_cache = None + +def get_all_desktop_files(): + global _desktop_file_cache + if _desktop_file_cache is None: + _desktop_file_cache = ( + glob.glob('/usr/share/applications/*.desktop') + + glob.glob(os.path.expanduser('~/.local/share/applications/*.desktop')) + + glob.glob(os.path.expanduser('~/.local/share/flatpak/exports/share/applications/*.desktop')) + + glob.glob('/var/lib/flatpak/exports/share/applications/*.desktop') + ) + return _desktop_file_cache + def resolve_app_info(app_id): if not app_id: return {"appId": "", "name": "Application", "icon": ""} @@ -249,12 +262,7 @@ def resolve_app_info(app_id): _icon_cache[app_lower] = game_info return game_info - desktop_files = ( - glob.glob('/usr/share/applications/*.desktop') + - glob.glob('/usr/share/applications/**/*.desktop', recursive=True) + - glob.glob(os.path.expanduser('~/.local/share/applications/*.desktop')) + - glob.glob(os.path.expanduser('~/.local/share/applications/**/*.desktop'), recursive=True) - ) + desktop_files = get_all_desktop_files() icon_name = None app_name = None @@ -262,16 +270,28 @@ def resolve_app_info(app_id): for df in desktop_files: basename = os.path.basename(df).lower() base_no_ext = basename.replace('.desktop', '') - if app_lower == base_no_ext or app_lower in basename or base_no_ext in app_lower: + if app_lower == base_no_ext: entry = parse_desktop(df) if entry: - if 'Icon' in entry and not icon_name: - icon_name = entry['Icon'] - if 'Name' in entry and not app_name: - app_name = entry['Name'] + icon_name = entry.get('Icon') + app_name = entry.get('Name') if icon_name and app_name: break + if not icon_name or not app_name: + for df in desktop_files: + basename = os.path.basename(df).lower() + base_no_ext = basename.replace('.desktop', '') + if app_lower in basename or base_no_ext in app_lower: + entry = parse_desktop(df) + if entry: + if 'Icon' in entry and not icon_name: + icon_name = entry['Icon'] + if 'Name' in entry and not app_name: + app_name = entry['Name'] + if icon_name and app_name: + break + if not icon_name: icon_name = app_lower if not app_name: @@ -289,10 +309,6 @@ def resolve_app_info(app_id): if os.path.exists(target): resolved_icon_path = target break - matches = glob.glob(os.path.join(d, f'*{icon_name}*{ext}')) - if matches: - resolved_icon_path = matches[0] - break if resolved_icon_path: break diff --git a/quickshell/services/python/launch_app.py b/quickshell/services/python/launch_app.py index a6306a7..c278605 100755 --- a/quickshell/services/python/launch_app.py +++ b/quickshell/services/python/launch_app.py @@ -69,29 +69,30 @@ def launch(): for fp_id in candidates_flatpak: if fp_id in installed_flatpaks: - subprocess.Popen(["flatpak", "run", fp_id], start_new_session=True) - return + subprocess.Popen(["flatpak", "run", fp_id], start_new_session=True, close_fds=True) + sys.exit(0) # Fallback check via flatpak info check = subprocess.run(["flatpak", "info", fp_id], capture_output=True, text=True) if check.returncode == 0: - subprocess.Popen(["flatpak", "run", fp_id], start_new_session=True) - return + subprocess.Popen(["flatpak", "run", fp_id], start_new_session=True, close_fds=True) + sys.exit(0) # 2. GTK Desktop launcher check (using clean desktop ID without paths) if shutil.which("gtk-launch"): for gtk_id in [base_name, f"{base_name}.desktop", lower_name]: res = subprocess.run(["gtk-launch", gtk_id], capture_output=True, text=True) if res.returncode == 0: - return + sys.exit(0) # 3. Direct binary execution bin_name = clean_cmd.split()[0] if shutil.which(bin_name): - subprocess.Popen(clean_cmd, shell=True, start_new_session=True) - return + subprocess.Popen(clean_cmd, shell=True, start_new_session=True, close_fds=True) + sys.exit(0) # 4. Fallback execution - subprocess.Popen(f"{clean_cmd} &", shell=True, start_new_session=True) + subprocess.Popen(f"{clean_cmd} &", shell=True, start_new_session=True, close_fds=True) + sys.exit(0) if __name__ == '__main__': launch()