Skip to content

Commit 8bd800f

Browse files
committed
Fix drag & drop in OSR Kivy.
Calling SendMouseMoveEvent in on_mouse_move_emulate() during drag was causing issues with RenderHandler.StartDragging not being called.
1 parent 7b2b8f5 commit 8bd800f

File tree

3 files changed

+116
-27
lines changed

3 files changed

+116
-27
lines changed
1.28 KB
Loading
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"kivy-dragdrop.png" downloaded from here:
2+
http://www.softicons.com/toolbar-icons/free-blue-button-icons-by-aha-soft/cursor-drag-arrow-icon
3+
4+
Author: Aha-Soft ( http://www.aha-soft.com/ )
5+
License: CC Attribution 3.0 United States

src/linux/binaries_64bit/kivy_.py

Lines changed: 111 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,11 @@ def devtools(self, *kwargs):
573573
self.browser.ShowDevTools()
574574

575575

576+
is_mouse_down = False
577+
is_drag = False
578+
is_drag_leave = False # Mouse leaves web view
579+
drag_data = None
580+
576581
def on_touch_down(self, touch, *kwargs):
577582
# Mouse scrolling
578583
if "button" in touch.profile:
@@ -598,14 +603,10 @@ def on_touch_down(self, touch, *kwargs):
598603
mouseUp=True, clickCount=1
599604
)
600605
else:
601-
print("~~ DragTargetDragEnter")
602606
self.browser.SendMouseClickEvent(touch.x, y,
603607
cefpython.MOUSEBUTTON_LEFT,
604608
mouseUp=False, clickCount=1)
605-
self.browser.DragTargetDragEnter(cefpython.DragData(), touch.x,
606-
y, cefpython.DRAG_OPERATION_EVERY)
607-
608-
609+
self.is_mouse_down = True
609610

610611

611612
def on_touch_up(self, touch, *kwargs):
@@ -624,16 +625,33 @@ def on_touch_up(self, touch, *kwargs):
624625
y = self.height-touch.pos[1]
625626
self.browser.SendMouseClickEvent(touch.x, y, cefpython.MOUSEBUTTON_LEFT,
626627
mouseUp=True, clickCount=1)
627-
628-
print("~~ DragTargetDrop")
629-
self.browser.DragTargetDrop(touch.x, y)
630-
631-
print("~~ DragSourceEndedAt")
632-
self.browser.DragSourceEndedAt(touch.x, y,
633-
cefpython.DRAG_OPERATION_MOVE)
634-
635-
print("~~ DragSourceSystemDragEnded")
636-
self.browser.DragSourceSystemDragEnded()
628+
self.is_mouse_down = False
629+
630+
if self.is_drag:
631+
#print("on_touch_up=%s/%s" % (touch.x,y))
632+
if self.is_drag_leave or not self.is_inside_web_view(touch.x, y):
633+
print("~~ DragSourceEndedAt")
634+
# See comment in is_inside_web_view() - x/y at borders
635+
# should be treated as outside of web view.
636+
x = touch.x
637+
if x == 0:
638+
x = -1
639+
if x == self.width-1:
640+
x = self.width
641+
if y == 0:
642+
y = -1
643+
if y == self.height-1:
644+
y = self.height
645+
self.browser.DragSourceEndedAt(x, y,
646+
cefpython.DRAG_OPERATION_MOVE)
647+
self.drag_ended()
648+
else:
649+
print("~~ DragTargetDrop")
650+
print("~~ DragSourceEndedAt")
651+
self.browser.DragTargetDrop(touch.x, y)
652+
self.browser.DragSourceEndedAt(touch.x, y,
653+
cefpython.DRAG_OPERATION_MOVE)
654+
self.drag_ended()
637655

638656
touch.ungrab(self)
639657

@@ -653,7 +671,10 @@ def on_mouse_move_emulate(self):
653671
y = int(mouse_pos[1]-self.height)
654672
if x >= 0 and y <= 0:
655673
y = abs(y)
656-
self.browser.SendMouseMoveEvent(x, y, mouseLeave=False)
674+
if not self.is_mouse_down and not self.is_drag:
675+
# When mouse is down on_touch_move will be called. Calling
676+
# mouse move event here caused issues with drag&drop.
677+
self.browser.SendMouseMoveEvent(x, y, mouseLeave=False)
657678

658679

