Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package uwsm for openSUSE:Factory checked in at 2026-01-31 16:16:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/uwsm (Old) and /work/SRC/openSUSE:Factory/.uwsm.new.1995 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "uwsm" Sat Jan 31 16:16:27 2026 rev:2 rq:1330081 version:0.26.1 Changes: -------- --- /work/SRC/openSUSE:Factory/uwsm/uwsm.changes 2026-01-22 15:13:38.700902598 +0100 +++ /work/SRC/openSUSE:Factory/.uwsm.new.1995/uwsm.changes 2026-01-31 16:16:28.706369425 +0100 @@ -1,0 +2,16 @@ +Fri Jan 30 16:30:14 UTC 2026 - Alexey Kolos <[email protected]> + +- Update to version 0.26.1: + * Added hyprlauncher support + * Added niri plugin + * Added sourcing of environment from env.d dirs + * Added may-start checks for root, local session +- Drop fix-quotes-in-f-string-for-python-before-3.12.patch + * Patch is included upstream + +------------------------------------------------------------------- +Tue Jan 27 10:03:35 UTC 2026 - Bernhard Wiedemann <[email protected]> + +- Run check without writing .pyc files for reproducible builds (boo#1227364) + +------------------------------------------------------------------- Old: ---- fix-quotes-in-f-string-for-python-before-3.12.patch uwsm-0.26.0.obscpio New: ---- uwsm-0.26.1.obscpio ----------(Old B)---------- Old: * Added may-start checks for root, local session - Drop fix-quotes-in-f-string-for-python-before-3.12.patch * Patch is included upstream ----------(Old E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ uwsm.spec ++++++ --- /var/tmp/diff_new_pack.yZIrww/_old 2026-01-31 16:16:30.158429754 +0100 +++ /var/tmp/diff_new_pack.yZIrww/_new 2026-01-31 16:16:30.162429921 +0100 @@ -17,15 +17,13 @@ Name: uwsm -Version: 0.26.0 +Version: 0.26.1 Release: 0 Summary: Universal Wayland Session Manager License: MIT Group: System/Management URL: https://github.com/Vladimir-csp/uwsm Source: %{name}-%{version}.tar.zst -# PATCH-FIX-UPSTREAM https://github.com/Vladimir-csp/uwsm/pull/201 -Patch: fix-quotes-in-f-string-for-python-before-3.12.patch BuildRequires: meson >= 1.3 BuildRequires: scdoc @@ -91,6 +89,7 @@ rm %{buildroot}/%{_userpresetdir}/80-ttyautolock.preset %check +export PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=%{buildroot}/%{_datadir}/%{name}/modules %{buildroot}/%{_bindir}/%{name} --version %files ++++++ _service ++++++ --- /var/tmp/diff_new_pack.yZIrww/_old 2026-01-31 16:16:30.194431250 +0100 +++ /var/tmp/diff_new_pack.yZIrww/_new 2026-01-31 16:16:30.198431417 +0100 @@ -2,7 +2,7 @@ <service name="obs_scm" mode="manual"> <param name="url">https://github.com/Vladimir-csp/uwsm.git</param> <param name="scm">git</param> - <param name="revision">v0.26.0</param> + <param name="revision">v0.26.1</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.yZIrww/_old 2026-01-31 16:16:30.218432247 +0100 +++ /var/tmp/diff_new_pack.yZIrww/_new 2026-01-31 16:16:30.230432746 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Vladimir-csp/uwsm.git</param> - <param name="changesrevision">433174c297ef858cc370f143657781ad4856263e</param></service></servicedata> + <param name="changesrevision">9c3f28beabda78f15330fa4d5c75a9ab190aaf2b</param></service></servicedata> (No newline at EOF) ++++++ uwsm-0.26.0.obscpio -> uwsm-0.26.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/README.md new/uwsm-0.26.1/README.md --- old/uwsm-0.26.0/README.md 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/README.md 2026-01-29 22:00:40.000000000 +0100 @@ -95,6 +95,9 @@ - `labwc` - `hyprland` +LXQt variants of the above are provided by the experimental [LXQt Universal +Wayland Session](https://github.com/basil/lxqt-uwsm-session). + </details> <details><summary> @@ -104,8 +107,9 @@ - On startup a specialized unit prepares environment by: - either loading environment context saved by `uwsm start` command or sourcing shell profile by itself - - sourcing `uwsm/env`, `uwsm/env-${desktop}` files from each dir of reversed - sequence `${XDG_CONFIG_HOME}:${XDG_CONFIG_DIRS}:${XDG_DATA_DIRS}` (in + - sourcing `uwsm/env`, `uwsm/env.d/*`, `uwsm/env-${desktop}`, + `uwsm/env-${desktop}.d/*` files from each dir of reversed sequence + `${XDG_CONFIG_HOME}:${XDG_CONFIG_DIRS}:${XDG_DATA_DIRS}` (in increasing priority), where `${desktop}` is each item of `${XDG_CURRENT_DESKTOP}`, lowercased - Difference between environment state before and after preparation is exported @@ -314,6 +318,7 @@ - `walker` - `wofi` - `rofi` + - `hyprlauncher` - `tofi` - `bemenu` - `wmenu` @@ -477,18 +482,19 @@ resulting command, so units will lack fancy description. Some examples: -| Launcher | Via | What | Entry | -| -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | -| vicinae | gui | `vicinae settings > extentions > Applications > Launch Prefix=uwsm app --` | no | -| fuzzel | command | `fuzzel "--launch-prefix=uwsm app --"` | no | -| fuzzel | config | `launch-prefix=uwsm app --` | no | -| albert | env var | `ALBERT_APPLICATIONS_COMMAND_PREFIX`: `uwsm;app;--` | no | -| albert | shell | `ALBERT_APPLICATIONS_COMMAND_PREFIX="uwsm;app;--" albert` | no | -| walker | config | `app_launch_prefix = "uwsm app -- "` | no | -| wofi | shell | `uwsm app -- "$(wofi --show drun --define=drun-print_desktop_file=true \| sed -E "s/(\.desktop) /\1:/")"` | yes | -| wofi | shell | `uwsm app -- "$(D=$(wofi --show drun --define=drun-print_desktop_file=true); case "$D" in *'.desktop '*) echo "${D%.desktop *}.desktop:${D#*.desktop }";; *) echo "$D";; esac)"` | yes | -| tofi | shell | `uwsm app -- $(tofi-drun)` | no | -| rofi | command | `rofi -show drun -run-command "uwsm app -- {cmd}"` | no | +| Launcher | Via | What | Entry | +| -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | +| vicinae | gui | `vicinae settings > extentions > Applications > Launch Prefix=uwsm app --` | no | +| fuzzel | command | `fuzzel "--launch-prefix=uwsm app --"` | no | +| fuzzel | config | `launch-prefix=uwsm app --` | no | +| albert | env var | `ALBERT_APPLICATIONS_COMMAND_PREFIX`: `uwsm;app;--` | no | +| albert | shell | `ALBERT_APPLICATIONS_COMMAND_PREFIX="uwsm;app;--" albert` | no | +| walker | config | `app_launch_prefix = "uwsm app -- "` | no | +| wofi | shell | `uwsm app -- "$(wofi --show drun --define=drun-print_desktop_file=true \| sed -E "s/(\.desktop) /\1:/")"` | yes | +| wofi | shell | `uwsm app -- "$(D=$(wofi --show drun --define=drun-print_desktop_file=true); case "$D" in *'.desktop '*) echo "${D%.desktop *}.desktop:${D#*.desktop }";; *) echo "$D";; esac)"` | yes | +| hyprlauncher | config | `desktop_launch_prefix = uwsm app --` | no | +| tofi | shell | `uwsm app -- $(tofi-drun)` | no | +| rofi | command | `rofi -show drun -run-command "uwsm app -- {cmd}"` | no | Compositor itself runs in `session.slice` which has priority in some resource allocation. It would be a bad practice to accumulate all apps there, and @@ -621,8 +627,10 @@ - For login shell context and uwsm environment preloader, including plugins: export in your shell's profile. - For uwsm-managed graphical session: export in `${XDG_CONFIG_HOME}/uwsm/env` + or `${XDG_CONFIG_HOME}/uwsm/env.d/my_vars` - For uwsm-managed graphical session of specific compositor: export in - `${XDG_CONFIG_HOME}/uwsm/env-${desktop}` + `${XDG_CONFIG_HOME}/uwsm/env-${desktop}` or + `${XDG_CONFIG_HOME}/uwsm/env-${desktop}.d/my_vars` Choose whatever scope suits your needs. @@ -755,8 +763,9 @@ if compositor's unit was activated without the use of `uwsm start` command). `uwsm check may-start` subcommand serves as a collection of useful checks. -By default: parent is a login shell (process name starts with `-`), tty1 is in -foreground, system's `graphical.target` is active or activating, user's +By default: user's dbus is available, parent is a login shell (process name +starts with `-`), tty1 is in foreground, login session's tty matches, login +session is local, system's `graphical.target` is active or activating, user's `graphical-session.target` and other related units are inactive. Also for convenience environment preloader defines `IN_UWSM_ENV_PRELOADER=true` @@ -943,7 +952,9 @@ It looks for environment saved by `uwsm start` command, then runs shell code to prepare environment. The code sources POSIX shell profile (if environment from -`uwsm start` was not found), `uwsm/env*` files, anything that plugins dictate. +`uwsm start` was not found), common and desktop-matching `uwsm/env*`, +`uwsm/env*.d/*` files, anything that plugins dictate. + Environment state at the end of shell code is given back to the main process. `uwsm` is also smart enough to find login session associated with current TTY and set `$XDG_SESSION_ID`, `$XDG_VTNR` if it was not found in the context saved @@ -1117,7 +1128,8 @@ - `process_config_dirs_reversed` - called by `load_wm_env`, same as `process_config_dirs`, but in reverse (increasing priority) - `in_each_config_dir_reversed` - called by `process_config_dirs_reversed` for - each config dir, loads `uwsm/env`, `uwsm/env-${desktop}` files + each config dir, loads `uwsm/env`, `uwsm/env.d/*`, `uwsm/env-${desktop}`, + `uwsm/env-${desktop}.d/*` files - `source_file` - sources `$1` file, providing messages for log. See code inside `uwsm/main.py` for more auxiliary functions. @@ -1180,3 +1192,4 @@ package. - @YaLTeR for an idea that lead to automatic compositor startup detection. - @izmyname for integration and documentation work on Hyprland's side. +- @basil for LXQt integration and documentation work. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/debian/changelog new/uwsm-0.26.1/debian/changelog --- old/uwsm-0.26.0/debian/changelog 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/debian/changelog 2026-01-29 22:00:40.000000000 +0100 @@ -1,5 +1,5 @@ -uwsm (0.26.0-1~local0) UNRELEASED; urgency=medium +uwsm (0.26.1-1~local0) UNRELEASED; urgency=medium * Upstream build. - -- Vladimir-csp <[email protected]> Sun, 28 Dec 2025 14:09:59 +0300 + -- Vladimir-csp <[email protected]> Fri, 30 Jan 2026 00:00:40 +0300 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/debian/control new/uwsm-0.26.1/debian/control --- old/uwsm-0.26.0/debian/control 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/debian/control 2026-01-29 22:00:40.000000000 +0100 @@ -1,7 +1,7 @@ Source: uwsm Section: x11 Priority: optional -Maintainer: Vladimir-csp +Maintainer: Vladimir-csp <[email protected]> Build-Depends: debhelper-compat (= 13), dh-sequence-python3, @@ -29,7 +29,7 @@ python3-dbus, Recommends: whiptail, - walker | fuzzel | wofi | rofi | tofi | bemenu | wmenu | dmenu, + walker | fuzzel | wofi | rofi | hyprlauncher | tofi | bemenu | wmenu | dmenu, libnotify-bin, inotify-tools, Suggests: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/example-units/uu2gslice.sh new/uwsm-0.26.1/example-units/uu2gslice.sh --- old/uwsm-0.26.0/example-units/uu2gslice.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/example-units/uu2gslice.sh 2026-01-29 22:00:40.000000000 +0100 @@ -7,7 +7,6 @@ # or reset # (optional) - UNIT=${1?First argument should be a unit to edit} SLICE=${2:-app-graphical.slice} @@ -34,7 +33,6 @@ ;; esac - case "$SLICE" in reset) echo "Removing 'graphical-slice.conf' drop-in from '$UNIT'" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/man/uuctl.1.scd new/uwsm-0.26.1/man/uuctl.1.scd --- old/uwsm-0.26.0/man/uuctl.1.scd 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/man/uuctl.1.scd 2026-01-29 22:00:40.000000000 +0100 @@ -28,10 +28,12 @@ Supported menu apps: +- vicinae - walker - fuzzel - wofi - rofi +- hyprlauncher - tofi - bemenu - wmenu diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/man/uwsm-plugins.3.scd new/uwsm-0.26.1/man/uwsm-plugins.3.scd --- old/uwsm-0.26.0/man/uwsm-plugins.3.scd 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/man/uwsm-plugins.3.scd 2026-01-29 22:00:40.000000000 +0100 @@ -55,7 +55,8 @@ reverse (increasing priority) *in\_each\_config\_dir\_reversed* called by *process\_config\_dirs\_reversed* for each config dir - as *$1*, loads *uwsm/env*, *uwsm/env-*_${desktop}_ files + as *$1*, loads *uwsm/env*, *uwsm/env.d/*\*, *uwsm/env-*_${desktop}_, + *uwsm/env-*_${desktop}_*.d/*\* files *in\_each\_config\_dir* called by *process\_config\_dirs* for each config dir as *$1*, does nothing ATM diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/man/uwsm.1.scd new/uwsm-0.26.1/man/uwsm.1.scd --- old/uwsm-0.26.0/man/uwsm.1.scd 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/man/uwsm.1.scd 2026-01-29 22:00:40.000000000 +0100 @@ -44,7 +44,11 @@ In XDG config hierarchy: |[ *uwsm/env* :< +| *uwsm/env.d/*\* +:< | *uwsm/env-*_${compositor}_ +:< +| *uwsm/env-*_${compositor}_*.d/*\* : Environment (shell) to be sourced for the graphical session. Sourced from directories of increasing priority, in each directory common file is sourced first, then suffixed files in the order of items listed in @@ -228,22 +232,28 @@ *uwsm* check may-start [-h] [-g [_S_]] [-v|-q] [_N_ ...] -|[ *-g* _S_ -:< wait _S_ seconds for graphical.target in queue (default: 60; 0 or +|[ _N_ ... +:< allowed VT numbers (default: 1) +| *-g* _S_ +: wait _S_ seconds for graphical.target in queue (default: 60; 0 or less disables check). +| *-i* +: do not check for login shell +| *-r* +: do not check for local session (allow remote session) | *-v* : show all failed tests | *-q* : be quiet -| _N_ ... -: allowed VT numbers (default: 1) Checks whether it is OK to launch a wayland session via the following conditions: +- *DBUS_SESSION_BUS_ADDRESS* is set - Running from login shell - System is at *graphical.target* - User *graphical-session\*.target* units are not yet active - Foreground VT is among allowed (default: 1) +- Login session's VT is matching ## start @@ -460,7 +470,7 @@ when logged in on VT 1: ``` - if uwsm may-start && uwsm select; then + if uwsm check may-start && uwsm select; then exec systemd-cat -t uwsm_start uwsm start default fi ``` @@ -468,9 +478,9 @@ This just starts a specific compositor depending on foreground VT: ``` - if uwsm may-start 1; then + if uwsm check may-start 1; then exec systemd-cat -t uwsm_start uwsm start sway.desktop - elif uwsm may-start 2; then + elif uwsm check may-start 2; then exec systemd-cat -t uwsm_start uwsm start labwc.desktop fi ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/scripts/ttyautolock.sh new/uwsm-0.26.1/scripts/ttyautolock.sh --- old/uwsm-0.26.0/scripts/ttyautolock.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/scripts/ttyautolock.sh 2026-01-29 22:00:40.000000000 +0100 @@ -68,7 +68,7 @@ *":${WATCH_TTY}") true ;; # leaving watched tty: lock "${WATCH_TTY}:"*) - if ! loginctl show-session "$S_ID" --property Id >/dev/null; then + if ! loginctl show-session "$S_ID" --property Id > /dev/null; then printf '%s\n' "Session disappeared, exiting." exit 0 fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/scripts/uuctl.sh new/uwsm-0.26.1/scripts/uuctl.sh --- old/uwsm-0.26.0/scripts/uuctl.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/scripts/uuctl.sh 2026-01-29 22:00:40.000000000 +0100 @@ -30,10 +30,11 @@ Menu tool and options are selected from predefined profiles for: vicinae - walker + walker fuzzel wofi rofi + hyprlauncher tofi bemenu wmenu @@ -202,7 +203,6 @@ walker -q } - df_vicinae() { vicinae dmenu } @@ -219,6 +219,10 @@ rofi -dmenu -p "$@" } +df_hyprlauncher() { + hyprlauncher -m +} + df_tofi() { tofi --prompt-text "$@" } @@ -252,7 +256,7 @@ DMENU_CLEANUP=true if [ "$#" -le "1" ]; then - dmenu_candidates="vicinae walker fuzzel wofi rofi tofi bemenu wmenu dmenu" + dmenu_candidates="vicinae walker fuzzel wofi rofi hyprlauncher tofi bemenu wmenu dmenu" if [ "$#" = "1" ]; then case " $dmenu_candidates " in @@ -430,8 +434,14 @@ ## special handling of some surviving actions disable+*+ufs:runtime-enabled+*+as:activ* | disable+*+ufs:runtime-enabled+*+as:reloading*) case "${UNIT}" in - *@*) DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable --runtime"; DISABLE_ACTIONS_SHOW=true ;; - *) DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable --runtime${N}disable --runtime --now"; DISABLE_ACTIONS_SHOW=true ;; + *@*) + DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable --runtime" + DISABLE_ACTIONS_SHOW=true + ;; + *) + DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable --runtime${N}disable --runtime --now" + DISABLE_ACTIONS_SHOW=true + ;; esac ACTIONS="${ACTIONS}${ACTIONS:+$N}${ACTION}" ;; @@ -443,7 +453,10 @@ disable+*+as:activ* | disable+*+as:reloading*) case "${UNIT}" in *@*) DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable" ;; - *) DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable${N}disable --now"; DISABLE_ACTIONS_SHOW=true ;; + *) + DISABLE_ACTIONS="${DISABLE_ACTIONS}${DISABLE_ACTIONS:+$N}disable${N}disable --now" + DISABLE_ACTIONS_SHOW=true + ;; esac ACTIONS="${ACTIONS}${ACTIONS:+$N}${ACTION}" ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm/main.py new/uwsm-0.26.1/uwsm/main.py --- old/uwsm-0.26.0/uwsm/main.py 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm/main.py 2026-01-29 22:00:40.000000000 +0100 @@ -2197,10 +2197,11 @@ epilog=dedent( """ Conditions:\n + - User's dbus is available - Running from login shell\n - System is at graphical.target\n - User graphical-session*.target are not yet active\n - - Foreground VT is among allowed (default: 1)\n + - Foreground and session's VT is among allowed (default: 1)\n \n This command is essential for integrating startup into shell profile. """ @@ -2231,6 +2232,12 @@ help="Do not check for login shell.", ) parsers["may_start"].add_argument( + "-r", + action="store_true", + dest="allow_remote", + help="Do not check for local session (allow remote).", + ) + parsers["may_start"].add_argument( "-g", type=int, dest="gst_seconds", @@ -3693,7 +3700,7 @@ final_args.extend( ["--property=Type=exec", "--property=ExitType=cgroup"] + [ - f"--setenv={var}={os.environ.get(var, "")}" + f"--setenv={var}={os.environ.get(var, '')}" for var in sorted(Varnames.session_specific) if os.environ.get(var, "") ] @@ -4477,6 +4484,147 @@ ) +def check_may_start(): + "Checks conditions for compositor startup, returns three sets: errors, v_dealbreakers, dealbreakers" + errors = set() + # visible dealbreakers + v_dealbreakers = set() + # silent dealbreakers + dealbreakers = set() + + # just bail out if root + if os.geteuid() == 0: + dealbreakers.add("Running as root") + return errors, v_dealbreakers, dealbreakers + + # start with checking DBus availability. Python module will try to + # start it unconditionally if not found, and make a fuss. + # silently fail if verbosity not requested. For ssh sessions and like. + if not os.environ.get("DBUS_SESSION_BUS_ADDRESS", ""): + dealbreakers.add("DBUS_SESSION_BUS_ADDRESS is not available") + return errors, v_dealbreakers, dealbreakers + + try: + if is_active(): + v_dealbreakers.add("A compositor and/or graphical-session* targets are already active") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + except Exception as caught_exception: + errors.update("Could not check for active compositor!", caught_exception) + return errors, v_dealbreakers, dealbreakers + + # check if parent process is a login shell + if not Args.parsed.nologin: + try: + with open( + f"/proc/{os.getppid()}/cmdline", "r", encoding="UTF-8" + ) as ppcmdline: + parent_cmdline = ppcmdline.read() + parent_cmdline = parent_cmdline.strip() + print_debug(f"parent_pid: {os.getppid()}") + print_debug(f"parent_cmdline: {parent_cmdline}") + if not parent_cmdline.startswith("-"): + dealbreakers.add("Not in login shell") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + except Exception as caught_exception: + errors.update("Could not determine parent process command!", caught_exception) + return errors, v_dealbreakers, dealbreakers + + # check foreground VT + fgvt = None + + # argparse does not pass default for this in some python versions + allowed_vtnr = Args.parsed.vtnr or [1] + print_debug("allowed_vtnr", allowed_vtnr) + if allowed_vtnr != [0]: + fgvt = get_fg_vt() + if fgvt is None: + dealbreakers.add("Could not determine foreground VT") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + else: + if fgvt not in allowed_vtnr: + dealbreakers.add( + f"Foreground VT ({fgvt}) is not among allowed VTs ({'|'.join([str(v) for v in allowed_vtnr])})" + ) + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + + bus_system = None + session_id_str = os.environ.get("XDG_SESSION_ID", "") + # check session VTNr + if allowed_vtnr != [0]: + if session_id_str: + try: + bus_system = DbusInteractions("system") + session_vtnr = int(bus_system.get_session_property(session_id_str, "VTNr")) + print_debug("session_vtnr", session_vtnr) + if session_vtnr == 0: + dealbreakers.add(f"Session {session_id_str} is not associated with a VT") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + elif session_vtnr not in allowed_vtnr: + dealbreakers.add( + f"Session VT ({session_vtnr}) is not among allowed VTs ({'|'.join([str(v) for v in allowed_vtnr])})" + ) + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + except Exception as caught_exception: + errors.update("Could not get session VTNr!", caught_exception) + return errors, v_dealbreakers, dealbreakers + else: + dealbreakers.add("XDG_SESSION_ID is not available") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + + # check local session + if not Args.parsed.allow_remote: + if session_id_str: + try: + if bus_system is None: + bus_system = DbusInteractions("system") + print_debug("bus_system initial", bus_system) + + session_remote = int(bus_system.get_session_property(session_id_str, "Remote")) + print_debug("session_remote", session_remote) + if session_remote: + dealbreakers.add(f"Session {session_id_str} is not local") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + except Exception as caught_exception: + errors.update("Could not get session Remote attr!", caught_exception) + return errors, v_dealbreakers, dealbreakers + else: + dealbreakers.add("XDG_SESSION_ID is not available") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + + # check for graphical target + if Args.parsed.gst_seconds > 0: + try: + if bus_system is None: + bus_system = DbusInteractions("system") + print_debug("bus_system initial", bus_system) + + if not wait_for_unit( + "graphical.target", + bus=bus_system, + states=["active", "activating"], + timeout=Args.parsed.gst_seconds, + quiet=Args.parsed.quiet, + ): + dealbreakers.add("System has not reached graphical.target") + if not Args.parsed.verbose: + return errors, v_dealbreakers, dealbreakers + + except Exception as caught_exception: + errors.update("Could not check if graphical.target is reached!", caught_exception) + return errors, v_dealbreakers, dealbreakers + + return errors, v_dealbreakers, dealbreakers + + def main(): "UWSM main entrypoint" @@ -4797,87 +4945,22 @@ sys.exit(1) elif Args.parsed.mode == "check" and Args.parsed.checker == "may-start": - # start with checking DBus availability. Python module will try to - # start it unconditionally if not found, and make a fuss. - # silently fail if verbosity not requested. For ssh sessions and like. - if not os.environ.get("DBUS_SESSION_BUS_ADDRESS", ""): - if Args.parsed.verbose: - print_warning("DBUS_SESSION_BUS_ADDRESS is not available") - sys.exit(1) - - already_active_msg = ( - "A compositor and/or graphical-session* targets are already active" - ) - dealbreakers = [] - - try: - if is_active(): - dealbreakers.append(already_active_msg) - except Exception as caught_exception: - print_error("Could not check for active compositor!") - print_error(caught_exception) - sys.exit(1) - - # check if parent process is a login shell - if not Args.parsed.nologin: - try: - with open( - f"/proc/{os.getppid()}/cmdline", "r", encoding="UTF-8" - ) as ppcmdline: - parent_cmdline = ppcmdline.read() - parent_cmdline = parent_cmdline.strip() - print_debug(f"parent_pid: {os.getppid()}") - print_debug(f"parent_cmdline: {parent_cmdline}") - except Exception as caught_exception: - print_error("Could not determine parent process command!") - print_error(caught_exception) - sys.exit(1) - if not parent_cmdline.startswith("-"): - dealbreakers.append("Not in login shell") - - # argparse does not pass default for this in some python versions - allowed_vtnr = Args.parsed.vtnr or [0] - if allowed_vtnr != [0]: - - # check foreground VT - fgvt = get_fg_vt() - if fgvt is None: - print_error("Could not determine foreground VT") - sys.exit(1) - else: - if fgvt not in allowed_vtnr: - dealbreakers.append( - f"Foreground VT ({fgvt}) is not among allowed VTs ({'|'.join([str(v) for v in allowed_vtnr])})" - ) - - # check for graphical target - if Args.parsed.gst_seconds > 0: - try: - bus_system = DbusInteractions("system") - print_debug("bus_system initial", bus_system) + errors, v_dealbreakers, dealbreakers = check_may_start() - if not wait_for_unit( - "graphical.target", - bus=bus_system, - states=["active", "activating"], - timeout=Args.parsed.gst_seconds, - quiet=Args.parsed.quiet, - ): - dealbreakers.append("System has not reached graphical.target") - - except Exception as caught_exception: - print_error("Could not check if graphical.target is reached!") - print_error(caught_exception) - sys.exit(1) - - if dealbreakers: - if Args.parsed.verbose or ( - # if the only failed condition is active graphical session, say it, - # unless -q is given - not Args.parsed.quiet - and dealbreakers == [already_active_msg] - ): - print_warning("\n ".join(["May not start compositor:"] + dealbreakers)) + # sum up, print, and exit with verdict + if errors or v_dealbreakers or dealbreakers: + if errors: + errors = list(errors) + errors.insert(0, "Got errors while checking if may start compositor:") + print_error(*errors, sep="\n") + if v_dealbreakers or dealbreakers: + v_dealbreakers = list(v_dealbreakers) + dealbreakers = list(dealbreakers) + if Args.parsed.verbose: + v_dealbreakers.insert(0, "May not start compositor:") + print_warning(*(v_dealbreakers + dealbreakers), sep="\n ") + elif not Args.parsed.quiet and v_dealbreakers: + print_warning(*v_dealbreakers, sep="\n") sys.exit(1) else: if Args.parsed.verbose: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-libexec/prepare-env.sh new/uwsm-0.26.1/uwsm-libexec/prepare-env.sh --- old/uwsm-0.26.0/uwsm-libexec/prepare-env.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-libexec/prepare-env.sh 2026-01-29 22:00:40.000000000 +0100 @@ -4,15 +4,15 @@ reverse() { # returns list $1 delimited by ${2:-:} in reverse - __REVERSE_OUT__='' + __reverse_out__='' IFS="${2:-:}" - for __ITEM__ in $1; do - if [ -n "${__ITEM__}" ]; then - __REVERSE_OUT__="${__ITEM__}${__REVERSE_OUT__:+$IFS}${__REVERSE_OUT__}" + for __item__ in $1; do + if [ -n "${__item__}" ]; then + __reverse_out__="${__item__}${__reverse_out__:+$IFS}${__reverse_out__}" fi done - printf '%s' "${__REVERSE_OUT__}" - unset __REVERSE_OUT__ + printf '%s' "${__reverse_out__}" + unset __reverse_out__ IFS="${__OIFS__}" } @@ -33,6 +33,19 @@ fi } +source_dir() { + # applies source_file to every file in dir + if [ -d "${1}" ]; then + # process in standard order and visibility given by ls + while IFS='' read -r __env_file__; do + source_file "${1}/${__env_file__}" + done <<- EOF + $(ls "${1}") + EOF + unset __env_file__ + fi +} + get_all_config_dirs() { # returns whole XDG_CONFIG hierarchy, :-delimited printf '%s' "${XDG_CONFIG_HOME}:${XDG_CONFIG_DIRS}" @@ -53,37 +66,38 @@ # compose sequence of env files from lowercase desktop names in reverse IFS=':' - __ENV_FILES__='' - for __DNLC__ in $(lowercase "$(reverse "${XDG_CURRENT_DESKTOP}")"); do + __env_files__='' + for __dnlc__ in $(lowercase "$(reverse "${XDG_CURRENT_DESKTOP}")"); do IFS="${__OIFS__}" - __ENV_FILES__="${__SELF_NAME__}/env-${__DNLC__}${__ENV_FILES__:+:}${__ENV_FILES__}" + __env_files__="${__SELF_NAME__}/env-${__dnlc__}${__env_files__:+:}${__env_files__}" done # add common env file at the beginning - __ENV_FILES__="${__SELF_NAME__}/env${__ENV_FILES__:+:}${__ENV_FILES__}" - unset __DNLC__ + __env_files__="${__SELF_NAME__}/env${__env_files__:+:}${__env_files__}" + unset __dnlc__ # load env file sequence from this config dir rung IFS=':' - for __ENV_FILE__ in ${__ENV_FILES__}; do - source_file "${1}/${__ENV_FILE__}" + for __env_file__ in ${__env_files__}; do + source_file "${1}/${__env_file__}" + source_dir "${1}/${__env_file__}.d" done - unset __ENV_FILE__ - unset __ENV_FILES__ + unset __env_file__ + unset __env_files__ IFS="${__OIFS__}" } process_config_dirs() { # iterate over config dirs (decreasing importance) and call in_each_config_dir* functions IFS=":" - for __CONFIG_DIR__ in $(get_all_config_dirs_extended); do + for __config_dir__ in $(get_all_config_dirs_extended); do IFS="${__OIFS__}" if type "in_each_config_dir_${__WM_BIN_ID__}" > /dev/null 2>&1; then - "in_each_config_dir_${__WM_BIN_ID__}" "${__CONFIG_DIR__}" || return $? + "in_each_config_dir_${__WM_BIN_ID__}" "${__config_dir__}" || return $? else - in_each_config_dir "${__CONFIG_DIR__}" || return $? + in_each_config_dir "${__config_dir__}" || return $? fi done - unset __CONFIG_DIR__ + unset __config_dir__ IFS="${__OIFS__}" return 0 } @@ -91,15 +105,15 @@ process_config_dirs_reversed() { # iterate over reverse config dirs (increasing importance) and call in_each_config_dir_reversed* functions IFS=":" - for __CONFIG_DIR__ in $(reverse "$(get_all_config_dirs_extended)"); do + for __config_dir__ in $(reverse "$(get_all_config_dirs_extended)"); do IFS="${__OIFS__}" if type "in_each_config_dir_reversed_${__WM_BIN_ID__}" > /dev/null 2>&1; then - "in_each_config_dir_reversed_${__WM_BIN_ID__}" "${__CONFIG_DIR__}" || return $? + "in_each_config_dir_reversed_${__WM_BIN_ID__}" "${__config_dir__}" || return $? else - in_each_config_dir_reversed "${__CONFIG_DIR__}" || return $? + in_each_config_dir_reversed "${__config_dir__}" || return $? fi done - unset __CONFIG_DIR__ + unset __config_dir__ IFS="${__OIFS__}" return 0 } @@ -129,7 +143,8 @@ shift if [ -z "${__RANDOM_MARK__}" ]; then - printf '%s\n' "Random mark \${__RANDOM_MARK__} not set! Exiting." >&2 + # shellcheck disable=SC2016 + printf '%s\n' 'Random mark ${__RANDOM_MARK__} not set! Exiting.' >&2 exit 1 fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/hyprland.sh new/uwsm-0.26.1/uwsm-plugins/hyprland.sh --- old/uwsm-0.26.0/uwsm-plugins/hyprland.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/hyprland.sh 2026-01-29 22:00:40.000000000 +0100 @@ -3,8 +3,7 @@ quirks_hyprland() { # append "Hyprland" to XDG_CURRENT_DESKTOP if not already there - if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ] - then + if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ]; then case "A:${XDG_CURRENT_DESKTOP}:Z" in *:Hyprland:*) true ;; *) export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP}:Hyprland" ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/labwc.sh new/uwsm-0.26.1/uwsm-plugins/labwc.sh --- old/uwsm-0.26.0/uwsm-plugins/labwc.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/labwc.sh 2026-01-29 22:00:40.000000000 +0100 @@ -3,8 +3,7 @@ quirks_labwc() { # append "wlroots" to XDG_CURRENT_DESKTOP if not already there - if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ] - then + if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ]; then case "A:${XDG_CURRENT_DESKTOP}:Z" in *:wlroots:*) true ;; *) @@ -47,7 +46,7 @@ TEMP_UPDATE_REQUIRED=false TEMP_RELOAD_REQUIRED=false if [ -f "${TEMP_DROPIN_DIR}/55_reload.conf" ]; then - { read -r TEMP_SUM1 TEMP_DROP && read -r TEMP_SUM2 TEMP_DROP ; } <<- EOF + { read -r TEMP_SUM1 TEMP_DROP && read -r TEMP_SUM2 TEMP_DROP; } <<- EOF $(printf '%s\n' "$TEMP_DROPIN_CONTENT" | md5sum - "${TEMP_DROPIN_DIR}/55_reload.conf") EOF if [ "$TEMP_SUM1" != "$TEMP_SUM2" ]; then @@ -91,7 +90,7 @@ # adds varnames to UWSM_FINALIZE_VARNAMES while read -r line; do case "$line" in - [!a-zA-Z_]* ) continue ;; + [!a-zA-Z_]*) continue ;; *=*) true ;; *) continue ;; esac diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/meson.build new/uwsm-0.26.1/uwsm-plugins/meson.build --- old/uwsm-0.26.0/uwsm-plugins/meson.build 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/meson.build 2026-01-29 22:00:40.000000000 +0100 @@ -4,6 +4,8 @@ 'sway.sh', 'hyprland.sh', 'start_hyprland.sh', + 'niri.sh', + 'niri_session.sh', ] install_data( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/niri.sh new/uwsm-0.26.1/uwsm-plugins/niri.sh --- old/uwsm-0.26.0/uwsm-plugins/niri.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/niri.sh 2026-01-29 22:00:40.000000000 +0100 @@ -0,0 +1,25 @@ +#!/bin/false +# sourced by uwsm environment preloader + +quirks_niri() { + # append "niri" to XDG_CURRENT_DESKTOP if not already there + if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ]; then + case "A:${XDG_CURRENT_DESKTOP}:Z" in + *:niri:*) true ;; + *) export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP}:niri" ;; + esac + fi + + # mark additional vars for export on finalize + UWSM_FINALIZE_VARNAMES="${UWSM_FINALIZE_VARNAMES}${UWSM_FINALIZE_VARNAMES:+ }NIRI_SOCKET XCURSOR_SIZE XCURSOR_THEME" + export UWSM_FINALIZE_VARNAMES + + # can't detect if niri has --session arg +} + +quirks_niri_session() { + quirks_niri "$@" + # mark additional vars to wait for + UWSM_WAIT_VARNAMES="${UWSM_WAIT_VARNAMES}${UWSM_WAIT_VARNAMES:+ }NIRI_SOCKET" + export UWSM_WAIT_VARNAMES +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/niri_session.sh new/uwsm-0.26.1/uwsm-plugins/niri_session.sh --- old/uwsm-0.26.0/uwsm-plugins/niri_session.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/niri_session.sh 2026-01-31 16:16:30.374438729 +0100 @@ -0,0 +1 @@ +symbolic link to niri.sh diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/sway.sh new/uwsm-0.26.1/uwsm-plugins/sway.sh --- old/uwsm-0.26.0/uwsm-plugins/sway.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/sway.sh 2026-01-29 22:00:40.000000000 +0100 @@ -3,16 +3,14 @@ quirks_sway() { # detect disabled xwayland - if grep -qE '^[[:space:]]*xwayland[[:space:]]+disable' "${XDG_CONFIG_HOME}/sway/config" 2>/dev/null - then + if grep -qE '^[[:space:]]*xwayland[[:space:]]+disable' "${XDG_CONFIG_HOME}/sway/config" 2> /dev/null; then XWAYLAND=false else XWAYLAND=true fi # append "wlroots" to XDG_CURRENT_DESKTOP if not already there - if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ] - then + if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ]; then case "A:${XDG_CURRENT_DESKTOP}:Z" in *:wlroots:*) true ;; *) export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP}:wlroots" ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/uwsm-plugins/wayfire.sh new/uwsm-0.26.1/uwsm-plugins/wayfire.sh --- old/uwsm-0.26.0/uwsm-plugins/wayfire.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/uwsm-plugins/wayfire.sh 2026-01-29 22:00:40.000000000 +0100 @@ -4,16 +4,14 @@ quirks_wayfire() { WAYFIRE_LOCAL_CONFIG="${XDG_CONFIG_HOME}/wayfire.ini" # detect disabled xwayland - if grep -qE '^[[:space:]]*xwayland[[:space:]]*=[[:space:]]*false' "${WAYFIRE_LOCAL_CONFIG}" 2>/dev/null - then + if grep -qE '^[[:space:]]*xwayland[[:space:]]*=[[:space:]]*false' "${WAYFIRE_LOCAL_CONFIG}" 2> /dev/null; then XWAYLAND=false else XWAYLAND=true fi # append "wlroots" to XDG_CURRENT_DESKTOP if not already there - if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ] - then + if [ "${__WM_DESKTOP_NAMES_EXCLUSIVE__}" != "true" ]; then case "A:${XDG_CURRENT_DESKTOP}:Z" in *:wlroots:*) true ;; *) export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP}:wlroots" ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.0/version.sh new/uwsm-0.26.1/version.sh --- old/uwsm-0.26.0/version.sh 2025-12-28 12:09:59.000000000 +0100 +++ new/uwsm-0.26.1/version.sh 2026-01-29 22:00:40.000000000 +0100 @@ -4,7 +4,7 @@ # or prints back UWSM_VERSION env if set, # or prints a fallback version if not in git repo. -VERSION=0.26.0 +VERSION=0.26.1 set -e ++++++ uwsm.obsinfo ++++++ --- /var/tmp/diff_new_pack.yZIrww/_old 2026-01-31 16:16:30.466442552 +0100 +++ /var/tmp/diff_new_pack.yZIrww/_new 2026-01-31 16:16:30.478443050 +0100 @@ -1,5 +1,5 @@ name: uwsm -version: 0.26.0 -mtime: 1766920199 -commit: 433174c297ef858cc370f143657781ad4856263e +version: 0.26.1 +mtime: 1769720440 +commit: 9c3f28beabda78f15330fa4d5c75a9ab190aaf2b
