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);
(double, double) GetFramebufferSize();
void ResizeContext(double width, double height);
void MakeCurrent();
(double, double) GetDpi();
}
}

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

@ -11,6 +11,7 @@ namespace Avalonia.Windowing.Bindings
public delegate void AwakenedEventCallback();
public delegate byte ShouldExitEventLoopCallback(WindowId windowId);
public delegate void CloseRequestedCallback(WindowId windowId);
public delegate void FocusedCallback(WindowId windowId, byte focused);
[StructLayout(LayoutKind.Sequential)]
public struct EventNotifier
@ -22,5 +23,6 @@ namespace Avalonia.Windowing.Bindings
public CharacterEventCallback OnCharacterEvent;
public ShouldExitEventLoopCallback OnShouldExitEventLoop;
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 ShouldExitEventLoopCallback OnShouldExitEventLoop;
public event CloseRequestedCallback OnCloseRequested;
public event FocusedCallback OnFocused;
public EventsLoop()
{
@ -46,7 +47,8 @@ namespace Avalonia.Windowing.Bindings
OnResized = (windowId, resizeEvent) => OnResized?.Invoke(windowId, resizeEvent),
OnAwakened = () => OnAwakened?.Invoke(),
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")]
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")]
private static extern void winit_gl_window_show(IntPtr handle);
@ -165,5 +168,10 @@ namespace Avalonia.Windowing.Bindings
var scaleFactor = GetScaleFactor();
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
{
IWindowWrapper _windowWrapper;
private LogicalPosition _lastPosition;
private readonly IWindowWrapper _windowWrapper;
private readonly ManagedWindowResizeDragHelper _managedDrag;
const int FramesPerSecond = 60;
private LogicalPosition _lastPosition;
private const int FramesPerSecond = 60;
public WindowImpl(IWindowWrapper wrapper)
{
_windowWrapper = wrapper;
_managedDrag = new ManagedWindowResizeDragHelper(this, _ => { }, ResizeForManagedDrag);
// TODO: This is only necessary when using ImmediateRenderer
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 Action<WindowState> WindowStateChanged { get; set; }
public Func<bool> Closing { get; set; }
@ -198,7 +206,7 @@ namespace Avalonia.Windowing
if (evt.Character >= 32)
{
Input
OnInput
(
new RawTextInputEventArgs
(
@ -242,7 +250,7 @@ namespace Avalonia.Windowing
if (keyCode.HasValue)
{
Input
OnInput
(
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)
{
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
@ -287,7 +303,7 @@ namespace Avalonia.Windowing
modifiers |= InputModifiers.Windows;
}
Input
OnInput
(
eventType != RawMouseEventType.Wheel ?
new RawMouseEventArgs
@ -315,9 +331,9 @@ namespace Avalonia.Windowing
public void OnResizeEvent(ResizeEvent evt)
{
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()
@ -327,7 +343,15 @@ namespace Avalonia.Windowing
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.OnShouldExitEventLoop += _eventsLoop_OnShouldExitEventLoop;
_eventsLoop.OnCloseRequested += _eventsLoop_OnCloseRequested;
_eventsLoop.OnFocused += _eventsLoop_OnFocused;
_windows = new Dictionary<WindowId, WindowImpl>();
}
@ -67,9 +67,19 @@ namespace Avalonia.Windowing
_windows[windowId].OnClosed();
_windows.Remove(windowId);
}
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)
{
Dispatcher.UIThread.RunJobs(DispatcherPriority.Layout);
@ -169,6 +179,7 @@ namespace Avalonia.Windowing
public void RunLoop(CancellationToken cancellationToken)
{
// TODO: Support canceling the EventLoop here.
_eventsLoop.Run();
}

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

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

Loading…
Cancel
Save