[GTK] WebKitWebView should send crossing events to the WebProcess
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Feb 2016 19:42:42 +0000 (19:42 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Feb 2016 19:42:42 +0000 (19:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153740

Reviewed by Michael Catanzaro.

Source/WebCore:

Update the target element under the mouse also when only updating
scrollbars, so that if the mouse enters the page when the window
is not active, the scroll animator is notified that the mouse
entered the scrollable area.

* page/EventHandler.cpp:
(WebCore::EventHandler::handleMouseMoveEvent): Call
updateMouseEventTargetNode() before early returning in case of
only updating scrollbars.

Source/WebKit2:

We don't currently handle crossing events in the web view
(enter/leave). That's why if you hover a scrollbar and leave the
window, the scrollbar is still rendered as hovered.

* Shared/gtk/WebEventFactory.cpp:
(WebKit::buttonForEvent): Handle the case of GDK_ENTER_NOTIFY and
GDK_LEAVE_NOTIFY events.
(WebKit::WebEventFactory::createWebMouseEvent): Ditto.
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseRealize): Add GDK_ENTER_NOTIFY_MASK and
GDK_LEAVE_NOTIFY_MASK flags to the web view event mask.
(webkitWebViewBaseCrossingNotifyEvent): Handle enter/leave notify
events by generating a mouse move event, ensuring the double to
int conversion will not cause any problem.
(webkit_web_view_base_class_init): Add an implementation for
enter_notify_event and leave_notify_event.

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

Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/gtk/WebEventFactory.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp

index 65bd2ff..a9eae39 100644 (file)
@@ -1,3 +1,20 @@
+2016-02-08  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] WebKitWebView should send crossing events to the WebProcess
+        https://bugs.webkit.org/show_bug.cgi?id=153740
+
+        Reviewed by Michael Catanzaro.
+
+        Update the target element under the mouse also when only updating
+        scrollbars, so that if the mouse enters the page when the window
+        is not active, the scroll animator is notified that the mouse
+        entered the scrollable area.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleMouseMoveEvent): Call
+        updateMouseEventTargetNode() before early returning in case of
+        only updating scrollbars.
+
 2016-02-08  Jeremy Jones  <jeremyj@apple.com>
 
         PiP and external playback are mutually exclusive.
index bc1061f..5194519 100644 (file)
@@ -1882,8 +1882,10 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE
         if (!m_mousePressed && scrollbar)
             scrollbar->mouseMoved(platformMouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
 #endif
-        if (onlyUpdateScrollbars)
+        if (onlyUpdateScrollbars) {
+            updateMouseEventTargetNode(mouseEvent.targetNode(), platformMouseEvent, true);
             return true;
+        }
     }
 
     bool swallowEvent = false;
index 7b57bfe..8726748 100644 (file)
@@ -1,5 +1,29 @@
 2016-02-08  Carlos Garcia Campos  <cgarcia@igalia.com>
 
+        [GTK] WebKitWebView should send crossing events to the WebProcess
+        https://bugs.webkit.org/show_bug.cgi?id=153740
+
+        Reviewed by Michael Catanzaro.
+
+        We don't currently handle crossing events in the web view
+        (enter/leave). That's why if you hover a scrollbar and leave the
+        window, the scrollbar is still rendered as hovered.
+
+        * Shared/gtk/WebEventFactory.cpp:
+        (WebKit::buttonForEvent): Handle the case of GDK_ENTER_NOTIFY and
+        GDK_LEAVE_NOTIFY events.
+        (WebKit::WebEventFactory::createWebMouseEvent): Ditto.
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (webkitWebViewBaseRealize): Add GDK_ENTER_NOTIFY_MASK and
+        GDK_LEAVE_NOTIFY_MASK flags to the web view event mask.
+        (webkitWebViewBaseCrossingNotifyEvent): Handle enter/leave notify
+        events by generating a mouse move event, ensuring the double to
+        int conversion will not cause any problem.
+        (webkit_web_view_base_class_init): Add an implementation for
+        enter_notify_event and leave_notify_event.
+
+2016-02-08  Carlos Garcia Campos  <cgarcia@igalia.com>
+
         Infinite loop when processing mouse events synchronously
         https://bugs.webkit.org/show_bug.cgi?id=153995
 
