Skip to content

Commit

Permalink
feat(skiawpf): Added support for pointers - first working version.
Browse files Browse the repository at this point in the history
  • Loading branch information
carldebilly committed Jul 30, 2020
1 parent ea5e7f8 commit 9801c51
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 12 deletions.
21 changes: 15 additions & 6 deletions src/Uno.UI.Runtime.Skia.Gtk/GTK/GtkHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Uno.UI.Runtime.Skia
{
public class GtkHost
public class GtkHost : ISkiaHost
{
private readonly string[] _args;
private Func<WUX.Application> _appBuilder;
Expand All @@ -20,6 +20,13 @@ public class GtkHost

public static Gtk.Window Window => _window;

static GtkHost()
{
ApiExtensibility.Register(typeof(Windows.UI.Core.ICoreWindowExtension), o => new GtkUIElementPointersSupport(o));
ApiExtensibility.Register(typeof(Windows.UI.ViewManagement.IApplicationViewExtension), o => new GtkApplicationViewExtension(o));
ApiExtensibility.Register(typeof(IApplicationExtension), o => new GtkApplicationExtension(o));
}

public GtkHost(Func<WUX.Application> appBuilder, string[] args)
{
_args = args;
Expand All @@ -30,10 +37,6 @@ public void Run()
{
Gtk.Application.Init();

ApiExtensibility.Register(typeof(Windows.UI.Core.ICoreWindowExtension), o => new GtkUIElementPointersSupport(o));
ApiExtensibility.Register(typeof(Windows.UI.ViewManagement.IApplicationViewExtension), o => new GtkApplicationViewExtension(o));
ApiExtensibility.Register(typeof(IApplicationExtension), o => new GtkApplicationExtension(o));

_window = new Gtk.Window("Uno Host");
_window.SetDefaultSize(1024, 800);
_window.SetPosition(Gtk.WindowPosition.Center);
Expand Down Expand Up @@ -92,7 +95,13 @@ public void Run()

_window.ShowAll();

WUX.Application.Start(_ => _appBuilder(), _args);
void CreateApp(ApplicationInitializationCallbackParams _)
{
var app = _appBuilder();
app.Host = this;
}

WUX.Application.Start(CreateApp, _args);

Gtk.Application.Run();
}
Expand Down
22 changes: 17 additions & 5 deletions src/Uno.UI.Runtime.Skia.Wpf/WPF/WpfHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,35 @@

namespace Uno.UI.Skia.Platform
{
public class WpfHost : FrameworkElement
public class WpfHost : FrameworkElement, WinUI.ISkiaHost
{
private readonly bool designMode;
private readonly Func<WinUI.Application> _appBuilder;
private WriteableBitmap bitmap;
private bool ignorePixelScaling;

public WpfHost(Func<WinUI.Application> appBuilder)
static WpfHost()
{
ApiExtensibility.Register(typeof(Windows.UI.Core.ICoreWindowExtension), o => new WpfUIElementPointersSupport(o));
ApiExtensibility.Register(typeof(Windows.UI.ViewManagement.IApplicationViewExtension), o => new WpfApplicationViewExtension(o));
ApiExtensibility.Register(typeof(WinUI.IApplicationExtension), o => new WpfApplicationExtension(o));
}

[ThreadStatic] private static WpfHost _current;
public static WpfHost Current => _current;

public WpfHost(Func<WinUI.Application> appBuilder)
{
_current = this;

designMode = DesignerProperties.GetIsInDesignMode(this);
_appBuilder = appBuilder;

WinUI.Application.Start(_ => appBuilder());
void CreateApp(WinUI.ApplicationInitializationCallbackParams _)
{
var app = appBuilder();
app.Host = this;
}

WinUI.Application.Start(CreateApp);

WinUI.Window.Current.InvalidateRender += () => InvalidateVisual();

Expand Down
217 changes: 217 additions & 0 deletions src/Uno.UI.Runtime.Skia.Wpf/WPF/WpfUIElementPointersSupport.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,234 @@
using System;
using Windows.Devices.Input;
using Windows.UI.Core;
using Uno.Extensions;
using Uno.Logging;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using WpfApplication = System.Windows.Application;
using WpfWindow = System.Windows.Window;
using System.Threading;
using System.Windows.Input;
using Windows.UI.Input;
using MouseDevice = System.Windows.Input.MouseDevice;

namespace Uno.UI.Skia.Platform
{
public class WpfUIElementPointersSupport : ICoreWindowExtension
{
private CoreWindow _owner;
private ICoreWindowEvents _ownerEvents;
private WpfWindow _mainWpfWindow;
private WpfHost _host;

private static int _currentFrameId;

public WpfUIElementPointersSupport(object owner)
{
_owner = (CoreWindow)owner;
_ownerEvents = (ICoreWindowEvents)owner;

_mainWpfWindow = WpfApplication.Current.MainWindow;
_host = WpfHost.Current;

_host.MouseEnter += HostOnMouseEnter;
_host.MouseLeave += HostOnMouseLeave;
_host.MouseMove += HostOnMouseMove;
_host.MouseDown += HostOnMouseDown;
_host.MouseUp += HostOnMouseUp;
_host.MouseWheel += HostOnMouseWheel;

}

private static uint GetNextFrameId() => (uint)Interlocked.Increment(ref _currentFrameId);

private static PointerPointProperties BuildPointerProperties(MouseEventArgs args, int wheelDelta = 0)
{
var properties = new PointerPointProperties
{
IsLeftButtonPressed = args.LeftButton == MouseButtonState.Pressed,
IsRightButtonPressed = args.RightButton == MouseButtonState.Pressed,
IsPrimary = true
};

if (wheelDelta != 0)
{
properties.MouseWheelDelta = -wheelDelta / 10;
}

return properties;
}

private static PointerDevice GetPointerDevice(MouseEventArgs args)
{
return args.Device switch
{
MouseDevice _ => PointerDevice.For(PointerDeviceType.Mouse),
StylusDevice _ => PointerDevice.For(PointerDeviceType.Pen),
TouchDevice _ => PointerDevice.For(PointerDeviceType.Touch),
_ => PointerDevice.For(PointerDeviceType.Mouse),
};
}

private void HostOnMouseEnter(object sender, MouseEventArgs args)
{
try
{
var position = args.GetPosition(_host);

_ownerEvents.RaisePointerEntered(
new PointerEventArgs(
new Windows.UI.Input.PointerPoint(
frameId: GetNextFrameId(),
timestamp: (uint)args.Timestamp,
device: GetPointerDevice(args),
pointerId: 0,
rawPosition: new Windows.Foundation.Point(position.X, position.Y),
position: new Windows.Foundation.Point(position.X, position.Y),
isInContact: false,
properties: BuildPointerProperties(args)
)
)
);
}
catch (Exception e)
{
this.Log().Error("Failed to raise PointerEntered", e);
}
}

private void HostOnMouseLeave(object sender, MouseEventArgs args)
{
try
{
var position = args.GetPosition(_host);

_ownerEvents.RaisePointerExited(
new PointerEventArgs(
new Windows.UI.Input.PointerPoint(
frameId: GetNextFrameId(),
timestamp: (uint)args.Timestamp,
device: GetPointerDevice(args),
pointerId: 0,
rawPosition: new Windows.Foundation.Point(position.X, position.Y),
position: new Windows.Foundation.Point(position.X, position.Y),
isInContact: false,
properties: BuildPointerProperties(args)
)
)
);
}
catch (Exception e)
{
this.Log().Error("Failed to raise PointerExited", e);
}
}

private void HostOnMouseMove(object sender, MouseEventArgs args)
{
try
{
var position = args.GetPosition(_host);

_ownerEvents.RaisePointerMoved(
new PointerEventArgs(
new Windows.UI.Input.PointerPoint(
frameId: GetNextFrameId(),
timestamp: (uint)args.Timestamp,
device: GetPointerDevice(args),
pointerId: 0,
rawPosition: new Windows.Foundation.Point(position.X, position.Y),
position: new Windows.Foundation.Point(position.X, position.Y),
isInContact: false,
properties: BuildPointerProperties(args)
)
)
);
}
catch (Exception e)
{
this.Log().Error("Failed to raise PointerMoved", e);
}
}

private void HostOnMouseDown(object sender, MouseButtonEventArgs args)
{
try
{
var position = args.GetPosition(_host);

_ownerEvents.RaisePointerPressed(
new PointerEventArgs(
new Windows.UI.Input.PointerPoint(
frameId: GetNextFrameId(),
timestamp: (uint)args.Timestamp,
device: GetPointerDevice(args),
pointerId: 0,
rawPosition: new Windows.Foundation.Point(position.X, position.Y),
position: new Windows.Foundation.Point(position.X, position.Y),
isInContact: false,
properties: BuildPointerProperties(args)
)
)
);
}
catch (Exception e)
{
this.Log().Error("Failed to raise PointerPressed", e);
}
}

private void HostOnMouseUp(object sender, MouseButtonEventArgs args)
{
try
{
var position = args.GetPosition(_host);

_ownerEvents.RaisePointerReleased(
new PointerEventArgs(
new Windows.UI.Input.PointerPoint(
frameId: GetNextFrameId(),
timestamp: (uint)args.Timestamp,
device: GetPointerDevice(args),
pointerId: 0,
rawPosition: new Windows.Foundation.Point(position.X, position.Y),
position: new Windows.Foundation.Point(position.X, position.Y),
isInContact: false,
properties: BuildPointerProperties(args)
)
)
);
}
catch (Exception e)
{
this.Log().Error("Failed to raise PointerReleased", e);
}
}

private void HostOnMouseWheel(object sender, MouseWheelEventArgs args)
{
try
{
var position = args.GetPosition(_host);

_ownerEvents.RaisePointerWheelChanged(
new PointerEventArgs(
new Windows.UI.Input.PointerPoint(
frameId: GetNextFrameId(),
timestamp: (uint)args.Timestamp,
device: GetPointerDevice(args),
pointerId: 0,
rawPosition: new Windows.Foundation.Point(position.X, position.Y),
position: new Windows.Foundation.Point(position.X, position.Y),
isInContact: false,
properties: BuildPointerProperties(args, args.Delta)
)
)
);
}
catch (Exception e)
{
this.Log().Error("Failed to raise PointerWheelChanged", e);
}
}
}
}
5 changes: 5 additions & 0 deletions src/Uno.UI/UI/Xaml/Application.Skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public partial class Application : IApplicationEvents
private static string[] _args;
private readonly IApplicationExtension _coreWindowExtension;

internal ISkiaHost Host { get; set; }

public Application()
{
if (!ApiExtensibility.CreateInstance(this, out _coreWindowExtension))
Expand Down Expand Up @@ -77,6 +79,9 @@ internal interface IApplicationExtension

internal interface IApplicationEvents
{
}

internal interface ISkiaHost
{
}
}
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/UIElement.Pointers.Skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private void CoreWindow_PointerReleased(CoreWindow sender, PointerEventArgs args
var pointer = new Pointer(args.CurrentPoint.PointerId, PointerDeviceType.Mouse, false, isInRange: true);
if (UIElement.PointerCapture.TryGet(pointer, out var capture))
{
foreach(var target in capture.Targets)
foreach(var target in capture.Targets.ToArray())
{
var pointerArgs = new PointerRoutedEventArgs(args, pointer, target.Element);
target.Element.OnNativePointerUp(pointerArgs);
Expand Down

0 comments on commit 9801c51

Please sign in to comment.