A cross-platform UI framework for .NET
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

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);
}
}
}