From 9b3d1a0dd1418af2fe28b07e3a8cf0e4c456bd77 Mon Sep 17 00:00:00 2001 From: Dalton Alexandre Date: Thu, 29 Oct 2026 13:25:13 -0700 Subject: [PATCH] Add Maximize Windows as a toggle that survives updates The menu's Maximize Windows toggle writes its labwc window rule to ~/.local/state/omarchy/xdg-config/labwc/rc.xml, never to ~/.config/labwc/rc.xml, which releases replace. The session puts that directory first in XDG_CONFIG_DIRS and starts labwc with -m, so labwc reads the rule file and then the user's rc.xml. Window rules from merged files accumulate. There is no /etc/xdg/labwc, so -m adds nothing else. Co-Authored-By: Claude Opus 5.5 --- desktop/configuration/login-session | 5 ++- .../shell/bin/omarchy-toggle-maximize-windows | 25 +++++++++++ .../shell/default/omarchy/omarchy-menu.jsonc | 2 + tests/test_menu_toggles.py | 42 +++++++++++++++++-- 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100755 desktop/shell/bin/omarchy-toggle-maximize-windows diff --git a/desktop/configuration/login-session b/desktop/configuration/login-session index 58765a7..ed0b906 100644 --- a/desktop/configuration/login-session +++ b/desktop/configuration/login-session @@ -21,4 +21,7 @@ export PATH=/usr/local/bin:/usr/bin # Quickshell. Do not spawn a separate dbus-run-session instance. systemctl --user import-environment DBUS_SESSION_BUS_ADDRESS XDG_SESSION_TYPE XDG_CURRENT_DESKTOP /usr/local/libexec/arch-ipad-first-theme -exec /usr/bin/labwc +# labwc -m reads labwc/rc.xml from each XDG config dir, then ~/.config/labwc/rc.xml. +# Menu toggles keep their rules under ~/.local/state, which a release never replaces. +export XDG_CONFIG_DIRS="$HOME/.local/state/omarchy/xdg-config:${XDG_CONFIG_DIRS:-/etc/xdg}" +exec /usr/bin/labwc -m diff --git a/desktop/shell/bin/omarchy-toggle-maximize-windows b/desktop/shell/bin/omarchy-toggle-maximize-windows new file mode 100755 index 0000000..ae4232b --- /dev/null +++ b/desktop/shell/bin/omarchy-toggle-maximize-windows @@ -0,0 +1,25 @@ +#!/bin/bash + +# omarchy:summary=Open new windows maximized, or not +# The rule lives in a labwc config that the session merges (labwc -m) before +# ~/.config/labwc/rc.xml, so updates that replace rc.xml keep it. Off by default. +set -euo pipefail +flag=$HOME/.local/state/omarchy/toggles/maximize-windows +rules=$HOME/.local/state/omarchy/xdg-config/labwc/rc.xml +mkdir -p "${flag%/*}" "${rules%/*}" +if [[ -e $flag ]]; then + rm -f "$flag" "$rules" +else + cat >"$rules.tmp" <<'XML' + + + + + + +XML + mv "$rules.tmp" "$rules" + : >"$flag" +fi +labwc=${LABWC_PID:-$(pgrep -u "$(id -u)" -x labwc | head -1 || true)} +[[ -z $labwc ]] || kill -HUP "$labwc" diff --git a/desktop/shell/default/omarchy/omarchy-menu.jsonc b/desktop/shell/default/omarchy/omarchy-menu.jsonc index c190497..f23752a 100644 --- a/desktop/shell/default/omarchy/omarchy-menu.jsonc +++ b/desktop/shell/default/omarchy/omarchy-menu.jsonc @@ -126,6 +126,8 @@ // Trigger "trigger.toggle": {"icon":"󰔎","label":"Toggle","aliases":["toggle","toggles"]}, + "trigger.toggle.maximize-windows-on": {"icon":"󰊓","label":"Maximize Windows On","when":"! omarchy-toggle-enabled maximize-windows","action":"omarchy-toggle-maximize-windows"}, + "trigger.toggle.maximize-windows-off": {"icon":"󰊓","label":"Maximize Windows Off","when":"omarchy-toggle-enabled maximize-windows","action":"omarchy-toggle-maximize-windows"}, "trigger.toggle.idle-lock-on": {"icon":"","label":"Stay Awake On","when":"[[ ! -f ~/.local/state/omarchy/indicators/stay-awake ]]","action":"omarchy-toggle-idle"}, "trigger.toggle.idle-lock-off": {"icon":"","label":"Stay Awake Off","when":"[[ -f ~/.local/state/omarchy/indicators/stay-awake ]]","action":"omarchy-toggle-idle"}, "trigger.toggle.notifications-on": {"icon":"󰂛","label":"Notifications On","when":"[[ $(omarchy-shell notifications isDnd) == on ]]","action":"omarchy-toggle-notification-silencing"}, diff --git a/tests/test_menu_toggles.py b/tests/test_menu_toggles.py index 6653dd8..92abec3 100644 --- a/tests/test_menu_toggles.py +++ b/tests/test_menu_toggles.py @@ -4,6 +4,7 @@ import subprocess import tempfile import unittest +import xml.etree.ElementTree as ET PROJECT = Path(__file__).resolve().parents[1] BIN = PROJECT / 'desktop/shell/bin' @@ -16,9 +17,12 @@ def setUp(self): self.home = Path(self.temp.name) self.env = {**os.environ, 'HOME': str(self.home)} + def run_bin(self, name, *args, **env): + return subprocess.run(['bash', str(BIN / name), *args], env={**self.env, **env}, + capture_output=True, text=True) + def toggle_enabled(self, *args): - return subprocess.run(['bash', str(BIN / 'omarchy-toggle-enabled'), *args], env=self.env, - capture_output=True, text=True).returncode + return self.run_bin('omarchy-toggle-enabled', *args).returncode def test_toggle_enabled_reflects_the_flag(self): self.assertEqual(self.toggle_enabled('bar-off'), 1) @@ -28,9 +32,41 @@ def test_toggle_enabled_reflects_the_flag(self): self.assertEqual(self.toggle_enabled('bar-off'), 0) self.assertEqual(self.toggle_enabled('../x'), 2) + def test_maximize_windows_round_trip_reloads_labwc(self): + flag = self.home / '.local/state/omarchy/toggles/maximize-windows' + rules = self.home / '.local/state/omarchy/xdg-config/labwc/rc.xml' + for expect_on in (True, False): + # Stand-in for labwc: SIGHUP ends a sleep, proving the reload signal. + labwc = subprocess.Popen(['sleep', '30']) + self.addCleanup(labwc.kill) + result = self.run_bin('omarchy-toggle-maximize-windows', LABWC_PID=str(labwc.pid)) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(labwc.wait(5), -1) # SIGHUP + self.assertEqual(flag.exists(), expect_on) + self.assertEqual(self.toggle_enabled('maximize-windows'), 0 if expect_on else 1) + self.assertEqual(rules.exists(), expect_on) + if expect_on: + tree = ET.fromstring(rules.read_bytes()) + found = tree.findall("./windowRules/windowRule[@identifier='*']/action[@name='Maximize']") + self.assertEqual(len(found), 1) + self.assertFalse((self.home / '.config').exists()) + + def test_session_merges_the_toggle_config_into_labwc(self): + # Releases replace ~/.config/labwc/rc.xml, so toggle rules must come from the + # state directory via labwc's XDG merge, never from edits to rc.xml. + session = (PROJECT / 'desktop/configuration/login-session').read_text() + self.assertIn('export XDG_CONFIG_DIRS="$HOME/.local/state/omarchy/xdg-config:', session) + self.assertEqual(session.rstrip().splitlines()[-1], 'exec /usr/bin/labwc -m') + toggle = (BIN / 'omarchy-toggle-maximize-windows').read_text() + self.assertIn('$HOME/.local/state/omarchy/xdg-config/labwc/rc.xml', toggle) + code = [line for line in toggle.splitlines() if not line.lstrip().startswith('#')] + self.assertFalse([line for line in code if '.config/labwc' in line]) + def test_menu_toggles_use_shipped_commands(self): menu = (PROJECT / 'desktop/shell/default/omarchy/omarchy-menu.jsonc').read_text() - for command in ('omarchy-toggle-bar', 'omarchy-toggle-enabled'): + for key in ('maximize-windows-on', 'maximize-windows-off'): + self.assertIn('"trigger.toggle.%s"' % key, menu) + for command in ('omarchy-toggle-maximize-windows', 'omarchy-toggle-bar', 'omarchy-toggle-enabled'): self.assertIn(command, menu) self.assertTrue((BIN / command).is_file(), command) bar = re.search(r'"appearance\.top-bar\.show": \{[^}]*\}', menu).group(0)