Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Merge remote-tracking branch 'upstream/main' into tkinter-dnd-cursor
# Conflicts:
#	Lib/test/test_tkinter/test_dnd.py
  • Loading branch information
serhiy-storchaka committed Jun 27, 2026
commit 16d3b01e7ffb2a00167a09cfa9d41f40733d2cb8
69 changes: 63 additions & 6 deletions Lib/test/test_tkinter/test_dnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,76 @@ def test_no_recursive_start(self):
def test_high_button_number_ignored(self):
self.assertIsNone(dnd.dnd_start(self.source, FakeEvent(self.canvas, num=6)))

def test_cursor_deferred_until_motion(self):
def test_restart_after_finish(self):
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
handler.cancel()
# Once a drag has finished a new one can start.
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.assertIsNotNone(handler)
handler.cancel()

def test_drag_cursor(self):
# The drag cursor is not shown on the initial press, only once the
# pointer moves past the threshold, so a plain click does not flash
# it (gh-43699).
self.canvas['cursor'] = 'arrow'
# it (gh-43699). The original cursor is restored afterwards.
self.canvas['cursor'] = 'watch'
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.assertEqual(str(self.canvas['cursor']), 'arrow')
self.assertEqual(handler.save_cursor, 'watch')
self.assertEqual(str(self.canvas['cursor']), 'watch')
handler.on_motion(FakeEvent(self.canvas, x_root=2)) # below threshold
self.assertEqual(str(self.canvas['cursor']), 'arrow')
self.assertEqual(str(self.canvas['cursor']), 'watch')
handler.on_motion(FakeEvent(self.canvas, x_root=20)) # past threshold
self.assertEqual(str(self.canvas['cursor']), 'hand2')
handler.cancel()
self.assertEqual(str(self.canvas['cursor']), 'arrow') # restored
self.assertEqual(str(self.canvas['cursor']), 'watch')

def test_bindings_added_and_removed(self):
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.assertIn('<Motion>', self.canvas.bind())
self.assertIn('<B1-ButtonRelease-1>', self.canvas.bind())
handler.cancel()
self.assertNotIn('<Motion>', self.canvas.bind())
self.assertNotIn('<B1-ButtonRelease-1>', self.canvas.bind())

def test_switch_target(self):
log1, log2 = [], []
w1, w2 = tkinter.Frame(self.root), tkinter.Frame(self.root)
target1, target2 = Target(w1, log1), Target(w2, log2)
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
self.canvas.winfo_containing = lambda x, y: w1
handler.on_motion(FakeEvent(self.canvas)) # Enter target1.
self.canvas.winfo_containing = lambda x, y: w2
handler.on_motion(FakeEvent(self.canvas)) # Leave target1, enter target2.
self.assertIs(handler.target, target2)
self.assertEqual(log1, ['accept', 'enter', 'leave'])
self.assertEqual(log2, ['accept', 'enter'])
handler.cancel()

def test_target_in_ancestor(self):
# The widget under the pointer has no dnd_accept, but an ancestor
# does: the search walks up the master chain to find it.
parent = tkinter.Frame(self.root)
self.log)
child = tkinter.Frame(parent)
self.canvas.winfo_containing = lambda x, y: child
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
handler.on_motion(FakeEvent(self.canvas))
self.assertIs(handler.target, target)
self.assertEqual(self.log, ['accept', 'enter'])
handler.cancel()

def test_accept_returning_none_continues(self):
# dnd_accept() returning None means "not me, keep looking up".
parent = tkinter.Frame(self.root)
self.log)
child = tkinter.Frame(parent)
child.dnd_accept = lambda source, event: None
self.canvas.winfo_containing = lambda x, y: child
handler = dnd.dnd_start(self.source, FakeEvent(self.canvas))
handler.on_motion(FakeEvent(self.canvas))
self.assertIs(handler.target, target)
handler.cancel()


if __name__ == "__main__":
unittest.main()
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.