659680
def on_touch_move(self, touch, *kwargs):
@@ -665,13 +686,69 @@ def on_touch_move(self, touch, *kwargs):
665686
modifiers = cefpython.EVENTFLAG_LEFT_MOUSE_BUTTON
666687
self.browser.SendMouseMoveEvent(touch.x, y, mouseLeave=False,
667688
modifiers=modifiers)
689+
if self.is_drag:
690+
#print("on_touch_move=%s/%s" % (touch.x, y))
691+
if self.is_inside_web_view(touch.x, y):
692+
if self.is_drag_leave:
693+
print("~~ DragTargetDragEnter")
694+
self.browser.DragTargetDragEnter(
695+
self.drag_data, touch.x, y,
696+
cefpython.DRAG_OPERATION_EVERY)
697+
self.is_drag_leave = False
698+
print("~~ DragTargetDragOver")
699+
self.browser.DragTargetDragOver(
700+
touch.x, y, cefpython.DRAG_OPERATION_MOVE)
701+
self.update_drag_icon(touch.x, y)
702+
else:
703+
if not self.is_drag_leave:
704+
self.is_drag_leave = True
705+
print("~~ DragTargetDragLeave")
706+
self.browser.DragTargetDragLeave()
707+
708+
709+
def is_inside_web_view(self, x, y):
710+
# When mouse is out of app window Kivy still generates move events
711+
# at the borders with x=0, x=width-1, y=0, y=height-1.
712+
if (x > 0 and x < self.width-1)\
713+
and (y > 0 and y < self.height-1):
714+
return True
715+
return False
668716

669-
print("~~ DragTargetDragOver")
670-
self.browser.DragTargetDragOver(touch.x, y,
671-
cefpython.DRAG_OPERATION_MOVE)
672717

718+
def drag_ended(self):
719+
# Either success or cancelled.
720+
self.is_drag = False
721+
self.is_drag_leave = False
722+
del self.drag_data
723+
self.update_drag_icon(None, None)
724+
print("~~ DragSourceSystemDragEnded")
725+
self.browser.DragSourceSystemDragEnded()
726+
727+
728+
drag_icon = None
729+
730+
def update_drag_icon(self, x, y):
731+
if self.drag_icon:
732+
self.canvas.remove(self.drag_icon)
733+
del self.drag_icon
734+
if self.is_drag:
735+
self.drag_icon = Rectangle(source="kivy-dragdrop.png",
736+
pos=self.flip_pos_vertical(x,y),
737+
size=(40,40))
738+
self.canvas.add(self.drag_icon)
673739

674740

741+
def flip_pos_vertical(self, x, y):
742+
half = self.height / 2
743+
if y > half:
744+
y = half - (y-half)
745+
elif y < half:
746+
y = half + (half-y)
747+
# Additionally position drag icon to the center of mouse cursor
748+
y = y - 20
749+
x = x - 20
750+
return (x, y)
751+
675752

676753
class ClientHandler:
677754

@@ -791,7 +868,6 @@ def OnLoadingStateChange(self, browser, isLoading, canGoBack,
791868
print("OnLoadingStateChange(): isLoading = %s" % isLoading)
792869
browserWidget = browser.GetUserData("browserWidget")
793870

794-
795871
def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width,
796872
height):
797873
# print "OnPaint()"
@@ -805,6 +881,7 @@ def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width,
805881
#update texture of canvas rectangle
806882
self.browserWidget.texture.blit_buffer(buffer, colorfmt='bgra',
807883
bufferfmt='ubyte')
884+
808885
self.browserWidget._update_rect()
809886

810887
return True
@@ -862,16 +939,23 @@ def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload,
862939

863940

864941
def StartDragging(self, browser, drag_data, allowed_ops, x, y):
865-
print("!!!! StartDragging()")
866-
# TODO: succession of calls:
942+
print("~~ StartDragging")
943+
# Succession of d&d calls:
867944
# DragTargetDragEnter
868-
# DragTargetDragOver
945+
# DragTargetDragOver - in touch move event
869946
# DragTargetDragLeave - optional
870947
# DragSourceSystemDragEnded - optional, to cancel dragging
871-
# DragTargetDrop
872-
# DragSourceEndedAt
873-
# DragSourceSystemDragEnded
874-
return False
948+
# DragTargetDrop - on mouse up
949+
# DragSourceEndedAt - on mouse up
950+
# DragSourceSystemDragEnded - on mouse up
951+
print("~~ DragTargetDragEnter")
952+
self.browserWidget.browser.DragTargetDragEnter(
953+
drag_data, x, y, cefpython.DRAG_OPERATION_EVERY)
954+
self.browserWidget.is_drag = True
955+
self.browserWidget.is_drag_leave = False
956+
self.browserWidget.drag_data = drag_data
957+
self.browserWidget.update_drag_icon(x, y)
958+
return True
875959

876960

877961
def UpdateDragCursor(self, browser, operation):

0 commit comments

Comments
 (0)