Is there a way to disable the 'touch fling scrolling' behaviour in CefSharp.Wpf (or potentially via Cef, Chromium, etc)?
I appreciate it's an unusual request as touch fling scrolling is a great feature. But unfortunately, I need to integrate with a dodgy touch screen hw/driver which works nicely for drag.. but fails miserably when flick scrolling as it consistently 'over scrolls'. e.g. a gentle flick on the screen causes the page content to scroll multiple pages (instead of just a few lines).
There's no CefSharp/Cef/Chromium flag or public method available to cancel Chromium's fling behavior.
Fortunately though, Chromium does internally cancel the fling behavior under certain scenarios (refer Chromium's fling_controller.cc). One such scenario is a user touch down event.
So the trick is to simulate a touch down cancel event pair. Because CefSharp doesn't offer a 'post touch down' event for users to implement the logic (i.e. too much of an edge case), the easiest way is to implement the feature via a derived class.
Here's a complete example (with dependency property binding) in case it helps anyone else look for the same solution..
public class ChromiumWebBrowserEx : ChromiumWebBrowser
{
public static readonly DependencyProperty IsFlingDisabledProperty = DependencyProperty.Register("IsFlingDisabled", typeof(bool), typeof(ChromiumWebBrowserEx));
public bool IsFlingDisabled
{
get => (bool) GetValue(IsFlingDisabledProperty);
set => SetValue(IsFlingDisabledProperty, value);
}
protected override void OnTouchUp(TouchEventArgs e)
{
base.OnTouchUp(e);
if (IsFlingDisabled)
CancelFling(e);
}
private void CancelFling(TouchEventArgs e)
{
// cancel the fling by creating a pseudo touch down followed by a cancellation
var touchPoint = e.GetTouchPoint(this);
if (touchPoint.Action == TouchAction.Up)
{
var touchEvent = new TouchEvent
{
Id = e.TouchDevice.Id,
X = (float) touchPoint.Position.X,
Y = (float) touchPoint.Position.Y,
PointerType = PointerType.Touch,
Modifiers = WpfExtensions.GetModifierKeys(),
Type = TouchEventType.Pressed
};
GetBrowser().GetHost().SendTouchEvent(touchEvent);
touchEvent.Type = TouchEventType.Cancelled;
GetBrowser().GetHost().SendTouchEvent(touchEvent);
}
}
}