bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103)
Convert mouse y to line number in the sidebar rather than the text.
diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py
index 76964a4..41c0968 100644
--- a/Lib/idlelib/sidebar.py
+++ b/Lib/idlelib/sidebar.py
@@ -204,10 +204,19 @@
bind_mouse_event(event_name,
target_event_name=f'<Button-{button}>')
+ # This is set by b1_mousedown_handler() and read by
+ # drag_update_selection_and_insert_mark(), to know where dragging
+ # began.
start_line = None
+ # These are set by b1_motion_handler() and read by selection_handler().
+ # last_y is passed this way since the mouse Y-coordinate is not
+ # available on selection event objects. last_yview is passed this way
+ # to recognize scrolling while the mouse isn't moving.
+ last_y = last_yview = None
+
def b1_mousedown_handler(event):
# select the entire line
- lineno = self.editwin.getlineno(f"@0,{event.y}")
+ lineno = int(float(self.sidebar_text.index(f"@0,{event.y}")))
self.text.tag_remove("sel", "1.0", "end")
self.text.tag_add("sel", f"{lineno}.0", f"{lineno+1}.0")
self.text.mark_set("insert", f"{lineno+1}.0")
@@ -217,15 +226,20 @@
start_line = lineno
self.sidebar_text.bind('<Button-1>', b1_mousedown_handler)
- # These are set by b1_motion_handler() and read by selection_handler();
- # see below. last_y is passed this way since the mouse Y-coordinate
- # is not available on selection event objects. last_yview is passed
- # this way to recognize scrolling while the mouse isn't moving.
- last_y = last_yview = None
+ def b1_mouseup_handler(event):
+ # On mouse up, we're no longer dragging. Set the shared persistent
+ # variables to None to represent this.
+ nonlocal start_line
+ nonlocal last_y
+ nonlocal last_yview
+ start_line = None
+ last_y = None
+ last_yview = None
+ self.sidebar_text.bind('<ButtonRelease-1>', b1_mouseup_handler)
def drag_update_selection_and_insert_mark(y_coord):
"""Helper function for drag and selection event handlers."""
- lineno = self.editwin.getlineno(f"@0,{y_coord}")
+ lineno = int(float(self.sidebar_text.index(f"@0,{y_coord}")))
a, b = sorted([start_line, lineno])
self.text.tag_remove("sel", "1.0", "end")
self.text.tag_add("sel", f"{a}.0", f"{b+1}.0")
@@ -253,6 +267,9 @@
# while the mouse isn't moving, leading to the above fix not scrolling
# properly.
def selection_handler(event):
+ if last_yview is None:
+ # This logic is only needed while dragging.
+ return
yview = self.sidebar_text.yview()
if yview != last_yview:
self.text.yview_moveto(yview[0])