Repository: beeware/briefcase
Pull request #1547 (2023-11-20 18:44:15)

Set runtime icon for PyGame apps
## Changes
- The default runtime icon for PyGame apps is now replaced with Brutus

## PR Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
- [X] All new features have been tested
- [X] All new features have been documented
- [X] I have read the **CONTRIBUTING.md** file
- [X] I will abide by the code of conduct


Patch:
diff --git a/changes/1532.bugfix.rst b/changes/1532.bugfix.rst
new file mode 100644
index 00000000..6aedec4d
--- /dev/null
+++ b/changes/1532.bugfix.rst
@@ -0,0 +1,1 @@
+The BeeWare icon of Brutus is now used as the runtime icon for new projects created with PyGame.
diff --git a/src/briefcase/bootstraps/pursuedpybear.py b/src/briefcase/bootstraps/pursuedpybear.py
index fdb43355..a166fd56 100644
--- a/src/briefcase/bootstraps/pursuedpybear.py
+++ b/src/briefcase/bootstraps/pursuedpybear.py
@@ -25,14 +25,14 @@ class {{ cookiecutter.class_name }}(ppb.Scene):
 
 
 def main():
-    # Linux desktop environments use app's .desktop file to integrate the app
-    # to their application menus. The .desktop file of this app will include
-    # StartupWMClass key, set to app's formal name, which helps associate
+    # Linux desktop environments use an app's .desktop file to integrate the app
+    # in to their application menus. The .desktop file of this app will include
+    # the StartupWMClass key, set to app's formal name. This helps associate the
     # app's windows to its menu item.
     #
-    # For association to work any windows of the app must have WMCLASS
-    # property set to match the value set in app's desktop file. For PPB this
-    # is set using environment variable.
+    # For association to work, any windows of the app must have WMCLASS property
+    # set to match the value set in app's desktop file. For PPB, this is set
+    # using the SDL_VIDEO_X11_WMCLASS environment variable.
 
     # Find the name of the module that was used to start the app
     app_module = sys.modules["__main__"].__package__
diff --git a/src/briefcase/bootstraps/pygame.py b/src/briefcase/bootstraps/pygame.py
index 34fa2d5a..b5d8f35f 100644
--- a/src/briefcase/bootstraps/pygame.py
+++ b/src/briefcase/bootstraps/pygame.py
@@ -9,6 +9,7 @@ class PygameGuiBootstrap(BaseGuiBootstrap):
 import importlib.metadata
 import os
 import sys
+from pathlib import Path
 
 import pygame
 
@@ -18,14 +19,14 @@ WHITE = (255, 255, 255)
 
 
 def main():
-    # Linux desktop environments use app's .desktop file to integrate the app
-    # to their application menus. The .desktop file of this app will include
-    # StartupWMClass key, set to app's formal name, which helps associate
+    # Linux desktop environments use an app's .desktop file to integrate the app
+    # in to their application menus. The .desktop file of this app will include
+    # the StartupWMClass key, set to app's formal name. This helps associate the
     # app's windows to its menu item.
     #
-    # For association to work any windows of the app must have WMCLASS
-    # property set to match the value set in app's desktop file. For PPB this
-    # is set using environment variable.
+    # For association to work, any windows of the app must have WMCLASS property
+    # set to match the value set in app's desktop file. For PyGame, this is set
+    # using the SDL_VIDEO_X11_WMCLASS environment variable.
 
     # Find the name of the module that was used to start the app
     app_module = sys.modules["__main__"].__package__
@@ -34,6 +35,13 @@ def main():
 
     os.environ["SDL_VIDEO_X11_WMCLASS"] = metadata["Formal-Name"]
 
+    # Set the app's runtime icon
+    pygame.display.set_icon(
+        pygame.image.load(
+            Path(__file__).parent / "resources" / "{{ cookiecutter.app_name }}.png"
+        )
+    )
+
     pygame.init()
     pygame.display.set_caption(metadata["Formal-Name"])
     screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
diff --git a/src/briefcase/bootstraps/pyside6.py b/src/briefcase/bootstraps/pyside6.py
index 0486a59c..3d2d0c78 100644
--- a/src/briefcase/bootstraps/pyside6.py
+++ b/src/briefcase/bootstraps/pyside6.py
@@ -23,14 +23,14 @@ class {{ cookiecutter.class_name }}(QtWidgets.QMainWindow):
 
 
 def main():
