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.5 KiB

using System;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using RemoteViewing.Vnc;
using RemoteViewing.Vnc.Server;
namespace Avalonia.Headless.Vnc
{
public class HeadlessVncFramebufferSource : IVncFramebufferSource
{
public IHeadlessWindow Window { get; set; }
private object _lock = new object();
public VncFramebuffer _framebuffer = new VncFramebuffer("Avalonia", 1, 1, VncPixelFormat.RGB32);
private VncButton _previousButtons;
public HeadlessVncFramebufferSource(VncServerSession session, Window window)
{
Window = (IHeadlessWindow)window.PlatformImpl;
session.PointerChanged += (_, args) =>
{
var pt = new Point(args.X, args.Y);
var buttons = (VncButton)args.PressedButtons;
int TranslateButton(VncButton vncButton) =>
vncButton == VncButton.Left ? 0 : vncButton == VncButton.Right ? 1 : 2;
var modifiers = (InputModifiers)(((int)buttons & 7) << 4);
Dispatcher.UIThread.Post(() =>
{
Window?.MouseMove(pt);
foreach (var btn in CheckedButtons)
if (_previousButtons.HasFlag(btn) && !buttons.HasFlag(btn))
Window?.MouseUp(pt, TranslateButton(btn), modifiers);
foreach (var btn in CheckedButtons)
if (!_previousButtons.HasFlag(btn) && buttons.HasFlag(btn))
Window?.MouseDown(pt, TranslateButton(btn), modifiers);
_previousButtons = buttons;
}, DispatcherPriority.Input);
};
}
[Flags]
enum VncButton
{
Left = 1,
Middle = 2,
Right = 4,
ScrollUp = 8,
ScrollDown = 16
}
private static VncButton[] CheckedButtons = new[] {VncButton.Left, VncButton.Middle, VncButton.Right};
public VncFramebuffer Capture()
{
lock (_lock)
{
using (var bmpRef = Window.GetLastRenderedFrame())
{
if (bmpRef?.Item == null)
return _framebuffer;
var bmp = bmpRef.Item;
if (bmp.PixelSize.Width != _framebuffer.Width || bmp.PixelSize.Height != _framebuffer.Height)
{
_framebuffer = new VncFramebuffer("Avalonia", bmp.PixelSize.Width, bmp.PixelSize.Height,
VncPixelFormat.RGB32);
}
using (var fb = bmp.Lock())
{
var buf = _framebuffer.GetBuffer();
if (_framebuffer.Stride == fb.RowBytes)
Marshal.Copy(fb.Address, buf, 0, buf.Length);
else
for (var y = 0; y < fb.Size.Height; y++)
{
var sourceStart = fb.RowBytes * y;
var dstStart = _framebuffer.Stride * y;
var row = fb.Size.Width * 4;
Marshal.Copy(new IntPtr(sourceStart + fb.Address.ToInt64()), buf, dstStart, row);
}
}
}
}
return _framebuffer;
}
}
}