bpo-41611: IDLE: Catch TclError exceptions in AutoCompleteWindow.winconfig_event() (GH-26404)

Since the <Configure> event may occur after the
completion window is gone, catch potential
TclError exceptions when accessing acw.

(cherry picked from commit 4e2e5c1c4f)
This commit is contained in:
Miss Islington (bot) 2021-05-27 23:39:59 -07:00 committed by GitHub
parent 427232f9d2
commit 21a56a4bce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 27 deletions

View file

@ -239,37 +239,46 @@ class AutoCompleteWindow:
self.is_configuring = True self.is_configuring = True
if not self.is_active(): if not self.is_active():
return return
# Position the completion list window
text = self.widget # Since the <Configure> event may occur after the completion window is gone,
text.see(self.startindex) # catch potential TclError exceptions when accessing acw. See: bpo-41611.
x, y, cx, cy = text.bbox(self.startindex) try:
acw = self.autocompletewindow # Position the completion list window
if platform.system().startswith('Windows'): text = self.widget
# On Windows an update() call is needed for the completion list text.see(self.startindex)
# window to be created, so that we can fetch its width and x, y, cx, cy = text.bbox(self.startindex)
# height. However, this is not needed on other platforms (tested acw = self.autocompletewindow
# on Ubuntu and macOS) but at one point began causing freezes on if platform.system().startswith('Windows'):
# macOS. See issues 37849 and 41611. # On Windows an update() call is needed for the completion
acw.update() # list window to be created, so that we can fetch its width
acw_width, acw_height = acw.winfo_width(), acw.winfo_height() # and height. However, this is not needed on other platforms
text_width, text_height = text.winfo_width(), text.winfo_height() # (tested on Ubuntu and macOS) but at one point began
new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) # causing freezes on macOS. See issues 37849 and 41611.
new_y = text.winfo_rooty() + y acw.update()
if (text_height - (y + cy) >= acw_height # enough height below acw_width, acw_height = acw.winfo_width(), acw.winfo_height()
or y < acw_height): # not enough height above text_width, text_height = text.winfo_width(), text.winfo_height()
# place acw below current line new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width))
new_y += cy new_y = text.winfo_rooty() + y
else: if (text_height - (y + cy) >= acw_height # enough height below
# place acw above current line or y < acw_height): # not enough height above
new_y -= acw_height # place acw below current line
acw.wm_geometry("+%d+%d" % (new_x, new_y)) new_y += cy
acw.update_idletasks() else:
# place acw above current line
new_y -= acw_height
acw.wm_geometry("+%d+%d" % (new_x, new_y))
acw.update_idletasks()
except TclError:
pass
if platform.system().startswith('Windows'): if platform.system().startswith('Windows'):
# See issue 15786. When on Windows platform, Tk will misbehave # See issue 15786. When on Windows platform, Tk will misbehave
# to call winconfig_event multiple times, we need to prevent this, # to call winconfig_event multiple times, we need to prevent this,
# otherwise mouse button double click will not be able to used. # otherwise mouse button double click will not be able to used.
acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) try:
acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
except TclError:
pass
self.winconfigid = None self.winconfigid = None
self.is_configuring = False self.is_configuring = False

View file

@ -0,0 +1 @@
Avoid uncaught exceptions in ``AutoCompleteWindow.winconfig_event()``.