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
19 changes: 14 additions & 5 deletions Lib/test/test_tkinter/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def destroy_default_root():
tkinter._default_root.destroy()
tkinter._default_root = None

def wait_until_mapped(widget, timeout=None):
def wait_until_mapped(widget, timeout=None, *, full_size=False):
"""Wait until *widget* is actually mapped and laid out by the window
manager, so that realized-geometry queries (winfo_width(), identify(),
coords(), ...) return meaningful values.
Expand All @@ -103,17 +103,26 @@ def wait_until_mapped(widget, timeout=None):
``support.LOOPBACK_TIMEOUT``). Unlike Misc.wait_visibility(), this
never blocks indefinitely, so it is safe under a window manager that
never maps the window (see gh-69134, gh-74941, bpo-40722).

If *full_size* is true, also wait until the realized size reaches the
requested size, so that per-pixel queries near an edge (e.g. identify())
are reliable even under load.
"""
if timeout is None:
timeout = support.LOOPBACK_TIMEOUT
deadline = time.monotonic() + timeout
widget.update_idletasks()
while True:
widget.update() # drain pending Map/Configure events
if (widget.winfo_ismapped()
and widget.winfo_width() > 1
and widget.winfo_height() > 1):
return True
if widget.winfo_ismapped():
if full_size:
w_ok = widget.winfo_width() >= widget.winfo_reqwidth() > 1
h_ok = widget.winfo_height() >= widget.winfo_reqheight() > 1
else:
w_ok = widget.winfo_width() > 1
h_ok = widget.winfo_height() > 1
if w_ok and h_ok:
return True
if time.monotonic() >= deadline:
return False
time.sleep(0.01)
Expand Down
15 changes: 12 additions & 3 deletions Lib/test/test_ttk/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1192,8 +1192,16 @@ def test_traversal(self):

self.nb.select(0)

focus_identify_as = 'focus' if sys.platform != 'darwin' else ''
self.assertEqual(self.nb.identify(5, 5), focus_identify_as)
if sys.platform == 'darwin':
focus_identify_as = ''
elif sys.platform == 'win32':
focus_identify_as = 'focus'
else:
focus_identify_as = 'focus' if tk_version < (8, 7) else 'padding'
# identify() at (5, 5) needs the tab realized there; under focus
# contention the mapped size can lag, so wait for the full size.
if wait_until_mapped(self.nb, full_size=True):
self.assertEqual(self.nb.identify(5, 5), focus_identify_as)
simulate_mouse_click(self.nb, 5, 5)
self.nb.focus_force()
self.nb.event_generate('<Control-Tab>')
Expand All @@ -1209,7 +1217,8 @@ def test_traversal(self):
self.nb.tab(self.child2, text='e', underline=0)
self.nb.enable_traversal()
self.nb.focus_force()
self.assertEqual(self.nb.identify(5, 5), focus_identify_as)
if wait_until_mapped(self.nb, full_size=True):
self.assertEqual(self.nb.identify(5, 5), focus_identify_as)
simulate_mouse_click(self.nb, 5, 5)
# on macOS Emacs-style keyboard shortcuts are region-dependent;
# let's use the regular arrow keys instead
Expand Down
Loading