Skip to content
Permalink
Browse files
[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.

Canonical link: https://commits.webkit.org/238957@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@279037 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
commit-queue@webkit.org committed Jun 18, 2021
1 parent 0afd994 commit 5395db4296d98e1f34f83af192bf2001b3269034
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 99 deletions.
@@ -1,3 +1,44 @@
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.

2021-06-18 Carlos Garcia Campos <cgarcia@igalia.com>

[SOUP] Add Timing-Allow-Origin checks to NetworkDataTaskSoup
@@ -180,7 +180,7 @@ UIProcess/API/glib/WebKitWebsitePolicies.cpp @no-unify

UIProcess/API/wpe/InputMethodFilterWPE.cpp @no-unify
UIProcess/API/wpe/PageClientImpl.cpp @no-unify
UIProcess/API/wpe/ScrollGestureController.cpp @no-unify
UIProcess/API/wpe/TouchGestureController.cpp @no-unify
UIProcess/API/wpe/WebKitColor.cpp @no-unify
UIProcess/API/wpe/WebKitInputMethodContextWPE.cpp @no-unify
UIProcess/API/wpe/WebKitPopupMenu.cpp @no-unify
@@ -30,7 +30,7 @@
#include "DrawingAreaProxyCoordinatedGraphics.h"
#include "NativeWebMouseEvent.h"
#include "NativeWebWheelEvent.h"
#include "ScrollGestureController.h"
#include "TouchGestureController.h"
#include "WPEView.h"
#include "WebContextMenuProxy.h"
#include "WebContextMenuProxyWPE.h"
@@ -212,42 +212,44 @@ void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& touchEvent, b
return;

auto& page = m_view.page();
auto& scrollGestureController = m_view.scrollGestureController();

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;
}

struct wpe_input_pointer_event pointerEvent {
wpe_input_pointer_event_type_null, touchPoint->time,
touchPoint->x, touchPoint->y,
1, 0, 0
};

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;
}

page.handleMouseEvent(NativeWebMouseEvent(&pointerEvent, page.deviceScaleFactor()));
auto& touchGestureController = m_view.touchGestureController();

auto generatedEvent = touchGestureController.handleEvent(touchPoint);
WTF::switchOn(generatedEvent,
[](TouchGestureController::NoEvent&) { },
[&](TouchGestureController::ClickEvent& clickEvent)
{
auto* event = &clickEvent.event;

// Mouse motion towards the point of the click.
event->type = wpe_input_pointer_event_type_motion;
page.handleMouseEvent(NativeWebMouseEvent(event, page.deviceScaleFactor()));

event->type = wpe_input_pointer_event_type_button;
event->button = 1;

// 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));
}
});
}
#endif

@@ -24,7 +24,7 @@
*/

#include "config.h"
#include "ScrollGestureController.h"
#include "TouchGestureController.h"

#include "WebKitSettings.h"
#include <WebCore/Scrollbar.h>
@@ -38,33 +38,47 @@ 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)
TouchGestureController::EventVariant TouchGestureController::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;
// 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:
if (m_start.active && !m_handling) {
{
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();
m_handling = std::abs(deltaX) >= 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;
}
if (m_handling) {
case GesturedEvent::Axis:
{
AxisEvent generatedEvent;
generatedEvent.phase = WebWheelEvent::Phase::PhaseChanged;

#if WPE_CHECK_VERSION(1, 5, 0)
m_axisEvent.base = {
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,
@@ -83,46 +97,70 @@ bool ScrollGestureController::handleEvent(const struct wpe_input_touch_event_raw
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;
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
m_axisEvent = {
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;
m_phase = WebWheelEvent::Phase::PhaseChanged;
return true;
return generatedEvent;
}
return false;
}
break;
}
case wpe_input_touch_event_type_up:
if (m_handling) {
m_start.active = false;
m_handling = false;
{
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)
m_axisEvent.base = {
m_axisEvent.base.type,
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
};
m_axisEvent.x_axis = m_axisEvent.y_axis = 0;
generatedEvent.event.x_axis = generatedEvent.event.y_axis = 0;
#else
m_axisEvent = {
m_axisEvent.type,
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;
m_phase = WebWheelEvent::Phase::PhaseEnded;
return generatedEvent;
}
return false;
}
break;
}
default:
return false;
break;
}

return NoEvent { };
}

} // namespace WebKit
@@ -27,29 +27,44 @@

#include "WebWheelEvent.h"
#include <wpe/wpe.h>
#include <wtf/Variant.h>

namespace WebKit {

class ScrollGestureController {
class TouchGestureController {
WTF_MAKE_FAST_ALLOCATED;
public:
ScrollGestureController() = default;
TouchGestureController() = default;

struct wpe_input_axis_event* axisEvent()
{
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)
return &m_axisEvent.base;
struct wpe_input_axis_2d_event event;
#else
return &m_axisEvent;
struct wpe_input_axis_event event;
#endif
}
WebWheelEvent::Phase phase;
};

WebWheelEvent::Phase phase() { return m_phase; }
using EventVariant = Variant<NoEvent, ClickEvent, AxisEvent>;

bool isHandling() const { return m_handling; }
bool handleEvent(const struct wpe_input_touch_event_raw*);
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 };
@@ -62,14 +77,6 @@ class ScrollGestureController {
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 };
};

0 comments on commit 5395db4

Please sign in to comment.