Closed dinoc closed 4 years ago
There is the --touch-events=enabled|disabled flag that enables multitouch events in javascript.
In CefBrowser there are methods like: SendMouseClickEvent(), SendMouseMoveEvent(). You can use these to send the touch-up, touch-down, touch-move events to CEF.
See also these issues/topics in CEF:
"Windows touch scroll acting as mouse click event" http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10321
"Touch support in CEF1 and CEF3 does not match Chromium browser" https://code.google.com/p/chromiumembedded/issues/detail?id=786
"Touch-screen generated MouseEvent(s) do not have the same XY coords as actual mouse clicks" https://code.google.com/p/chromiumembedded/issues/detail?id=959
"Multi-touch screen : No virtual screen displayed on focus in an input" https://code.google.com/p/chromiumembedded/issues/detail?id=985
"Cef3: Multi-touch support with offscreen rendering." https://code.google.com/p/chromiumembedded/issues/detail?id=1059
https://bitbucket.org/chromiumembedded/cef/issues/1059/cef3-multi-touch-support-with-offscreen
Until the upstream
issue has been resolved it's not possible to implement MultiTouch
in the WPF
version. If you require it now then you will have to use the the WinForms
version hosted in a WindowsFormsHost
control.
Please no further comments asking when it will be ready, it's out of our control.
Just as a status update, there are two PR's
currently being reviewed, neither is complete. You can view them both at
https://bitbucket.org/chromiumembedded/cef/pull-requests/104 https://bitbucket.org/chromiumembedded/cef/pull-requests/100
If this is a feature you require and you have a C++
background then you should contribute to one or both.
This is just a status update, no further comments required.
Only for Touch Scrolling Bellow code works for me
1) Add the Following line in CefSharp.Example => Init() settings.CefCommandLineArgs.Add("touch-events", "1");
2) Open the Browser Window's Code, Define bellow variables at class level bool IsMouseDown = false; Point? LastSavedPoint = null; IBrowserHost host;
3) Add Touch events for the Web Browser
#region Touch Events
private void browser_TouchMove(object sender, TouchEventArgs e)
{
if (host != null && IsMouseDown)
{
TouchPoint t = e.GetTouchPoint(this);
Point p = t.Position;
if (!LastSavedPoint.HasValue)
LastSavedPoint = p;
int x = (int)p.X;
int y = (int)p.Y;
int oldX = (int)LastSavedPoint.Value.X;
int oldy = (int)LastSavedPoint.Value.Y;
host.SendMouseWheelEvent(x, y, 0, y - oldy, CefEventFlags.MiddleMouseButton);
LastSavedPoint = p; //Store the last Point for reference
}
}
void browser_TouchDown(object sender, TouchEventArgs e)
{
if (host == null)
{
IWebBrowser host2 = browser; // **your Browser's Instance**
IBrowser bworser = host2.GetBrowser();
host = bworser.GetHost(); // Get host from Browser
}
IsMouseDown = true;
// this.Cursor = System.Windows.Input.Cursors.None;
}
private void browser_TouchLeave(object sender, TouchEventArgs e)
{
IsMouseDown = false;
LastSavedPoint = null;
}
void browser_TouchUp(object sender, TouchEventArgs e)
{
IsMouseDown = false;
LastSavedPoint = null;
}
#endregion
Other implementations, one with touch events and one with manipulation events. Just copied it from my project, you need to translate to c# i guess. No need to set "touch-events=1", it has no effect in WPF.
Common for both methods:
` Private TouchMoveState As Integer = 0
Private Const cTouchMoveFactor As Double = 1.2
Private LastMouseButtonDown As Long = Now.Ticks - TimeSpan.TicksPerMinute
Private FirstTouchPoint As Point = New Point(-1, -1)
Private LastTouchPoint As Point = New Point(-1, -1)
Private Sub Scroll(ByVal intX As Integer, ByVal intY As Integer)
Dim blnSendMouseWheelEvent As Boolean = False
blnSendMouseWheelEvent = True
'If Not String.IsNullOrEmpty(Me.Address) Then
' If Me.Address.EndsWith(".pdf", StringComparison.InvariantCultureIgnoreCase) Then
' blnSendMouseWheelEvent = True
' End If
'End If
'SendMouseWheelEvent:
'- for PDF's only scroll down works
'- can stop working, see https://github.com/cefsharp/CefSharp/issues/2064
If blnSendMouseWheelEvent Then
Dim browser As CefSharp.IBrowser = Nothing
Dim host As CefSharp.IBrowserHost = Nothing
Try
Dim intMouseX As Integer = 50
Dim intMouseY As Integer = 50
browser = GetBrowser()
If browser IsNot Nothing Then
host = browser.GetHost()
If host IsNot Nothing Then
host.SendMouseWheelEvent(intMouseX, intMouseY, intX, intY, 0)
End If
End If
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
Finally
End Try
Exit Sub
End If
'window.scrollBy
'- does not work with PDF
'- does not work with all websites
''window.scrollBy(xnum, ynum)
''xnum: Required. How many pixels to scroll by, along the x-axis (horizontal).
'' Positive values will scroll to the right, while negative values will scroll to the left
''ynum: Required. How many pixels to scroll by, along the y-axis (vertical).
'' Positive values will scroll down, while negative values scroll up
Dim frame As CefSharp.IFrame = Nothing
Try
Dim browser As CefSharp.IBrowser = GetBrowser()
If browser IsNot Nothing Then
frame = browser.MainFrame
If frame IsNot Nothing Then
Dim script As String = "window.scrollBy(" & (intX * -1).ToString & "," & (intY * -1).ToString & ");"
frame.ExecuteJavaScriptAsync(script)
End If
End If
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
Finally
Try
If frame IsNot Nothing Then
If Not frame.IsDisposed Then
frame.Dispose()
frame = Nothing
End If
End If
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
End Try
End Try
End Sub`
With touch events:
` Private Sub CefSharpBrowserControl_StylusSystemGesture_TouchScroll(sender As Object, e As StylusSystemGestureEventArgs)
Try
Select Case e.SystemGesture
Case SystemGesture.HoldEnter, SystemGesture.Drag
'to prevent jumpy scrolling on finger clicks, dont use TouchDown for scrolling start
'Remember where this contact took place.
FirstTouchPoint = e.GetPosition(Me)
LastTouchPoint = FirstTouchPoint
Me.TouchMoveState = 1 'scrolling can start now
End Select
Catch ex As Exception
Me.TouchMoveState = 0
FirstTouchPoint.X = -1
LastTouchPoint.X = -1
LogManager.LogMessage(LogType.Errors, ex)
End Try
End Sub
Private Sub CefSharpBrowserControl_TouchMove(sender As Object, e As TouchEventArgs)
Try
If (Me.TouchMoveState = 0) Or (LastTouchPoint.X = -1) Then
Exit Sub
End If
Me.TouchMoveState = 2 'scrolling actually happend now
'Get the current position of the contact.
Dim tp As TouchPoint = e.GetTouchPoint(Me)
Dim currentTouchPoint As Point = tp.Position
'Get the change between the controlling contact point and the changed contact point.
'scroll either horizontally or vertically, scrolling in both directions at the same time does not work well
Dim dblCumulativeX As Double = Math.Abs(currentTouchPoint.X - FirstTouchPoint.X)
Dim dblCumulativeY As Double = Math.Abs(currentTouchPoint.Y - FirstTouchPoint.Y)
Dim intDeltaX = 0
Dim intDeltaY = 0
If dblCumulativeX > dblCumulativeY Then
Dim dblDeltaX As Double = currentTouchPoint.X - LastTouchPoint.X
If dblDeltaX <> 0 Then
dblDeltaX *= cTouchMoveFactor
'round the change up
If dblDeltaX > 0 Then
dblDeltaX += 0.99
ElseIf dblDeltaX < 0 Then
dblDeltaX -= 0.99
End If
intDeltaX = Math.Truncate(dblDeltaX)
End If
Else
Dim dblDeltaY As Double = currentTouchPoint.Y - LastTouchPoint.Y
If dblDeltaY <> 0 Then
dblDeltaY *= cTouchMoveFactor
'round the change up
If dblDeltaY > 0 Then
dblDeltaY += 0.99
ElseIf dblDeltaY < 0 Then
dblDeltaY -= 0.99
End If
intDeltaY = Math.Truncate(dblDeltaY)
End If
End If
If (intDeltaX <> 0) Or (intDeltaY <> 0) Then
Scroll(intDeltaX, intDeltaY)
End If
'Forget the old contact point, and remember the new contact point.
LastTouchPoint = currentTouchPoint
Catch ex As Exception
Me.TouchMoveState = 0
FirstTouchPoint.X = -1
LastTouchPoint.X = -1
LogManager.LogMessage(LogType.Errors, ex)
End Try
End Sub
Private Sub CefSharpBrowserControl_TouchUp(sender As Object, e As TouchEventArgs)
Try
'Forget about this contact.
Me.TouchMoveState = 0
FirstTouchPoint.X = -1
LastTouchPoint.X = -1
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
End Try
End Sub
Private Sub CefSharpBrowserControl_PreviewMouseMove(sender As Object, e As MouseEventArgs)
'MouseMove event is triggered even when e.Handled = True in all Touch events
'e.StylusDevice.Name = "Stylus" no matter if pen or fingers are used!
Try
If e.StylusDevice IsNot Nothing Then
If Me.TouchMoveState = 2 Then
e.Handled = True
End If
End If
Catch ex As Exception
Me.TouchMoveState = 0
FirstTouchPoint.X = -1
LastTouchPoint.X = -1
LogManager.LogMessage(LogType.Errors, ex)
End Try
End Sub
With manipulation events `(need to set IsManipulationEnabled = True):
` Private Sub CefSharpBrowserControl_PreviewMouseButtonDown(sender As Object, e As MouseButtonEventArgs)
'if IsManipulationEnabled = True then
'- click by finger does not trigger Mouse events
'- click by pen triggers Mouse events
'--> save the last click time to determine later in StylusSystemGesture if it was triggered by pen or finger
Me.LastMouseButtonDown = Now.Ticks
End Sub
Private Sub CefSharpBrowserControl_StylusSystemGesture_ManipulationScroll(sender As Object, e As StylusSystemGestureEventArgs)
Try
Select Case e.SystemGesture
Case SystemGesture.HoldEnter, SystemGesture.Drag
'to prevent jumpy scrolling on finger clicks
Dim diffTime As Long = Now.Ticks - Me.LastMouseButtonDown
If (diffTime >= -3000000) And (diffTime <= 3000000) Then
'MouseButtonDown happened shortly before
'--> event triggered by Pen
Exit Sub
End If
Me.TouchMoveState = 1 'scrolling can start now
Case SystemGesture.Tap
'click by finger does not work anymore if IsManipulationEnabled=True
'TimeSpan.TicksPerSecond = 10.000.000
Dim diffTime As Long = Now.Ticks - Me.LastMouseButtonDown
If (diffTime >= -3000000) And (diffTime <= 3000000) Then
'MouseButtonDown happened shortly before
'--> event triggered by Pen, click gets normally processed, sending a click event would lead to a double-click
Else
'--> event triggered by finger
Dim host As CefSharp.IBrowserHost = Nothing
Try
Dim browser As CefSharp.IBrowser = Nothing
If browser IsNot Nothing Then
host = browser.GetHost()
If host IsNot Nothing Then
Dim pt As Point = e.GetPosition(Me)
host.SendMouseClickEvent(pt.X, pt.Y, CefSharp.MouseButtonType.Left, False, 1, CefSharp.CefEventFlags.None)
System.Threading.Thread.Sleep(100)
host.SendMouseClickEvent(pt.X, pt.Y, CefSharp.MouseButtonType.Left, True, 1, CefSharp.CefEventFlags.None)
End If
End If
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
Finally
End Try
End If
'e.StylusDevice.Name is always "Stylus" no matter if triggered by pen or finger
Case SystemGesture.RightTap
'click by finger does not work anymore if IsManipulationEnabled=True
'TimeSpan.TicksPerSecond = 10.000.000
Dim diffTime As Long = Now.Ticks - Me.LastMouseButtonDown
If (diffTime >= -3000000) And (diffTime <= 3000000) Then
'MouseButtonDown happened shortly before
'--> event triggered by Pen, click gets normally processed, sending a click event would lead to a double-click
Else
'--> event triggered by finger
Dim host As CefSharp.IBrowserHost = Nothing
Try
Dim browser As CefSharp.IBrowser = Nothing
If browser IsNot Nothing Then
host = browser.GetHost()
If host IsNot Nothing Then
Dim pt As Point = e.GetPosition(Me)
host.SendMouseClickEvent(pt.X, pt.Y, CefSharp.MouseButtonType.Right, False, 1, CefSharp.CefEventFlags.None)
System.Threading.Thread.Sleep(100)
host.SendMouseClickEvent(pt.X, pt.Y, CefSharp.MouseButtonType.Right, True, 1, CefSharp.CefEventFlags.None)
End If
End If
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
Finally
End Try
End If
End Select
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
End Try
End Sub
Private Sub CefSharpBrowserControl_ManipulationStarting(sender As Object, e As ManipulationStartingEventArgs)
'The ContainerElement is the UI element to which all manipulation calculations and events are relative.
'If you do not set a ContainerElement, the UI element that is firing the event will be used.
'This works well for Zoom/Scale, but for all Translate or Rotate manipulations you should set a ContainerElement,
'or else the UI will flicker and be jumpy.
'This is not a UI glitch, it happens because a single manipulation will fire multiple deltas,
'so you are recording movements relative to the UI element that is being moved. Not cool!
e.ManipulationContainer = Me
'In ManipulationStarting, you can also set your ManipulationMode to control the manipulations you are allowing.
'You can select from All | None | Rotate | Translate | Scale | TranslateX | TranslateY.
'If you don’t override it, the default is All.
e.Mode = ManipulationModes.Translate
End Sub
Private Sub CefSharpBrowserControl_ManipulationDelta(sender As Object, e As ManipulationDeltaEventArgs)
Try
If e.Source Is Nothing Then
GoTo done
End If
If Me.TouchMoveState = 0 Then
GoTo done
End If
'e.DeltaManipulation has the changes
'Scale is a delta multiplier; 1.0 is last size, (so 1.1 == scale 10%, 0.8 = shrink 20%)
'Rotate = Rotation, in degrees
'Pan = Translation, == Translate offset, in Device Independent Pixels
'scroll either horizontally or vertically, scrolling in both directions at the same time does not work well
Dim dblCumulativeX As Double = Math.Abs(e.CumulativeManipulation.Translation.X)
Dim dblCumulativeY As Double = Math.Abs(e.CumulativeManipulation.Translation.Y)
Dim intDeltaX = 0
Dim intDeltaY = 0
If dblCumulativeX > dblCumulativeY Then
Dim dblDeltaX As Double = e.DeltaManipulation.Translation.X
If dblDeltaX <> 0 Then
dblDeltaX *= cTouchMoveFactor
'round the change up
If dblDeltaX > 0 Then
dblDeltaX += 0.99
ElseIf dblDeltaX < 0 Then
dblDeltaX -= 0.99
End If
intDeltaX = Math.Truncate(dblDeltaX)
End If
Else
Dim dblDeltaY As Double = e.DeltaManipulation.Translation.Y
If dblDeltaY <> 0 Then
dblDeltaY *= cTouchMoveFactor
'round the change up
If dblDeltaY > 0 Then
dblDeltaY += 0.99
ElseIf dblDeltaY < 0 Then
dblDeltaY -= 0.99
End If
intDeltaY = Math.Truncate(dblDeltaY)
End If
End If
If (intDeltaX <> 0) Or (intDeltaY <> 0) Then
Scroll(intDeltaX, intDeltaY)
End If
''we could add code at our ManipulationDelta event handler for inertia.
''This is optional, if you run the code at this point, inertia is already working, but you will notice there is no boundaries (the images fly off the screen).
''So, just as an example, I will add code to handle the boundaries and stop the inertia when we reach the boundaries.
'If e.IsInertial Then
' 'check if further scrolling is not possible anymore, if yes:
' '/Report that we have gone over our boundary
' e.ReportBoundaryFeedback(e.DeltaManipulation)
' 'comment out this line to see the Window 'shake' or 'bounce'
' 'similar to Win32 Windows when they reach a boundary; this comes for free in .NET 4
' e.Complete()
'End If
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
End Try
done:
e.Handled = True
End Sub
Private Sub CefSharpBrowserControl_ManipulationInertiaStarting(sender As Object, e As ManipulationInertiaStartingEventArgs)
Try
'Decrease the velocity of the Rectangle's movement by 20 inches per second every second.
'(20 inches * 96 DIPS per inch / 1000ms^2)
e.TranslationBehavior.DesiredDeceleration = 20.0 * 96.0 / (1000.0 * 1000.0)
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
End Try
e.Handled = True
End Sub
Private Sub CefSharpBrowserControl_ManipulationCompleted(sender As Object, e As ManipulationCompletedEventArgs)
Try
Me.TouchMoveState = 0
Catch ex As Exception
LogManager.LogMessage(LogType.Errors, ex)
End Try
e.Handled = True
End Sub`
Would anyone be kind enough to add a PR that provides an example on how to set this up easily? (You an also refer to this issue if you like, to give people more info on what's needed for it.)
That way, we should be able to close this issue.
I would need to figure out how this works, clone the project, make changes, check in changed project and hope that my spent time was not useless (you merge the changes into CefSharp) ?
My posted implementation with manipulation events works pretty well for me in "competitor" project. Not as smoothly as in WinForms, but good. The posted code is not up to date, i made a few changes. To make it working here, it would require to: 1) Change the Popup to overlay image, otherwise touch scroll does not work in dropdowns. The CEF "popup" is not a normal Windows popup, not in the offscreen version. CEF knows the position and size of the "popup" and handles all sent mouse and keyboard events properly. I don't spend time if you disagree on this point. 2) Try to resolve an issue with broken SendMouseWheelEvent, seems to happen when CefSharp tries to handle Drag&Drop
2018... My solution...
Change "Emulation.setEmitTouchEventsForMouse"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using CefSharp;
using WebSocket4Net;
namespace YourNamespace {
public static class CefMobile {
public const int RemoteDebuggingPort = 8087;
private static Dictionary<string, WebSocket> _prevList = new Dictionary<string, WebSocket>();
static CefMobile() {
Cef.Initialize(new CefSettings {
CefCommandLineArgs = { },
UserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1",
RemoteDebuggingPort = CefMobile.RemoteDebuggingPort
});
Task.Run(async () => {
while (true) {
try {
using (var client = new HttpClient()) {
var response = client.GetAsync($"http://localhost:{CefMobile.RemoteDebuggingPort}/json").Result.Content.ReadAsStringAsync().Result;
var json = NetJSON.NetJSON.Deserialize<List<IDictionary<string, string>>>(response);
var newList = new Dictionary<string, string>();
foreach (var o in json) {
o.TryGetValue("id", out var id);
o.TryGetValue("webSocketDebuggerUrl", out var webSocketDebuggerUrl);
newList.Add(id, webSocketDebuggerUrl);
}
foreach (var id in newList.Keys.Except(CefMobile._prevList.Keys)) {
newList.TryGetValue(id, out var webSocketDebuggerUrl);
var ws = new WebSocket(webSocketDebuggerUrl);
CefMobile._prevList.Add(id, ws);
ws.Closed += (sender, args) => ws.Dispose();
ws.Opened += (sender, args) => ws.Send(@"{""id"":0,""method"":""Emulation.setEmitTouchEventsForMouse"",""params"":{""enabled"":true,""configuration"":""mobile""}}");
ws.Open();
}
foreach (var id in CefMobile._prevList.Keys.Except(newList.Keys)) {
CefMobile._prevList.TryGetValue(id, out var webSocket);
webSocket.Close();
CefMobile._prevList.Remove(id);
}
}
} catch (Exception) {
// ignored
}
await Task.Delay(100);
}
});
}
public static void Init() { }
}
}
U need to call CefMobile.Init();
before creating ChromiumWebBrowser
@equimal, thanks for the workaround. A few comments:
Why not move the static constructor code into the Init
method? It would feel more natural this way.
Also, polling the remote debugging port 10 times per second like this can potentially have a bit of performance impact. I guess there's no better way, like leaving the websocket open and wait for more events before closing it?
@perlun you are right, now I will change something
Update 1.0.0.0.0.1 XD
Emulation.setDeviceMetricsOverride with mobile: true
- hide scrollbarsusing System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using CefSharp;
using WebSocket4Net;
namespace YourNamespace {
public static class CefMobile {
public static int RemoteDebuggingPort = 8087;
private static readonly Dictionary<string, WebSocket> PrevDict = new Dictionary<string, WebSocket>();
public static void Initialize(CefSettings cefSettings = null) {
if (cefSettings is null) {
Cef.Initialize(new CefSettings {
UserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1",
RemoteDebuggingPort = CefMobile.RemoteDebuggingPort
});
} else {
CefMobile.RemoteDebuggingPort = cefSettings.RemoteDebuggingPort;
Cef.Initialize(cefSettings);
}
Task.Run(async () => {
while (true) {
try {
using (var client = new HttpClient()) {
var response = client.GetAsync($"http://localhost:{CefMobile.RemoteDebuggingPort}/json").Result.Content.ReadAsStringAsync().Result;
var json = NetJSON.NetJSON.Deserialize<List<IDictionary<string, string>>>(response);
var NewDict = new Dictionary<string, string>();
foreach (var o in json) {
o.TryGetValue("id", out var id);
o.TryGetValue("webSocketDebuggerUrl", out var webSocketDebuggerUrl);
NewDict.Add(id, webSocketDebuggerUrl);
}
foreach (var id in NewDict.Keys.Except(CefMobile.PrevDict.Keys)) {
NewDict.TryGetValue(id, out var webSocketDebuggerUrl);
var ws = new WebSocket(webSocketDebuggerUrl) {
EnableAutoSendPing = false
};
var tcs = new TaskCompletionSource<bool>();
ws.Opened += (sender, args) => {
ws.Send(@"{""id"":0,""method"":""Emulation.setEmitTouchEventsForMouse"",""params"":{""enabled"":true,""configuration"":""mobile""}}");
ws.Send(@"{""id"":1,""method"":""Emulation.setTouchEmulationEnabled"",""params"":{""enabled"":true,""maxTouchPoints"":1}}");
ws.Send(@"{""id"":2,""method"":""Emulation.setDeviceMetricsOverride"",""params"":{""width"":0,""height"":0,""deviceScaleFactor"":3,""mobile"":true}}");
CefMobile.PrevDict.Add(id, ws);
tcs.SetResult(true);
};
ws.MessageReceived += (sender, args) => Console.WriteLine($@"WebSocket Message: {args.Message}");
ws.Error += (sender, args) => Console.WriteLine($@"WebSocket Error: {args.Exception.Message}");
ws.Closed += (sender, args) => {
CefMobile.PrevDict.Remove(CefMobile.PrevDict.FirstOrDefault(x => x.Value == ws).Key);
ws.Dispose();
};
ws.Open();
await tcs.Task;
}
foreach (var id in CefMobile.PrevDict.Keys.Except(NewDict.Keys)) {
CefMobile.PrevDict.TryGetValue(id, out var webSocket);
webSocket.Close();
}
}
} catch (Exception) {
// ignored
}
await Task.Delay(1000);
}
});
}
}
}
U can use any websocket and json-decoding libraries
Once #2663 is resolved it will be possible to implement Touch Support
in WPF
.
Who's interested in actually helping to implement support? By implement I mean actual programming/debugg, not just testing.
I'm tempted to help, but not sure about the time I can dedicate and the other problem is that I don't have a touch screen on my workstation - would have to use a laptop or something.
Once #2663 is resolved it will be possible to implement
Touch Support
inWPF
.
The new CEF API
has been added.
For reference WPF
will be supporting WM_POINTER
optionally in .Net 4.7
https://github.com/dotnet/docs/blob/master/docs/framework/migration-guide/mitigation-pointer-based-touch-and-stylus-support.md
Experimental
support has been added thanks to #2745
CefSharp.Wpf.Experimental.ChromiumWebBrowserWithTouchSupport
can be used to replace the current ChromiumWebBrowser
, remember that by default the WM_TOUCH
implementation will be used, this has significant performance problems and it's worth investigating the WM_POINTER
option listed above if you have Windows 10
.
Code was added in https://github.com/cefsharp/CefSharp/commit/3d14f198674dba6516276897d384c1cc0c996f92
I will leave this open for until the code has been thoroughly tested at which time it will be enabled by default and ChromiumWebBrowserWithTouchSupport
will be removed.
73.1.130
includes CefSharp.Wpf.Experimental.ChromiumWebBrowserWithTouchSupport
, anyone interested can test it out.
Great news! I found a little issue. Report here or create a new issue?
You can report it here.
I have tested on MS Surface Pro 4. I changed the CefSharp.Wpf.Example project to use ChromiumWebBrowserWithTouchSupport. Touch scroll and zoom works fine so far. Maybe not 100% as smoothly as in WinForms... but good in my quick tests.
I encountered one issue:
Marking text with stylus does not work. When i move the pen down, press the right-click button and move the pen then no text gets selected. Sometimes one word gets selected but i cannot select a text area.
When i do this another issue happens:
o Enter www.google.com into the address box and press enter.
o Try to select a text with with pen and right click button
o Click into the address box with pen
Then a click with pen into the search box has no effect, the input focus remains in the address box.
When i click with my finger long time in the search box then the search box gets focused.
The input focus issue happens also in CefSharp.WinForms.Example. There i can reproduce it by:
o Enter www.google.com into the address box and press enter.
o Click with pen into the search box.
The search box seems to get focused, the cursor is blinking in the search box... but pressing keys has no effect.
This input focus issue happens also in CefGlue and cefclient.exe, so i guess it's a CEF or Chromium error.
My workaround for this is to watch for WM_PARENTNOTIFY: WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN, WM_POINTERDOWN and focus the CEF browser window when it's not focused.
Stylus/Pen support has been improved in #2817 the changes will be in version 75
, it's still Experimental
.
Anyone testing this out please report back here.
Awesome. I switched our system to use the experimental browser with touch support and zooming and scrolling works great.
I was just wondering is it possible to use gestures like "two finger panning" with it?
Awesome. I switched our system to use the experimental browser with touch support and zooming and scrolling works great.
I was just wondering is it possible to use gestures like "two finger panning" with it?
Ah, seems to be working fine already. Thanks for great work guys!
Only for Touch Scrolling Bellow code works for me
- Add the Following line in CefSharp.Example => Init() settings.CefCommandLineArgs.Add("touch-events", "1");
- Open the Browser Window's Code, Define bellow variables at class level bool IsMouseDown = false; Point? LastSavedPoint = null; IBrowserHost host;
Add Touch events for the Web Browser
#region Touch Events private void browser_TouchMove(object sender, TouchEventArgs e) { if (host != null && IsMouseDown) { TouchPoint t = e.GetTouchPoint(this); Point p = t.Position; if (!LastSavedPoint.HasValue) LastSavedPoint = p; int x = (int)p.X; int y = (int)p.Y; int oldX = (int)LastSavedPoint.Value.X; int oldy = (int)LastSavedPoint.Value.Y; host.SendMouseWheelEvent(x, y, 0, y - oldy, CefEventFlags.MiddleMouseButton); LastSavedPoint = p; //Store the last Point for reference } } void browser_TouchDown(object sender, TouchEventArgs e) { if (host == null) { IWebBrowser host2 = browser; // **your Browser's Instance** IBrowser bworser = host2.GetBrowser(); host = bworser.GetHost(); // Get host from Browser } IsMouseDown = true; // this.Cursor = System.Windows.Input.Cursors.None; } private void browser_TouchLeave(object sender, TouchEventArgs e) { IsMouseDown = false; LastSavedPoint = null; } void browser_TouchUp(object sender, TouchEventArgs e) { IsMouseDown = false; LastSavedPoint = null; } #endregion
A slightly cutdown / cleaner version of this (thanks @dhpanteon it worked a treat):
private void InitialiseTouchScrolling()
{
BrowserView.TouchDown += TableBrowserUserControl_TouchDown;
BrowserView.TouchMove += TableBrowserUserControl_TouchMove;
BrowserView.TouchLeave += TableBrowserUserControl_TouchUp;
BrowserView.TouchUp += TableBrowserUserControl_TouchUp;
}
Point? LastSavedPoint = null;
private void TableBrowserUserControl_TouchUp(object sender, System.Windows.Input.TouchEventArgs e)
{
LastSavedPoint = null;
}
private void TableBrowserUserControl_TouchDown(object sender, System.Windows.Input.TouchEventArgs e)
{
LastSavedPoint = e.GetTouchPoint(this).Position;
}
private void TableBrowserUserControl_TouchMove(object sender, System.Windows.Input.TouchEventArgs e)
{
if (null != LastSavedPoint)
{
Point p = e.GetTouchPoint(this).Position;
BrowserView.GetBrowser().GetHost().SendMouseWheelEvent((int)p.X, (int)p.Y, 0, (int)(p.Y - LastSavedPoint.Value.Y), CefEventFlags.MiddleMouseButton);
LastSavedPoint = p;
}
}
Unless there are any further reports of errors between now and the 77
release then the code from CefSharp.Wpf.Experimental.ChromiumWebBrowserWithTouchSupport
will be merged into the default ChromiumWebBrowser
class.
Anyone who has a few moments please test CefSharp.Wpf.Experimental.ChromiumWebBrowserWithTouchSupport
and report back if you experience any problems.
@amaitland can you kindly explain us how to enable ChromiumWebBrowserWithTouchSupport ?
Sorry amaitland - installing x86 version of Visual C++ runtime helped - i deleted the issue.
I changed namespace from CefSharp.Wpf.Experimental to CefSharp.Wpf in ChromiumWebBrowserWithTouchSupport.cs
Then i replaced ChromiumWebBrowser by ChromiumWebBrowserWithTouchSupport where i thought it makes sense (in XAML and on new statements) in CefSharp.Wpf.Example project.
On my Tablet i cannot scroll or zoom with my fingers. I think in my previous test i did the same and it worked. How can i make it working?
can you kindly explain us how to enable ChromiumWebBrowserWithTouchSupport ?
@cristiancarli Use ChromiumWebBrowserWithTouchSupport
instead of ChromiumWebBrowser
in your Xaml
or .Net
code.
On my Tablet i cannot scroll or zoom with my fingers. I think in my previous test i did the same and it worked. How can i make it working?
@Clemani If you are using a build of master
(which I don't recommend for testing, use https://github.com/cefsharp/CefSharp.MinimalExample instead) then you will need to comment out
System.AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.DisableStylusAndTouchSupport", true);
At line https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/App.xaml.cs#L16
There's a bug in WPF
(https://github.com/dotnet/wpf/issues/1323) that I've temp disabled DisableStylusAndTouchSupport
to allow for testing of another feature/improvement.
Thanks amaitland.
I tested today with master branch and CefSharp.Wpf.Example.
Touch scroll and zoom seems to work fine.
But with ChromiumWebBrowserWithTouchSupport selecting text with pen does not work anymore, and there is an issue with keyboard input. Please see my comment from May 28 which fully applies also to current master branch.
Not an issue, but i miss the "afterburner" effect when i scroll by finger. In the WinForms version when i move the finger and lift it off while i am moving the browser continues to scroll for a while - this does not happen in ChromiumWebBrowserWithTouchSupport.
@amaitland Hi, will the multitouch feature of CefSharp.Wpf.Experimental.ChromiumWebBrowserWithTouchSupport
also be available in 77 for CefSharp.OffScreen.ChromiumWebBrowser
? For example by injecting fingers events like currently existing SendMouseClickEvent()
and SendMouseWheelEvent()
...
But with ChromiumWebBrowserWithTouchSupport selecting text with pen does not work anymore
@Clemani Thanks for the feedback, based on this I'll leave out the Pen/Stylus
methods. I don't have a Pen/Stylus
so I cannot test this currently so I was wondering if it might be best left as part of the Experimental
implementation. Will merge basic touch support into ChromiumWebBrowser
there is an issue with keyboard input.
Can you please clarify which keyboard issue
Not an issue, but i miss the "afterburner" effect when i scroll by finger. In the WinForms version when i move the finger and lift it off while i am moving the browser continues to scroll for a while - this does not happen in ChromiumWebBrowserWithTouchSupport.
How does the CEF Sample
application behave? You can download from http://opensource.spotify.com/cefbuilds/cef_binary_77.1.6%2Bga0ea7e6%2Bchromium-77.0.3865.90_windows32_client.tar.bz2
Please test with the following
cefclient --multi-threaded-message-loop --off-screen-rendering-enabled --enable-gpu
For example by injecting fingers events like currently existing
SendMouseClickEvent()
andSendMouseWheelEvent()
...
@DelTaGC The SendTouchEvent
method was added in version 73
. Look at the ChromiumWebBrowserWithTouchSupport
source if you need an example.
Touch support has been moved from ChromiumWebBrowserWithTouchSupport
to ChromiumWebBrowser
in commit https://github.com/cefsharp/CefSharp/commit/b31a365dd41585ba24433dc2655dbfa03ea18e1a
Stylus/Pen support is still in ChromiumWebBrowserWithTouchSupport
. I'll likely close this issue and create a new one to track adding Stylus/Pen
support.
Can you please clarify which keyboard issue
o For ex. enter www.google.com into the address box and press enter.
o Try to select a text on the web page with with pen and right click button
o Click into the address box with pen
o Then a click with pen into the search box on the web page has no effect, the input focus remains in the address box.
I cannot reproduce this reliable, sometimes the issue happens and sometimes not. When you have no pen then i think you cannot reproduce this issue.
Off-topic: The WinForms keyboard issue on touch devices is described here: https://bitbucket.org/chromiumembedded/cef/issues/1797/windows-touch-does-not-return-focus-to-the
How does the CEF Sample application behave? ...
How can i inject finger events ? Changing and compiling CEF is out of my scope.
How can i inject finger events ? Changing and compiling CEF is out of my scope.
@Clemani Just download an run cefclient
from the link provided with the command line args referenced. If the fling
behaviour works there then we can look at implementing it, if not then it's unlikely something CEF
supports.
With this commandline args i cannot do anything in cefclient on a web page, finger and pen does not work at all.
It appears that Fling scrolling
is currently broken in CEF
. Relevant issue is https://bitbucket.org/chromiumembedded/cef/issues/2745/osr-fling-scrolling-doesnt-work-in-without
It appears that
Fling scrolling
is currently broken inCEF
. Relevant issue is https://bitbucket.org/chromiumembedded/cef/issues/2745/osr-fling-scrolling-doesnt-work-in-without
Fling Scrolling
should now be resolved upstream
Touch Support
will be part of version 79
, Stylus
support is still only in the CefSharp.Wpf.Experimental.ChromiumWebBrowserWithTouchSupport
class, I've created
Stylus
please comment on #3028 instead of here.Anyone experiencing problems with Touch Support
in version 79
or above please open a new issue using the Bug Report Template, please make sure to include a detailed list of steps to reproduce the problem you are seeing.
There is no default virtual keyboard implementation as WPF
doesn't provide an out of the box solution that works on all supported operating systems. If you require a virtual keyboard when using your touch screen please read OnScreen Virtual Keyboard. There's some additional information in #1736
I guess this is more of a feature request than an issue but it would be nice to have multitouch support:
-Scrolling with one finger -Zooming with pinch zoom gesture