From 62248711f8a18f43f2726e1ba489fdf779fa6463 Mon Sep 17 00:00:00 2001 From: krisnaparahita Date: Thu, 10 Sep 2026 10:08:00 +0800 Subject: [PATCH 1/2] Scale down tray icon on Linux to avoid oversized/blurry rendering Part of #528: taskbar.png is sized for macOS/Windows (88x88), which renders poorly in Linux system trays that typically expect ~22-24px icons. Scale down on Linux with LANCZOS resampling before handing the image to pystray. Deliberately does not touch the click-to-open-menu half of #528: an earlier community PR (#1063) that set default=True on Linux was found to be unsafe on the AppIndicator backend (pystray's docs/behavior mean default has no effect there, and AppIndicator already owns left-click to open the menu by design) and was closed unmerged, untested on real Linux hardware. This change is scoped to the uncontroversial half and verified only via unit tests (no Linux GUI available in this sandbox either) - visual confirmation on a real Linux desktop is still needed before wider claims about the click behavior. Co-Authored-By: Claude Sonnet 5 --- app/desktop/desktop.py | 5 +++++ app/desktop/test_desktop.py | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/app/desktop/desktop.py b/app/desktop/desktop.py index 3a9aa660c6..487f349ad8 100644 --- a/app/desktop/desktop.py +++ b/app/desktop/desktop.py @@ -119,6 +119,11 @@ def run_tray(self): tray_image = Image.open(self.resource_path("taskbar.png")) + # taskbar.png is sized for macOS/Windows; Linux trays typically render icons + # at ~22-24px, so the source image looks oversized/blurry there unless scaled down. + if sys.platform.startswith("linux"): + tray_image = tray_image.resize((24, 24), Image.Resampling.LANCZOS) + # Use default on Windows to get "left click to open" behaviour. # It looks ugly on MacOS (just a bold effect Apple never uses), so don't use it there make_open_studio_default = sys.platform in ("win32", "Windows") diff --git a/app/desktop/test_desktop.py b/app/desktop/test_desktop.py index d59229f24f..7ee52669f2 100644 --- a/app/desktop/test_desktop.py +++ b/app/desktop/test_desktop.py @@ -236,6 +236,32 @@ def test_run_tray_macos_no_default( menu_calls = mock_kiln_menu_item.call_args_list assert menu_calls[0][1]["default"] is False + @patch("app.desktop.desktop.sys.platform", "linux") + def test_run_tray_linux_icon_scaling( + self, mock_tk_root, mock_image, mock_kiln_tray, mock_kiln_menu_item + ): + """Test run_tray scales the tray icon down on Linux.""" + app = DesktopApp(port=TEST_PORT) + + with patch.object(app, "resource_path", return_value="taskbar.png"): + app.run_tray() + + mock_image.resize.assert_called_once() + args, _ = mock_image.resize.call_args + assert args[0] == (24, 24) + + @patch("app.desktop.desktop.sys.platform", "win32") + def test_run_tray_windows_no_icon_scaling( + self, mock_tk_root, mock_image, mock_kiln_tray, mock_kiln_menu_item + ): + """Test run_tray does not scale the tray icon on Windows.""" + app = DesktopApp(port=TEST_PORT) + + with patch.object(app, "resource_path", return_value="taskbar.png"): + app.run_tray() + + mock_image.resize.assert_not_called() + def test_close_splash_with_pyi_splash(self, mock_tk_root): """Test close_splash when pyi_splash is available.""" app = DesktopApp(port=TEST_PORT) From ea8c0bdb94e068907fb1959e31c7ffa20e35d66c Mon Sep 17 00:00:00 2001 From: krisnaparahita Date: Sun, 13 Sep 2026 18:49:43 +0800 Subject: [PATCH 2/2] Strengthen Linux tray icon scaling test --- app/desktop/test_desktop.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/app/desktop/test_desktop.py b/app/desktop/test_desktop.py index 7ee52669f2..104032e67f 100644 --- a/app/desktop/test_desktop.py +++ b/app/desktop/test_desktop.py @@ -5,6 +5,7 @@ import pytest import requests +from PIL import Image from uvicorn import Config as UvicornConfig import app.desktop.desktop_server as desktop_server @@ -32,9 +33,9 @@ def mock_tk_root(): @pytest.fixture def mock_image(): """Mock PIL Image.""" - with patch("app.desktop.desktop.Image") as mock_img: + with patch("app.desktop.desktop.Image.open") as mock_image_open: mock_image_obj = Mock() - mock_img.open.return_value = mock_image_obj + mock_image_open.return_value = mock_image_obj yield mock_image_obj @@ -238,17 +239,24 @@ def test_run_tray_macos_no_default( @patch("app.desktop.desktop.sys.platform", "linux") def test_run_tray_linux_icon_scaling( - self, mock_tk_root, mock_image, mock_kiln_tray, mock_kiln_menu_item + self, mock_tk_root, mock_image, mock_kiln_menu_item ): """Test run_tray scales the tray icon down on Linux.""" app = DesktopApp(port=TEST_PORT) - with patch.object(app, "resource_path", return_value="taskbar.png"): + with ( + patch.object(app, "resource_path", return_value="taskbar.png"), + patch("app.desktop.desktop.KilnTray") as mock_kiln_tray_class, + ): app.run_tray() mock_image.resize.assert_called_once() - args, _ = mock_image.resize.call_args - assert args[0] == (24, 24) + mock_image.resize.assert_called_once_with( + (24, 24), Image.Resampling.LANCZOS + ) + resized_image = mock_image.resize.return_value + mock_kiln_tray_class.assert_called_once() + assert mock_kiln_tray_class.call_args.args[1] is resized_image @patch("app.desktop.desktop.sys.platform", "win32") def test_run_tray_windows_no_icon_scaling(