csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
3.2 KiB
96 lines
3.2 KiB
using System;
|
|
using System.Runtime.InteropServices;
|
|
using Avalonia.Media;
|
|
using Avalonia.Media.Imaging;
|
|
using Avalonia.Remote.Protocol;
|
|
using Avalonia.Remote.Protocol.Viewport;
|
|
using Avalonia.Threading;
|
|
using PixelFormat = Avalonia.Platform.PixelFormat;
|
|
|
|
namespace Avalonia.Controls.Remote
|
|
{
|
|
public class RemoteWidget : Control
|
|
{
|
|
public enum SizingMode
|
|
{
|
|
Local,
|
|
Remote
|
|
}
|
|
|
|
private readonly IAvaloniaRemoteTransportConnection _connection;
|
|
private FrameMessage _lastFrame;
|
|
private WriteableBitmap _bitmap;
|
|
public RemoteWidget(IAvaloniaRemoteTransportConnection connection)
|
|
{
|
|
Mode = SizingMode.Local;
|
|
|
|
_connection = connection;
|
|
_connection.OnMessage += (t, msg) => Dispatcher.UIThread.Post(() => OnMessage(msg));
|
|
_connection.Send(new ClientSupportedPixelFormatsMessage
|
|
{
|
|
Formats = new[]
|
|
{
|
|
Avalonia.Remote.Protocol.Viewport.PixelFormat.Bgra8888,
|
|
Avalonia.Remote.Protocol.Viewport.PixelFormat.Rgba8888,
|
|
}
|
|
});
|
|
}
|
|
|
|
public SizingMode Mode { get; set; }
|
|
|
|
private void OnMessage(object msg)
|
|
{
|
|
if (msg is FrameMessage frame)
|
|
{
|
|
_connection.Send(new FrameReceivedMessage
|
|
{
|
|
SequenceId = frame.SequenceId
|
|
});
|
|
_lastFrame = frame;
|
|
InvalidateVisual();
|
|
}
|
|
|
|
}
|
|
|
|
protected override void ArrangeCore(Rect finalRect)
|
|
{
|
|
if (Mode == SizingMode.Local)
|
|
{
|
|
_connection.Send(new ClientViewportAllocatedMessage
|
|
{
|
|
Width = finalRect.Width,
|
|
Height = finalRect.Height,
|
|
DpiX = 10 * 96,
|
|
DpiY = 10 * 96 //TODO: Somehow detect the actual DPI
|
|
});
|
|
}
|
|
|
|
base.ArrangeCore(finalRect);
|
|
}
|
|
|
|
public override void Render(DrawingContext context)
|
|
{
|
|
if (_lastFrame != null)
|
|
{
|
|
var fmt = (PixelFormat) _lastFrame.Format;
|
|
if (_bitmap == null || _bitmap.PixelSize.Width != _lastFrame.Width ||
|
|
_bitmap.PixelSize.Height != _lastFrame.Height)
|
|
{
|
|
_bitmap?.Dispose();
|
|
_bitmap = new WriteableBitmap(new PixelSize(_lastFrame.Width, _lastFrame.Height),
|
|
new Vector(96, 96), fmt);
|
|
}
|
|
using (var l = _bitmap.Lock())
|
|
{
|
|
var lineLen = (fmt == PixelFormat.Rgb565 ? 2 : 4) * _lastFrame.Width;
|
|
for (var y = 0; y < _lastFrame.Height; y++)
|
|
Marshal.Copy(_lastFrame.Data, y * _lastFrame.Stride,
|
|
new IntPtr(l.Address.ToInt64() + l.RowBytes * y), lineLen);
|
|
}
|
|
context.DrawImage(_bitmap, new Rect(0, 0, _bitmap.PixelSize.Width, _bitmap.PixelSize.Height),
|
|
new Rect(Bounds.Size));
|
|
}
|
|
base.Render(context);
|
|
}
|
|
}
|
|
}
|
|
|