diff --git a/changes/2782.feature.md b/changes/2782.feature.md new file mode 100644 index 000000000..2b5660af8 --- /dev/null +++ b/changes/2782.feature.md @@ -0,0 +1 @@ +Windows MSI installers can now customize the background image used on the first page of the installer, and the banner image used on all subsequent pages of the installer. diff --git a/docs/en/reference/configuration.md b/docs/en/reference/configuration.md index 55ca6dc9a..7bc613b06 100644 --- a/docs/en/reference/configuration.md +++ b/docs/en/reference/configuration.md @@ -224,7 +224,7 @@ The application name as it should be displayed to humans. This name may contain A path, relative to the directory where the `pyproject.toml` file is located, to an image to use as the icon for the application. The path should *exclude* the extension; Briefcase will append a platform appropriate extension when configuring the application. For example, an icon specification of `icon = "resources/icon"` will use `resources/icon.icns` on macOS, and `resources/icon.ico` on Windows. -Some platforms require multiple icons, at different sizes; these will be handled by appending the required size to the provided icon name. For example, iOS requires multiple icon sizes (ranging from 20px to 1024px); Briefcase will look for `resources/icon-20.png`, `resources/icon-1024.png`, and so on. The sizes that are required are determined by the platform template. +Some platforms require multiple icons, at different sizes; these will be handled by appending the required size to the provided icon name. For example, iOS requires multiple icon sizes (ranging from 20px to 1024px); Briefcase will look for `resources/icon-20.png`, `resources/icon-1024.png`, and so on. The sizes that are required are determined by the platform template. See the documentation for each platform for the required icon sizes. #### `install_launcher` @@ -234,11 +234,15 @@ This setting is only used on Windows. #### `installer_icon` -A path, relative to the directory where the `pyproject.toml` file is located, to an image to use as the icon for the installer. As with [`icon`][], the path should *exclude* the extension, and a platform-appropriate extension will be appended when the application is built. +A path, relative to the directory where the `pyproject.toml` file is located, to an image to use as the icon for the installer. As with [`icon`][], the path should *exclude* the extension, and a platform-appropriate extension will be appended when the application is built. See the documentation for each platform for how the installer image will be used, and the required icon sizes. #### `installer_background` -A path, relative to the directory where the `pyproject.toml` file is located, to an image to use as the background for the installer. The path should *exclude* the extension, and a platform-appropriate extension will be appended when the application is built. +A path, relative to the directory where the `pyproject.toml` file is located, to an image to use as the background for the installer. The path should *exclude* the extension, and a platform-appropriate extension will be appended when the application is built. See the documentation for each platform for how the installer image will be used, and the required image size. + +#### `installer_banner` + +A path, relative to the directory where the `pyproject.toml` file is located, to an image to use as a banner for installer dialogs. The path should *exclude* the extension, and a platform-appropriate extension will be appended when the application is built. See the documentation for each platform for how the installer image will be used, and the required image size. #### `long_description` diff --git a/docs/en/reference/platforms/windows/index.md b/docs/en/reference/platforms/windows/index.md index 38304eb30..d00df8c9b 100644 --- a/docs/en/reference/platforms/windows/index.md +++ b/docs/en/reference/platforms/windows/index.md @@ -74,7 +74,7 @@ Briefcase uses the [WiX Toolset](https://www.firegiant.com/wixtoolset/) to build ## Icon format -Windows apps installers use multi-format `.ico` icons; these icons should contain images in the following sizes: +Windows apps use multi-format `.ico` icons; these icons should contain images in the following sizes: - 16px - 32px @@ -82,7 +82,13 @@ Windows apps installers use multi-format `.ico` icons; these icons should contai - 64px - 256px -Windows Apps do not support splash screens or installer images. +This icon will also be used for the entry in the Windows launcher menu, if required. + +If provided, the `installer_background` should be a 493x312px BMP image. It will be shown on the first page of an MSI installer. + +If provided, the `installer_banner` should be a 493x58px BMP image. It will be shown at the top of every page of an MSI installer *except* the first page. + +Windows apps do not support splash screens or custom installer icons. ## Additional options diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index c36e54cbb..a5bc8998f 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -25,6 +25,7 @@ beeware BeeWare BeeWare's blobless +BMP breakpoint Bugfix Bugfixes diff --git a/src/briefcase/platforms/windows/__init__.py b/src/briefcase/platforms/windows/__init__.py index 01b5279f7..4df865ff4 100644 --- a/src/briefcase/platforms/windows/__init__.py +++ b/src/briefcase/platforms/windows/__init__.py @@ -204,12 +204,27 @@ def output_format_template_context(self, app: FinalizedAppConfig): # system_installer not defined in config; default to asking the user install_scope = "perUserOrMachine" + installer_images = {} + try: + installer_images["background"] = str( + (self.base_path / app.installer_background).with_suffix(".bmp") + ) + except AttributeError: + installer_images["background"] = "" + try: + installer_images["banner"] = str( + (self.base_path / app.installer_banner).with_suffix(".bmp") + ) + except AttributeError: + installer_images["banner"] = "" + return { "version_triple": version_triple, "guid": str(guid), "install_scope": install_scope, "package_path": str(self.package_path(app)), "binary_path": self.package_executable_path(app), + "installer_images": installer_images, } def _cleanup_app_support_package(self, support_path): diff --git a/tests/platforms/windows/app/create/test_create.py b/tests/platforms/windows/app/create/test_create.py index 61b036e60..623cca0cd 100644 --- a/tests/platforms/windows/app/create/test_create.py +++ b/tests/platforms/windows/app/create/test_create.py @@ -115,6 +115,7 @@ def test_context(create_command, first_app_config): "binary_path", "guid", "install_scope", + "installer_images", "package_path", "version_triple", ] @@ -169,6 +170,31 @@ def test_explicit_guid(create_command, first_app_config, tmp_path): assert context["guid"] == "e822176f-b755-589f-849c-6c6600f7efb1" +def test_no_installer_images(create_command, first_app_config, tmp_path): + """If no installer images are specified, blank values are used.""" + context = create_command.output_format_template_context(first_app_config) + + # Installer images have been converted to a full path + assert context["installer_images"] == { + "background": "", + "banner": "", + } + + +def test_installer_images(create_command, first_app_config, tmp_path): + """If installer images are specified, they are converted and used.""" + first_app_config.installer_background = "path/to/background" + first_app_config.installer_banner = "path/to/banner" + + context = create_command.output_format_template_context(first_app_config) + + # Installer images have been converted to a full path + assert context["installer_images"] == { + "background": str(tmp_path / "base_path/path/to/background.bmp"), + "banner": str(tmp_path / "base_path/path/to/banner.bmp"), + } + + @pytest.mark.parametrize( ("revision", "micro"), [