From 09ef3e446aa88c0de2a8e96b55dd658c84e58174 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 15 Oct 2026 00:35:02 +0900 Subject: [PATCH 01/17] change: set flatpak option sensitivity dynamically --- dzgui/api/steam.py | 8 ++++---- dzgui/app_init.py | 4 ++-- dzgui/init/prereqs.py | 27 ++++++++++++++++++++------- dzgui/views/components/misc.py | 25 +++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/dzgui/api/steam.py b/dzgui/api/steam.py index 2d0ee1e..5e914ae 100644 --- a/dzgui/api/steam.py +++ b/dzgui/api/steam.py @@ -11,7 +11,7 @@ from typing import Any, Union from warnings import deprecated from dzgui.api.acf import ACF -from dzgui.init.prereqs import has_steam_client +from dzgui.init.prereqs import has_any_client from dzgui.const.constants import ( APPID_DAYZ, APPID_DAYZ_EXP, @@ -59,7 +59,7 @@ class VDFLoadError(Exception): def get_steam_paths() -> list[tuple[Path, str]]: paths = [] - if has_steam_client(): + if has_any_client(): HOME = Path.home() env = os.environ.get("XDG_DATA_HOME") if env is not None: @@ -265,12 +265,12 @@ def find_user_id_32(path: Path) -> int: class SteamAPIKeyError(Exception): - def __init__(self, msg=None): + def __init__(self, msg: str | None = None) -> None: super().__init__(msg or api_validation_error) class SteamWorkshopEndpointError(Exception): - def __init__(self, msg=None): + def __init__(self, msg: str | None = None) -> None: super().__init__(msg or workshop_endpoint_error) diff --git a/dzgui/app_init.py b/dzgui/app_init.py index 643d32c..c200189 100644 --- a/dzgui/app_init.py +++ b/dzgui/app_init.py @@ -15,7 +15,7 @@ from dzgui.init.migrate import ( migrate_cols_file, ) from dzgui.init.flock import lock_acquire -from dzgui.init.prereqs import has_steam_client +from dzgui.init.prereqs import has_any_client from dzgui.strings import boot from dzgui.util.deck import is_steam_deck, is_game_mode @@ -136,7 +136,7 @@ def load_gui(version: str, is_debug: bool) -> None: # TODO: sudo escalation dialog # count = get_map_count() # TODO: move into module - if has_steam_client() is False: + if has_any_client() is False: EarlyAlertDialog(init.requires_steam) bootwin = BootWindow(XDG, version) diff --git a/dzgui/init/prereqs.py b/dzgui/init/prereqs.py index be92e20..5dce626 100644 --- a/dzgui/init/prereqs.py +++ b/dzgui/init/prereqs.py @@ -7,19 +7,32 @@ from dzgui.const.constants import APP_NAME, FLATPAK_APPID, FLATPAK_CMD, STEAM_CM logger = logging.getLogger(APP_NAME) -def has_steam_client() -> bool: - if shutil.which(STEAM_CMD): - return True - if not shutil.which(FLATPAK_CMD): - return False +def has_flatpak_client() -> bool: try: res = subprocess.run( - [FLATPAK_CMD, "list"], capture_output=True, text=True, check=True + [FLATPAK_CMD, "list", "--columns=application"], + capture_output=True, + text=True, + check=True, ) if FLATPAK_APPID in res.stdout: return True else: return False - except subprocess.CalledProcessError as e: + except Exception as e: logger.critical(e) return False + + +def has_steam_client() -> bool: + if shutil.which(STEAM_CMD): + return True + return False + + +def has_any_client() -> bool: + if shutil.which(STEAM_CMD): + return True + if not shutil.which(FLATPAK_CMD): + return False + return has_flatpak_client() diff --git a/dzgui/views/components/misc.py b/dzgui/views/components/misc.py index 9186246..80ef5fd 100644 --- a/dzgui/views/components/misc.py +++ b/dzgui/views/components/misc.py @@ -3,6 +3,8 @@ from dzgui.strings import options from dzgui.views.components.box import HBox from dzgui.views.components.buttons import Icon +from typing import Self +from dzgui.init.prereqs import has_steam_client, has_flatpak_client import gi @@ -14,36 +16,55 @@ class ClientCombo(Gtk.ComboBox): def __init__(self) -> None: super().__init__() - self.client_store = Gtk.ListStore(str, str) + has_steam = has_steam_client() + has_flatpak = has_flatpak_client() + self.client_store = Gtk.ListStore(str, str, bool) self.clients = ( ( options.steam_combo, STEAM_CMD, + has_steam, ), ( options.flatpak_combo, FLATPAK_RUN_CMD, + has_flatpak, ), ( options.flatpak_container_combo, FLATPAK_SANDBOX, + has_flatpak, ), ) for client in self.clients: self.client_store.append(client) + self.set_model(self.client_store) renderer_text = Gtk.CellRendererText() self.pack_start(renderer_text, True) self.add_attribute(renderer_text, "text", 0) self.set_active(0) + self.set_cell_data_func(self.get_cells()[0], self.data_func) + + def data_func( + self, + combo: Self, + cell: Gtk.CellRendererText, + model: Gtk.ListStore, + _iter: Gtk.TreeIter, + ) -> None: + sens = model[_iter][2] + cell.set_property("sensitive", sens) + def get_client_human_readable(self, cmd: str) -> str: for client in self.clients: - human, command = client + human, command, sens = client if command == cmd: return human raise TypeError("Not a valid Steam client selection") + class ErrorPopover(Gtk.Popover): def __init__(self, relative_to: Gtk.Widget, position: Gtk.PositionType) -> None: super().__init__(relative_to=relative_to, position=position) From 4eec00e8e7e9a80f19466f36baef136c3b81c878 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Thu, 15 Oct 2026 00:36:09 +0900 Subject: [PATCH 02/17] chore: trigger checks From ef1e7d17f5f5d36d18f5b332bffe5597a0deed33 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:39:23 +0900 Subject: [PATCH 03/17] chore: drop unused functions --- dzgui/config/query.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/dzgui/config/query.py b/dzgui/config/query.py index 602b082..1af14a5 100644 --- a/dzgui/config/query.py +++ b/dzgui/config/query.py @@ -4,8 +4,6 @@ from pathlib import Path from dzgui.util._json import read_json from dzgui.const.enum import Preferences -from dzgui.const.constants import STEAM_CMD, FLATPAK_RUN_CMD, FLATPAK_SANDBOX - class ConfigFileError(Exception): pass @@ -40,23 +38,5 @@ def get_favorites(path: Path) -> list[str]: return list(conf["ip_list"]) -# def is_in_favs(record: str, path: Path) -> bool: -# favs = get_favorites(path) -# if record in favs: -# return True -# return False - - def enum_to_key(enum: Preferences) -> str: return str(enum.dict["key"]) - - -def get_client_index(client: str) -> int: - if client == STEAM_CMD: - return 0 - elif client == FLATPAK_RUN_CMD: - return 1 - elif client == FLATPAK_SANDBOX: - return 2 - else: - return 0 From 31b67050170a15112c31fbd3a390ff9934d90ebf Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:40:03 +0900 Subject: [PATCH 04/17] change: parse client from path --- dzgui/init/proc.py | 9 +++++++-- dzgui/views/dialogs/wizard.py | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 9be760f..1104433 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -3,6 +3,8 @@ import subprocess import shutil import logging +from pathlib import Path + from dzgui.const.constants import ( APP_NAME, STEAM_CMD, @@ -29,8 +31,6 @@ def is_steam_running(cmd: str) -> bool: raise TypeError("Not a valid Steam client selection") -# CHORE: test alternate clients -# TODO: has_flatpak_steam def is_flatpak_steam_running() -> bool: if has_cmd(FLATPAK_CMD) is False: return False @@ -54,3 +54,8 @@ def has_cmd(cmd: str) -> bool: if shutil.which(cmd) is not None: return True return False + + +def path_to_steam_cmd(path: Path) -> str: + cmd = FLATPAK_RUN_CMD if FLATPAK_STEAM_PATH in path else STEAM_CMD + return cmd diff --git a/dzgui/views/dialogs/wizard.py b/dzgui/views/dialogs/wizard.py index b755b4a..dcb4784 100644 --- a/dzgui/views/dialogs/wizard.py +++ b/dzgui/views/dialogs/wizard.py @@ -11,12 +11,16 @@ from dzgui.api.steam import get_steam_paths from dzgui.const.constants import ( APP_NAME, APP_NAME_LOWER, + FLATPAK_RUN_CMD, + FLATPAK_STEAM_PATH, HERO_PATH, LEGACY_CONFIG_PATH, + STEAM_CMD, ) from dzgui.const.boilerplate import config_boilerplate from dzgui.const.endpoints import STEAM_API_SETUP from dzgui.config import freedesktop +from dzgui.init.proc import path_to_steam_cmd from dzgui.init.migrate import migrate_legacy_conf from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager from dzgui.strings import wizard @@ -499,7 +503,9 @@ class Assistant(Gtk.Assistant): self.config_values = self.page_migration.migrated_conf return self.get_final_page() case SteamPathPage(): - self.config_values["default_steam_path"] = page.get_path_from_radio() + path = page.get_path_from_radio() + self.config_values["default_steam_path"] = path + self.config_values["client"] = path_to_steam_cmd(path) case SteamValidationPage(): self.config_values["steam_api"] = page.get_api_key() case PreferencesPage(): @@ -507,7 +513,6 @@ class Assistant(Gtk.Assistant): name, use_miles, client = self.page_prefs.get_prefs() self.config_values["name"] = name self.config_values["use_miles"] = use_miles - self.config_values["client"] = client self.page_shortcuts.set_steam_path( self.config_values["default_steam_path"] ) From 8cdb61579626aba71a3aa2a9107e5ce760390031 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:40:56 +0900 Subject: [PATCH 05/17] chore: drop unused imports --- dzgui/views/dialogs/wizard.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/dzgui/views/dialogs/wizard.py b/dzgui/views/dialogs/wizard.py index dcb4784..c7d0440 100644 --- a/dzgui/views/dialogs/wizard.py +++ b/dzgui/views/dialogs/wizard.py @@ -11,11 +11,8 @@ from dzgui.api.steam import get_steam_paths from dzgui.const.constants import ( APP_NAME, APP_NAME_LOWER, - FLATPAK_RUN_CMD, - FLATPAK_STEAM_PATH, HERO_PATH, LEGACY_CONFIG_PATH, - STEAM_CMD, ) from dzgui.const.boilerplate import config_boilerplate from dzgui.const.endpoints import STEAM_API_SETUP From 6feae44887ef9a21b181644422b49660bd194e34 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:41:10 +0900 Subject: [PATCH 06/17] chore: add import --- dzgui/init/proc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 1104433..b063f23 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -12,6 +12,7 @@ from dzgui.const.constants import ( FLATPAK_CMD, FLATPAK_RUN_CMD, FLATPAK_SANDBOX, + FLATPAK_STEAM_PATH, ) logger = logging.getLogger(APP_NAME) From 052f7f0708eea2d1f45a649c6ffe4deac8afc6d9 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:42:50 +0900 Subject: [PATCH 07/17] chore: remove client combo from options page --- dzgui/controllers/mc.py | 3 --- dzgui/managers/config.py | 12 ------------ dzgui/views/components/misc.py | 8 +++++--- dzgui/views/pages/options.py | 25 +------------------------ 4 files changed, 6 insertions(+), 42 deletions(-) diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 59d2dd2..8267777 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -541,9 +541,6 @@ class Controller(GObject.GObject): def update_status(self) -> None: self.mediator.preconnect.mark_finished() - def get_steam_client_name(self, cmd: str) -> str: - return self.mediator.options.get_client_name(cmd) - def present_window(self) -> None: self.mediator.window.present_with_time(Gdk.CURRENT_TIME) diff --git a/dzgui/managers/config.py b/dzgui/managers/config.py index 5783b5e..7490b15 100644 --- a/dzgui/managers/config.py +++ b/dzgui/managers/config.py @@ -6,9 +6,6 @@ from typing import Any, TYPE_CHECKING from dzgui.const.constants import ( APP_NAME, - FLATPAK_RUN_CMD, - FLATPAK_SANDBOX, - STEAM_CMD, WINDOW_DEFAULT_X, WINDOW_DEFAULT_Y, ) @@ -129,15 +126,6 @@ class ConfigManager: def enum_to_key(self, enum: Preferences) -> str: return str(enum.dict["key"]) - def get_client_index(self, client: str) -> int: - if client == STEAM_CMD: - return 0 - if client == FLATPAK_RUN_CMD: - return 1 - if client == FLATPAK_SANDBOX: - return 2 - return 0 - def toggle_config(self, key: Preferences) -> None: try: real_key = self.enum_to_key(key) diff --git a/dzgui/views/components/misc.py b/dzgui/views/components/misc.py index 80ef5fd..cdc3f49 100644 --- a/dzgui/views/components/misc.py +++ b/dzgui/views/components/misc.py @@ -1,17 +1,19 @@ +from typing import Self +from warnings import deprecated + from dzgui.const.constants import ERROR, FLATPAK_RUN_CMD, FLATPAK_SANDBOX, STEAM_CMD +from dzgui.init.prereqs import has_steam_client, has_flatpak_client from dzgui.strings import options from dzgui.views.components.box import HBox from dzgui.views.components.buttons import Icon -from typing import Self -from dzgui.init.prereqs import has_steam_client, has_flatpak_client - import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk # noqa +@deprecated("Client choice is determined at setup time") class ClientCombo(Gtk.ComboBox): def __init__(self) -> None: super().__init__() diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 6b5da07..91e0b72 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -25,7 +25,7 @@ from dzgui.views.components.eventbox import InfoEventBox from dzgui.views.components.labels import LeftLabel from dzgui.views.components.buttons import SpinnerButton, WebButton from dzgui.views.components.frame import HeadingFrame -from dzgui.views.components.misc import ClientCombo, ErrorPopover +from dzgui.views.components.misc import ErrorPopover from dzgui.views.dialogs.generic import ExceptionDialog from dzgui.views.mixins.scrollable_mixin import ScrollableMixin @@ -281,11 +281,6 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore Preferences.WINDOW, ) - self.client_combo = ClientCombo() - self.client_combo.connect("changed", self._on_client_changed) - - client_hbox = ShortHBox(self.client_combo) - self.distance_toggle = ToggleField( self.controller, strings.options.km, strings.options.mi, Preferences.DIST ) @@ -309,7 +304,6 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore self.start_tab_combo.connect("changed", self._on_start_tab_changed) pref_rows = [ - [LeftLabel(strings.options.client), client_hbox], [LeftLabel(strings.options.window_size), self.fullscreen_toggle], [LeftLabel(strings.options.distance), self.distance_toggle], [LeftLabel(options.start_tab), start_tab_hbox], @@ -367,17 +361,11 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore self.connect("key-press-event", self._on_keypress) - def get_client_name(self, cmd: str) -> str: - return self.client_combo.get_client_human_readable(cmd) - def block_text_entry(self) -> None: self.steam_box.block_text_entry() - # self.steam_entry.set_position(-1) - # self.steam_entry.set_can_focus(False) def unblock_text_entry(self) -> None: self.steam_box.unblock_text_entry() - # self.steam_entry.set_can_focus(True) def _on_developers_clicked(self, button: Gtk.Button) -> None: self.controller.show_developers_page() @@ -412,13 +400,6 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore index = enum.value self.controller.update_config(Preferences.START_TAB, index) - def _on_client_changed(self, combo: Gtk.ComboBoxText) -> None: - _iter = combo.get_active_iter() - if _iter is None: - raise ValueError(f"No active iterator set on {combo}") - real_cmd = combo.get_model()[_iter][1] - self.controller.update_config(Preferences.CLIENT, real_cmd) - def populate_settings(self) -> None: prefs = self.controller.get_prefs() # NOTE: re-check in case file was removed by user between runs @@ -464,10 +445,6 @@ class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore self.dayz_version_label.set_text(dayz_version) self.dayz_exp_version_label.set_text(dayz_exp_version) - # TODO: bicolumn list store with no cell renderer on index 1, use raw command names - active_combo = query.get_client_index(config["client"]) - self.client_combo.set_active(active_combo) - start_tab = self.controller.query_config(Preferences.START_TAB) self.start_tab_combo.set_active(start_tab) From a74d576387f6d70be32c00f919a7faf3c07783f0 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:43:20 +0900 Subject: [PATCH 08/17] change: interpolate client name from full command --- dzgui/managers/connection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index 8f2a8d5..1089b4c 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -185,7 +185,8 @@ class ConnectionManager: allows_downloads = (True, "") client = self.controller.query_config(Preferences.CLIENT) - client_name = self.controller.get_steam_client_name(client) + # TODO: add test + client_name = client.split()[0].capitalize() running = is_steam_running(client) steam_proc = SteamProcess(client_name, running) self.client = client From 07460a1f8f80ff5ddfecbe8ed6f60a108ff1b2c2 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:44:41 +0900 Subject: [PATCH 09/17] chore: clear typehinting errors --- dzgui/init/proc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index b063f23..7ee9cc9 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -57,6 +57,6 @@ def has_cmd(cmd: str) -> bool: return False -def path_to_steam_cmd(path: Path) -> str: +def path_to_steam_cmd(path: str) -> str: cmd = FLATPAK_RUN_CMD if FLATPAK_STEAM_PATH in path else STEAM_CMD return cmd From eed40e6f1a91702b31244667e7b0496dea51402b Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 12:59:54 +0900 Subject: [PATCH 10/17] change: return client name from controller --- dzgui/controllers/mc.py | 5 +++++ dzgui/managers/connection.py | 3 +-- tests/test_client_name.py | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/test_client_name.py diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 8267777..afc1cba 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -541,6 +541,11 @@ class Controller(GObject.GObject): def update_status(self) -> None: self.mediator.preconnect.mark_finished() + def get_client_name(self) -> str: + # NOTE: only possible values are "Steam" and "Flatpak" + cmd = self.query_config(Preferences.CLIENT) + return cmd.split()[0].capitalize() + def present_window(self) -> None: self.mediator.window.present_with_time(Gdk.CURRENT_TIME) diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index 1089b4c..574f622 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -185,8 +185,7 @@ class ConnectionManager: allows_downloads = (True, "") client = self.controller.query_config(Preferences.CLIENT) - # TODO: add test - client_name = client.split()[0].capitalize() + client_name = self.controller.get_client_name() running = is_steam_running(client) steam_proc = SteamProcess(client_name, running) self.client = client diff --git a/tests/test_client_name.py b/tests/test_client_name.py new file mode 100644 index 0000000..27f81fc --- /dev/null +++ b/tests/test_client_name.py @@ -0,0 +1,19 @@ +import pytest + +from dzgui.const.constants import FLATPAK_RUN_CMD, STEAM_CMD +from dzgui.controllers.mc import Controller + + +@pytest.mark.parametrize( + "value, expected", [(FLATPAK_RUN_CMD, "Flatpak"), (STEAM_CMD, "Steam")] +) +def test_human_name(monkeypatch, value, expected) -> None: + def mock_query_config(*args) -> str: + return value + + monkeypatch.setattr( + "dzgui.controllers.mc.Controller.query_config", mock_query_config + ) + controller = Controller() + client = controller.get_client_name() + assert client == expected From 95988459d5b7ffc02899a78478c5860cc863246d Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:00:06 +0900 Subject: [PATCH 11/17] chore: drop unused import --- dzgui/init/proc.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 7ee9cc9..49ae327 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -3,8 +3,6 @@ import subprocess import shutil import logging -from pathlib import Path - from dzgui.const.constants import ( APP_NAME, STEAM_CMD, From 0f8b6fcaad39b5b1313083653856e873c671b62c Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:03:30 +0900 Subject: [PATCH 12/17] change: drop client combo from wizard --- dzgui/views/dialogs/wizard.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/dzgui/views/dialogs/wizard.py b/dzgui/views/dialogs/wizard.py index c7d0440..3aa6aa3 100644 --- a/dzgui/views/dialogs/wizard.py +++ b/dzgui/views/dialogs/wizard.py @@ -26,7 +26,6 @@ from dzgui.util.open_links import open_link_by_url from dzgui.util.css import add_class, load_css from dzgui.views.components.buttons import WebButton from dzgui.views.components.entry import APIEntry -from dzgui.views.components.misc import ClientCombo from dzgui.views.mixins.colorscheme import ColorAwareApp import gi @@ -385,26 +384,17 @@ class PreferencesPage(EnumeratedWizardPage): self.dist_box.add(self.radio_km) self.dist_box.add(self.radio_miles) - client_label = Gtk.Label(label=wizard.label_client, halign=Gtk.Align.START) - self.client_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) - self.client_combo = ClientCombo() - self.client_box.add(client_label) - self.client_box.add(self.client_combo) - outer_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, halign=Gtk.Align.CENTER, spacing=10 ) - for el in self.name_box, self.client_box, self.dist_box: + for el in self.name_box, self.dist_box: outer_box.add(el) self.add_start(outer_box) - def get_prefs(self) -> tuple[str, bool, str]: + def get_prefs(self) -> tuple[str, bool]: name = self.name_entry.get_text().strip() use_miles = self.radio_miles.get_active() - model = self.client_combo.get_model() - ind = self.client_combo.get_active() - client = model[ind][1] - return name, use_miles, client + return name, use_miles def _on_entry_changed(self, entry: Gtk.Entry) -> None: text = entry.get_text() @@ -507,7 +497,7 @@ class Assistant(Gtk.Assistant): self.config_values["steam_api"] = page.get_api_key() case PreferencesPage(): # NOTE: collects config values before advancing to last page - name, use_miles, client = self.page_prefs.get_prefs() + name, use_miles = self.page_prefs.get_prefs() self.config_values["name"] = name self.config_values["use_miles"] = use_miles self.page_shortcuts.set_steam_path( From 2a08b9ba82e02d32a1453fbe2b6b6e2c6937dc43 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:04:12 +0900 Subject: [PATCH 13/17] chore: clear typehinting errors --- dzgui/controllers/mc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index afc1cba..c7f3f02 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -544,7 +544,7 @@ class Controller(GObject.GObject): def get_client_name(self) -> str: # NOTE: only possible values are "Steam" and "Flatpak" cmd = self.query_config(Preferences.CLIENT) - return cmd.split()[0].capitalize() + return str(cmd.split()[0].capitalize()) def present_window(self) -> None: self.mediator.window.present_with_time(Gdk.CURRENT_TIME) From 00b5476aaff8bd877682708f7d287b310cfc1294 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 14:51:56 +0900 Subject: [PATCH 14/17] change: treat steam clients as separate processes --- dzgui/const/constants.py | 3 ++- dzgui/init/proc.py | 21 +++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/dzgui/const/constants.py b/dzgui/const/constants.py index ce90d9c..686dece 100644 --- a/dzgui/const/constants.py +++ b/dzgui/const/constants.py @@ -84,7 +84,8 @@ HERO_PATH = "data/images/_hero.png" CSS_PATH = "data/app.css" VDF_PATH = "steamapps/libraryfolders.vdf" DEFAULT_STEAM_PATH = ".local/share/Steam" -FLATPAK_STEAM_PATH = ".var/app/com.valvesoftware.Steam/data/Steam" +FLATPAK_ROOT_PATH = ".var/app/com.valvesoftware.Steam" +FLATPAK_STEAM_PATH = FLATPAK_ROOT_PATH + "/data/Steam" UBUNTU_STEAM_PATH = ".steam/steam" DEBIAN_STEAM_PATH = ".steam/debian-installation" diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 49ae327..2ad459e 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -10,6 +10,7 @@ from dzgui.const.constants import ( FLATPAK_CMD, FLATPAK_RUN_CMD, FLATPAK_SANDBOX, + FLATPAK_ROOT_PATH, FLATPAK_STEAM_PATH, ) @@ -17,15 +18,10 @@ logger = logging.getLogger(APP_NAME) def is_steam_running(cmd: str) -> bool: - is_flatpak_running = is_flatpak_steam_running() if cmd in (FLATPAK_RUN_CMD, FLATPAK_SANDBOX): - return is_flatpak_running + return is_flatpak_steam_running() elif cmd == STEAM_CMD: - if is_flatpak_running: - return False - if has_cmd(STEAM_CMD) is False: - return False - return is_running(STEAM_CMD) + return is_native_steam_running() else: raise TypeError("Not a valid Steam client selection") @@ -42,11 +38,12 @@ def is_flatpak_steam_running() -> bool: return False -def is_running(proc: str) -> bool: - for process in psutil.process_iter(["pid", "name"]): - if process.info["name"] == proc: - return True - return False +def is_native_steam_running() -> bool: + if has_cmd(STEAM_CMD) is False: + return False + procs = [p.cmdline() for p in psutil.process_iter(["pid", "name"]) if STEAM_CMD in p.info["name"]] + steam_procs = [p for p in procs if not any(FLATPAK_ROOT_PATH in sub for sub in p)] + return bool(steam_procs) def has_cmd(cmd: str) -> bool: From f2a7bde432d944ed770ff39ef3040d4a4b406a04 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 16:32:38 +0900 Subject: [PATCH 15/17] fix: collision with steam-runtime-launcher-service --- dzgui/init/proc.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 2ad459e..5e49ffb 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -38,12 +38,25 @@ def is_flatpak_steam_running() -> bool: return False +def get_steam_procs() -> list[str]: + return [ + p.cmdline() + for p in psutil.process_iter(["pid", "name"]) + if STEAM_CMD in p.info["name"] + ] + + def is_native_steam_running() -> bool: if has_cmd(STEAM_CMD) is False: return False - procs = [p.cmdline() for p in psutil.process_iter(["pid", "name"]) if STEAM_CMD in p.info["name"]] - steam_procs = [p for p in procs if not any(FLATPAK_ROOT_PATH in sub for sub in p)] - return bool(steam_procs) + substrings = [FLATPAK_ROOT_PATH, "steam-runtime-launcher-service"] + steam_procs = get_steam_procs() + native_steam_procs = [ + proc + for proc in steam_procs + if not any(sub in item for item in proc for sub in substrings) + ] + return bool(native_steam_procs) def has_cmd(cmd: str) -> bool: From 7822672cdae5a1b92fd7a3635689367d7630c409 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 16:33:17 +0900 Subject: [PATCH 16/17] chore: clear typehinting errors --- dzgui/init/proc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 5e49ffb..3d76516 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -38,7 +38,7 @@ def is_flatpak_steam_running() -> bool: return False -def get_steam_procs() -> list[str]: +def get_steam_procs() -> list[list[str]]: return [ p.cmdline() for p in psutil.process_iter(["pid", "name"]) From ae1c3a19d4d3170aa2a69af6c2673307ff02a2b9 Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Wed, 21 Oct 2026 16:35:01 +0900 Subject: [PATCH 17/17] chore: update tests --- tests/test_process_detection.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/test_process_detection.py b/tests/test_process_detection.py index 2e36063..16909fa 100644 --- a/tests/test_process_detection.py +++ b/tests/test_process_detection.py @@ -3,6 +3,7 @@ from unittest.mock import patch from dzgui.const.constants import ( FLATPAK_APPID, + FLATPAK_ROOT_PATH, FLATPAK_RUN_CMD, FLATPAK_SANDBOX, STEAM_CMD, @@ -45,16 +46,30 @@ class TestSteamDetection(unittest.TestCase): def test_native_steam(self): with patch.object(proc, "has_cmd", return_value=True): - for running in (True, False): + for output, expected in ( + ( + [ + [FLATPAK_ROOT_PATH], + "/home/user/.local/share/Steam/ubuntu12_64/steamwebhelper", + ], + True, + ), + ([[FLATPAK_ROOT_PATH]], False), + ([[FLATPAK_ROOT_PATH], ["steam-runtime-launcher-service"]], False), + ([["/home/user/.local/share/Steam/ubuntu12_64/steamwebhelper"]], True), + ( + [ + ["/home/user/.local/share/Steam/ubuntu12_64/steamwebhelper"], + "steam-runtime-launcher-service", + ], + True, + ), + ): with ( - self.subTest(running=running), - patch.object(proc, "is_running", return_value=running), + self.subTest(running=output), + patch.object(proc, "get_steam_procs", return_value=output), ): - self.assertEqual(proc.is_steam_running(STEAM_CMD), running) - - def test_native_steam_while_flatpak_is_running(self): - with patch.object(proc, "is_flatpak_steam_running", return_value=True): - self.assertEqual(proc.is_steam_running(STEAM_CMD), False) + self.assertEqual(proc.is_native_steam_running(), expected) def test_invalid_client(self): with self.assertRaises(TypeError):