Patch #1037 2006-05-07 22:58

pecan

Fix bug 6884 dragNdrop hang
Download
1037-Fix_bug_6884_d.patch (4.7 KB)
Category
 
Status
Accepted
Close date
2006-05-09 08:32
Assigned to
 
Index: src/scintilla/src/Editor.cxx
===================================================================
--- src/scintilla/src/Editor.cxx    (revision 2387)
+++ src/scintilla/src/Editor.cxx    (working copy)
@@ -5,6 +5,18 @@
 // Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
+//Lines tagged //pecan 20060506 is a patch to avoid the GTK drag'n'drop hang bug.
+//GTK is not handling a mouse "moving buttonUp" event well. The keyUp event is completely missed
+// causing wxGTK to hang in the drag routine waiting for the up event.GTK has the mouse captured,
+// so no event will ever be seen by wxGTK.
+//This is aggravated by the manner in which scintilla coded the mouse doubleClick.
+// It treats it as two single ButtonDown clicks, entering DragNdrop over and over again.
+//This patch moves the initiation of the drag into the MouseMove code to avoid the double click
+// problem. It will not allow secondary drags until a subsequent mouse up event.
+//This patch does not cure the problem, it can still happen if the user quickly drags
+// and lifts the mouse key at the same time the mouse is moving. But it's much harder
+// to cause the hang. Pecan
+
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -442,6 +454,9 @@
     hsEnd = -1;
 
     llc.SetLevel(LineLayoutCache::llcCaret);
+    #ifdef __WXGTK__
+    m_mouseButtonDownCnt = 0;   //pecan 20060507
+    #endif
 }
 
 Editor::~Editor() {
@@ -1212,7 +1227,7 @@
 where most code reside, and the lines after the caret, eg. the body of a function.
 
      |        |       |      |                                            |
-slop | strict | jumps | even | Caret can go to the margin                 | When reaching limitÝ(caret going out of
+slop | strict | jumps | even | Caret can go to the margin                 | When reaching limit (caret going out of
      |        |       |      |                                            | visibility or going into the UZ) display is...
 -----+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
   0  |   0    |   0   |   0  | Yes                                        | moved to put caret on top/on right
@@ -5037,6 +5052,9 @@
 
 void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
     //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);
+    #ifdef __WXGTK__
+    m_mouseButtonDownCnt++;    //pecan 20060507
+    #endif
     ptMouseLast = pt;
     int newPos = PositionFromLocation(pt);
     newPos = MovePositionOutsideChar(newPos, currentPos - newPos);
@@ -5124,12 +5142,18 @@
             }
             if (!shift) {
                 inDragDrop = PointInSelection(pt) && !SelectionEmpty();
+                #ifdef __WXGTK__
+                if (m_mouseButtonDownCnt>1)     //pecan 20060507
+                    inDragDrop = false;         //pecan 20060507
+                #endif
             }
             if (inDragDrop) {
+                #ifndef __WXGTK__       //for GTK, code moved to ButtonMove() //pecan 20060507
                 SetMouseCapture(false);
                 SetDragPosition(newPos);
                 CopySelectionRange(&drag);
                 StartDrag();
+                #endif
             } else {
                 SetDragPosition(invalidPosition);
                 SetMouseCapture(true);
@@ -5203,6 +5227,18 @@
     }
     ptMouseLast = pt;
     //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
+    #ifdef __WXGTK__        //pecan 20060507
+    // code moved here from ButtonDown to avoid GTK doubleClick/drag hang bug
+    if (inDragDrop) {
+        SetMouseCapture(false);
+        int newPos = PositionFromLocation(pt);
+        SetDragPosition(newPos);
+        CopySelectionRange(&drag);
+        m_mouseButtonDownCnt++; //don't do again until mouse ButtonUp //pecan 20060507
+        StartDrag();
+    }
+    #endif  //pecan 20060507
+
     if (HaveMouseCapture()) {
 
         // Slow down autoscrolling/selection
@@ -5289,7 +5325,10 @@
 }
 
 void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
-    //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
+    //Platform::DebugPrintf("ButtonUp mouseCapture%d downCnt:%d", HaveMouseCapture(), m_mouseButtonDownCnt);
+    #ifdef __WXGTK__
+    m_mouseButtonDownCnt = 0;   //pecan 20060507
+    #endif
     if (HaveMouseCapture()) {
         if (PointInSelMargin(pt)) {
             DisplayCursor(Window::cursorReverseArrow);
Index: src/scintilla/src/Editor.h
===================================================================
--- src/scintilla/src/Editor.h    (revision 2387)
+++ src/scintilla/src/Editor.h    (working copy)
@@ -528,6 +528,8 @@
 
     virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
 
+    int m_mouseButtonDownCnt;   //pecan 20060507
+
 public:
     // Public so the COM thunks can access it.
     bool IsUnicodeMode() const;
pecan 2006-05-07 23:01

Proposed fix for dragNdrop hang on GTK. Patch moves Scintilla drag initiation into ButtonMove routine to avoid loop initiation of drag from within ButtonDown. Also avoids doubleClick aggravation of GTK bug.

mandrav 2006-05-09 08:32

Patch applied, thanks.

I would advise you report it to the scintilla (or wxScintilla) folks too or else, the next time we upgrade our wxScintilla version, your patch will be lost again...