|
|
@@ -1,8 +1,13 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using Avalonia.Controls.Platform.Surfaces;
|
|
|
using Avalonia.Input;
|
|
|
using Avalonia.Platform;
|
|
|
+using Avalonia.Utilities;
|
|
|
+
|
|
|
+#nullable enable
|
|
|
|
|
|
namespace Avalonia.X11
|
|
|
{
|
|
|
@@ -67,9 +72,9 @@ namespace Avalonia.X11
|
|
|
return new PlatformHandle(handle, "XCURSOR");
|
|
|
}
|
|
|
|
|
|
- public IPlatformHandle CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot)
|
|
|
+ public unsafe IPlatformHandle CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot)
|
|
|
{
|
|
|
- throw new NotImplementedException();
|
|
|
+ return new XImageCursor(_display, cursor, hotSpot);
|
|
|
}
|
|
|
|
|
|
private static IntPtr GetNullCursor(IntPtr display)
|
|
|
@@ -79,5 +84,55 @@ namespace Avalonia.X11
|
|
|
IntPtr pixmap = XLib.XCreateBitmapFromData(display, window, NullCursorData, 1, 1);
|
|
|
return XLib.XCreatePixmapCursor(display, pixmap, pixmap, ref color, ref color, 0, 0);
|
|
|
}
|
|
|
+
|
|
|
+ private unsafe class XImageCursor : IFramebufferPlatformSurface, IPlatformHandle, IDisposable
|
|
|
+ {
|
|
|
+ private readonly PixelSize _pixelSize;
|
|
|
+ private readonly IUnmanagedBlob _blob;
|
|
|
+
|
|
|
+ public XImageCursor(IntPtr display, IBitmapImpl bitmap, PixelPoint hotSpot)
|
|
|
+ {
|
|
|
+ var size = Marshal.SizeOf<XcursorImage>() +
|
|
|
+ (bitmap.PixelSize.Width * bitmap.PixelSize.Height * 4);
|
|
|
+
|
|
|
+ _pixelSize = bitmap.PixelSize;
|
|
|
+ _blob = AvaloniaLocator.Current.GetService<IRuntimePlatform>().AllocBlob(size);
|
|
|
+
|
|
|
+ var image = (XcursorImage*)_blob.Address;
|
|
|
+ image->version = 1;
|
|
|
+ image->size = Marshal.SizeOf<XcursorImage>();
|
|
|
+ image->width = bitmap.PixelSize.Width;
|
|
|
+ image->height = bitmap.PixelSize.Height;
|
|
|
+ image->xhot = hotSpot.X;
|
|
|
+ image->yhot = hotSpot.Y;
|
|
|
+ image->pixels = (IntPtr)(image + 1);
|
|
|
+
|
|
|
+ using (var renderTarget = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>().CreateRenderTarget(new[] { this }))
|
|
|
+ using (var ctx = renderTarget.CreateDrawingContext(null))
|
|
|
+ {
|
|
|
+ var r = new Rect(_pixelSize.ToSize(1));
|
|
|
+ ctx.DrawBitmap(RefCountable.CreateUnownedNotClonable(bitmap), 1, r, r);
|
|
|
+ }
|
|
|
+
|
|
|
+ Handle = XLib.XcursorImageLoadCursor(display, _blob.Address);
|
|
|
+ }
|
|
|
+
|
|
|
+ public IntPtr Handle { get; }
|
|
|
+ public string HandleDescriptor => "XCURSOR";
|
|
|
+
|
|
|
+ public void Dispose()
|
|
|
+ {
|
|
|
+ XLib.XcursorImageDestroy(Handle);
|
|
|
+ _blob.Dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ public ILockedFramebuffer Lock()
|
|
|
+ {
|
|
|
+ return new LockedFramebuffer(
|
|
|
+ _blob.Address + Marshal.SizeOf<XcursorImage>(),
|
|
|
+ _pixelSize, _pixelSize.Width * 4,
|
|
|
+ new Vector(96, 96), PixelFormat.Bgra8888, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|