2011-04-20 Yuzhu Shen <yzshen@chromium.org>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Apr 2011 22:32:47 +0000 (22:32 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Apr 2011 22:32:47 +0000 (22:32 +0000)
        Reviewed by Tony Chang.

        [chromium] linux chromium doesn't set click count for mouse up events.
        https://bugs.webkit.org/show_bug.cgi?id=58921

        The reason why we need such a fix is that the Pepper API passes this information to plugins,
        and some consumers (e.g., Flash) need it to detect double-clicks.

        * src/gtk/WebInputEventFactory.cpp: set click count for mouse up events.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@84427 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/gtk/WebInputEventFactory.cpp
Source/WebKit/chromium/tests/WebInputEventFactoryTestGtk.cpp

index eec809c..3ca8870 100644 (file)
@@ -1,3 +1,15 @@
+2011-04-20  Yuzhu Shen  <yzshen@chromium.org>
+
+        Reviewed by Tony Chang.
+
+        [chromium] linux chromium doesn't set click count for mouse up events.
+        https://bugs.webkit.org/show_bug.cgi?id=58921
+
+        The reason why we need such a fix is that the Pepper API passes this information to plugins,
+        and some consumers (e.g., Flash) need it to detect double-clicks.
+
+        * src/gtk/WebInputEventFactory.cpp: set click count for mouse up events.
+        * tests/WebInputEventFactoryTestGtk.cpp: added test case MouseUpClickCount.
 2011-04-20  Evan Martin  <evan@chromium.org>
 
         Reviewed by Tony Chang.
index 71d1b39..4e355d2 100644 (file)
 
 namespace {
 
-bool countsAsDoubleClick(gint timeDiff, gint xDiff, gint yDiff)
+// For click count tracking.
+static int gNumClicks = 0;
+static GdkWindow* gLastClickEventWindow = 0;
+static gint gLastClickTime = 0;
+static gint gLastClickX = 0;
+static gint gLastClickY = 0;
+static WebKit::WebMouseEvent::Button gLastClickButton = WebKit::WebMouseEvent::ButtonNone;
+
+bool shouldForgetPreviousClick(GdkWindow* window, gint time, gint x, gint y)
 {
     static GtkSettings* settings = gtk_settings_get_default();
+
+    if (window != gLastClickEventWindow)
+      return true;
+
     gint doubleClickTime = 250;
     gint doubleClickDistance = 5;
     g_object_get(G_OBJECT(settings),
                  "gtk-double-click-time", &doubleClickTime,
                  "gtk-double-click-distance", &doubleClickDistance, NULL);
-    return timeDiff <= doubleClickTime && abs(xDiff) <= doubleClickDistance && abs(yDiff) <= doubleClickDistance;
+    return (time - gLastClickTime) > doubleClickTime
+           || abs(x - gLastClickX) > doubleClickDistance
+           || abs(y - gLastClickY) > doubleClickDistance;
+}
+
+void resetClickCountState()
+{
+    gNumClicks = 0;
+    gLastClickEventWindow = 0;
+    gLastClickTime = 0;
+    gLastClickX = 0;
+    gLastClickY = 0;
+    gLastClickButton = WebKit::WebMouseEvent::ButtonNone;
 }
 
 }  // namespace
@@ -407,28 +431,6 @@ WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventButton* event)
         ASSERT_NOT_REACHED();
     };
 
-    if (GDK_BUTTON_PRESS == event->type) {
-        static int numClicks = 0;
-        static GdkWindow* eventWindow = 0;
-        static gint lastLeftClickTime = 0;
-        static gint lastLeftClickX = 0;
-        static gint lastLeftClickY = 0;
-
-        gint timeDiff = event->time - lastLeftClickTime;
-        gint xDiff = event->x - lastLeftClickX;
-        gint yDiff = event->y - lastLeftClickY;
-        if (eventWindow == event->window && countsAsDoubleClick(timeDiff, xDiff, yDiff))
-            numClicks++;
-        else
-            numClicks = 1;
-
-        result.clickCount = numClicks;
-        eventWindow = event->window;
-        lastLeftClickTime = event->time;
-        lastLeftClickX = event->x;
-        lastLeftClickY = event->y;
-    }
-
     result.button = WebMouseEvent::ButtonNone;
     if (event->button == 1)
         result.button = WebMouseEvent::ButtonLeft;
@@ -437,6 +439,23 @@ WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventButton* event)
     else if (event->button == 3)
         result.button = WebMouseEvent::ButtonRight;
 
