Browse Source

WIP: Initial commit of winit support

repro-window-close
Nelson Carrillo 8 years ago
parent
commit
6f4b3e1b65
  1. 18
      src/Avalonia.Windowing/Avalonia.Windowing.csproj
  2. 66
      src/Avalonia.Windowing/Bindings/EventsLoop.cs
  3. 37
      src/Avalonia.Windowing/Bindings/GlWindow.cs
  4. 11
      src/Avalonia.Windowing/Bindings/IWindowWrapper.cs
  5. 11
      src/Avalonia.Windowing/Bindings/Monitors.cs
  6. 30
      src/Avalonia.Windowing/Bindings/Window.cs
  7. 35
      src/Avalonia.Windowing/IconLoader.cs
  8. 93
      src/Avalonia.Windowing/WIndowingPlatform.cs
  9. 140
      src/Avalonia.Windowing/WindowImpl.cs
  10. 15
      src/Avalonia.Windowing/WindowingPlatformExtensions.cs

18
src/Avalonia.Windowing/Avalonia.Windowing.csproj

@ -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>

66
src/Avalonia.Windowing/Bindings/EventsLoop.cs

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

37
src/Avalonia.Windowing/Bindings/GlWindow.cs

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

11
src/Avalonia.Windowing/Bindings/IWindowWrapper.cs

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

11
src/Avalonia.Windowing/Bindings/Monitors.cs

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

30
src/Avalonia.Windowing/Bindings/Window.cs

@ -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)
{
}
}
}

35
src/Avalonia.Windowing/IconLoader.cs

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

93
src/Avalonia.Windowing/WIndowingPlatform.cs

@ -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(() => { });
}
}
}

140
src/Avalonia.Windowing/WindowImpl.cs

@ -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)
{
}
}
}

15
src/Avalonia.Windowing/WindowingPlatformExtensions.cs

@ -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…
Cancel
Save