bpo-37849: IDLE: fix completion window positioning above line (GH-15267)


diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py
index c69ab4a..5035e06 100644
--- a/Lib/idlelib/autocomplete_w.py
+++ b/Lib/idlelib/autocomplete_w.py
@@ -52,10 +52,12 @@
         # (for example, he clicked the list)
         self.userwantswindow = None
         # event ids
-        self.hideid = self.keypressid = self.listupdateid = self.winconfigid \
-        = self.keyreleaseid = self.doubleclickid                         = None
+        self.hideid = self.keypressid = self.listupdateid = \
+            self.winconfigid = self.keyreleaseid = self.doubleclickid = None
         # Flag set if last keypress was a tab
         self.lastkey_was_tab = False
+        # Flag set to avoid recursive <Configure> callback invocations.
+        self.is_configuring = False
 
     def _change_start(self, newstart):
         min_len = min(len(self.start), len(newstart))
@@ -223,12 +225,18 @@
         self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE)
         self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE,
                                          self.listselect_event)
+        self.is_configuring = False
         self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event)
         self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE,
                                           self.doubleclick_event)
         return None
 
     def winconfig_event(self, event):
+        if self.is_configuring:
+            # Avoid running on recursive <Configure> callback invocations.
+            return
+
+        self.is_configuring = True
         if not self.is_active():
             return
         # Position the completion list window
@@ -236,6 +244,7 @@
         text.see(self.startindex)
         x, y, cx, cy = text.bbox(self.startindex)
         acw = self.autocompletewindow
+        acw.update()
         acw_width, acw_height = acw.winfo_width(), acw.winfo_height()
         text_width, text_height = text.winfo_width(), text.winfo_height()
         new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width))
@@ -256,6 +265,8 @@
             acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
             self.winconfigid = None
 
+        self.is_configuring = False
+
     def _hide_event_check(self):
         if not self.autocompletewindow:
             return