+    if (result.type == WebInputEvent::MouseDown) {
+        bool forgetPreviousClick = shouldForgetPreviousClick(event->window, event->time, event->x, event->y);
+
+        if (!forgetPreviousClick && result.button == gLastClickButton)
+            ++gNumClicks;
+        else {
+            gNumClicks = 1;
+
+            gLastClickEventWindow = event->window;
+            gLastClickX = event->x;
+            gLastClickY = event->y;
+            gLastClickButton = result.button;
+        }
+        gLastClickTime = event->time;
+    }
+    result.clickCount = gNumClicks;
+
     return result;
 }
 
@@ -469,6 +488,9 @@ WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventMotion* event)
     else if (event->state & GDK_BUTTON3_MASK)
         result.button = WebMouseEvent::ButtonRight;
 
+    if (shouldForgetPreviousClick(event->window, event->time, event->x, event->y))
+        resetClickCountState();
+
     return result;
 }
 
@@ -505,6 +527,9 @@ WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventCrossing* event)
     else if (event->state & GDK_BUTTON3_MASK)
         result.button = WebMouseEvent::ButtonRight;
 
+    if (shouldForgetPreviousClick(event->window, event->time, event->x, event->y))
+        resetClickCountState();
+
     return result;
 }
 
index 7cd4837..64c63ea 100644 (file)
@@ -109,4 +109,67 @@ TEST(WebInputEventFactoryTest, DoubleClick)
     EXPECT_EQ(1, secondClickEvent.clickCount);
 }
 
+TEST(WebInputEventFactoryTest, MouseUpClickCount)
+{
+    GdkEventButton mouseDown;
+    memset(&mouseDown, 0, sizeof(mouseDown));
+    mouseDown.type = GDK_BUTTON_PRESS;
+    mouseDown.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
+    mouseDown.x = mouseDown.y = mouseDown.x_root = mouseDown.y_root = 100;
+    mouseDown.time = 0;
+    mouseDown.button = 1;
+
+    // Properly set the last click time, so that the internal state won't be affected by previous tests.
+    WebInputEventFactory::mouseEvent(&mouseDown);
+
+    mouseDown.time += 10000;
+    GdkEventButton mouseUp = mouseDown;
+    mouseUp.type = GDK_BUTTON_RELEASE;
+    WebMouseEvent mouseDownEvent;
+    WebMouseEvent mouseUpEvent;
+
+    // Click for three times.
+    for (int i = 1; i < 4; ++i) {
+        mouseDown.time += 100;
+        mouseDownEvent = WebInputEventFactory::mouseEvent(&mouseDown);
+        EXPECT_EQ(i, mouseDownEvent.clickCount);
+
+        mouseUp.time = mouseDown.time + 50;
+        mouseUpEvent = WebInputEventFactory::mouseEvent(&mouseUp);
+        EXPECT_EQ(i, mouseUpEvent.clickCount);
+    }
+
+    // Reset the click count.
+    mouseDown.time += 10000;
+    mouseDownEvent = WebInputEventFactory::mouseEvent(&mouseDown);
+    EXPECT_EQ(1, mouseDownEvent.clickCount);
+
+    // Moving the cursor for a significant distance will reset the click count to 0.
+    GdkEventMotion mouseMove;
+    memset(&mouseMove, 0, sizeof(mouseMove));
+    mouseMove.type = GDK_MOTION_NOTIFY;
+    mouseMove.window = mouseDown.window;
+    mouseMove.time = mouseDown.time;
+    mouseMove.x = mouseMove.y = mouseMove.x_root = mouseMove.y_root = mouseDown.x + 100;
+    WebInputEventFactory::mouseEvent(&mouseMove);
+
+    mouseUp.time = mouseDown.time + 50;
+    mouseUpEvent = WebInputEventFactory::mouseEvent(&mouseUp);
+    EXPECT_EQ(0, mouseUpEvent.clickCount);
+
+    // Reset the click count.
+    mouseDown.time += 10000;
+    mouseDownEvent = WebInputEventFactory::mouseEvent(&mouseDown);
+    EXPECT_EQ(1, mouseDownEvent.clickCount);
+
+    // Moving the cursor with a significant delay will reset the click count to 0.
+    mouseMove.time = mouseDown.time + 1000;
+    mouseMove.x = mouseMove.y = mouseMove.x_root = mouseMove.y_root = mouseDown.x;
+    WebInputEventFactory::mouseEvent(&mouseMove);
+
+    mouseUp.time = mouseMove.time + 50;
+    mouseUpEvent = WebInputEventFactory::mouseEvent(&mouseUp);
+    EXPECT_EQ(0, mouseUpEvent.clickCount);
+}
+
 } // anonymous namespace