Browse Source

Add MakeCurrent to IGpuContext. Add support for Focused events. Improve Popup support.

thread-issue-repro
Nelson Carrillo 8 years ago
parent
commit
1cc237e971
  1. 1
      src/Avalonia.Gpu/IGpuContext.cs
  2. 2
      src/Avalonia.Windowing/Bindings/EventNotifier.cs
  3. 4
      src/Avalonia.Windowing/Bindings/EventsLoop.cs
  4. 8
      src/Avalonia.Windowing/Bindings/GlWindow.cs
  5. 44
      src/Avalonia.Windowing/WindowImpl.cs
  6. 85
      src/Avalonia.Windowing/WindowResizeDragHelper.cs
  7. 13
      src/Avalonia.Windowing/WindowingPlatform.cs
  8. 3
      src/Skia/Avalonia.Skia/GlRenderTarget.cs

1
src/Avalonia.Gpu/IGpuContext.cs

@ -8,6 +8,7 @@ namespace Avalonia.Gpu
IntPtr GetProcAddress(string symbol); IntPtr GetProcAddress(string symbol);
(double, double) GetFramebufferSize(); (double, double) GetFramebufferSize();
void ResizeContext(double width, double height); void ResizeContext(double width, double height);
void MakeCurrent();
(double, double) GetDpi(); (double, double) GetDpi();
} }
} }

2
src/Avalonia.Windowing/Bindings/EventNotifier.cs

@ -11,6 +11,7 @@ namespace Avalonia.Windowing.Bindings
public delegate void AwakenedEventCallback(); public delegate void AwakenedEventCallback();
public delegate byte ShouldExitEventLoopCallback(WindowId windowId); public delegate byte ShouldExitEventLoopCallback(WindowId windowId);
public delegate void CloseRequestedCallback(WindowId windowId); public delegate void CloseRequestedCallback(WindowId windowId);
public delegate void FocusedCallback(WindowId windowId, byte focused);
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct EventNotifier public struct EventNotifier
@ -22,5 +23,6 @@ namespace Avalonia.Windowing.Bindings
public CharacterEventCallback OnCharacterEvent; public CharacterEventCallback OnCharacterEvent;
public ShouldExitEventLoopCallback OnShouldExitEventLoop; public ShouldExitEventLoopCallback OnShouldExitEventLoop;
public CloseRequestedCallback OnCloseRequested; public CloseRequestedCallback OnCloseRequested;
public FocusedCallback OnFocused;
} }
} }

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

@ -33,6 +33,7 @@ namespace Avalonia.Windowing.Bindings
public event ResizeEventCallback OnResized; public event ResizeEventCallback OnResized;
public event ShouldExitEventLoopCallback OnShouldExitEventLoop; public event ShouldExitEventLoopCallback OnShouldExitEventLoop;
public event CloseRequestedCallback OnCloseRequested; public event CloseRequestedCallback OnCloseRequested;
public event FocusedCallback OnFocused;
public EventsLoop() public EventsLoop()
{ {
@ -46,7 +47,8 @@ namespace Avalonia.Windowing.Bindings
OnResized = (windowId, resizeEvent) => OnResized?.Invoke(windowId, resizeEvent), OnResized = (windowId, resizeEvent) => OnResized?.Invoke(windowId, resizeEvent),
OnAwakened = () => OnAwakened?.Invoke(), OnAwakened = () => OnAwakened?.Invoke(),
OnShouldExitEventLoop = (windowId) => (byte)OnShouldExitEventLoop?.Invoke(windowId), OnShouldExitEventLoop = (windowId) => (byte)OnShouldExitEventLoop?.Invoke(windowId),
OnCloseRequested = (windowId) => OnCloseRequested?.Invoke(windowId) OnCloseRequested = (windowId) => OnCloseRequested?.Invoke(windowId),
OnFocused = (windowId, focused) => OnFocused?.Invoke(windowId, focused)
}; };
} }

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

@ -43,6 +43,9 @@ namespace Avalonia.Windowing.Bindings
[DllImport("winit_wrapper")] [DllImport("winit_wrapper")]
private static extern void winit_gl_window_present(IntPtr handle); private static extern void winit_gl_window_present(IntPtr handle);
[DllImport("winit_wrapper")]
private static extern void winit_gl_window_make_current(IntPtr handle);
[DllImport("winit_wrapper")] [DllImport("winit_wrapper")]
private static extern void winit_gl_window_show(IntPtr handle); private static extern void winit_gl_window_show(IntPtr handle);
@ -165,5 +168,10 @@ namespace Avalonia.Windowing.Bindings
var scaleFactor = GetScaleFactor(); var scaleFactor = GetScaleFactor();
return (scaleFactor, scaleFactor); return (scaleFactor, scaleFactor);
} }
public void MakeCurrent()
{
winit_gl_window_make_current(_handle);
}
} }
} }

