Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/rules/rleapp-build-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ installs only on ARM64. macOS (Apple silicon and Intel): `.app` and `.dmg`. The
laid out by dmgbuild from `packaging/dmg_settings.py`: the app and an Applications link
either side of the arrow on `packaging/dmg_background.png`. The settings place the icons
for that 960x540 image, so a new background keeps its size and its arrow where it is.
The background of 2026-10-01 moved the arrow 44 points right (88 pixels on the @2x image),
to a centre at x=479, and the icons with it, from (260, 290) and (610, 290) to (304, 290)
and (654, 290). A test finds the arrow on the background and requires the two icons to
straddle it, so a background that moves it again fails there rather than on a Mac.
`dmg_background@2x.png` beside it, at exactly 1920x1080, is what a Retina screen shows:
dmgbuild finds it by name and joins the two into one TIFF with `tiffutil
-cathidpicheck`, which refuses a pair that is not exactly 1x and 2x. Without it the
Expand Down
17 changes: 17 additions & 0 deletions admin/test/scripts/test_packaging_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,23 @@ def test_the_window_is_as_wide_as_its_background(self):
self.assertEqual(win_w, width)
self.assertGreaterEqual(win_h, height)

def test_the_icons_sit_either_side_of_the_arrow(self):
"""A new background that moves the arrow, as the one of 2026-10-01 did by 44 points,
leaves the icons off centre unless the settings move with it. The arrow is the only
dark mark in its band."""
from PIL import Image # pylint: disable=import-outside-toplevel
with Image.open(PACKAGING / 'dmg_background.png') as img:
rgb = img.convert('RGB')
dark = [x for y in range(250, 320) for x in range(rgb.width)
if sum(rgb.getpixel((x, y))) < 600]
arrow_centre = (min(dark) + max(dark)) / 2
locations = _dmg_settings()['icon_locations']
(app_x, app_y), (apps_x, apps_y) = locations['RLEAPP.app'], locations['Applications']
self.assertEqual(app_y, apps_y)
self.assertLess(app_x, min(dark))
self.assertGreater(apps_x, max(dark))
self.assertLessEqual(abs((app_x + apps_x) / 2 - arrow_centre), 2)

def test_the_retina_background_is_exactly_twice_the_size(self):
"""dmgbuild joins dmg_background@2x.png to the background with tiffutil
-cathidpicheck, which refuses a pair that is not exactly 1x and 2x, and the disk
Expand Down
Binary file modified packaging/dmg_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packaging/dmg_background@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion packaging/dmg_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@
icon_size = 144
text_size = 14
label_pos = "bottom"
icon_locations = {appname: (260, 290), "Applications": (610, 290)}
# Either side of the arrow, whose centre is at x=479 on the background. The arrow moved 44
# points right with the background of 2026-10-01, and the icons with it, from (260, 290)
# and (610, 290).
icon_locations = {appname: (304, 290), "Applications": (654, 290)}
Loading