Browse Source

Merge pull request #7295 from Mikolaytis/WasmCursors

[WASM] Implement Cursors API
pull/7296/head
Max Katz 5 years ago
committed by GitHub
parent
commit
ba9c0b3cfd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
  2. 93
      src/Web/Avalonia.Web.Blazor/Cursor.cs
  3. 14
      src/Web/Avalonia.Web.Blazor/RazorViewTopLevelImpl.cs
  4. 21
      src/Web/Avalonia.Web.Blazor/WinStubs.cs
  5. 2
      src/Web/Avalonia.Web.Blazor/WindowingPlatform.cs

5
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

@ -22,6 +22,7 @@ namespace Avalonia.Web.Blazor
private DpiWatcherInterop _dpiWatcher = null!;
private SKHtmlCanvasInterop.GLInfo? _jsGlInfo = null!;
private InputHelperInterop _inputHelper = null!;
private InputHelperInterop _canvasHelper = null!;
private ElementReference _htmlCanvas;
private ElementReference _inputElement;
private double _dpi;
@ -254,9 +255,11 @@ namespace Avalonia.Web.Blazor
Threading.Dispatcher.UIThread.Post(async () =>
{
_inputHelper = await InputHelperInterop.ImportAsync(Js, _inputElement);
_canvasHelper = await InputHelperInterop.ImportAsync(Js, _htmlCanvas);
_inputHelper.Hide();
_inputHelper.SetCursor("default");
_canvasHelper.SetCursor("default");
_topLevelImpl.SetCssCursor = _canvasHelper.SetCursor;
Console.WriteLine("starting html canvas setup");
_interop = await SKHtmlCanvasInterop.ImportAsync(Js, _htmlCanvas, OnRenderFrame);

93
src/Web/Avalonia.Web.Blazor/Cursor.cs

@ -0,0 +1,93 @@
using Avalonia.Input;
using Avalonia.Platform;
namespace Avalonia.Web.Blazor
{
public class CssCursor : ICursorImpl
{
public const string Default = "default";
public string? Value { get; set; }
public CssCursor(StandardCursorType type)
{
Value = ToKeyword(type);
}
/// <summary>
/// Create a cursor from base64 image
/// </summary>
public CssCursor(string base64, string format, PixelPoint hotspot, StandardCursorType fallback)
{
Value = $"url(\"data:image/{format};base64,{base64}\") {hotspot.X} {hotspot.Y}, {ToKeyword(fallback)}";
}
/// <summary>
/// Create a cursor from url to *.cur file.
/// </summary>
public CssCursor(string url, StandardCursorType fallback)
{
Value = $"url('{url}'), {ToKeyword(fallback)}";
}
/// <summary>
/// Create a cursor from png/svg and hotspot position
/// </summary>
public CssCursor(string url, PixelPoint hotSpot, StandardCursorType fallback)
{
Value = $"url('{url}') {hotSpot.X} {hotSpot.Y}, {ToKeyword(fallback)}";
}
private static string ToKeyword(StandardCursorType type) => type switch
{
StandardCursorType.Hand => "pointer",
StandardCursorType.Cross => "crosshair",
StandardCursorType.Help => "help",
StandardCursorType.Ibeam => "text",
StandardCursorType.No => "not-allowed",
StandardCursorType.None => "none",
StandardCursorType.Wait => "progress",
StandardCursorType.AppStarting => "wait",
StandardCursorType.DragMove => "move",
StandardCursorType.DragCopy => "copy",
StandardCursorType.DragLink => "alias",
StandardCursorType.UpArrow => "default",/*not found matching one*/
StandardCursorType.SizeWestEast => "ew-resize",
StandardCursorType.SizeNorthSouth => "ns-resize",
StandardCursorType.SizeAll => "move",
StandardCursorType.TopSide => "n-resize",
StandardCursorType.BottomSide => "s-resize",
StandardCursorType.LeftSide => "w-resize",
StandardCursorType.RightSide => "e-resize",
StandardCursorType.TopLeftCorner => "nw-resize",
StandardCursorType.TopRightCorner => "ne-resize",
StandardCursorType.BottomLeftCorner => "sw-resize",
StandardCursorType.BottomRightCorner => "se-resize",
_ => Default,
};
public void Dispose() {}
}
internal class CssCursorFactory : ICursorFactory
{
public ICursorImpl CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot)
{
using var imageStream = new MemoryStream();
cursor.Save(imageStream);
//not memory optimized because CryptoStream with ToBase64Transform is not supported in the browser.
var base64String = Convert.ToBase64String(imageStream.ToArray());
return new CssCursor(base64String, "png", hotSpot, StandardCursorType.Arrow);
}
ICursorImpl ICursorFactory.GetCursor(StandardCursorType cursorType)
{
return new CssCursor(cursorType);
}
}
}

14
src/Web/Avalonia.Web.Blazor/RazorViewTopLevelImpl.cs

@ -21,6 +21,7 @@ namespace Avalonia.Web.Blazor
private readonly Stopwatch _sw = Stopwatch.StartNew();
private readonly ITextInputMethodImpl _textInputMethod;
private readonly TouchDevice _touchDevice;
private string _currentCursor = CssCursor.Default;
public RazorViewTopLevelImpl(ITextInputMethodImpl textInputMethod)
{
@ -126,8 +127,16 @@ namespace Avalonia.Web.Blazor
public void SetCursor(ICursorImpl cursor)
{
// nop
var cur = cursor as CssCursor;
var val = CssCursor.Default;
if (cur != null && cur.Value != null)
{
val = cur.Value;
}
if (_currentCursor != val)
{
SetCssCursor?.Invoke(val);
}
}
public IPopupImpl? CreatePopup()
@ -146,6 +155,7 @@ namespace Avalonia.Web.Blazor
public IEnumerable<object> Surfaces => new object[] { _currentSurface! };
public Action<string>? SetCssCursor { get; set; }
public Action<RawInputEventArgs>? Input { get; set; }
public Action<Rect>? Paint { get; set; }
public Action<Size, PlatformResizeReason>? Resized { get; set; }

21
src/Web/Avalonia.Web.Blazor/WinStubs.cs

@ -23,27 +23,6 @@ namespace Avalonia.Web.Blazor
public Task<object> GetDataAsync(string format) => Task.FromResult<object>(new ());
}
internal class CursorStub : ICursorImpl
{
public void Dispose()
{
}
}
internal class CursorFactoryStub : ICursorFactory
{
public ICursorImpl CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot)
{
return new CursorStub();
}
ICursorImpl ICursorFactory.GetCursor(StandardCursorType cursorType)
{
return new CursorStub();
}
}
internal class IconLoaderStub : IPlatformIconLoader
{
private class IconStub : IWindowIconImpl

2
src/Web/Avalonia.Web.Blazor/WindowingPlatform.cs

@ -35,7 +35,7 @@ namespace Avalonia.Web.Blazor
s_keyboard = new KeyboardDevice();
AvaloniaLocator.CurrentMutable
.Bind<IClipboard>().ToSingleton<ClipboardStub>()
.Bind<ICursorFactory>().ToSingleton<CursorFactoryStub>()
.Bind<ICursorFactory>().ToSingleton<CssCursorFactory>()
.Bind<IKeyboardDevice>().ToConstant(s_keyboard)
.Bind<IPlatformSettings>().ToConstant(instance)
.Bind<IPlatformThreadingInterface>().ToConstant(instance)

Loading…
Cancel
Save