44
src/Avalonia.Windowing/WindowImpl.cs

@ -18,14 +18,16 @@ namespace Avalonia.Windowing
{ {
public class WindowImpl : IWindowImpl public class WindowImpl : IWindowImpl
{ {
IWindowWrapper _windowWrapper; private readonly IWindowWrapper _windowWrapper;
private LogicalPosition _lastPosition; private readonly ManagedWindowResizeDragHelper _managedDrag;
const int FramesPerSecond = 60; private LogicalPosition _lastPosition;
private const int FramesPerSecond = 60;
public WindowImpl(IWindowWrapper wrapper) public WindowImpl(IWindowWrapper wrapper)
{ {
_windowWrapper = wrapper; _windowWrapper = wrapper;
_managedDrag = new ManagedWindowResizeDragHelper(this, _ => { }, ResizeForManagedDrag);
// TODO: This is only necessary when using ImmediateRenderer // TODO: This is only necessary when using ImmediateRenderer
Observable.Repeat(Observable.Timer(TimeSpan.FromMilliseconds(1000 / FramesPerSecond))) Observable.Repeat(Observable.Timer(TimeSpan.FromMilliseconds(1000 / FramesPerSecond)))
@ -43,6 +45,12 @@ namespace Avalonia.Windowing
}); });
} }
private void ResizeForManagedDrag(Rect obj)
{
//this._windowWrapper.SetPosition(obj.X, obj.Y);
// this._windowWrapper.SetSize(obj.Width, obj.Height);
}
public WindowState WindowState { get; set; } public WindowState WindowState { get; set; }
public Action<WindowState> WindowStateChanged { get; set; } public Action<WindowState> WindowStateChanged { get; set; }
public Func<bool> Closing { get; set; } public Func<bool> Closing { get; set; }
@ -198,7 +206,7 @@ namespace Avalonia.Windowing
if (evt.Character >= 32) if (evt.Character >= 32)
{ {
Input OnInput
( (
new RawTextInputEventArgs new RawTextInputEventArgs
( (
@ -242,7 +250,7 @@ namespace Avalonia.Windowing
if (keyCode.HasValue) if (keyCode.HasValue)
{ {
Input OnInput
( (
new RawKeyEventArgs new RawKeyEventArgs
( (
@ -256,6 +264,14 @@ namespace Avalonia.Windowing
} }
} }
public void OnInput(RawInputEventArgs args)
{
if (_managedDrag.PreprocessInputEvent(ref args))
return;
Input?.Invoke(args);
}
public void OnMouseEvent(MouseEvent evt) public void OnMouseEvent(MouseEvent evt)
{ {
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
@ -287,7 +303,7 @@ namespace Avalonia.Windowing
modifiers |= InputModifiers.Windows; modifiers |= InputModifiers.Windows;
} }
Input OnInput
( (
eventType != RawMouseEventType.Wheel ? eventType != RawMouseEventType.Wheel ?
new RawMouseEventArgs new RawMouseEventArgs
@ -315,9 +331,9 @@ namespace Avalonia.Windowing
public void OnResizeEvent(ResizeEvent evt) public void OnResizeEvent(ResizeEvent evt)
{ {
Resized?.Invoke(ClientSize); Resized?.Invoke(ClientSize);
if (_windowWrapper is IGpuContext gpuCtx) {
gpuCtx.ResizeContext(ClientSize.Width, ClientSize.Height); // TODO: There's a bug in winit where OSX resizing blocks the event loop, to work around this, paint while resizing.
} Paint?.Invoke(new Rect(ClientSize));
} }
public void OnClosed() public void OnClosed()
@ -327,7 +343,15 @@ namespace Avalonia.Windowing
public bool OnCloseRequested() public bool OnCloseRequested()
{ {
return (bool)Closing?.Invoke(); return Closing?.Invoke() ?? false;
}
public void OnFocused(bool focused)
{
if (focused)
Activated?.Invoke();
else
Deactivated?.Invoke();
} }
} }
} }

85
src/Avalonia.Windowing/WindowResizeDragHelper.cs

@ -0,0 +1,85 @@
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
namespace Avalonia
{
internal class ManagedWindowResizeDragHelper
{
private readonly IWindowBaseImpl _window;
private readonly Action<bool> _captureMouse;
private readonly Action<Rect> _resize;
private WindowEdge? _edge;
private Point _prevPoint;
public ManagedWindowResizeDragHelper(IWindowBaseImpl window, Action<bool> captureMouse, Action<Rect> resize = null)
{
_window = window;
_captureMouse = captureMouse;
_resize = resize;
}
public void BeginResizeDrag(WindowEdge edge, Point currentMousePosition)
{
_captureMouse(true);
_prevPoint = currentMousePosition;
_edge = edge;
}
public bool PreprocessInputEvent(ref RawInputEventArgs e)
{
if (_edge == null)
return false;
if (e is RawMouseEventArgs args)
{
if (args.Type == RawMouseEventType.LeftButtonUp)
{
_edge = null;
_captureMouse(false);
}
if (args.Type == RawMouseEventType.Move)
{
MoveWindow(args.Position);
return true;
}
_edge = null;
}
return false;
}
private void MoveWindow(Point position)
{
var diff = position - _prevPoint;
var edge = _edge.Value;
var rc = new Rect(_window.Position, _window.ClientSize);
if (edge == WindowEdge.East || edge == WindowEdge.NorthEast || edge == WindowEdge.SouthEast)
{
rc = rc.WithWidth(rc.Width + diff.X);
_prevPoint = _prevPoint.WithX(position.X);
}
if (edge == WindowEdge.West || edge == WindowEdge.NorthWest || edge == WindowEdge.SouthWest)
rc = rc.WithX(rc.X + diff.X).WithWidth(rc.Width - diff.X);
if (edge == WindowEdge.South || edge == WindowEdge.SouthWest || edge == WindowEdge.SouthEast)
{
rc = rc.WithHeight(rc.Height + diff.Y);
_prevPoint = _prevPoint.WithY(position.Y);
}
if (edge == WindowEdge.North || edge == WindowEdge.NorthWest || edge == WindowEdge.NorthEast)
rc = rc.WithY(rc.Y + diff.Y).WithHeight(rc.Height - diff.Y);
if (_resize != null)
_resize(rc);
else
{
if (_window.Position != rc.Position)
_window.Position = rc.Position;
if (_window.ClientSize != rc.Size)
_window.Resize(rc.Size);
}
}
}
}

13
src/Avalonia.Windowing/WIndowingPlatform.cs → src/Avalonia.Windowing/WindowingPlatform.cs

@ -45,7 +45,7 @@ namespace Avalonia.Windowing
_eventsLoop.OnResized += _eventsLoop_Resized; _eventsLoop.OnResized += _eventsLoop_Resized;
_eventsLoop.OnShouldExitEventLoop += _eventsLoop_OnShouldExitEventLoop; _eventsLoop.OnShouldExitEventLoop += _eventsLoop_OnShouldExitEventLoop;
_eventsLoop.OnCloseRequested += _eventsLoop_OnCloseRequested; _eventsLoop.OnCloseRequested += _eventsLoop_OnCloseRequested;
_eventsLoop.OnFocused += _eventsLoop_OnFocused;
_windows = new Dictionary<WindowId, WindowImpl>(); _windows = new Dictionary<WindowId, WindowImpl>();
} }
@ -67,9 +67,19 @@ namespace Avalonia.Windowing
_windows[windowId].OnClosed(); _windows[windowId].OnClosed();
_windows.Remove(windowId); _windows.Remove(windowId);
} }
return _windows.Any() ? (byte)0 : (byte)1; return _windows.Any() ? (byte)0 : (byte)1;
} }
void _eventsLoop_OnFocused(WindowId windowId, byte focused)
{
if (_windows.ContainsKey(windowId))
{
_windows[windowId].OnFocused(focused == 0 ? true : false);
}
}
void _eventsLoop_Resized(WindowId windowId, ResizeEvent resizeEvent) void _eventsLoop_Resized(WindowId windowId, ResizeEvent resizeEvent)
{ {
Dispatcher.UIThread.RunJobs(DispatcherPriority.Layout); Dispatcher.UIThread.RunJobs(DispatcherPriority.Layout);
@ -169,6 +179,7 @@ namespace Avalonia.Windowing
public void RunLoop(CancellationToken cancellationToken) public void RunLoop(CancellationToken cancellationToken)
{ {
// TODO: Support canceling the EventLoop here.
_eventsLoop.Run(); _eventsLoop.Run();
} }

3
src/Skia/Avalonia.Skia/GlRenderTarget.cs

@ -10,7 +10,7 @@ namespace Avalonia.Skia
{ {
public class GlRenderTarget : IRenderTarget public class GlRenderTarget : IRenderTarget
{ {
private readonly GRContext _grContext; private GRContext _grContext;
private readonly IGpuContext _context; private readonly IGpuContext _context;
public GlRenderTarget(IGpuContext context) public GlRenderTarget(IGpuContext context)
@ -71,6 +71,7 @@ namespace Avalonia.Skia
return new DrawingContextImpl(createInfo, Disposable.Create(() => return new DrawingContextImpl(createInfo, Disposable.Create(() =>
{ {
_context.MakeCurrent();
_grContext.Flush(); _grContext.Flush();
_context.Present(); _context.Present();
})); }));

Loading…
Cancel
Save