diff --git a/README.md b/README.md index f547845..c2ac008 100644 --- a/README.md +++ b/README.md @@ -366,7 +366,7 @@ On the other hand, if you are in a Wayland session, it is only possible to obtai For Wayland+GNOME this requires at least one of the known compatible GNOME Shell extensions to be installed and enabled. See above in [**Requirements**](#requirements). I do not maintain the GNOME shell extensions, and they frequently need to be updated for new GNOME releases. -There are specific remaps or overrides of default remaps for several common desktop environments (or distros which have shortcut peculiarities in their default desktop setups). They become active if the desktop environment is detected correctly by the `env.py` environment evaluation module used by the config file. If that isn't working for some reason, the information about the desktop environment can be placed in some `OVERRIDE` variables in the config file. But open an issue if that seems to be necessary. +There are specific remaps or overrides of default remaps for several common desktop environments (or distros which have shortcut peculiarities in their default desktop setups). They become active if the desktop environment is detected correctly by the environment evaluation module used by the config file. If that isn't working for some reason, the information about the desktop environment can be placed in some `OVERRIDE` variables in the config file. But open an issue if that seems to be necessary. Tiling window managers may need [some adjustments](https://github.com/RedBearAK/toshy/issues/294). The example issue at the link is for i3 WM, with the physical `Meta/Super/Win` key chosen as the `Mod` key in i3 config, on a PC keyboard type. Other WMs or other configuration choices will need modifications of the solution shown. diff --git a/cosmic-dbus-service/toshy_cosmic_dbus_service.py b/cosmic-dbus-service/toshy_cosmic_dbus_service.py index 31d366e..b5764e8 100755 --- a/cosmic-dbus-service/toshy_cosmic_dbus_service.py +++ b/cosmic-dbus-service/toshy_cosmic_dbus_service.py @@ -57,6 +57,8 @@ # local imports now that path is prepped import lib.env as env +from lib.env_context import EnvironmentInfo + from protocols.cosmic_toplevel_info_unstable_v1.zcosmic_toplevel_info_v1 import ( ZcosmicToplevelInfoV1, ZcosmicToplevelInfoV1Proxy, @@ -113,14 +115,16 @@ def clean_shutdown(): def check_environment(): """Retrieve the current environment from env module""" - env_info: Dict[str, str] = env.get_env_info() # Returns a dict + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() global DISTRO_ID, DISTRO_VER, VARIANT_ID, SESSION_TYPE, DESKTOP_ENV, DE_MAJ_VER - DISTRO_ID = env_info.get('DISTRO_ID', 'keymissing') - DISTRO_VER = env_info.get('DISTRO_VER', 'keymissing') - VARIANT_ID = env_info.get('VARIANT_ID', 'keymissing') - SESSION_TYPE = env_info.get('SESSION_TYPE', 'keymissing') - DESKTOP_ENV = env_info.get('DESKTOP_ENV', 'keymissing') - DE_MAJ_VER = env_info.get('DE_MAJ_VER', 'keymissing') + DISTRO_ID = env_info_dct.get('DISTRO_ID', 'keymissing') + DISTRO_VER = env_info_dct.get('DISTRO_VER', 'keymissing') + VARIANT_ID = env_info_dct.get('VARIANT_ID', 'keymissing') + SESSION_TYPE = env_info_dct.get('SESSION_TYPE', 'keymissing') + DESKTOP_ENV = env_info_dct.get('DESKTOP_ENV', 'keymissing') + DE_MAJ_VER = env_info_dct.get('DE_MAJ_VER', 'keymissing') check_environment() diff --git a/default-toshy-config/DO_NOT_EDIT_THESE_FILES_README b/default-toshy-config/DO_NOT_EDIT_THESE_FILES_README new file mode 100644 index 0000000..9581a22 --- /dev/null +++ b/default-toshy-config/DO_NOT_EDIT_THESE_FILES_README @@ -0,0 +1,29 @@ +DO NOT EDIT THE FILES IN THIS FOLDER + + +The files in this folder are meant to be "clean" copies of the +default Toshy configuration files, to be used by the installer +or copied by the user into the parent folder in case there is +a major problem with the user's `toshy_config.py` config file. + + + +The user's editable config file is located here in the parent folder: + +~/.config/toshy/toshy_config.py + + + +To replace your config file with a new default config: + +mv ~/.config/toshy/toshy_config.py ~/.config/toshy/toshy_config.py.old +cp ~/.config/toshy/default-toshy-config/toshy_config.py ~/.config/toshy/toshy_config.py +toshy-services-restart + + + +Or, if you were using the "barebones" config file: + +mv ~/.config/toshy/toshy_config.py ~/.config/toshy/toshy_config.py.old +cp ~/.config/toshy/default-toshy-config/toshy_config_barebones.py ~/.config/toshy/toshy_config.py +toshy-services-restart diff --git a/default-toshy-config/toshy_config.py b/default-toshy-config/toshy_config.py index 45a9150..a4d0001 100644 --- a/default-toshy-config/toshy_config.py +++ b/default-toshy-config/toshy_config.py @@ -146,6 +146,8 @@ sys.path.insert(0, current_folder_path) import lib.env + +from lib.env_context import EnvironmentInfo from lib.settings_class import Settings from lib.notification_manager import NotificationManager @@ -157,7 +159,7 @@ # Toshy config file TOSHY_PART = 'config' # CUSTOMIZE TO SPECIFIC TOSHY COMPONENT! (gui, tray, config) TOSHY_PART_NAME = 'Toshy Config file' -APP_VERSION = '2024.0804' +APP_VERSION = '2024.0904' # Settings object used to tweak preferences "live" between gui, tray and config. cnfg = Settings(current_folder_path) @@ -191,6 +193,7 @@ OVERRIDE_SESSION_TYPE = None OVERRIDE_DESKTOP_ENV = None OVERRIDE_DE_MAJ_VER = None +OVERRIDE_WINDOW_MGR = None wlroots_compositors = [ # Comma-separated list of Wayland desktop environments or window managers @@ -204,30 +207,44 @@ ### SLICE_MARK_END: env_overrides ### EDITS OUTSIDE THESE MARKS WILL BE LOST ON UPGRADE ################################################################################################### -# leave all of this alone! +# Leave all of this alone! Don't try to override values here. DISTRO_ID = None DISTRO_VER = None VARIANT_ID = None SESSION_TYPE = None DESKTOP_ENV = None DE_MAJ_VER = None +WINDOW_MGR = None + +# env_info: Dict[str, str] = lib.env.get_env_info() + +# DISTRO_ID = locals().get('OVERRIDE_DISTRO_ID') or env_info.get('DISTRO_ID', 'keymissing') +# DISTRO_VER = locals().get('OVERRIDE_DISTRO_VER') or env_info.get('DISTRO_VER', 'keymissing') +# VARIANT_ID = locals().get('OVERRIDE_VARIANT_ID') or env_info.get('VARIANT_ID', 'keymissing') +# SESSION_TYPE = locals().get('OVERRIDE_SESSION_TYPE') or env_info.get('SESSION_TYPE', 'keymissing') +# DESKTOP_ENV = locals().get('OVERRIDE_DESKTOP_ENV') or env_info.get('DESKTOP_ENV', 'keymissing') +# DE_MAJ_VER = locals().get('OVERRIDE_DE_MAJ_VER') or env_info.get('DE_MAJ_VER', 'keymissing') -env_info: Dict[str, str] = lib.env.get_env_info() +env_ctxt_getter = EnvironmentInfo() +env_ctxt: Dict[str, str] = env_ctxt_getter.get_env_info() -DISTRO_ID = locals().get('OVERRIDE_DISTRO_ID') or env_info.get('DISTRO_ID', 'keymissing') -DISTRO_VER = locals().get('OVERRIDE_DISTRO_VER') or env_info.get('DISTRO_VER', 'keymissing') -VARIANT_ID = locals().get('OVERRIDE_VARIANT_ID') or env_info.get('VARIANT_ID', 'keymissing') -SESSION_TYPE = locals().get('OVERRIDE_SESSION_TYPE') or env_info.get('SESSION_TYPE', 'keymissing') -DESKTOP_ENV = locals().get('OVERRIDE_DESKTOP_ENV') or env_info.get('DESKTOP_ENV', 'keymissing') -DE_MAJ_VER = locals().get('OVERRIDE_DE_MAJ_VER') or env_info.get('DE_MAJ_VER', 'keymissing') +DISTRO_ID = locals().get('OVERRIDE_DISTRO_ID') or env_ctxt.get('DISTRO_ID', 'keymissing') +DISTRO_VER = locals().get('OVERRIDE_DISTRO_VER') or env_ctxt.get('DISTRO_VER', 'keymissing') +VARIANT_ID = locals().get('OVERRIDE_VARIANT_ID') or env_ctxt.get('VARIANT_ID', 'keymissing') +SESSION_TYPE = locals().get('OVERRIDE_SESSION_TYPE') or env_ctxt.get('SESSION_TYPE', 'keymissing') +DESKTOP_ENV = locals().get('OVERRIDE_DESKTOP_ENV') or env_ctxt.get('DESKTOP_ENV', 'keymissing') +DE_MAJ_VER = locals().get('OVERRIDE_DE_MAJ_VER') or env_ctxt.get('DE_MAJ_VER', 'keymissing') +WINDOW_MGR = locals().get('OVERRIDE_WINDOW_MGR') or env_ctxt.get('WINDOW_MGR', 'keymissing') debug("") debug( f'Toshy config sees this environment:' f'\n\t{DISTRO_ID = }' f'\n\t{DISTRO_VER = }' + f'\n\t{VARIANT_ID = }' f'\n\t{SESSION_TYPE = }' f'\n\t{DESKTOP_ENV = }' - f'\n\t{DE_MAJ_VER = }\n', ctx="CG") + f'\n\t{DE_MAJ_VER = }' + f'\n\t{WINDOW_MGR = }\n', ctx="CG") # TODO: Add a list here to concat with 'wlroots_compositors', instead of @@ -235,15 +252,20 @@ # the keymapper. known_wlroots_compositors = [ 'hyprland', + 'labwc', # untested but should work 'niri', 'qtile', + 'river', # untested but should work 'sway', + 'wayfire', # untested but should work ] # Make sure the 'wlroots_compositors' list variable exists before checking it. # Older config files won't have it in the 'env_overrides' slice. wlroots_compositors = locals().get('wlroots_compositors', []) +all_wlroots_compositors = known_wlroots_compositors + wlroots_compositors + # Direct the keymapper to try to use `wlroots` window context for # all DEs/WMs in user list, if list is not empty. if wlroots_compositors and DESKTOP_ENV in wlroots_compositors: @@ -253,6 +275,13 @@ elif DESKTOP_ENV in known_wlroots_compositors: debug(f"DE/WM '{DESKTOP_ENV}' is in known 'wlroots' compositor list.", ctx="CG") _desktop_env = 'wlroots' +elif (SESSION_TYPE, DESKTOP_ENV) == ('wayland', 'lxqt') and WINDOW_MGR == 'kwin_wayland': + # The Toshy KWin script must be installed in the LXQt/KWin environment for this to work! + debug(f"DE is LXQt, WM is '{WINDOW_MGR}', using 'kde' window context method.", ctx="CG") + _desktop_env = 'kde' +elif (SESSION_TYPE, DESKTOP_ENV) == ('wayland', 'lxqt') and WINDOW_MGR in all_wlroots_compositors: + debug(f"DE is LXQt, WM is '{WINDOW_MGR}', using 'wlroots' window context method.", ctx="CG") + _desktop_env = 'wlroots' else: _desktop_env = DESKTOP_ENV @@ -1250,6 +1279,7 @@ def escape_markup(text: str): f" • SESSION_TYPE _________ '{SESSION_TYPE }' {nwln_str}" f" • DESKTOP_ENV __________ '{DESKTOP_ENV }' {nwln_str}" f" • DE_MAJ_VER ___________ '{DE_MAJ_VER }' {nwln_str}" + f" • WINDOW_MGR ___________ '{WINDOW_MGR }' {nwln_str}" f"{nwln_str}" f"Do any app class groups match on this window?: {nwln_str}" f" • Terminals ____________ '{ctx_term}' {nwln_str}" diff --git a/default-toshy-config/toshy_config_barebones.py b/default-toshy-config/toshy_config_barebones.py index 4682a9c..f45de75 100644 --- a/default-toshy-config/toshy_config_barebones.py +++ b/default-toshy-config/toshy_config_barebones.py @@ -76,6 +76,8 @@ sys.path.insert(0, current_folder_path) import lib.env + +from lib.env_context import EnvironmentInfo from lib.settings_class import Settings from lib.notification_manager import NotificationManager @@ -87,7 +89,7 @@ # Toshy config file TOSHY_PART = 'config' # CUSTOMIZE TO SPECIFIC TOSHY COMPONENT! (gui, tray, config) TOSHY_PART_NAME = 'Toshy Barebones Config' -APP_VERSION = '2024.0801' +APP_VERSION = '2024.0904' # Settings object used to tweak preferences "live" between gui, tray and config. cnfg = Settings(current_folder_path) @@ -121,6 +123,7 @@ OVERRIDE_SESSION_TYPE = None OVERRIDE_DESKTOP_ENV = None OVERRIDE_DE_MAJ_VER = None +OVERRIDE_WINDOW_MGR = None wlroots_compositors = [ # Comma-separated list of Wayland desktop environments or window managers @@ -134,30 +137,44 @@ ### SLICE_MARK_END: env_overrides ### EDITS OUTSIDE THESE MARKS WILL BE LOST ON UPGRADE ################################################################################################### -# leave all of this alone! +# Leave all of this alone! Don't try to override values here. DISTRO_ID = None DISTRO_VER = None VARIANT_ID = None SESSION_TYPE = None DESKTOP_ENV = None DE_MAJ_VER = None +WINDOW_MGR = None + +# env_info: Dict[str, str] = lib.env.get_env_info() + +# DISTRO_ID = locals().get('OVERRIDE_DISTRO_ID') or env_info.get('DISTRO_ID', 'keymissing') +# DISTRO_VER = locals().get('OVERRIDE_DISTRO_VER') or env_info.get('DISTRO_VER', 'keymissing') +# VARIANT_ID = locals().get('OVERRIDE_VARIANT_ID') or env_info.get('VARIANT_ID', 'keymissing') +# SESSION_TYPE = locals().get('OVERRIDE_SESSION_TYPE') or env_info.get('SESSION_TYPE', 'keymissing') +# DESKTOP_ENV = locals().get('OVERRIDE_DESKTOP_ENV') or env_info.get('DESKTOP_ENV', 'keymissing') +# DE_MAJ_VER = locals().get('OVERRIDE_DE_MAJ_VER') or env_info.get('DE_MAJ_VER', 'keymissing') -env_info: Dict[str, str] = lib.env.get_env_info() +env_ctxt_getter = EnvironmentInfo() +env_ctxt: Dict[str, str] = env_ctxt_getter.get_env_info() -DISTRO_ID = locals().get('OVERRIDE_DISTRO_ID') or env_info.get('DISTRO_ID', 'keymissing') -DISTRO_VER = locals().get('OVERRIDE_DISTRO_VER') or env_info.get('DISTRO_VER', 'keymissing') -VARIANT_ID = locals().get('OVERRIDE_VARIANT_ID') or env_info.get('VARIANT_ID', 'keymissing') -SESSION_TYPE = locals().get('OVERRIDE_SESSION_TYPE') or env_info.get('SESSION_TYPE', 'keymissing') -DESKTOP_ENV = locals().get('OVERRIDE_DESKTOP_ENV') or env_info.get('DESKTOP_ENV', 'keymissing') -DE_MAJ_VER = locals().get('OVERRIDE_DE_MAJ_VER') or env_info.get('DE_MAJ_VER', 'keymissing') +DISTRO_ID = locals().get('OVERRIDE_DISTRO_ID') or env_ctxt.get('DISTRO_ID', 'keymissing') +DISTRO_VER = locals().get('OVERRIDE_DISTRO_VER') or env_ctxt.get('DISTRO_VER', 'keymissing') +VARIANT_ID = locals().get('OVERRIDE_VARIANT_ID') or env_ctxt.get('VARIANT_ID', 'keymissing') +SESSION_TYPE = locals().get('OVERRIDE_SESSION_TYPE') or env_ctxt.get('SESSION_TYPE', 'keymissing') +DESKTOP_ENV = locals().get('OVERRIDE_DESKTOP_ENV') or env_ctxt.get('DESKTOP_ENV', 'keymissing') +DE_MAJ_VER = locals().get('OVERRIDE_DE_MAJ_VER') or env_ctxt.get('DE_MAJ_VER', 'keymissing') +WINDOW_MGR = locals().get('OVERRIDE_WINDOW_MGR') or env_ctxt.get('WINDOW_MGR', 'keymissing') debug("") debug( f'Toshy (barebones) config sees this environment:' f'\n\t{DISTRO_ID = }' f'\n\t{DISTRO_VER = }' + f'\n\t{VARIANT_ID = }' f'\n\t{SESSION_TYPE = }' f'\n\t{DESKTOP_ENV = }' - f'\n\t{DE_MAJ_VER = }\n', ctx="CG") + f'\n\t{DE_MAJ_VER = }' + f'\n\t{WINDOW_MGR = }\n', ctx="CG") # TODO: Add a list here to concat with 'wlroots_compositors', instead of @@ -209,7 +226,7 @@ # Establish important global variables here -startup_timestamp = time.time() # only gets evaluated once for each run of keymapper +STARTUP_TIMESTAMP = time.time() # only gets evaluated once for each run of keymapper # Variable to hold the keyboard type KBTYPE = None @@ -542,6 +559,11 @@ def _isDoubleTap(): return _isDoubleTap +total_matchProps_iterations = 0 +MAX_MATCHPROPS_ITERATIONS = 1000 +MAX_MATCHPROPS_ITERATIONS_REACHED = False + + # Correct syntax to reject all positional parameters: put `*,` at beginning def matchProps(*, # string parameters (positive matching) @@ -605,15 +627,31 @@ def matchProps(*, # https://stackoverflow.com/questions/406230/\ # regular-expression-to-match-a-line-that-doesnt-contain-a-word - logging_enabled = False + global MAX_MATCHPROPS_ITERATIONS_REACHED + global total_matchProps_iterations + + # Return `False` immediately if screen does not have focus (e.g. Synergy), + # but only after the guard clauses have had a chance to evaluate on + # all possible uses of the function that may exist in the config. + if MAX_MATCHPROPS_ITERATIONS_REACHED and not cnfg.screen_has_focus: + return False + + if total_matchProps_iterations >= MAX_MATCHPROPS_ITERATIONS: + MAX_MATCHPROPS_ITERATIONS_REACHED = True + bypass_guard_clauses = True + else: + total_matchProps_iterations += 1 + current_timestamp = time.time() - current_timestamp = time.time() - time_elapsed = current_timestamp - startup_timestamp + # 'STARTUP_TIMESTAMP' is a global variable, set when config is executed + time_elapsed = current_timestamp - STARTUP_TIMESTAMP - # Bypass all guard clauses if more than a few seconds have passed since keymapper - # started and loaded the config file. Inputs never change until keymapper - # restarts and reloads the config file, so we don't need to keep checking. - bypass_guard_clauses = time_elapsed > 6 + # Bypass all guard clauses if more than a few seconds have passed since keymapper + # started and loaded the config file. Inputs never change until keymapper + # restarts and reloads the config file, so we don't need to keep checking. + bypass_guard_clauses = time_elapsed > 6 + + logging_enabled = False allowed_params = (clas, name, devn, not_clas, not_name, not_devn, numlk, capslk, cse, lst, not_lst, dbg) @@ -633,7 +671,7 @@ def matchProps(*, 'numlk', 'capslk', 'cse', 'lst', 'not_lst', 'dbg' ] - if not bypass_guard_clauses: + if not MAX_MATCHPROPS_ITERATIONS_REACHED or not bypass_guard_clauses: if all([x is None for x in allowed_params]): raise ValueError(f"\n\n(EE) matchProps(): Received no valid argument\n") if any([x not in (True, False, None) for x in (numlk, capslk, cse)]): @@ -655,7 +693,7 @@ def matchProps(*, # process lists of conditions if _lst is not None: - if not bypass_guard_clauses: + if not MAX_MATCHPROPS_ITERATIONS_REACHED or not bypass_guard_clauses: if any([x is not None for x in lst_dct_params]): raise TypeError(f"\n\n(EE) matchProps(): Param 'lst|not_lst' must be used alone\n") if not isinstance(_lst, list) or not all(isinstance(item, dict) for item in _lst): @@ -871,6 +909,7 @@ def escape_markup(text: str): f" • SESSION_TYPE _________ '{SESSION_TYPE }' {nwln_str}" f" • DESKTOP_ENV __________ '{DESKTOP_ENV }' {nwln_str}" f" • DE_MAJ_VER ___________ '{DE_MAJ_VER }' {nwln_str}" + f" • WINDOW_MGR ___________ '{WINDOW_MGR }' {nwln_str}" f"{nwln_str}" f" __________________________________________________ {nwln_str}" f"Keyboard shortcuts (Ctrl+C/Cmd+C) may not work here.{nwln_str}" diff --git a/kde-kwin-dbus-service/toshy_kde_dbus_service.py b/kde-kwin-dbus-service/toshy_kde_dbus_service.py index 7b66cf0..eabd901 100755 --- a/kde-kwin-dbus-service/toshy_kde_dbus_service.py +++ b/kde-kwin-dbus-service/toshy_kde_dbus_service.py @@ -37,6 +37,8 @@ # local imports now that path is prepped import lib.env as env +from lib.env_context import EnvironmentInfo + if os.name == 'posix' and os.geteuid() == 0: error("This app should not be run as root/superuser.") sys.exit(1) @@ -72,14 +74,16 @@ def signal_handler(sig, frame): def check_environment(): """Retrieve the current environment from env module""" - env_info: Dict[str, str] = env.get_env_info() # Returns a dict + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() global DISTRO_ID, DISTRO_VER, VARIANT_ID, SESSION_TYPE, DESKTOP_ENV, DE_MAJ_VER - DISTRO_ID = env_info.get('DISTRO_ID', 'keymissing') - DISTRO_VER = env_info.get('DISTRO_VER', 'keymissing') - VARIANT_ID = env_info.get('VARIANT_ID', 'keymissing') - SESSION_TYPE = env_info.get('SESSION_TYPE', 'keymissing') - DESKTOP_ENV = env_info.get('DESKTOP_ENV', 'keymissing') - DE_MAJ_VER = env_info.get('DE_MAJ_VER', 'keymissing') + DISTRO_ID = env_info_dct.get('DISTRO_ID', 'keymissing') + DISTRO_VER = env_info_dct.get('DISTRO_VER', 'keymissing') + VARIANT_ID = env_info_dct.get('VARIANT_ID', 'keymissing') + SESSION_TYPE = env_info_dct.get('SESSION_TYPE', 'keymissing') + DESKTOP_ENV = env_info_dct.get('DESKTOP_ENV', 'keymissing') + DE_MAJ_VER = env_info_dct.get('DE_MAJ_VER', 'keymissing') check_environment() diff --git a/kde-kwin-dbus-service/toshy_kde_kwin_script_setup.py b/kde-kwin-dbus-service/toshy_kde_kwin_script_setup.py index abbb556..c54c35d 100755 --- a/kde-kwin-dbus-service/toshy_kde_kwin_script_setup.py +++ b/kde-kwin-dbus-service/toshy_kde_kwin_script_setup.py @@ -31,6 +31,8 @@ # local imports now that path is prepped import lib.env as env +from lib.env_context import EnvironmentInfo + if os.name == 'posix' and os.geteuid() == 0: error("This app should not be run as root/superuser.") sys.exit(1) @@ -68,14 +70,16 @@ def signal_handler(sig, frame): def check_environment(): """Retrieve the current environment from env module""" - env_info: Dict[str, str] = env.get_env_info() # Returns a dict + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() global DISTRO_ID, DISTRO_VER, VARIANT_ID, SESSION_TYPE, DESKTOP_ENV, DE_MAJ_VER - DISTRO_ID = env_info.get('DISTRO_ID', 'keymissing') - DISTRO_VER = env_info.get('DISTRO_VER', 'keymissing') - VARIANT_ID = env_info.get('VARIANT_ID', 'keymissing') - SESSION_TYPE = env_info.get('SESSION_TYPE', 'keymissing') - DESKTOP_ENV = env_info.get('DESKTOP_ENV', 'keymissing') - DE_MAJ_VER = env_info.get('DE_MAJ_VER', 'keymissing') + DISTRO_ID = env_info_dct.get('DISTRO_ID', 'keymissing') + DISTRO_VER = env_info_dct.get('DISTRO_VER', 'keymissing') + VARIANT_ID = env_info_dct.get('VARIANT_ID', 'keymissing') + SESSION_TYPE = env_info_dct.get('SESSION_TYPE', 'keymissing') + DESKTOP_ENV = env_info_dct.get('DESKTOP_ENV', 'keymissing') + DE_MAJ_VER = env_info_dct.get('DE_MAJ_VER', 'keymissing') check_environment() diff --git a/lib/env_context.py b/lib/env_context.py new file mode 100644 index 0000000..15bfda4 --- /dev/null +++ b/lib/env_context.py @@ -0,0 +1,520 @@ +#!/usr/bin/env python3 + +import re +import os +import time +import shutil +import subprocess + +from typing import Dict + +# ENV_CONTEXT module version: 2024-09-06 + +VERBOSE = True +FLUSH = True + +def debug(*args, ctx="DD"): + if not VERBOSE: + return + + # allow blank lines without context + if len(args) == 0 or (len(args) == 1 and args[0] == ""): + print("", flush=FLUSH) + return + print(f"({ctx})", *args, flush=FLUSH) + +def warn(*args, ctx="WW"): + print(f"({ctx})", *args, flush=FLUSH) + +def error(*args, ctx="EE"): + print(f"({ctx})", *args, flush=FLUSH) + +def log(*args, ctx="--"): + print(f"({ctx})", *args, flush=FLUSH) + +def info(*args, ctx="--"): + log(*args, ctx=ctx) + + + +############################# ENVIRONMENT ############################## +### ### +### ### +### ███████ ███ ██ ██ ██ ██ ██████ ██████ ███ ██ ### +### ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ### +### █████ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██ ### +### ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ### +### ███████ ██ ████ ████ ██ ██ ██ ██████ ██ ████ ### +### ### +### ### +########################################################################## +# Set up some useful environment variables + + +class EnvironmentInfo: + def __init__(self): + self.DISTRO_ID = None + self.DISTRO_VER = None + self.VARIANT_ID = None + self.SESSION_TYPE = None + self.DESKTOP_ENV = None + self.DE_MAJ_VER = None + self.WINDOW_MGR = None + + self.env_info_dct: Dict[str, str] = {} + self.release_files: Dict[str, str] = self.read_release_files() + + def get_env_info(self): + """Primary method to get complete environment info""" + + # Call methods to populate the instance variables with info. + # As of 2024-09-04 there are seven different bits of info to generate. + self.get_distro_id() + self.get_distro_version() + self.get_variant_id() + self.get_session_type() + self.get_desktop_environment() + self.get_desktop_env_version() + self.get_window_manager() + + # Collect all info into a dictionary + self.env_info_dct = { + 'DISTRO_ID': self.DISTRO_ID, + 'DISTRO_VER': self.DISTRO_VER, + 'VARIANT_ID': self.VARIANT_ID, + 'SESSION_TYPE': self.SESSION_TYPE, + 'DESKTOP_ENV': self.DESKTOP_ENV, + 'DE_MAJ_VER': self.DE_MAJ_VER, + 'WINDOW_MGR': self.WINDOW_MGR, + } + return self.env_info_dct + + def read_release_files(self) -> Dict[str, str]: + paths = [ + '/etc/os-release', '/etc/lsb-release', '/etc/arch-release' + ] + contents = {} + for path in paths: + if os.path.isfile(path): + with open(path, 'r', encoding='UTF-8') as file: + contents[path] = file.read().splitlines() + return contents + + def get_distro_id(self): + """logic to set self.DISTRO_ID""" + _distro_id = "" + + if _distro_id == "" and self.release_files['/etc/os-release']: + for prefix in ['ID=', 'NAME=', 'PRETTY_NAME=']: + for line in self.release_files['/etc/os-release']: + if line.startswith(prefix): + _distro_id = line.split('=')[1].strip().strip('"') + break + if _distro_id != "": + break + + if _distro_id == "" and self.release_files['/etc/lsb-release']: + for prefix in ['DISTRIB_ID=', 'DISTRIB_DESCRIPTION=']: + for line in self.release_files['/etc/lsb-release']: + if line.startswith(prefix): + _distro_id = line.split('=')[1].strip().strip('"') + break + if _distro_id != "": + break + + if _distro_id == "" and self.release_files['/etc/arch-release']: + _distro_id = 'arch' + + distro_names = { # simplify distro names to an ID, if necessary + 'Debian.*': 'debian', + # 'elementary': 'eos', + 'Fedora.*': 'fedora', + 'LMDE.*': 'lmde', + 'Manjaro': 'manjaro', + 'KDE.*Neon': 'neon', + 'Linux.*Mint': 'mint', + 'openSUSE.*Tumbleweed': 'opensuse-tumbleweed', + 'Peppermint.*': 'peppermint', + 'Pop!_OS': 'pop', + 'Red.*Hat.*': 'rhel', + 'Rocky.*': 'rocky', + 'Ubuntu': 'ubuntu', + 'Ultramarine.*Linux': 'ultramarine', + 'Zorin.*': 'zorin', + } + + # if the regex string from dict key is in the distro name name retrieved, + # replace with corresponding simplified dict value for simpler matching + for k, v in distro_names.items(): + # debug(f'{k = :<10} {v = :<10}') + if re.search(k, _distro_id, re.I): + self.DISTRO_ID = v + break + + # If distro name not found in list, just show original name + if not self.DISTRO_ID: + self.DISTRO_ID = _distro_id + + # filter distro name to lower case if string (not `None`) + if isinstance(self.DISTRO_ID, str): + self.DISTRO_ID = self.DISTRO_ID.casefold() + + def get_distro_version(self): + """logic to set self.DISTRO_VER""" + + if self.release_files['/etc/os-release']: + for line in self.release_files['/etc/os-release']: + line: str + if line.startswith('VERSION_ID='): + self.DISTRO_VER = line.split('=')[1].strip().strip('"') + break + elif self.release_files['/etc/lsb-release']: + for line in self.release_files['/etc/lsb-release']: + line: str + if line.startswith('DISTRIB_RELEASE='): + self.DISTRO_VER = line.split('=')[1].strip().strip('"') + break + + if not self.DISTRO_VER: + self.DISTRO_VER = 'notfound' + + def get_variant_id(self): + """logic to set self.VARIANT_ID, if variant info available""" + + if self.release_files['/etc/os-release']: + for line in self.release_files['/etc/os-release']: + line: str + if line.startswith('VARIANT_ID='): + self.VARIANT_ID = line.split('=')[1].strip().strip('"') + break + elif self.release_files['/etc/lsb-release']: + for line in self.release_files['/etc/lsb-release']: + line: str + if line.startswith('DISTRIB_DESCRIPTION='): + self.VARIANT_ID = line.split('=')[1].strip().strip('"') + break + + if not self.VARIANT_ID: + self.VARIANT_ID = 'notfound' + + def get_session_type(self): + """logic to set self.SESSION_TYPE""" + self.SESSION_TYPE = os.environ.get("XDG_SESSION_TYPE") or None + + if not self.SESSION_TYPE: # Why isn't XDG_SESSION_TYPE set? This shouldn't happen. + error(f'ENV: XDG_SESSION_TYPE should really be set. Are you in a graphical environment?') + time.sleep(3) + + # Deal with archaic distros like antiX that fail to set XDG_SESSION_TYPE + xorg_check_p1 = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE) + xorg_check_p2 = subprocess.Popen( + ['grep', '-i', '-c', 'xorg'], + stdin=xorg_check_p1.stdout, + stdout=subprocess.PIPE) + xorg_check_p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. + xorg_check_output = xorg_check_p2.communicate()[0] + xorg_count = int(xorg_check_output.decode()) - 1 + + if xorg_count: + self.SESSION_TYPE = 'x11' + + wayland_check_p1 = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE) + wayland_check_p2 = subprocess.Popen( + ['grep', '-i', '-c', 'wayland'], + stdin=wayland_check_p1.stdout, + stdout=subprocess.PIPE) + wayland_check_p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. + wayland_check_output = wayland_check_p2.communicate()[0] + wayland_count = int(wayland_check_output.decode()) - 1 + + if wayland_count: + self.SESSION_TYPE = 'wayland' + + if not self.SESSION_TYPE: + self.SESSION_TYPE = os.environ.get("WAYLAND_DISPLAY") or None + if not self.SESSION_TYPE: + raise EnvironmentError( + f'\n\nENV: Detecting session type failed.\n') + + if isinstance(self.SESSION_TYPE, str): + self.SESSION_TYPE = self.SESSION_TYPE.casefold() + + if self.SESSION_TYPE not in ['x11', 'wayland', 'tty']: + error(f'\n\nENV: Unknown session type: {self.SESSION_TYPE}.\n') + + def is_qtile_running(self): + """Utility function to detect Qtile if the usual environment vars are not set/empty""" + xdg_cache_home = os.environ.get('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + display = os.environ.get('DISPLAY') + wayland_display = os.environ.get('WAYLAND_DISPLAY') + desktop_session = os.environ.get('DESKTOP_SESSION') + + socket_paths = [] + + if display: + socket_paths.append(os.path.join(xdg_cache_home, f'qtile/qtilesocket.{display}')) + + if wayland_display: + socket_paths.append(os.path.join(xdg_cache_home, f'qtile/qtilesocket.{wayland_display}')) + + if desktop_session and 'qtile' in desktop_session: + return True + + for socket_path in socket_paths: + if os.path.exists(socket_path): + return True + + return False + + def get_desktop_environment(self): + """logic to set self.DESKTOP_ENV and self.DE_MAJ_VER""" + _desktop_env = "" + + _desktop_env = ( + os.environ.get("XDG_CURRENT_DESKTOP") or + os.environ.get("XDG_SESSION_DESKTOP") or + os.environ.get("DESKTOP_SESSION") + ) + + # Check for Qtile if the environment variables were not set/empty + if not _desktop_env and self.is_qtile_running(): + _desktop_env = 'qtile' + + if not _desktop_env: + _desktop_env = None + error("ERR: DE not found in XDG_SESSION_DESKTOP, XDG_CURRENT_DESKTOP or DESKTOP_SESSION.") + error("ERR: Config file will not be able to adapt automatically to Desktop Environment.") + if self.SESSION_TYPE == 'wayland': + error("ERR: No generic Wayland window context method is currently available.") + + # Protect '.lower()' method from NoneType error + if _desktop_env and 'unity' in _desktop_env.lower(): + self.DESKTOP_ENV = 'unity' + + # Produce a simplified desktop environment name + desktop_env_names = { + 'Budgie': 'budgie', + 'Cinnamon': 'cinnamon', + 'COSMIC': 'cosmic', + 'Cutefish': 'cutefish', + 'DDE': 'dde', + 'Deepin': 'deepin', + 'Enlightenment': 'enlightenment', + 'GNOME': 'gnome', + 'Hyprland': 'hyprland', + 'i3': 'i3', + 'i3wm': 'i3', + 'IceWM': 'icewm', + 'KDE': 'kde', + 'LXDE': 'lxde', + 'LXQt': 'lxqt', + 'MATE': 'mate', + 'Niri': 'niri', + 'Pantheon': 'pantheon', + 'Plasma': 'kde', + 'qtile:wlroots': 'qtile', + 'Qtile': 'qtile', + 'qtilewaylan': 'qtile', # actual value in real life (typo in Qtile code?) + 'qtilewayland': 'qtile', # might appear if they fix the typo + 'qtilex11': 'qtile', + 'Sway': 'sway', + 'SwayWM': 'sway', + 'Trinity': 'trinity', + 'UKUI': 'ukui', # Ubuntu Kylin desktop shell + 'Unity': 'unity', # keep above "Ubuntu" to always catch 'unity' first + 'Ubuntu': 'gnome', # "Ubuntu" in XDG_CURRENT_DESKTOP, but DE is GNOME + 'Wayfire': 'wayfire', + 'WindowMaker': 'wmaker', + 'Xfce': 'xfce', + } + + if not self.DESKTOP_ENV: + for k, v in desktop_env_names.items(): + # debug(f'{k = :<10} {v = :<10}') + if _desktop_env is None: break # watch out for NoneType here + if re.search(k, _desktop_env, re.I): + self.DESKTOP_ENV = v + if self.DESKTOP_ENV: + break + + # say DE should be added to list only if it it isn't None + if not self.DESKTOP_ENV and _desktop_env is not None: + error(f'DE or window manager not in desktop_env_names list! Should fix this.\n\t{_desktop_env}') + self.DESKTOP_ENV = _desktop_env + + # do this only if DESKTOP_ENV is still None after the above step + if not self.DESKTOP_ENV: + # Doublecheck the desktop environment by checking for identifiable running processes + def check_process(names, desktop_env): + # nonlocal DESKTOP_ENV + for name in names: + command = f"pgrep {name}" + try: + subprocess.check_output(command, shell=True) + if self.DESKTOP_ENV != desktop_env: + error( f"Desktop may be misidentified: '{self.DESKTOP_ENV}'\n" + f"'{desktop_env}' was detected and will be used instead.") + self.DESKTOP_ENV = desktop_env + break # Stop checking if any of the processes are found + except subprocess.CalledProcessError: + pass + + processes = { + 'kde': ['plasmashell', 'kwin_ft', 'kwin_wayland', 'kwin_x11', 'kwin'], + 'gnome': ['gnome-shell'], + 'sway': ['sway', 'swaywm'], + 'hyprland': ['hyprland'], + } + + for desktop_env, process_names in processes.items(): + check_process(process_names, desktop_env) + + def get_kde_version(self): + kde_session_version = os.environ.get('KDE_SESSION_VERSION') + if kde_session_version: + if kde_session_version in ['3', '4', '5', '6']: + return kde_session_version + else: + error(f"KDE_SESSION_VERSION contains unrecognized value: '{kde_session_version}'") + if shutil.which("kpackagetool6"): # or shutil.which("kwriteconfig6"): + return '6' + elif shutil.which("kpackagetool5"): # or shutil.which("kwriteconfig5"): + return '5' + elif shutil.which("kpackagetool"): # or shutil.which("kwriteconfig"): + # In KDE 4, these tools don't have a version number in their name + # Additional check for KDE 4 versioning can be done here if necessary + return '4' + # no 'kpackagetool' command in KDE 3? + return 'kde_ver_check_err' + + def get_desktop_env_version(self): + """logic to set self.DE_MAJ_VER""" + + if self.DESKTOP_ENV == 'gnome': + try: + # Run the gnome-shell command to get the version + output = subprocess.check_output(["gnome-shell", "--version"]).decode().strip() + # Use regular expression to extract the major version number + match = re.search(r"GNOME Shell (\d+)\.", output) + if match: + self.DE_MAJ_VER = match.group(1) + except subprocess.CalledProcessError as proc_err: + error(f"Error obtaining GNOME version: {proc_err}") + + elif self.DESKTOP_ENV == 'kde': + self.DE_MAJ_VER = self.get_kde_version() + + if not self.DE_MAJ_VER: + self.DE_MAJ_VER = 'no_logic_for_DE' + + def get_lxqt_window_manager(self): + """Further steps to identify possible LXQt window manager""" + # If DE is LXQt and WM still not found after above search, try checking its config file: + # cat ~/.config/lxqt/session.conf | grep WindowManager + config_path = os.path.expanduser('~/.config/lxqt/session.conf') + try: + with open(config_path, 'r') as config_file: + for line in config_file: + if line.startswith('window_manager='): + # Typically the line would be like "window_manager=openbox\n" + wm_name = line.strip().split('=')[1] + if self.is_process_running(wm_name): + self.WINDOW_MGR = wm_name + return + else: + # Fallback to checking other known WMs in case config is outdated + break + except FileNotFoundError: + # Handle cases where the config file does not exist + print(f"Could not find LXQt config file at: {config_path}") + + def is_process_running(self, process_name): + try: + subprocess.check_output(['pgrep', '-x', process_name]) + return True + except subprocess.CalledProcessError: + return False + + def get_window_manager(self): + """ + logic to set self.WINDOW_MGR + Useful in environments like LXQt that can have various window managers. + """ + + # Common "desktop environments" mapped to likely actual "window manager" process names + de_wm_map = { + + # Older KDE may use 'kwin' process name + 'kde': [ + 'kwin', + 'kwin_x11', + 'kwin_wayland' + ], + + # Older GNOME may have 'mutter' integrated into 'gnome-shell' process + 'gnome': [ + 'mutter', + 'gnome-shell' + ], + + # LXQt often uses OpenBox, but can use a number of different WMs in X11 or Wayland + 'lxqt': [ + 'openbox', + 'labwc', + 'sway', + 'hyprland', + 'kwin_wayland', + 'wayfire', + 'river' + ], + + 'openbox': 'openbox', + 'xfce': 'xfwm4', + 'i3': 'i3', + 'i3-gaps': 'i3', + 'sway': 'sway', + 'awesome': 'awesome', + 'dwm': 'dwm', + + } + + # First try to limit search for window managers associated with desktop environment + if self.DESKTOP_ENV and self.DESKTOP_ENV in de_wm_map: + possible_wms = de_wm_map[self.DESKTOP_ENV] + for wm in possible_wms: + if self.is_process_running(wm): + self.WINDOW_MGR = wm + return + + if self.DESKTOP_ENV and self.DESKTOP_ENV == 'lxqt' and not self.WINDOW_MGR: + self.get_lxqt_window_manager() + if self.WINDOW_MGR: + return + + # Iterate through whole dictionary if desktop environment not found in de_wm_map + for DE, process_names in de_wm_map.items(): + if not isinstance(process_names, list): + process_names = [process_names] # Ensure we can iterate + for process_name in process_names: + if self.is_process_running(process_name): + self.WINDOW_MGR = process_name + return + + # If nothing found, set a default value + if not self.WINDOW_MGR: + self.WINDOW_MGR = 'WM_unidentified_by_logic' + + +if __name__ == "__main__": + env_info_getter = EnvironmentInfo() + _env_info = env_info_getter.get_env_info() + print('') + debug( f'Toshy env_info module sees this environment:' + f'\n\t\t DISTRO_ID = \'{_env_info["DISTRO_ID"]}\'' + f'\n\t\t DISTRO_VER = \'{_env_info["DISTRO_VER"]}\'' + f'\n\t\t VARIANT_ID = \'{_env_info["VARIANT_ID"]}\'' + f'\n\t\t SESSION_TYPE = \'{_env_info["SESSION_TYPE"]}\'' + f'\n\t\t DESKTOP_ENV = \'{_env_info["DESKTOP_ENV"]}\'' + f'\n\t\t DE_MAJ_VER = \'{_env_info["DE_MAJ_VER"]}\'' + f'\n\t\t WINDOW_MGR = \'{_env_info["WINDOW_MGR"]}\'' + f'\n', ctx="EV") diff --git a/scripts/bin/toshy-env.sh b/scripts/bin/toshy-env.sh index 7524fa3..2acf9b0 100755 --- a/scripts/bin/toshy-env.sh +++ b/scripts/bin/toshy-env.sh @@ -19,4 +19,4 @@ fi # shellcheck disable=SC1091 source "$HOME/.config/toshy/.venv/bin/activate" -python3 "$HOME/.config/toshy/lib/env.py" +python3 "$HOME/.config/toshy/lib/env_context.py" diff --git a/setup_toshy.py b/setup_toshy.py index 71e5075..29ed828 100755 --- a/setup_toshy.py +++ b/setup_toshy.py @@ -25,6 +25,8 @@ # local import import lib.env as env + +from lib.env_context import EnvironmentInfo from lib.logger import debug, error, warn, info from lib import logger @@ -163,6 +165,7 @@ def __init__(self) -> None: self.SESSION_TYPE = None self.DESKTOP_ENV = None self.DE_MAJ_VER: str = "" + self.WINDOW_MGR = None self.distro_mjr_ver: str = "" self.distro_mnr_ver: str = "" @@ -267,7 +270,7 @@ def show_reboot_prompt(): def get_environment_info(): """Get back the distro name (ID), distro version, session type and desktop - environment from `env.py` module""" + environment from the environment evaluation module""" print(f'\n§ Getting environment information...\n{cnfg.separator}') known_init_systems = { @@ -305,7 +308,9 @@ def get_environment_info(): # we don't care what it is, just that it is set to avoid errors in get_env_info() os.environ['XDG_SESSION_TYPE'] = 'x11' - env_info_dct = env.get_env_info() + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() # Avoid casefold() errors by converting all to strings if cnfg.override_distro: @@ -317,6 +322,7 @@ def get_environment_info(): cnfg.SESSION_TYPE = str(env_info_dct.get('SESSION_TYPE', 'keymissing')).casefold() cnfg.DESKTOP_ENV = str(env_info_dct.get('DESKTOP_ENV', 'keymissing')).casefold() cnfg.DE_MAJ_VER = str(env_info_dct.get('DE_MAJ_VER', 'keymissing')).casefold() + cnfg.WINDOW_MGR = str(env_info_dct.get('WINDOW_MGR', 'keymissing')).casefold() # split out the major version from the minor version, if there is one distro_ver_parts = cnfg.DISTRO_VER.split('.') if cnfg.DISTRO_VER else [] @@ -330,6 +336,7 @@ def get_environment_info(): f"\n\t SESSION_TYPE = '{cnfg.SESSION_TYPE}'" f"\n\t DESKTOP_ENV = '{cnfg.DESKTOP_ENV}'" f"\n\t DE_MAJ_VER = '{cnfg.DE_MAJ_VER}'" + f"\n\t WINDOW_MGR = '{cnfg.WINDOW_MGR}'" # '\n', ctx='EV') '', ctx='EV') @@ -653,6 +660,7 @@ def elevate_privileges(): # - AlmaLinux 8.x [Provided by 'glib2'] # - AlmaLinux 9.x [Provided by 'glib2'] # - CentOS 7 [Provided by 'glib2'] +# - Fedora [Provided by 'glib2'] # - KDE Neon User Edition (Ubuntu 22.04 LTS) [Provided by 'libglib2.0-bin'] # - Manjaro KDE (Arch-based) [Provided by 'glib2'] # - OpenMandriva Lx 5.0 (Plasma Slim) [Provided by 'glib2.0-common'] diff --git a/toshy_tray.py b/toshy_tray.py index 1360bb9..4d9d2bc 100755 --- a/toshy_tray.py +++ b/toshy_tray.py @@ -29,6 +29,8 @@ # Local imports import lib.env as env + +from lib.env_context import EnvironmentInfo from lib.logger import * from lib import logger from lib.settings_class import Settings @@ -916,7 +918,9 @@ def main(): global loop global DESKTOP_ENV - env_info_dct = env.get_env_info() + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() DESKTOP_ENV = str(env_info_dct.get('DESKTOP_ENV', None)).casefold() if shutil.which('systemctl') and is_init_systemd(): diff --git a/wlroots-dbus-service/toshy_wlroots_dbus_service.py b/wlroots-dbus-service/toshy_wlroots_dbus_service.py index 6033271..8215808 100755 --- a/wlroots-dbus-service/toshy_wlroots_dbus_service.py +++ b/wlroots-dbus-service/toshy_wlroots_dbus_service.py @@ -53,6 +53,8 @@ # local imports now that path is prepped import lib.env as env +from lib.env_context import EnvironmentInfo + from protocols.wlr_foreign_toplevel_management_unstable_v1.zwlr_foreign_toplevel_manager_v1 import ( ZwlrForeignToplevelManagerV1, ZwlrForeignToplevelManagerV1Proxy, @@ -109,14 +111,16 @@ def clean_shutdown(): def check_environment(): """Retrieve the current environment from env module""" - env_info: Dict[str, str] = env.get_env_info() # Returns a dict + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() global DISTRO_ID, DISTRO_VER, VARIANT_ID, SESSION_TYPE, DESKTOP_ENV, DE_MAJ_VER - DISTRO_ID = env_info.get('DISTRO_ID') - DISTRO_VER = env_info.get('DISTRO_VER') - VARIANT_ID = env_info.get('VARIANT_ID') - SESSION_TYPE = env_info.get('SESSION_TYPE') - DESKTOP_ENV = env_info.get('DESKTOP_ENV') - DE_MAJ_VER = env_info.get('DE_MAJ_VER') + DISTRO_ID = env_info_dct.get('DISTRO_ID') + DISTRO_VER = env_info_dct.get('DISTRO_VER') + VARIANT_ID = env_info_dct.get('VARIANT_ID') + SESSION_TYPE = env_info_dct.get('SESSION_TYPE') + DESKTOP_ENV = env_info_dct.get('DESKTOP_ENV') + DE_MAJ_VER = env_info_dct.get('DE_MAJ_VER') check_environment() diff --git a/wlroots-dev/wlr_forn_topl_mgmt_dbus_svc_without_Wayland_class.py b/wlroots-dev/wlr_forn_topl_mgmt_dbus_svc_without_Wayland_class.py index 3ea91be..7038b9c 100755 --- a/wlroots-dev/wlr_forn_topl_mgmt_dbus_svc_without_Wayland_class.py +++ b/wlroots-dev/wlr_forn_topl_mgmt_dbus_svc_without_Wayland_class.py @@ -54,6 +54,8 @@ # local imports now that path is prepped import lib.env as env +from lib.env_context import EnvironmentInfo + from protocols.wlr_foreign_toplevel_management_unstable_v1.zwlr_foreign_toplevel_manager_v1 import ( ZwlrForeignToplevelManagerV1, ZwlrForeignToplevelManagerV1Proxy, @@ -108,14 +110,16 @@ def clean_shutdown(): def check_environment(): """Retrieve the current environment from env module""" - env_info: Dict[str, str] = env.get_env_info() # Returns a dict + # env_info_dct = env.get_env_info() + env_ctxt_getter = EnvironmentInfo() + env_info_dct = env_ctxt_getter.get_env_info() global DISTRO_ID, DISTRO_VER, VARIANT_ID, SESSION_TYPE, DESKTOP_ENV, DE_MAJ_VER - DISTRO_ID = env_info.get('DISTRO_ID') - DISTRO_VER = env_info.get('DISTRO_VER') - VARIANT_ID = env_info.get('VARIANT_ID') - SESSION_TYPE = env_info.get('SESSION_TYPE') - DESKTOP_ENV = env_info.get('DESKTOP_ENV') - DE_MAJ_VER = env_info.get('DE_MAJ_VER') + DISTRO_ID = env_info_dct.get('DISTRO_ID') + DISTRO_VER = env_info_dct.get('DISTRO_VER') + VARIANT_ID = env_info_dct.get('VARIANT_ID') + SESSION_TYPE = env_info_dct.get('SESSION_TYPE') + DESKTOP_ENV = env_info_dct.get('DESKTOP_ENV') + DE_MAJ_VER = env_info_dct.get('DE_MAJ_VER') check_environment()