10 changed files with 456 additions and 0 deletions
@ -0,0 +1,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" /> |
|||
<ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Folder Include="Bindings\" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Remove="Properties\AssemblyInfo.cs" /> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace Avalonia.Windowing.Bindings |
|||
{ |
|||
public class EventsLoop : IDisposable |
|||
{ |
|||
[DllImport("winit_wrapper")] |
|||
private static extern IntPtr winit_events_loop_new(out IntPtr eventsLoopProxyHandle); |
|||
|
|||
[DllImport("winit_wrapper")] |
|||
private static extern void winit_events_loop_destroy(IntPtr handle); |
|||
|
|||
[DllImport("winit_wrapper")] |
|||
private static extern void winit_events_loop_run(IntPtr handle); |
|||
|
|||
public IntPtr Handle { get; private set; } |
|||
private readonly EventsLoopProxy _eventsLoopProxy; |
|||
|
|||
public EventsLoop() |
|||
{ |
|||
Handle = winit_events_loop_new(out var elpHandle); |
|||
_eventsLoopProxy = new EventsLoopProxy(elpHandle); |
|||
} |
|||
|
|||
public void Run() |
|||
{ |
|||
// We need a delegate callback here to support talking back to the C# code.
|
|||
// Send an event type enum and then unsafely construct the event
|
|||
winit_events_loop_run(Handle); |
|||
} |
|||
|
|||
public void Wakeup() |
|||
{ |
|||
_eventsLoopProxy.Wakeup(); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_eventsLoopProxy.Dispose(); |
|||
winit_events_loop_destroy(Handle); |
|||
} |
|||
|
|||
private class EventsLoopProxy : IDisposable |
|||
{ |
|||
[DllImport("winit_wrapper")] |
|||
private static extern void winit_events_loop_proxy_destroy(IntPtr handle); |
|||
|
|||
private readonly IntPtr _handle; |
|||
public EventsLoopProxy(IntPtr handle) |
|||
{ |
|||
_handle = handle; |
|||
} |
|||
|
|||
public void Wakeup() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
winit_events_loop_proxy_destroy(_handle); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace Avalonia.Windowing.Bindings |
|||
{ |
|||
/// <summary>
|
|||
/// A window and GL context pair.
|
|||
/// Due to platform specific quirks, the ordering of window and context creation must be controlled by winit.
|
|||
/// </summary>
|
|||
public class GlWindowWrapper : IWindowWrapper |
|||
{ |
|||
[DllImport("winit_wrapper")] |
|||
private static extern IntPtr winit_gl_window_new(IntPtr eventsLoopHandle); |
|||
|
|||
[DllImport("winit_wrapper")] |
|||
private static extern IntPtr winit_gl_window_destroy(IntPtr handle); |
|||
|
|||
[DllImport("winit_wrapper")] |
|||
private static extern IntPtr winit_gl_window_set_title(IntPtr handle, string title); |
|||
|
|||
private IntPtr _handle; |
|||
public GlWindowWrapper(EventsLoop eventsLoop) |
|||
{ |
|||
_handle = winit_gl_window_new(eventsLoop.Handle); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
winit_gl_window_destroy(_handle); |
|||
} |
|||
|
|||
public void SetTitle(string title) |
|||
{ |
|||
winit_gl_window_set_title(_handle, title); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
namespace Avalonia.Windowing.Bindings |
|||
{ |
|||
/// <summary>
|
|||
/// An interface used to abstract between Window and GlWindow.
|
|||
/// </summary>
|
|||
public interface IWindowWrapper : IDisposable |
|||
{ |
|||
void SetTitle(string title); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Windowing.Bindings |
|||
{ |
|||
public class Monitors : IScreenImpl |
|||
{ |
|||
public int ScreenCount => 1; |
|||
public Screen[] AllScreens => new Screen[] { new Screen(Rect.Empty, Rect.Empty, true) }; |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace Avalonia.Windowing.Bindings |
|||
{ |
|||
public class WindowWrapper : IWindowWrapper |
|||
{ |
|||
[DllImport("winit_wrapper")] |
|||
private static extern IntPtr winit_window_new(IntPtr eventsLoopHandle); |
|||
|
|||
[DllImport("winit_wrapper")] |
|||
private static extern IntPtr winit_window_destroy(IntPtr handle); |
|||
|
|||
private IntPtr _handle; |
|||
public WindowWrapper(EventsLoop eventsLoop) |
|||
{ |
|||
_handle = winit_window_new(eventsLoop.Handle); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
winit_window_destroy(_handle); |
|||
} |
|||
|
|||
public void SetTitle(string title) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System; |
|||
using System.IO; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Windowing |
|||
{ |
|||
public class WindowIcon : IWindowIconImpl |
|||
{ |
|||
public void Save(Stream outputStream) |
|||
{ |
|||
} |
|||
} |
|||
|
|||
public class IconLoader : IPlatformIconLoader |
|||
{ |
|||
public IconLoader() |
|||
{ |
|||
} |
|||
|
|||
public IWindowIconImpl LoadIcon(string fileName) |
|||
{ |
|||
return new WindowIcon(); |
|||
} |
|||
|
|||
public IWindowIconImpl LoadIcon(Stream stream) |
|||
{ |
|||
return new WindowIcon(); |
|||
} |
|||
|
|||
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) |
|||
{ |
|||
return new WindowIcon(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
using System; |
|||
using System.Reactive.Disposables; |
|||
using System.Runtime.InteropServices; |
|||
using System.Threading; |
|||
using Avalonia.Input; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Threading; |
|||
using Avalonia.Windowing.Bindings; |
|||
|
|||
namespace Avalonia.Windowing |
|||
{ |
|||
// Exposing C# Enums to Rust will again prove to be a massive PITA.
|
|||
public enum WinitEventType |
|||
{ |
|||
MouseMove |
|||
} |
|||
|
|||
public struct MouseMoveData |
|||
{ |
|||
} |
|||
|
|||
public class DummyPlatformHandle : IPlatformHandle |
|||
{ |
|||
public IntPtr Handle => IntPtr.Zero; |
|||
|
|||
public string HandleDescriptor => "Dummy"; |
|||
} |
|||
|
|||
|
|||
public class CursorFactory : IStandardCursorFactory |
|||
{ |
|||
public IPlatformHandle GetCursor(StandardCursorType cursorType) |
|||
{ |
|||
return new DummyPlatformHandle(); |
|||
} |
|||
} |
|||
|
|||
public class WindowingPlatform : IPlatformThreadingInterface, IWindowingPlatform |
|||
{ |
|||
internal static WindowingPlatform Instance { get; private set; } |
|||
private readonly EventsLoop _eventsLoop; |
|||
|
|||
public WindowingPlatform() |
|||
{ |
|||
_eventsLoop = new EventsLoop(); |
|||
} |
|||
|
|||
public static void Initialize() |
|||
{ |
|||
Instance = new WindowingPlatform(); |
|||
Instance.DoInitialize(); |
|||
} |
|||
|
|||
public void DoInitialize() |
|||
{ |
|||
AvaloniaLocator.CurrentMutable |
|||
.Bind<IWindowingPlatform>().ToConstant(this) |
|||
.Bind<IPlatformIconLoader>().ToConstant(new IconLoader()) |
|||
.Bind<IStandardCursorFactory>().ToConstant(new CursorFactory()) |
|||
.Bind<IPlatformThreadingInterface>().ToConstant(this); |
|||
} |
|||
|
|||
public bool CurrentThreadIsLoopThread => true; |
|||
public event Action<DispatcherPriority?> Signaled; |
|||
|
|||
public IEmbeddableWindowImpl CreateEmbeddableWindow() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IPopupImpl CreatePopup() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public IWindowImpl CreateWindow() => new Window(new GlWindowWrapper(_eventsLoop)); |
|||
|
|||
public void RunLoop(CancellationToken cancellationToken) |
|||
{ |
|||
_eventsLoop.Run(); |
|||
} |
|||
|
|||
public void Signal(DispatcherPriority priority) |
|||
{ |
|||
_eventsLoop.Wakeup(); |
|||
} |
|||
|
|||
public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick) |
|||
{ |
|||
return Disposable.Create(() => { }); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,140 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Input; |
|||
using Avalonia.Input.Raw; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Rendering; |
|||
using Avalonia.Windowing.Bindings; |
|||
|
|||
namespace Avalonia.Windowing |
|||
{ |
|||
public class Window : IWindowImpl |
|||
{ |
|||
IWindowWrapper _windowWrapper; |
|||
|
|||
public Window(IWindowWrapper wrapper) |
|||
{ |
|||
_windowWrapper = wrapper; |
|||
} |
|||
|
|||
public WindowState WindowState { get; set; } |
|||
public Action<WindowState> WindowStateChanged { get; set; } |
|||
public Func<bool> Closing { get; set; } |
|||
public Point Position { get; set; } |
|||
public Action<Point> PositionChanged { get; set; } |
|||
public Action Deactivated { get; set; } |
|||
public Action Activated { get; set; } |
|||
|
|||
public IPlatformHandle Handle => new DummyPlatformHandle(); |
|||
|
|||
public Size MaxClientSize => Size.Empty; |
|||
|
|||
public IScreenImpl Screen => new Monitors(); |
|||
|
|||
public Size ClientSize => Size.Empty; |
|||
public double Scaling => 1.0; |
|||
|
|||
public IEnumerable<object> Surfaces => new List<object>() { this }; |
|||
|
|||
public Action<RawInputEventArgs> Input { get; set; } |
|||
public Action<Rect> Paint { get; set; } |
|||
public Action<Size> Resized { get; set; } |
|||
public Action<double> ScalingChanged { get; set; } |
|||
public Action Closed { get; set; } |
|||
|
|||
public IMouseDevice MouseDevice => throw new NotImplementedException(); |
|||
|
|||
public void Activate() |
|||
{ |
|||
} |
|||
|
|||
public void BeginMoveDrag() |
|||
{ |
|||
} |
|||
|
|||
public void BeginResizeDrag(WindowEdge edge) |
|||
{ |
|||
} |
|||
|
|||
public void CanResize(bool value) |
|||
{ |
|||
} |
|||
|
|||
public IRenderer CreateRenderer(IRenderRoot root) |
|||
{ |
|||
return new ImmediateRenderer(root); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_windowWrapper.Dispose(); |
|||
} |
|||
|
|||
public void Hide() |
|||
{ |
|||
} |
|||
|
|||
public void Invalidate(Rect rect) |
|||
{ |
|||
//Paint?.Invoke(rect);
|
|||
} |
|||
|
|||
public Point PointToClient(Point point) |
|||
{ |
|||
return point; |
|||
} |
|||
|
|||
public Point PointToScreen(Point point) |
|||
{ |
|||
return point; |
|||
} |
|||
|
|||
public void Resize(Size clientSize) |
|||
{ |
|||
// This is where we size the window accordingly..
|
|||
} |
|||
|
|||
public void SetCursor(IPlatformHandle cursor) |
|||
{ |
|||
} |
|||
|
|||
public void SetIcon(IWindowIconImpl icon) |
|||
{ |
|||
} |
|||
|
|||
public void SetInputRoot(IInputRoot inputRoot) |
|||
{ |
|||
} |
|||
|
|||
public void SetMinMaxSize(Size minSize, Size maxSize) |
|||
{ |
|||
} |
|||
|
|||
public void SetSystemDecorations(bool enabled) |
|||
{ |
|||
} |
|||
|
|||
public void SetTitle(string title) |
|||
{ |
|||
_windowWrapper.SetTitle(title); |
|||
} |
|||
|
|||
public void SetTopmost(bool value) |
|||
{ |
|||
} |
|||
|
|||
public void Show() |
|||
{ |
|||
} |
|||
|
|||
public IDisposable ShowDialog() |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
public void ShowTaskbarIcon(bool value) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia |
|||
{ |
|||
public static class WindowingPlatformExtensions |
|||
{ |
|||
public static T UseWinit<T>(this T builder, bool? useDeferredRendering = null) where T : AppBuilderBase<T>, new() |
|||
{ |
|||
// if (useDeferredRendering.HasValue)
|
|||
// MonoMac.MonoMacPlatform.UseDeferredRendering = useDeferredRendering.Value;
|
|||
return builder.UseWindowingSubsystem(Windowing.WindowingPlatform.Initialize, "Winit"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue