<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[279037] trunk/Source/WebKit</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/279037">279037</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2021-06-18 07:01:49 -0700 (Fri, 18 Jun 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WPE] Rework touch-based gesture controller
https://bugs.webkit.org/show_bug.cgi?id=226456

Patch by Zan Dobersek <zdobersek@igalia.com> on 2021-06-18
Reviewed by Alejandro G. Castro.

Rename WPE's ScrollGestureController to TouchGestureController since now
it also handles production of touch-based click events.

TouchGestureController now internally manages all the related state,
tracking the touch interaction and determining whether it progresses
into a scrolling gesture or whether, upon finishing, it should be
translated into a simple click event.

In PageClientImpl, any unhandled event is pushed into
TouchGestureController and a variant of different outcomes is returned.
No-event result is ignored, and click or axis events are dispatched as
appropriate.

In WPEView, where the touch events arrive into the engine, we keep the
shortcut where touch events are piped directly into the controller if
said controller is already gesturing scrolling behavior. In that case
the touch events are not dispatched into the engine, with the exception
of touch-up events which are, to provide matching closure for the
touch-down events.

* SourcesWPE.txt:
* UIProcess/API/wpe/PageClientImpl.cpp:
(WebKit::PageClientImpl::doneWithTouchEvent):
* UIProcess/API/wpe/TouchGestureController.cpp: Renamed from Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp.
(WebKit::TouchGestureController::handleEvent):
* UIProcess/API/wpe/TouchGestureController.h: Renamed from Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h.
(WebKit::TouchGestureController::gesturedEvent const):
* UIProcess/API/wpe/WPEView.cpp:
(WKWPE::View::View):
(WKWPE::m_backend):
* UIProcess/API/wpe/WPEView.h:
(WKWPE::View::touchGestureController const):
(WKWPE::View::scrollGestureController const): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitSourcesWPEtxt">trunk/Source/WebKit/SourcesWPE.txt</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIwpePageClientImplcpp">trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIwpeWPEViewcpp">trunk/Source/WebKit/UIProcess/API/wpe/WPEView.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIwpeWPEViewh">trunk/Source/WebKit/UIProcess/API/wpe/WPEView.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitUIProcessAPIwpeTouchGestureControllercpp">trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIwpeTouchGestureControllerh">trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitUIProcessAPIwpeScrollGestureControllercpp">trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIwpeScrollGestureControllerh">trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/ChangeLog       2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -1,3 +1,44 @@
</span><ins>+2021-06-18  Zan Dobersek  <zdobersek@igalia.com>
+
+        [WPE] Rework touch-based gesture controller
+        https://bugs.webkit.org/show_bug.cgi?id=226456
+
+        Reviewed by Alejandro G. Castro.
+
+        Rename WPE's ScrollGestureController to TouchGestureController since now
+        it also handles production of touch-based click events.
+
+        TouchGestureController now internally manages all the related state,
+        tracking the touch interaction and determining whether it progresses
+        into a scrolling gesture or whether, upon finishing, it should be
+        translated into a simple click event.
+
+        In PageClientImpl, any unhandled event is pushed into
+        TouchGestureController and a variant of different outcomes is returned.
+        No-event result is ignored, and click or axis events are dispatched as
+        appropriate.
+
+        In WPEView, where the touch events arrive into the engine, we keep the
+        shortcut where touch events are piped directly into the controller if
+        said controller is already gesturing scrolling behavior. In that case
+        the touch events are not dispatched into the engine, with the exception
+        of touch-up events which are, to provide matching closure for the
+        touch-down events.
+
+        * SourcesWPE.txt:
+        * UIProcess/API/wpe/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::doneWithTouchEvent):
+        * UIProcess/API/wpe/TouchGestureController.cpp: Renamed from Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp.
+        (WebKit::TouchGestureController::handleEvent):
+        * UIProcess/API/wpe/TouchGestureController.h: Renamed from Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h.
+        (WebKit::TouchGestureController::gesturedEvent const):
+        * UIProcess/API/wpe/WPEView.cpp:
+        (WKWPE::View::View):
+        (WKWPE::m_backend):
+        * UIProcess/API/wpe/WPEView.h:
+        (WKWPE::View::touchGestureController const):
+        (WKWPE::View::scrollGestureController const): Deleted.
+
</ins><span class="cx"> 2021-06-18  Carlos Garcia Campos  <cgarcia@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [SOUP] Add Timing-Allow-Origin checks to NetworkDataTaskSoup
</span></span></pre></div>
<a id="trunkSourceWebKitSourcesWPEtxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/SourcesWPE.txt (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/SourcesWPE.txt       2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/SourcesWPE.txt  2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -180,7 +180,7 @@
</span><span class="cx"> 
</span><span class="cx"> UIProcess/API/wpe/InputMethodFilterWPE.cpp @no-unify
</span><span class="cx"> UIProcess/API/wpe/PageClientImpl.cpp @no-unify
</span><del>-UIProcess/API/wpe/ScrollGestureController.cpp @no-unify
</del><ins>+UIProcess/API/wpe/TouchGestureController.cpp @no-unify
</ins><span class="cx"> UIProcess/API/wpe/WebKitColor.cpp @no-unify
</span><span class="cx"> UIProcess/API/wpe/WebKitInputMethodContextWPE.cpp @no-unify
</span><span class="cx"> UIProcess/API/wpe/WebKitPopupMenu.cpp @no-unify
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpePageClientImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp 2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp    2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> #include "DrawingAreaProxyCoordinatedGraphics.h"
</span><span class="cx"> #include "NativeWebMouseEvent.h"
</span><span class="cx"> #include "NativeWebWheelEvent.h"
</span><del>-#include "ScrollGestureController.h"
</del><ins>+#include "TouchGestureController.h"
</ins><span class="cx"> #include "WPEView.h"
</span><span class="cx"> #include "WebContextMenuProxy.h"
</span><span class="cx"> #include "WebContextMenuProxyWPE.h"
</span><span class="lines">@@ -212,42 +212,44 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     auto& page = m_view.page();
</span><del>-    auto& scrollGestureController = m_view.scrollGestureController();
</del><ins>+    auto& touchGestureController = m_view.touchGestureController();
</ins><span class="cx"> 
</span><del>-    if (scrollGestureController.handleEvent(touchPoint)) {
-        struct wpe_input_axis_event* axisEvent = scrollGestureController.axisEvent();
-        if (axisEvent->type != wpe_input_axis_event_type_null)
-            page.handleWheelEvent(WebKit::NativeWebWheelEvent(axisEvent, m_view.page().deviceScaleFactor(), scrollGestureController.phase(), WebWheelEvent::Phase::PhaseNone));
-        return;
-    }
</del><ins>+    auto generatedEvent = touchGestureController.handleEvent(touchPoint);
+    WTF::switchOn(generatedEvent,
+        [](TouchGestureController::NoEvent&) { },
+        [&](TouchGestureController::ClickEvent& clickEvent)
+        {
+            auto* event = &clickEvent.event;
</ins><span class="cx"> 
</span><del>-    struct wpe_input_pointer_event pointerEvent {
-        wpe_input_pointer_event_type_null, touchPoint->time,
-        touchPoint->x, touchPoint->y,
-        1, 0, 0
-    };
</del><ins>+            // Mouse motion towards the point of the click.
+            event->type = wpe_input_pointer_event_type_motion;
+            page.handleMouseEvent(NativeWebMouseEvent(event, page.deviceScaleFactor()));
</ins><span class="cx"> 
</span><del>-    switch (touchPoint->type) {
-    case wpe_input_touch_event_type_down:
-        pointerEvent.type = wpe_input_pointer_event_type_button;
-        pointerEvent.state = 1;
-        pointerEvent.modifiers |= wpe_input_pointer_modifier_button1;
-        break;
-    case wpe_input_touch_event_type_motion:
-        pointerEvent.type = wpe_input_pointer_event_type_motion;
-        pointerEvent.state = 1;
-        break;
-    case wpe_input_touch_event_type_up:
-        pointerEvent.type = wpe_input_pointer_event_type_button;
-        pointerEvent.state = 0;
-        pointerEvent.modifiers &= ~wpe_input_pointer_modifier_button1;
-        break;
-    case wpe_input_touch_event_type_null:
-        ASSERT_NOT_REACHED();
-        return;
-    }
</del><ins>+            event->type = wpe_input_pointer_event_type_button;
+            event->button = 1;
</ins><span class="cx"> 
</span><del>-    page.handleMouseEvent(NativeWebMouseEvent(&pointerEvent, page.deviceScaleFactor()));
</del><ins>+            // Mouse down on the point of the click.
+            event->state = 1;
+            event->modifiers |= wpe_input_pointer_modifier_button1;
+            page.handleMouseEvent(NativeWebMouseEvent(event, page.deviceScaleFactor()));
+
+            // Mouse up on the same location.
+            event->state = 0;
+            event->modifiers &= ~wpe_input_pointer_modifier_button1;
+            page.handleMouseEvent(NativeWebMouseEvent(event, page.deviceScaleFactor()));
+        },
+        [&](TouchGestureController::AxisEvent& axisEvent)
+        {
+#if WPE_CHECK_VERSION(1, 5, 0)
+            auto* event = &axisEvent.event.base;
+#else
+            auto* event = &axisEvent.event;
+#endif
+            if (event->type != wpe_input_axis_event_type_null) {
+                page.handleWheelEvent(WebKit::NativeWebWheelEvent(event, page.deviceScaleFactor(),
+                    axisEvent.phase, WebWheelEvent::Phase::PhaseNone));
+            }
+        });
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpeScrollGestureControllercpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp        2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp   2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -1,128 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "ScrollGestureController.h"
-
-#include "WebKitSettings.h"
-#include <WebCore/Scrollbar.h>
-
-namespace WebKit {
-
-// FIXME: These ought to be either configurable or derived from system
-//        properties, such as screen size and pixel density.
-static constexpr uint32_t scrollCaptureThreshold { 200 };
-static constexpr uint32_t axisLockMovementThreshold { 8 };
-static constexpr uint32_t axisLockActivationThreshold { 15 };
-static constexpr uint32_t axisLockReleaseThreshold { 30 };
-
-bool ScrollGestureController::handleEvent(const struct wpe_input_touch_event_raw* touchPoint)
-{
-    switch (touchPoint->type) {
-    case wpe_input_touch_event_type_down:
-        m_start.active = true;
-        m_start.time = touchPoint->time;
-        m_start.x = touchPoint->x;
-        m_start.y = touchPoint->y;
-        m_offset.x = touchPoint->x;
-        m_offset.y = touchPoint->y;
-        m_xAxisLockBroken = false;
-        m_yAxisLockBroken = false;
-        return false;
-    case wpe_input_touch_event_type_motion:
-        if (m_start.active && !m_handling) {
-            int32_t deltaX = touchPoint->x - m_start.x;
-            int32_t deltaY = touchPoint->y - m_start.y;
-            uint32_t deltaTime = touchPoint->time - m_start.time;
-
-            int pixelsPerLineStep = WebCore::Scrollbar::pixelsPerLineStep();
-            m_handling = std::abs(deltaX) >= pixelsPerLineStep
-                || std::abs(deltaY) >= pixelsPerLineStep
-                || deltaTime >= scrollCaptureThreshold;
-        }
-        if (m_handling) {
-#if WPE_CHECK_VERSION(1, 5, 0)
-            m_axisEvent.base = {
-                static_cast<enum wpe_input_axis_event_type>(wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth),
-                touchPoint->time, m_start.x, m_start.y,
-                0, 0, 0,
-            };
-
-            uint32_t xOffset = std::abs(touchPoint->x - m_start.x);
-            uint32_t yOffset = std::abs(touchPoint->y - m_start.y);
-
-            if (xOffset >= axisLockReleaseThreshold)
-                m_xAxisLockBroken = true;
-            if (yOffset >= axisLockReleaseThreshold)
-                m_yAxisLockBroken = true;
-
-            if (xOffset >= axisLockMovementThreshold && yOffset >= axisLockMovementThreshold && xOffset < axisLockActivationThreshold && yOffset < axisLockActivationThreshold) {
-                m_xAxisLockBroken = true;
-                m_yAxisLockBroken = true;
-            }
-
-            m_axisEvent.x_axis = (m_xAxisLockBroken || yOffset < axisLockActivationThreshold) ?  -(m_offset.x - touchPoint->x) : 0;
-            m_axisEvent.y_axis = (m_yAxisLockBroken || xOffset < axisLockActivationThreshold) ?  -(m_offset.y - touchPoint->y) : 0;
-#else
-            m_axisEvent = {
-                wpe_input_axis_event_type_motion,
-                touchPoint->time, m_start.x, m_start.y,
-                2, (touchPoint->y - m_offset.y), 0
-            };
-#endif
-            m_offset.x = touchPoint->x;
-            m_offset.y = touchPoint->y;
-            m_phase = WebWheelEvent::Phase::PhaseChanged;
-            return true;
-        }
-        return false;
-    case wpe_input_touch_event_type_up:
-        if (m_handling) {
-            m_start.active = false;
-            m_handling = false;
-#if WPE_CHECK_VERSION(1, 5, 0)
-            m_axisEvent.base = {
-                m_axisEvent.base.type,
-                touchPoint->time, m_start.x, m_start.y,
-                0, 0, 0
-            };
-            m_axisEvent.x_axis = m_axisEvent.y_axis = 0;
-#else
-            m_axisEvent = {
-                m_axisEvent.type,
-                touchPoint->time, m_start.x, m_start.y,
-                0, 0, 0
-            };
-#endif
-            m_offset.x = m_offset.y = 0;
-            m_phase = WebWheelEvent::Phase::PhaseEnded;
-        }
-        return false;
-    default:
-        return false;
-    }
-}
-
-} // namespace WebKit
</del></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpeScrollGestureControllerh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h  2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h     2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -1,77 +0,0 @@
</span><del>-/*
- * Copyright (C) 2017 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "WebWheelEvent.h"
-#include <wpe/wpe.h>
-
-namespace WebKit {
-
-class ScrollGestureController {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    ScrollGestureController() = default;
-
-    struct wpe_input_axis_event* axisEvent()
-    {
-#if WPE_CHECK_VERSION(1, 5, 0)
-        return &m_axisEvent.base;
-#else
-        return &m_axisEvent;
-#endif
-    }
-
-    WebWheelEvent::Phase phase() { return m_phase; }
-
-    bool isHandling() const { return m_handling; }
-    bool handleEvent(const struct wpe_input_touch_event_raw*);
-
-private:
-    struct {
-        bool active { false };
-        uint32_t time { 0 };
-        int32_t x { 0 };
-        int32_t y { 0 };
-    } m_start;
-
-    struct {
-        int32_t x { 0 };
-        int32_t y { 0 };
-    } m_offset;
-
-    bool m_handling { false };
-#if WPE_CHECK_VERSION(1, 5, 0)
-    struct wpe_input_axis_2d_event m_axisEvent;
-#else
-    struct wpe_input_axis_event m_axisEvent;
-#endif
-    WebWheelEvent::Phase m_phase { WebWheelEvent::Phase::PhaseNone };
-
-    bool m_xAxisLockBroken { false };
-    bool m_yAxisLockBroken { false };
-};
-
-} // namespace WebKit
</del></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpeTouchGestureControllercppfromrev279036trunkSourceWebKitUIProcessAPIwpeScrollGestureControllercpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.cpp (from rev 279036, trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.cpp) (0 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.cpp                         (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.cpp    2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -0,0 +1,166 @@
</span><ins>+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TouchGestureController.h"
+
+#include "WebKitSettings.h"
+#include <WebCore/Scrollbar.h>
+
+namespace WebKit {
+
+// FIXME: These ought to be either configurable or derived from system
+//        properties, such as screen size and pixel density.
+static constexpr uint32_t scrollCaptureThreshold { 200 };
+static constexpr uint32_t axisLockMovementThreshold { 8 };
+static constexpr uint32_t axisLockActivationThreshold { 15 };
+static constexpr uint32_t axisLockReleaseThreshold { 30 };
+
+TouchGestureController::EventVariant TouchGestureController::handleEvent(const struct wpe_input_touch_event_raw* touchPoint)
+{
+    switch (touchPoint->type) {
+    case wpe_input_touch_event_type_down:
+        // Start of the touch interaction, first possible event is a mouse click.
+        m_gesturedEvent = GesturedEvent::Click;
+        m_start = { true, touchPoint->time, touchPoint->x, touchPoint->y };
+        m_offset = { touchPoint->x, touchPoint->y };
+        m_xAxisLockBroken = m_yAxisLockBroken = false;
+        break;
+    case wpe_input_touch_event_type_motion:
+    {
+        switch (m_gesturedEvent) {
+        case GesturedEvent::None:
+            break;
+        case GesturedEvent::Click:
+        {
+            // If currently only gesturing a click, determine if the touch has progressed
+            // so far that it should become a scrolling gesture.
+            int32_t deltaX = touchPoint->x - m_start.x;
+            int32_t deltaY = touchPoint->y - m_start.y;
+            uint32_t deltaTime = touchPoint->time - m_start.time;
+
+            int pixelsPerLineStep = WebCore::Scrollbar::pixelsPerLineStep();
+            bool overThreshold = std::abs(deltaX) >= pixelsPerLineStep
+                || std::abs(deltaY) >= pixelsPerLineStep
+                || deltaTime >= scrollCaptureThreshold;
+            if (!overThreshold)
+                break;
+
+            // Over threshold, bump the gestured event and directly fall through to handling it.
+            m_gesturedEvent = GesturedEvent::Axis;
+            FALLTHROUGH;
+        }
+        case GesturedEvent::Axis:
+        {
+            AxisEvent generatedEvent;
+            generatedEvent.phase = WebWheelEvent::Phase::PhaseChanged;
+
+#if WPE_CHECK_VERSION(1, 5, 0)
+            generatedEvent.event.base = {
+                static_cast<enum wpe_input_axis_event_type>(wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth),
+                touchPoint->time, m_start.x, m_start.y,
+                0, 0, 0,
+            };
+
+            uint32_t xOffset = std::abs(touchPoint->x - m_start.x);
+            uint32_t yOffset = std::abs(touchPoint->y - m_start.y);
+
+            if (xOffset >= axisLockReleaseThreshold)
+                m_xAxisLockBroken = true;
+            if (yOffset >= axisLockReleaseThreshold)
+                m_yAxisLockBroken = true;
+
+            if (xOffset >= axisLockMovementThreshold && yOffset >= axisLockMovementThreshold && xOffset < axisLockActivationThreshold && yOffset < axisLockActivationThreshold) {
+                m_xAxisLockBroken = true;
+                m_yAxisLockBroken = true;
+            }
+
+            generatedEvent.event.x_axis = (m_xAxisLockBroken || yOffset < axisLockActivationThreshold) ?  -(m_offset.x - touchPoint->x) : 0;
+            generatedEvent.event.y_axis = (m_yAxisLockBroken || xOffset < axisLockActivationThreshold) ?  -(m_offset.y - touchPoint->y) : 0;
+#else
+            generatedEvent.event = {
+                wpe_input_axis_event_type_motion,
+                touchPoint->time, m_start.x, m_start.y,
+                2, (touchPoint->y - m_offset.y), 0
+            };
+#endif
+            m_offset.x = touchPoint->x;
+            m_offset.y = touchPoint->y;
+            return generatedEvent;
+        }
+        }
+        break;
+    }
+    case wpe_input_touch_event_type_up:
+    {
+        switch (m_gesturedEvent) {
+        case GesturedEvent::None:
+            break;
+        case GesturedEvent::Click:
+        {
+            m_gesturedEvent = GesturedEvent::None;
+
+            ClickEvent generatedEvent;
+            generatedEvent.event = {
+                wpe_input_pointer_event_type_null, touchPoint->time, touchPoint->x, touchPoint->y,
+                0, 0, 0,
+            };
+            return generatedEvent;
+        }
+        case GesturedEvent::Axis:
+        {
+            m_gesturedEvent = GesturedEvent::None;
+
+            AxisEvent generatedEvent;
+            generatedEvent.phase = WebWheelEvent::Phase::PhaseEnded;
+
+#if WPE_CHECK_VERSION(1, 5, 0)
+            generatedEvent.event.base = {
+                static_cast<enum wpe_input_axis_event_type>(wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth),
+                touchPoint->time, m_start.x, m_start.y,
+                0, 0, 0
+            };
+            generatedEvent.event.x_axis = generatedEvent.event.y_axis = 0;
+#else
+            generatedEvent.event = {
+                wpe_input_axis_event_type_motion,
+                touchPoint->time, m_start.x, m_start.y,
+                0, 0, 0
+            };
+#endif
+            m_offset.x = m_offset.y = 0;
+            return generatedEvent;
+        }
+        }
+        break;
+    }
+    default:
+        break;
+    }
+
+    return NoEvent { };
+}
+
+} // namespace WebKit
</ins></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpeTouchGestureControllerhfromrev279036trunkSourceWebKitUIProcessAPIwpeScrollGestureControllerh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.h (from rev 279036, trunk/Source/WebKit/UIProcess/API/wpe/ScrollGestureController.h) (0 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.h                           (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/wpe/TouchGestureController.h      2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "WebWheelEvent.h"
+#include <wpe/wpe.h>
+#include <wtf/Variant.h>
+
+namespace WebKit {
+
+class TouchGestureController {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    TouchGestureController() = default;
+
+    enum class GesturedEvent {
+        None,
+        Click,
+        Axis,
+    };
+
+    struct NoEvent { };
+
+    struct ClickEvent {
+        struct wpe_input_pointer_event event;
+    };
+
+    struct AxisEvent {
+#if WPE_CHECK_VERSION(1, 5, 0)
+        struct wpe_input_axis_2d_event event;
+#else
+        struct wpe_input_axis_event event;
+#endif
+        WebWheelEvent::Phase phase;
+    };
+
+    using EventVariant = Variant<NoEvent, ClickEvent, AxisEvent>;
+
+    GesturedEvent gesturedEvent() const { return m_gesturedEvent; }
+    EventVariant handleEvent(const struct wpe_input_touch_event_raw*);
+
+private:
+    GesturedEvent m_gesturedEvent { GesturedEvent::None };
+
+    struct {
+        bool active { false };
+        uint32_t time { 0 };
+        int32_t x { 0 };
+        int32_t y { 0 };
+    } m_start;
+
+    struct {
+        int32_t x { 0 };
+        int32_t y { 0 };
+    } m_offset;
+
+    bool m_xAxisLockBroken { false };
+    bool m_yAxisLockBroken { false };
+};
+
+} // namespace WebKit
</ins></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpeWPEViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/wpe/WPEView.cpp (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/WPEView.cpp        2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WPEView.cpp   2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> #include "NativeWebMouseEvent.h"
</span><span class="cx"> #include "NativeWebTouchEvent.h"
</span><span class="cx"> #include "NativeWebWheelEvent.h"
</span><del>-#include "ScrollGestureController.h"
</del><ins>+#include "TouchGestureController.h"
</ins><span class="cx"> #include "WebPageGroup.h"
</span><span class="cx"> #include "WebProcessPool.h"
</span><span class="cx"> #include <WebCore/CompositionUnderline.h>
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> View::View(struct wpe_view_backend* backend, const API::PageConfiguration& baseConfiguration)
</span><span class="cx">     : m_client(makeUnique<API::ViewClient>())
</span><del>-    , m_scrollGestureController(makeUnique<ScrollGestureController>())
</del><ins>+    , m_touchGestureController(makeUnique<TouchGestureController>())
</ins><span class="cx">     , m_pageClient(makeUnique<PageClientImpl>(*this))
</span><span class="cx">     , m_size { 800, 600 }
</span><span class="cx">     , m_viewStateFlags { WebCore::ActivityState::WindowIsActive, WebCore::ActivityState::IsFocused, WebCore::ActivityState::IsVisible, WebCore::ActivityState::IsInWindow }
</span><span class="lines">@@ -216,13 +216,35 @@
</span><span class="cx"> 
</span><span class="cx">             WebKit::NativeWebTouchEvent touchEvent(event, page.deviceScaleFactor());
</span><span class="cx"> 
</span><del>-            auto& scrollGestureController = *view.m_scrollGestureController;
-            if (scrollGestureController.isHandling()) {
-                const struct wpe_input_touch_event_raw* touchPoint = touchEvent.nativeFallbackTouchPoint();
-                if (touchPoint->type != wpe_input_touch_event_type_null && scrollGestureController.handleEvent(touchPoint)) {
-                    page.handleWheelEvent(WebKit::NativeWebWheelEvent(scrollGestureController.axisEvent(), page.deviceScaleFactor(), scrollGestureController.phase(), WebWheelEvent::Phase::PhaseNone));
</del><ins>+            // If already gesturing axis events, short-cut directly to the controller,
+            // avoiding the usual roundtrip.
+            auto& touchGestureController = *view.m_touchGestureController;
+            if (touchGestureController.gesturedEvent() == TouchGestureController::GesturedEvent::Axis) {
+                bool handledThroughGestureController = false;
+
+                auto generatedEvent = touchGestureController.handleEvent(touchEvent.nativeFallbackTouchPoint());
+                WTF::switchOn(generatedEvent,
+                    [](TouchGestureController::NoEvent&) { },
+                    [](TouchGestureController::ClickEvent&) { },
+                    [&](TouchGestureController::AxisEvent& axisEvent)
+                    {
+#if WPE_CHECK_VERSION(1, 5, 0)
+                        auto* event = &axisEvent.event.base;
+#else
+                        auto* event = &axisEvent.event;
+#endif
+                        if (event->type != wpe_input_axis_event_type_null) {
+                            page.handleWheelEvent(WebKit::NativeWebWheelEvent(event, page.deviceScaleFactor(),
+                                axisEvent.phase, WebWheelEvent::Phase::PhaseNone));
+                            handledThroughGestureController = true;
+                        }
+                    });
+
+                // In case of the axis event gesturing, the generic touch event handling should be skipped.
+                // Exception to this are touch-up events that should still be handled just like the corresponding
+                // touch-down events were.
+                if (handledThroughGestureController && event->type != wpe_input_touch_event_type_up)
</ins><span class="cx">                     return;
</span><del>-                }
</del><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             page.handleTouchEvent(touchEvent);
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIwpeWPEViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/wpe/WPEView.h (279036 => 279037)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/wpe/WPEView.h  2021-06-18 13:37:53 UTC (rev 279036)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WPEView.h     2021-06-18 14:01:49 UTC (rev 279037)
</span><span class="lines">@@ -54,7 +54,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> class DownloadProxy;
</span><del>-class ScrollGestureController;
</del><ins>+class TouchGestureController;
</ins><span class="cx"> class WebPageGroup;
</span><span class="cx"> class WebProcessPool;
</span><span class="cx"> struct EditingRange;
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">     WebKitWebViewAccessible* accessible() const;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    WebKit::ScrollGestureController& scrollGestureController() const { return *m_scrollGestureController; }
</del><ins>+    WebKit::TouchGestureController& touchGestureController() const { return *m_touchGestureController; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     View(struct wpe_view_backend*, const API::PageConfiguration&);
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr<API::ViewClient> m_client;
</span><span class="cx"> 
</span><del>-    std::unique_ptr<WebKit::ScrollGestureController> m_scrollGestureController;
</del><ins>+    std::unique_ptr<WebKit::TouchGestureController> m_touchGestureController;
</ins><span class="cx">     std::unique_ptr<WebKit::PageClientImpl> m_pageClient;
</span><span class="cx">     RefPtr<WebKit::WebPageProxy> m_pageProxy;
</span><span class="cx">     WebCore::IntSize m_size;
</span></span></pre>
</div>
</div>

</body>
</html>