Repository navigation
Description
Bug report
With the python.org macOS installer for 3.13.17, widgets inside a hidden toplevel (withdrawn, or iconified) receive no events. This includes events sent synchronously with event_generate and ttk's <<ThemeChanged>>. The events are dropped rather than deferred: none are delivered after the window is shown. 3.13.16 with the same Tk patchlevel (8.6.18) delivers them all, as do Windows and Linux builds.
import sys
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
print("python", sys.version.split()[0], "tk", root.tk.call("info", "patchlevel"))
def run(label, hide):
top = tk.Toplevel(root)
hide(top)
frame = ttk.Frame(top, width=50, height=50)
hits = []
for ev in ("<Enter>", "<<Custom>>", "<<ThemeChanged>>"):
frame.bind(ev, lambda e, ev=ev: hits.append(ev), "+")
frame.pack()
root.update()
frame.event_generate("<Enter>")
frame.event_generate("<<Custom>>")
style = ttk.Style()
style.theme_use("alt" if style.theme_use() != "alt" else "clam")
root.update()
hidden = list(hits)
top.deiconify()
root.update()
print(f"{label:24} while hidden: {hidden} after show: {hits[len(hidden):]}")
top.destroy()
def shown_then_withdrawn(top):
root.update()
top.withdraw()
root.update()
run("never shown, withdrawn", lambda t: t.withdraw())
run("shown, then withdrawn", shown_then_withdrawn)
run("iconified", lambda t: t.iconify())
root.destroy()3.13.16 (expected):
python 3.13.16 tk 8.6.18
never shown, withdrawn while hidden: ['<<ThemeChanged>>', '<Enter>', '<<Custom>>', '<<ThemeChanged>>'] after show: []
shown, then withdrawn while hidden: ['<Enter>', '<<Custom>>', '<<ThemeChanged>>'] after show: []
iconified while hidden: ['<Enter>', '<<Custom>>', '<<ThemeChanged>>'] after show: []
3.13.17 (actual):
python 3.13.17 tk 8.6.18
never shown, withdrawn while hidden: [] after show: []
shown, then withdrawn while hidden: [] after show: []
iconified while hidden: [] after show: []
Both runs are on the same GitHub Actions macos-latest image (macos-26-arm64, 20261102.0473.1), using the python.org builds installed by actions/setup-python.
Practical effect: apps that build windows while hidden (a common pattern to avoid visible re-layout), or that update hidden or minimized windows through virtual events, silently lose those updates. For example, a ttk theme switch doesn't reach hidden windows.
CPython versions tested on:
3.13
Operating systems tested on:
macOS
Activity
ned-deily commentedon Nov 6, 2026
As noted on the 3.13.17 release page, "The macOS installer for this release is built with a pre-release of Tk [8.6], fixing a possible hang on macOS 27.0 in applications using tkinter, like IDLE, in older releases." #158053 links to the 8.6 pre-release source used. Presumably, the difference in behavior is due to some change in Tk since the 8.6.18 release and prior to the snapshot of the Tk core-8-6-branch.
However, your test case also fails with the current python.org macOS Python 3.15.2 which used a post-9.0.4 snapshot of the Tk core-9-0-branch (to also get around the menu hang on macOS 27) but behaves as expected using the 3.15.0 installer which was built with the Tk 9.0.4 release.
Perhaps @culler has an idea whether this was a known issue and is fixed in the upcoming 9.0.5 release?
(Keep in mind that Python 3.13 has now reached the security-fix-only phase of its release cycle which means that only source code is included in future releases and no binaries including no installers for macOS or Windows. The latest release, 3.13.18, was source-only.)
ThingamabobsCoding commentedon Nov 6, 2026
Arranges for window to be withdrawn from the screen. This causes the window to be unmapped and forgotten about by the window manager. If the window has never been mapped, then this command causes the window to be mapped in the withdrawn state. Not all window managers appear to know how to handle windows that are mapped in the withdrawn state. Note that it sometimes seems to be necessary to withdraw a window and then re-map it (e.g. with wm deiconify) to get some window managers to pay attention to changes in window attributes such as group See: https://www.tcl-lang.org/man/tcl9.0/TkCmd/wm.html#M72
Withdrawn is a special state, you could to try to refactor to use overrideredirect in combination with a fully transparent window or positioning the window outside of the screen. I prefer to show a loading screen btw but this may take some more considerations
serhiy-storchaka commentedon Nov 6, 2026
This is a Tk regression. The fix for Tk ticket 88ffa70453 (3d4a73e5eba6, 2026-10-20) stopped realizing a ttk widget when it is created, and both snapshots contain it.
Generated events have always been silently dropped for a widget whose window does not exist yet, as they still are for classic widgets. ttk widgets were the exception since 2008, and they have now lost it. Calling
winfo_id()on the widget restores delivery.It is not macOS-specific, and not fixed in the upcoming 9.0.5. I will report it upstream.
The same change breaks several tkinter and IDLE tests, tracked in gh-161441.
ned-deily commentedon Nov 10, 2026
@culler, @serhiy-storchaka What is the consensus on this issue? Is it agreed that it is a Tk regression that needs to be fixed and, if so, is there a Tk issue tracking this? Or is it something else that a tkinter user needs to be aware of? If there is a Tk change needed, it would be good to get it into 9.0.5.
culler commentedon Nov 10, 2026
I agree that we should fix it ASAP. I did not see a ticket about it. I think @serhiy-storchaka knows
what to do about it - I haven't looked at it myself, but I could if necessary.
[-]macOS 3.13.17 installer: tkinter drops all events sent to widgets in a hidden window[/-][+]tkinter with pre-release versions of Tk 9.0.5 or 8.6.18 drops all events sent to widgets in a hidden window[/+]ned-deily commentedon Nov 10, 2026
Updating the issue title to better reflect the scope of the problem. FTR, this affects the most recent python.org macOS installers (3.13.17, 3.14.9 & .10, 3.15.1 & .2, and 3.16.0a2) which use pre-release versions of Tk to address the critical menu hang issue seen on macOS 27. It could also affect Python builds on other platforms.
culler commentedon Nov 10, 2026
I looked at the Tk tickets pertinent to this. (At lease one of them was originally reported as a tkinter bug.)
Here is a synopsis, based on looking at the tickets. The issue was that creating more than 10000 ttk widgets on Windows was causing bad behavior, such as hangs or weird artifacts. The cause was a per-process limit on the number of system handles of a certain type, one of which is associated with each widget. That limit could be exceeded even when most of the widgets involved were never mapped. The fix for thar was to defer the creation of a widget until the first time that it actually gets mapped. That would at least allow 20000 widgets as long as fewer than 10000 of them were mapped. But a widget which does not exist does not receive virtual events, so it is not aware that its theme has changed when it actually gets created on its first map.
The fix was applied to all platforms. Undoing that change for other platforms would only requjire one #ifndef and one #endif, as far as I can tell.
Regarding macOS, I should mention that the macOS port of Tk 9.1 will provide a different way of "hiding" windows by setting a new attribute -hidden to True. That causes the window to be removed from the screen but has no effect on its underlying Tk structures. A window hidden in that sense will be able to receive events and will appear to Tk as a normal window. Something which can be used as a substitute for that, to provide a workaround right now, is to "hide" a window by setting its alpha attribute to 0 instead of withdrawing it.
serhiy-storchaka commentedon Nov 11, 2026
First of all, what is the scope of the issue? Is it the theme change only, or there are other practical cases? I have several options for theme changes, but supporting other events (which may be never needed on practice) may need larger changes.
ThingamabobsCoding commentedon Nov 11, 2026
As far as I know, people use WM_WITHDRAW only to "hide" the rendering process. A simple, effective and good change would when the window just gets out of screen for it.
win32: https://github.com/tcltk/tk/blob/main/win/tkWinWm.c#L8862
Unix: https://github.com/tcltk/tk/blob/main/unix/tkUnixWm.c#L7867
OSX: https://github.com/tcltk/tk/blob/main/macosx/tkMacOSXWm.c#L7032
To make this a great change, please update the screen_info to be able to use with multiple monitors. A lazy approach however can be to position the window -10_000 x and y pixel and remove the thumbnail (maybe just call overrideredirct for it) if present. WITHDRAW seems to originate on X-Systems and for every other system it gets copied in its behavior.
culler commentedon Nov 11, 2026
Yes, they do that. But it doesn't actually accomplish what they want because the
wm withdrawcommand unmaps the toplevel window and all of its descendants, and unmapped widgets do not get drawn. What actually happens, if you are lucky, is that the drawing takes place during the fade-and-scale animation when the window is restored to the screen. The window and its widgets do get configured to their final size while the window is withdrawn. But they do not get rendered.See TIP #765 for more details.
Better support for multiple monitors would be a good thing. Moving the window to a position out of all monitors is not a good idea.
Also, this discussion is off-topic for this Python issue. Feel free to move it to the Tcl Core list, after reading the TIP.
culler commentedon Nov 12, 2026
The change that led to this behavior has now been reverted in all three Tk branches, so the upcoming release of 9.0.5 will not include it.
ned-deily commentedon Nov 13, 2026
Thanks everyone who was involved with reporting and with fixing this issue. Since the behavior change has now been reverted in the relevant Tk branches (see the Tk issue for the details), I am going to close this issue. The incorrect behavior should disappear as new versions of Tk are released and distributors of Python for macOS update the versions of Tk that they use. In particular, the next releases of the python.org installers for macOS (3.14.11, 3.15.3, and 3.16.0a3) will include this fix.