index f7e897e..2d66393 100644 (file)
@@ -72,15 +72,20 @@ static inline WebMouseEvent::Button buttonForEvent(const GdkEvent* event)
     unsigned button = 0;
 
     switch (event->type) {
-    case GDK_MOTION_NOTIFY:
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+    case GDK_MOTION_NOTIFY: {
         button = WebMouseEvent::NoButton;
-        if (event->motion.state & GDK_BUTTON1_MASK)
+        GdkModifierType state;
+        gdk_event_get_state(event, &state);
+        if (state & GDK_BUTTON1_MASK)
             button = WebMouseEvent::LeftButton;
-        else if (event->motion.state & GDK_BUTTON2_MASK)
+        else if (state & GDK_BUTTON2_MASK)
             button = WebMouseEvent::MiddleButton;
-        else if (event->motion.state & GDK_BUTTON3_MASK)
+        else if (state & GDK_BUTTON3_MASK)
             button = WebMouseEvent::RightButton;
         break;
+    }
     case GDK_BUTTON_PRESS:
     case GDK_2BUTTON_PRESS:
     case GDK_3BUTTON_PRESS:
@@ -108,6 +113,8 @@ WebMouseEvent WebEventFactory::createWebMouseEvent(const GdkEvent* event, int cu
     WebEvent::Type type = static_cast<WebEvent::Type>(0);
     switch (event->type) {
     case GDK_MOTION_NOTIFY:
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
         type = WebEvent::MouseMove;
         break;
     case GDK_BUTTON_PRESS:
index 68c6002..69e592c 100644 (file)
@@ -359,6 +359,8 @@ static void webkitWebViewBaseRealize(GtkWidget* widget)
         | GDK_SCROLL_MASK
         | GDK_SMOOTH_SCROLL_MASK
         | GDK_POINTER_MOTION_MASK
+        | GDK_ENTER_NOTIFY_MASK
+        | GDK_LEAVE_NOTIFY_MASK
         | GDK_KEY_PRESS_MASK
         | GDK_KEY_RELEASE_MASK
         | GDK_BUTTON_MOTION_MASK
@@ -835,6 +837,47 @@ static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMo
     return FALSE;
 }
 
+static gboolean webkitWebViewBaseCrossingNotifyEvent(GtkWidget* widget, GdkEventCrossing* crosssingEvent)
+{
+    WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
+    WebKitWebViewBasePrivate* priv = webViewBase->priv;
+
+    if (priv->authenticationDialog)
+        return FALSE;
+
+    // In the case of crossing events, it's very important the actual coordinates the WebProcess receives, because once the mouse leaves
+    // the web view, the WebProcess won't receive more events until the mouse enters again in the web view. So, if the coordinates of the leave
+    // event are not accurate, the WebProcess might not know the mouse left the view. This can happen because of double to integer conversion,
+    // if the coordinates of the leave event are for example (25.2, -0.9), the WebProcess will receive (25, 0) and any hit test will succeed
+    // because those coordinates are inside the web view.
+    GtkAllocation allocation;
+    gtk_widget_get_allocation(widget, &allocation);
+    double width = allocation.width;
+    double height = allocation.height;
+    double x = crosssingEvent->x;
+    double y = crosssingEvent->y;
+    if (x < 0 && x > -1)
+        x = -1;
+    else if (x >= width && x < width + 1)
+        x = width + 1;
+    if (y < 0 && y > -1)
+        y = -1;
+    else if (y >= height && y < height + 1)
+        y = height + 1;
+
+    GdkEvent* event = reinterpret_cast<GdkEvent*>(crosssingEvent);
+    GUniquePtr<GdkEvent> copiedEvent;
+    if (x != crosssingEvent->x || y != crosssingEvent->y) {
+        copiedEvent.reset(gdk_event_copy(event));
+        copiedEvent->crossing.x = x;
+        copiedEvent->crossing.y = y;
+    }
+
+    priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(copiedEvent ? copiedEvent.get() : event, 0 /* currentClickCount */));
+
+    return FALSE;
+}
+
 #if ENABLE(TOUCH_EVENTS)
 static void appendTouchEvent(Vector<WebPlatformTouchPoint>& touchPoints, const GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
 {
@@ -1079,6 +1122,8 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie
     widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
     widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
     widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
+    widgetClass->enter_notify_event = webkitWebViewBaseCrossingNotifyEvent;
+    widgetClass->leave_notify_event = webkitWebViewBaseCrossingNotifyEvent;
 #if ENABLE(TOUCH_EVENTS)
     widgetClass->touch_event = webkitWebViewBaseTouchEvent;
 #endif