Skip to content

Commit 3280579

Browse files
authored
bpo-15786: IDLE: Fix mouse clicks on autocompletetion window (#1811) (#2187)
Patch by Louie Lu. (cherry picked from commit 778b484)
1 parent c2a506e commit 3280579

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

‎Lib/idlelib/autocomplete_w.py‎

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
"""
22
An auto-completion window for IDLE, used by the autocomplete extension
33
"""
4+
import platform
5+
46
from tkinter import *
57
from tkinter.ttk import Scrollbar
68

79
from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES
810
from idlelib.multicall import MC_SHIFT
911

1012
HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>"
11-
HIDE_SEQUENCES = ("<FocusOut>", "<ButtonPress>")
13+
HIDE_FOCUS_OUT_SEQUENCE = "<FocusOut>"
14+
HIDE_SEQUENCES = (HIDE_FOCUS_OUT_SEQUENCE, "<ButtonPress>")
1215
KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
1316
# We need to bind event beyond <Key> so that the function will be called
1417
# before the default specific IDLE function
@@ -201,10 +204,12 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin):
201204
self._selection_changed()
202205

203206
# bind events
204-
self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME,
205-
self.hide_event)
207+
self.hideaid = acw.bind(HIDE_VIRTUAL_EVENT_NAME, self.hide_event)
208+
self.hidewid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME, self.hide_event)
209+
acw.event_add(HIDE_VIRTUAL_EVENT_NAME, HIDE_FOCUS_OUT_SEQUENCE)
206210
for seq in HIDE_SEQUENCES:
207211
self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq)
212+
208213
self.keypressid = self.widget.bind(KEYPRESS_VIRTUAL_EVENT_NAME,
209214
self.keypress_event)
210215
for seq in KEYPRESS_SEQUENCES:
@@ -240,9 +245,37 @@ def winconfig_event(self, event):
240245
new_y -= acw_height
241246
acw.wm_geometry("+%d+%d" % (new_x, new_y))
242247

248+
if platform.system().startswith('Windows'):
249+
# See issue 15786. When on windows platform, Tk will misbehaive
250+
# to call winconfig_event multiple times, we need to prevent this,
251+
# otherwise mouse button double click will not be able to used.
252+
acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
253+
self.winconfigid = None
254+
255+
def _hide_event_check(self):
256+
if not self.autocompletewindow:
257+
return
258+
259+
try:
260+
if not self.autocompletewindow.focus_get():
261+
self.hide_window()
262+
except KeyError:
263+
# See issue 734176, when user click on menu, acw.focus_get()
264+
# will get KeyError.
265+
self.hide_window()
266+
243267
def hide_event(self, event):
268+
# Hide autocomplete list if it exists and does not have focus or
269+
# mouse click on widget / text area.
244270
if self.is_active():
245-
self.hide_window()
271+
if event.type == EventType.FocusOut:
272+
# On windows platform, it will need to delay the check for
273+
# acw.focus_get() when click on acw, otherwise it will return
274+
# None and close the window
275+
self.widget.after(1, self._hide_event_check)
276+
elif event.type == EventType.ButtonPress:
277+
# ButtonPress event only bind to self.widget
278+
self.hide_window()
246279

247280
def listselect_event(self, event):
248281
if self.is_active():
@@ -391,10 +424,15 @@ def hide_window(self):
391424
return
392425

393426
# unbind events
427+
self.autocompletewindow.event_delete(HIDE_VIRTUAL_EVENT_NAME,
428+
HIDE_FOCUS_OUT_SEQUENCE)
394429
for seq in HIDE_SEQUENCES:
395430
self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq)
396-
self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid)
397-
self.hideid = None
431+
432+
self.autocompletewindow.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideaid)
433+
self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hidewid)
434+
self.hideaid = None
435+
self.hidewid = None
398436
for seq in KEYPRESS_SEQUENCES:
399437
self.widget.event_delete(KEYPRESS_VIRTUAL_EVENT_NAME, seq)
400438
self.widget.unbind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypressid)
@@ -405,8 +443,12 @@ def hide_window(self):
405443
self.keyreleaseid = None
406444
self.listbox.unbind(LISTUPDATE_SEQUENCE, self.listupdateid)
407445
self.listupdateid = None
408-
self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
409-
self.winconfigid = None
446+
if self.winconfigid:
447+
self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
448+
self.winconfigid = None
449+
450+
# Re-focusOn frame.text (See issue #15786)
451+
self.widget.focus_set()
410452

411453
# destroy widgets
412454
self.scrollbar.destroy()

0 commit comments

Comments
 (0)