diff options
author | terryjreedy <tjreedy@udel.edu> | 2017-06-14 15:43:49 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-14 15:43:49 (GMT) |
commit | 3280579450e3ee94e4916e2543b4dd8898d51b02 (patch) | |
tree | 70af6cf421b9eceeb96a03191bf0d1a9475bd74c /Lib/idlelib/autocomplete_w.py | |
parent | c2a506e40e9135bfd17b59fffc62261dc95bc535 (diff) | |
download | cpython-3280579450e3ee94e4916e2543b4dd8898d51b02.zip cpython-3280579450e3ee94e4916e2543b4dd8898d51b02.tar.gz cpython-3280579450e3ee94e4916e2543b4dd8898d51b02.tar.bz2 |
bpo-15786: IDLE: Fix mouse clicks on autocompletetion window (#1811) (#2187)
Patch by Louie Lu.
(cherry picked from commit 778b484145edfd0d9b65129322d3295bed8eb71a)
Diffstat (limited to 'Lib/idlelib/autocomplete_w.py')
-rw-r--r-- | Lib/idlelib/autocomplete_w.py | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 3374c6e..e7354d0 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -1,6 +1,8 @@ """ An auto-completion window for IDLE, used by the autocomplete extension """ +import platform + from tkinter import * from tkinter.ttk import Scrollbar @@ -8,7 +10,8 @@ from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES from idlelib.multicall import MC_SHIFT HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>" -HIDE_SEQUENCES = ("<FocusOut>", "<ButtonPress>") +HIDE_FOCUS_OUT_SEQUENCE = "<FocusOut>" +HIDE_SEQUENCES = (HIDE_FOCUS_OUT_SEQUENCE, "<ButtonPress>") KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>" # We need to bind event beyond <Key> so that the function will be called # before the default specific IDLE function @@ -201,10 +204,12 @@ class AutoCompleteWindow: self._selection_changed() # bind events - self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, - self.hide_event) + self.hideaid = acw.bind(HIDE_VIRTUAL_EVENT_NAME, self.hide_event) + self.hidewid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, self.hide_event) + acw.event_add(HIDE_VIRTUAL_EVENT_NAME, HIDE_FOCUS_OUT_SEQUENCE) for seq in HIDE_SEQUENCES: self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq) + self.keypressid = self.widget.bind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypress_event) for seq in KEYPRESS_SEQUENCES: @@ -240,9 +245,37 @@ class AutoCompleteWindow: new_y -= acw_height acw.wm_geometry("+%d+%d" % (new_x, new_y)) + if platform.system().startswith('Windows'): + # See issue 15786. When on windows platform, Tk will misbehaive + # to call winconfig_event multiple times, we need to prevent this, + # otherwise mouse button double click will not be able to used. + acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + self.winconfigid = None + + def _hide_event_check(self): + if not self.autocompletewindow: + return + + try: + if not self.autocompletewindow.focus_get(): + self.hide_window() + except KeyError: + # See issue 734176, when user click on menu, acw.focus_get() + # will get KeyError. + self.hide_window() + def hide_event(self, event): + # Hide autocomplete list if it exists and does not have focus or + # mouse click on widget / text area. if self.is_active(): - self.hide_window() + if event.type == EventType.FocusOut: + # On windows platform, it will need to delay the check for + # acw.focus_get() when click on acw, otherwise it will return + # None and close the window + self.widget.after(1, self._hide_event_check) + elif event.type == EventType.ButtonPress: + # ButtonPress event only bind to self.widget + self.hide_window() def listselect_event(self, event): if self.is_active(): @@ -391,10 +424,15 @@ class AutoCompleteWindow: return # unbind events + self.autocompletewindow.event_delete(HIDE_VIRTUAL_EVENT_NAME, + HIDE_FOCUS_OUT_SEQUENCE) for seq in HIDE_SEQUENCES: self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq) - self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid) - self.hideid = None + + self.autocompletewindow.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideaid) + self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hidewid) + self.hideaid = None + self.hidewid = None for seq in KEYPRESS_SEQUENCES: self.widget.event_delete(KEYPRESS_VIRTUAL_EVENT_NAME, seq) self.widget.unbind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypressid) @@ -405,8 +443,12 @@ class AutoCompleteWindow: self.keyreleaseid = None self.listbox.unbind(LISTUPDATE_SEQUENCE, self.listupdateid) self.listupdateid = None - self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid) - self.winconfigid = None + if self.winconfigid: + self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + self.winconfigid = None + + # Re-focusOn frame.text (See issue #15786) + self.widget.focus_set() # destroy widgets self.scrollbar.destroy() |