-    # Linux desktop environments use app's .desktop file to integrate the app
-    # to their application menus. The .desktop file of this app will include
-    # StartupWMClass key, set to app's formal name, which helps associate
+    # Linux desktop environments use an app's .desktop file to integrate the app
+    # in to their application menus. The .desktop file of this app will include
+    # the StartupWMClass key, set to app's formal name. This helps associate the
     # app's windows to its menu item.
     #
-    # For association to work any windows of the app must have WMCLASS
-    # property set to match the value set in app's desktop file. For PySide6
-    # this is set with setApplicationName().
+    # For association to work, any windows of the app must have WMCLASS property
+    # set to match the value set in app's desktop file. For PySide6, this is set
+    # with setApplicationName().
 
     # Find the name of the module that was used to start the app
     app_module = sys.modules["__main__"].__package__


Test patch:
diff --git a/tests/commands/new/test_build_context.py b/tests/commands/new/test_build_context.py
index fb58c13a..56f160ab 100644
--- a/tests/commands/new/test_build_context.py
+++ b/tests/commands/new/test_build_context.py
@@ -304,14 +304,14 @@ class {{ cookiecutter.class_name }}(QtWidgets.QMainWindow):
 
 
 def main():
-    # Linux desktop environments use app's .desktop file to integrate the app
-    # to their application menus. The .desktop file of this app will include
-    # StartupWMClass key, set to app's formal name, which helps associate
+    # Linux desktop environments use an app's .desktop file to integrate the app
+    # in to their application menus. The .desktop file of this app will include
+    # the StartupWMClass key, set to app's formal name. This helps associate the
     # app's windows to its menu item.
     #
-    # For association to work any windows of the app must have WMCLASS
-    # property set to match the value set in app's desktop file. For PySide6
-    # this is set with setApplicationName().
+    # For association to work, any windows of the app must have WMCLASS property
+    # set to match the value set in app's desktop file. For PySide6, this is set
+    # with setApplicationName().
 
     # Find the name of the module that was used to start the app
     app_module = sys.modules["__main__"].__package__
@@ -496,14 +496,14 @@ class {{ cookiecutter.class_name }}(ppb.Scene):
 
 
 def main():
-    # Linux desktop environments use app's .desktop file to integrate the app
-    # to their application menus. The .desktop file of this app will include
-    # StartupWMClass key, set to app's formal name, which helps associate
+    # Linux desktop environments use an app's .desktop file to integrate the app
+    # in to their application menus. The .desktop file of this app will include
+    # the StartupWMClass key, set to app's formal name. This helps associate the
     # app's windows to its menu item.
     #
-    # For association to work any windows of the app must have WMCLASS
-    # property set to match the value set in app's desktop file. For PPB this
-    # is set using environment variable.
+    # For association to work, any windows of the app must have WMCLASS property
+    # set to match the value set in app's desktop file. For PPB, this is set
+    # using the SDL_VIDEO_X11_WMCLASS environment variable.
 
     # Find the name of the module that was used to start the app
     app_module = sys.modules["__main__"].__package__
@@ -647,6 +647,7 @@ def test_question_sequence_pygame(new_command):
 import importlib.metadata
 import os
 import sys
+from pathlib import Path
 
 import pygame
 
@@ -656,14 +657,14 @@ WHITE = (255, 255, 255)
 
 
 def main():
-    # Linux desktop environments use app's .desktop file to integrate the app
-    # to their application menus. The .desktop file of this app will include
-    # StartupWMClass key, set to app's formal name, which helps associate
+    # Linux desktop environments use an app's .desktop file to integrate the app
+    # in to their application menus. The .desktop file of this app will include
+    # the StartupWMClass key, set to app's formal name. This helps associate the
     # app's windows to its menu item.
     #
-    # For association to work any windows of the app must have WMCLASS
-    # property set to match the value set in app's desktop file. For PPB this
-    # is set using environment variable.
+    # For association to work, any windows of the app must have WMCLASS property
+    # set to match the value set in app's desktop file. For PyGame, this is set
+    # using the SDL_VIDEO_X11_WMCLASS environment variable.
 
     # Find the name of the module that was used to start the app
     app_module = sys.modules["__main__"].__package__
@@ -672,6 +673,13 @@ def main():
 
     os.environ["SDL_VIDEO_X11_WMCLASS"] = metadata["Formal-Name"]
 
+    # Set the app's runtime icon
+    pygame.display.set_icon(
+        pygame.image.load(
+            Path(__file__).parent / "resources" / "{{ cookiecutter.app_name }}.png"
+        )
+    )
+
     pygame.init()
     pygame.display.set_caption(metadata["Formal-Name"])
     screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))