diff --git a/Directory.Build.props b/Directory.Build.props
index 26b8f48..13ee287 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -11,7 +11,7 @@
$([System.DateTime]::Now.ToString('yyyy'))
- 0.5.5
+ 0.5.6
vvvv group
diff --git a/VL.CEF.Skia/VL.CEF.Skia.vl b/VL.CEF.Skia/VL.CEF.Skia.vl
index a6c9d55..52ecbea 100644
--- a/VL.CEF.Skia/VL.CEF.Skia.vl
+++ b/VL.CEF.Skia/VL.CEF.Skia.vl
@@ -114,5 +114,5 @@
-
+
\ No newline at end of file
diff --git a/VL.CEF.Stride/VL.CEF.Stride.vl b/VL.CEF.Stride/VL.CEF.Stride.vl
index a621ccb..95c58ae 100644
--- a/VL.CEF.Stride/VL.CEF.Stride.vl
+++ b/VL.CEF.Stride/VL.CEF.Stride.vl
@@ -115,5 +115,5 @@
-
+
\ No newline at end of file
diff --git a/VL.CEF/src/WebBrowser.InputHandling.cs b/VL.CEF/src/WebBrowser.InputHandling.cs
new file mode 100644
index 0000000..ca6cc2d
--- /dev/null
+++ b/VL.CEF/src/WebBrowser.InputHandling.cs
@@ -0,0 +1,213 @@
+using Stride.Core.Mathematics;
+using System;
+using System.Diagnostics;
+using VL.Lib.IO;
+using VL.Lib.IO.Notifications;
+using Xilium.CefGlue;
+
+namespace VL.CEF
+{
+ partial class WebBrowser
+ {
+ CefEventFlags mouseModifiers;
+
+ public bool SendNotification(INotification notification)
+ {
+ if (notification is MouseNotification mouseNotification)
+ {
+ HandleMouseNotification(mouseNotification);
+ return true;
+ }
+ else if (notification is KeyNotification keyNotification)
+ {
+ HandleKeyNotification(keyNotification);
+ return true;
+ }
+ else if (notification is TouchNotification touchNotification)
+ {
+ HandleTouchNotification(touchNotification);
+ return true;
+ }
+ return false;
+ }
+
+ private void HandleTouchNotification(TouchNotification n)
+ {
+ var position = n.Position.DeviceToLogical(ScaleFactor);
+ var touchEvent = new CefTouchEvent()
+ {
+ Id = n.Id,
+ Modifiers = GetModifiers(n),
+ PointerType = CefPointerType.Touch,
+ Pressure = 1f,
+ RadiusX = n.ContactArea.X,
+ RadiusY = n.ContactArea.Y,
+ RotationAngle = 0,
+ Type = GetTouchType(n.Kind),
+ X = position.X,
+ Y = position.Y
+ };
+ BrowserHost.SendTouchEvent(touchEvent);
+
+ CefTouchEventType GetTouchType(TouchNotificationKind kind)
+ {
+ switch (kind)
+ {
+ case TouchNotificationKind.TouchDown:
+ return CefTouchEventType.Pressed;
+ case TouchNotificationKind.TouchUp:
+ return CefTouchEventType.Released;
+ case TouchNotificationKind.TouchMove:
+ return CefTouchEventType.Moved;
+ default:
+ return CefTouchEventType.Cancelled;
+ }
+ }
+ }
+
+ private void HandleKeyNotification(KeyNotification n)
+ {
+ var keyEvent = new CefKeyEvent()
+ {
+ Modifiers = GetModifiers(n)
+ };
+ switch (n.Kind)
+ {
+ case KeyNotificationKind.KeyDown:
+ var keyDown = n as KeyDownNotification;
+ keyEvent.EventType = CefKeyEventType.KeyDown;
+ keyEvent.WindowsKeyCode = (int)keyDown.KeyCode;
+ keyEvent.NativeKeyCode = (int)keyDown.KeyCode;
+ break;
+ case KeyNotificationKind.KeyPress:
+ var keyPress = n as KeyPressNotification;
+ keyEvent.EventType = CefKeyEventType.Char;
+ keyEvent.Character = keyPress.KeyChar;
+ keyEvent.UnmodifiedCharacter = keyPress.KeyChar;
+ keyEvent.WindowsKeyCode = (int)keyPress.KeyChar;
+ keyEvent.NativeKeyCode = (int)keyPress.KeyChar;
+ break;
+ case KeyNotificationKind.KeyUp:
+ var keyUp = n as KeyUpNotification;
+ keyEvent.EventType = CefKeyEventType.KeyUp;
+ keyEvent.WindowsKeyCode = (int)keyUp.KeyCode;
+ keyEvent.NativeKeyCode = (int)keyUp.KeyCode;
+ break;
+ default:
+ break;
+ }
+ BrowserHost.SendKeyEvent(keyEvent);
+ }
+
+ int clickCount = 1;
+ MouseButtons? lastButton;
+ Vector2 lastPosition;
+ Stopwatch stopwatch = Stopwatch.StartNew();
+
+ private void HandleMouseNotification(MouseNotification n)
+ {
+ if (n is MouseButtonNotification buttonNotification)
+ {
+ var position = n.Position;
+ var delta = lastPosition - position;
+ var deltaTime = stopwatch.ElapsedMilliseconds;
+ stopwatch.Restart();
+
+ if (n is MouseDownNotification)
+ {
+ if (buttonNotification.Buttons == lastButton &&
+ Math.Abs(delta.X) < Mouse.DoubleClickSize.Width / 2 &&
+ Math.Abs(delta.Y) < Mouse.DoubleClickSize.Height / 2 &&
+ deltaTime < Mouse.DoubleClickTime)
+ {
+ clickCount++;
+ }
+ else
+ {
+ clickCount = 1;
+ }
+ }
+ else if (buttonNotification.Buttons != lastButton)
+ {
+ clickCount = 1;
+ }
+
+ lastButton = buttonNotification.Buttons;
+ lastPosition = position;
+
+ if (n is MouseDownNotification mouseDown)
+ mouseModifiers |= ToCefEventFlags(mouseDown.Buttons);
+ else if (n is MouseUpNotification mouseUp)
+ mouseModifiers &= ~ToCefEventFlags(mouseUp.Buttons);
+ }
+
+ {
+ var position = n.Position.DeviceToLogical(ScaleFactor);
+ var mouseEvent = new CefMouseEvent((int)position.X, (int)position.Y, GetModifiers(n));
+ var browserHost = BrowserHost;
+ switch (n.Kind)
+ {
+ case MouseNotificationKind.MouseDown:
+ var mouseDown = n as MouseDownNotification;
+ browserHost.SendMouseClickEvent(mouseEvent, GetMouseButtonType(mouseDown.Buttons), mouseUp: false, clickCount: clickCount);
+ break;
+ case MouseNotificationKind.MouseUp:
+ var mouseUp = n as MouseUpNotification;
+ browserHost.SendMouseClickEvent(mouseEvent, GetMouseButtonType(mouseUp.Buttons), mouseUp: true, clickCount: clickCount);
+ break;
+ case MouseNotificationKind.MouseMove:
+ browserHost.SendMouseMoveEvent(mouseEvent, mouseLeave: false);
+ break;
+ case MouseNotificationKind.MouseWheel:
+ var mouseWheel = n as MouseWheelNotification;
+ browserHost.SendMouseWheelEvent(mouseEvent, 0, mouseWheel.WheelDelta);
+ break;
+ case MouseNotificationKind.MouseHorizontalWheel:
+ var mouseHWheel = n as MouseHorizontalWheelNotification;
+ browserHost.SendMouseWheelEvent(mouseEvent, mouseHWheel.WheelDelta, 0);
+ break;
+ case MouseNotificationKind.DeviceLost:
+ browserHost.SendMouseMoveEvent(mouseEvent, mouseLeave: true);
+ break;
+ }
+ }
+
+ CefMouseButtonType GetMouseButtonType(MouseButtons buttons)
+ {
+ if ((buttons & MouseButtons.Left) != 0)
+ return CefMouseButtonType.Left;
+ if ((buttons & MouseButtons.Middle) != 0)
+ return CefMouseButtonType.Middle;
+ if ((buttons & MouseButtons.Right) != 0)
+ return CefMouseButtonType.Right;
+ return default;
+ }
+
+ static CefEventFlags ToCefEventFlags(MouseButtons buttons)
+ {
+ switch (buttons)
+ {
+ case MouseButtons.Left:
+ return CefEventFlags.LeftMouseButton;
+ case MouseButtons.Middle:
+ return CefEventFlags.MiddleMouseButton;
+ case MouseButtons.Right:
+ return CefEventFlags.RightMouseButton;
+ }
+ return default;
+ }
+ }
+
+ CefEventFlags GetModifiers(NotificationBase n)
+ {
+ var result = CefEventFlags.None;
+ if (n.AltKey)
+ result |= CefEventFlags.AltDown | CefEventFlags.IsLeft;
+ if (n.ShiftKey)
+ result |= CefEventFlags.ShiftDown | CefEventFlags.IsLeft;
+ if (n.CtrlKey)
+ result |= CefEventFlags.ControlDown | CefEventFlags.IsLeft;
+ return result | mouseModifiers;
+ }
+ }
+}