From 15859ded052a05d89ada453f44ce6f25b67f364d Mon Sep 17 00:00:00 2001 From: John Pals <7024725+DigitalPals@users.noreply.github.com> Date: Wed, 30 Sep 2026 09:49:45 +0200 Subject: [PATCH] Fix ChatGPT display scaling with native Wayland Launch ChatGPT with the Wayland backend so it follows monitor scaling when XWayland scaling is disabled. Keep checkout and ISO launchers aligned, update installed-system verification, and cover both installation paths with a parity fixture. --- image/desktop_payload.py | 10 ++++++ image/package | 5 ++- image/test_installation_parity.py | 31 +++++++++++++++++++ roles/dotfiles/files/chatgpt.desktop | 2 +- .../deployment-convergence.test.cjs | 4 +-- tests/verify-system | 4 +-- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/image/desktop_payload.py b/image/desktop_payload.py index dc06f16b..9ff908a5 100644 --- a/image/desktop_payload.py +++ b/image/desktop_payload.py @@ -45,6 +45,16 @@ def prepare_defaults(root, payload, environment, inventory): KITTY_INCLUDE = "# BEGIN CYBEXOS MANAGED INCLUDE\ninclude cybexos.conf\n# END CYBEXOS MANAGED INCLUDE\n" +def prepare_app_launchers(root, payload): + """Package the same desktop launchers that checkout installs deploy.""" + applications = payload / 'usr/share/cybexos/user-seed/.local/share/applications' + applications.mkdir(parents=True, exist_ok=True) + for name in ('nvim-kitty', 'brave-origin', 'chatgpt', 'com.onepassword.OnePassword'): + target = applications / (name + '.desktop') + shutil.copyfile(root / 'roles/dotfiles/files' / target.name, target) + target.chmod(0o644) + + def prepare_session(root, payload, inventory): """Session pieces the workstation installs per user, packaged once. diff --git a/image/package b/image/package index 465aef3b..17b8de36 100755 --- a/image/package +++ b/image/package @@ -14,7 +14,7 @@ import urllib.request import jinja2 import yaml from application_payload import relativize_seed_links, include_applications -from desktop_payload import prepare_defaults, prepare_session, split_seed, prepare_managed_defaults +from desktop_payload import prepare_defaults, prepare_session, split_seed, prepare_managed_defaults, prepare_app_launchers from provision_payload import prepare_provision from release_metadata import install_update_channel, render_spec @@ -112,8 +112,7 @@ def main(): content = (ROOT / "roles/dotfiles/templates" / (name + ".desktop.j2")).read_text() write(f"{seed}/.local/share/applications/{name}.desktop", content.replace("{{ primary_home }}/.local/bin/", "")) - for name in ("nvim-kitty", "brave-origin", "chatgpt", "com.onepassword.OnePassword"): - copy(f"roles/dotfiles/files/{name}.desktop", f"{seed}/.local/share/applications/{name}.desktop") + prepare_app_launchers(ROOT, payload) t3_desktop = (ROOT / "roles/dotfiles/templates/t3code-nightly.desktop.j2").read_text() write(f"{seed}/.local/share/applications/t3code-nightly.desktop", t3_desktop.replace("{{ primary_home }}/.local/bin/", "")) diff --git a/image/test_installation_parity.py b/image/test_installation_parity.py index cdb92ec8..ec1c1b7c 100644 --- a/image/test_installation_parity.py +++ b/image/test_installation_parity.py @@ -188,6 +188,37 @@ def test_packaged_policy_is_the_same_source_used_by_checkout(self): with self.assertRaisesRegex(ValueError, 'both installer schemas'): defaults(Path('fixture')) + def test_chatgpt_launcher_matches_checkout_and_iso_at_native_display_scale(self): + from desktop_payload import prepare_app_launchers + from test_desktop_payload import INIT + + launcher = '.local/share/applications/chatgpt.desktop' + (self.home / launcher).parent.mkdir(parents=True) + task = next(task for task in yaml.safe_load( + (ROOT / 'roles/dotfiles/tasks/main.yml').read_text()) + if task.get('name') == 'Install MIME defaults and desktop launchers') + task['become'] = False + task['loop'] = [item for item in task['loop'] if item['name'] == 'chatgpt.desktop'] + task['ansible.builtin.copy']['src'] = str(ROOT / 'roles/dotfiles/files') + '/{{ item.name }}' + playbook = self.root / 'chatgpt-launcher.yml' + playbook.write_text(yaml.safe_dump([{ + 'hosts': 'localhost', 'connection': 'local', 'gather_facts': False, + 'vars': {'primary_home': str(self.home), 'primary_user': 'fixture', + 'features': {'proprietary_apps': True}}, + 'tasks': [task], + }])) + result = subprocess.run(['ansible-playbook', '-i', 'localhost,', str(playbook)], + env=os.environ, text=True, capture_output=True, timeout=30) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + payload = self.root / 'payload' + prepare_app_launchers(ROOT, payload) + iso_home = self.root / 'iso-account' + INIT.seed_applications(payload / 'usr/share/cybexos/user-seed', iso_home) + self.assertEqual((self.home / launcher).read_bytes(), (iso_home / launcher).read_bytes()) + self.assertIn('Exec=chatgpt --ozone-platform=wayland %U', + (iso_home / launcher).read_text().splitlines()) + if __name__ == '__main__': unittest.main() diff --git a/roles/dotfiles/files/chatgpt.desktop b/roles/dotfiles/files/chatgpt.desktop index 91db0543..93fe462d 100644 --- a/roles/dotfiles/files/chatgpt.desktop +++ b/roles/dotfiles/files/chatgpt.desktop @@ -2,7 +2,7 @@ Name=ChatGPT Comment=ChatGPT by OpenAI GenericName=AI assistant -Exec=chatgpt %U +Exec=chatgpt --ozone-platform=wayland %U Icon=chatgpt Type=Application Terminal=false diff --git a/tests/quickshell/deployment-convergence.test.cjs b/tests/quickshell/deployment-convergence.test.cjs index d64aa6ee..f6f7b97d 100644 --- a/tests/quickshell/deployment-convergence.test.cjs +++ b/tests/quickshell/deployment-convergence.test.cjs @@ -136,8 +136,8 @@ test("ChatGPT launcher follows portable desktop scaling", () => { assert.match(dotfileTasks, /Install MIME defaults and desktop launchers[\s\S]{0,1200}?name: chatgpt\.desktop[\s\S]{0,120}?features\.proprietary_apps/, "the launcher must be deployed as a per-user package override"); - assert.match(launcher, /^Exec=chatgpt %U$/m, - "ChatGPT follows the display scale selected by the desktop"); + assert.match(launcher, /^Exec=chatgpt --ozone-platform=wayland %U$/m, + "native Wayland follows the display scale even when XWayland scaling is disabled"); }); test("disabled Docker and Tailscale retire activation and imported trust", () => { diff --git a/tests/verify-system b/tests/verify-system index d5a325fc..dfa451ce 100755 --- a/tests/verify-system +++ b/tests/verify-system @@ -668,8 +668,8 @@ if feature_enabled proprietary_apps; then check 'ChatGPT repository key matches the reviewed OpenAI key' \ cmp -s "$repo_root/roles/apps/files/chatgpt-repository-key.asc" \ /etc/pki/rpm-gpg/RPM-GPG-KEY-chatgpt - check 'ChatGPT launcher follows the desktop display scale' \ - grep -qx 'Exec=chatgpt %U' \ + check 'ChatGPT launcher uses native Wayland for desktop display scaling' \ + grep -qx 'Exec=chatgpt --ozone-platform=wayland %U' \ "$HOME/.local/share/applications/chatgpt.desktop" check 'Brave restore, locale spellcheck, and 1Password policy is valid JSON' \ jq -e --arg language "${regional_locale%%_*}" \