Skip to content

Commit c733415

Browse files
committed
Show correct Dock icon on macOS when run from source
Fixes #238
1 parent 0376500 commit c733415

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Release Notes ⋮
2222
* Development improvements
2323
* Manually bring app to front on macOS when run from source,
2424
to workaround a wxPython 4.2.3 bug.
25+
* Show correct Dock icon on macOS when run from source.
2526

2627
### v2.0.0 (September 26, 2025)
2728

src/crystal/main.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,6 @@ def sys_unraisablehook(args) -> None:
314314
import wx.richtext # must import before wx.App object is created, according to wx.richtext module docstring
315315
import wx.xml # required by wx.richtext; use explicit import as hint to py2app
316316

317-
@atexit.register
318317
def on_atexit() -> None:
319318
"""Called when the main thread and all non-daemon threads have exited."""
320319

@@ -327,6 +326,7 @@ def on_atexit() -> None:
327326
# Exit process immediately, without bothering to run garbage collection
328327
# or other cleanup processes that can take a long time
329328
os._exit(exit_code)
329+
atexit.register(on_atexit)
330330

331331
# Set headless mode, before anybody tries to call fg_call_later
332332
from crystal.util.headless import set_headless_mode
@@ -350,6 +350,8 @@ class MyApp(wx.App):
350350
def __init__(self, *args, **kwargs):
351351
from crystal import APP_NAME
352352
from crystal.util.wx_bind import bind
353+
from crystal.util.xos import is_mac_os
354+
import wx
353355

354356
self._keepalive_frame = None
355357
self._did_finish_launch = False
@@ -358,6 +360,22 @@ def __init__(self, *args, **kwargs):
358360
# macOS: Define app name used by the "Quit X" and "Hide X" menuitems
359361
self.SetAppDisplayName(APP_NAME)
360362

363+
# macOS + non-.app: Set Dock icon explicitly
364+
if is_mac_os() and getattr(sys, 'frozen', None) != 'macosx_app':
365+
from crystal import resources
366+
import wx.adv
367+
368+
appicon = wx.Icon()
369+
success = appicon.LoadFile(resources.get_filepath('appicon.png'), wx.BITMAP_TYPE_PNG)
370+
if not success:
371+
print('Warning: Failed to load Dock icon', file=sys.stderr)
372+
else:
373+
tbi = wx.adv.TaskBarIcon(wx.adv.TBI_DOCK)
374+
tbi.SetIcon(appicon, 'Crystal')
375+
# Store in field to avoid garbage collection,
376+
# which will unset the Dock icon
377+
self._tbi = tbi
378+
361379
# Listen for OS logout
362380
bind(self, wx.EVT_QUERY_END_SESSION, self._on_query_end_session)
363381
bind(self, wx.EVT_END_SESSION, self._on_end_session)

0 commit comments

Comments
 (0)