diff --git a/Lib/test/test_tkinter/support.py b/Lib/test/test_tkinter/support.py index 84c83306e57ebae..ea2f9012a705498 100644 --- a/Lib/test/test_tkinter/support.py +++ b/Lib/test/test_tkinter/support.py @@ -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. @@ -103,6 +103,10 @@ 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 @@ -110,10 +114,15 @@ def wait_until_mapped(widget, timeout=None): 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) diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py index 5054ad8b9adf3fc..f134f88aedf6cbc 100644 --- a/Lib/test/test_ttk/test_widgets.py +++ b/Lib/test/test_ttk/test_widgets.py @@ -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('') @@ -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