Browse Source

Fix segfault on Linux related to EventsLoopProxy. Implement OS window button close

thread-issue-repro
Nelson Carrillo 8 years ago
parent
commit
036cebb80d
  1. 2
      src/Avalonia.Windowing/Bindings/EventNotifier.cs
  2. 14
      src/Avalonia.Windowing/Bindings/EventsLoop.cs
  3. 17
      src/Avalonia.Windowing/WIndowingPlatform.cs
  4. 10
      src/Avalonia.Windowing/WindowImpl.cs

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

@ -10,6 +10,7 @@ namespace Avalonia.Windowing.Bindings
public delegate void CharacterEventCallback(WindowId windowId, CharacterEvent characterEvent);
public delegate void AwakenedEventCallback();
public delegate byte ShouldExitEventLoopCallback(WindowId windowId);
public delegate void CloseRequestedCallback(WindowId windowId);
[StructLayout(LayoutKind.Sequential)]
public struct EventNotifier
@ -20,5 +21,6 @@ namespace Avalonia.Windowing.Bindings
public KeyboardEventCallback OnKeyboardEvent;
public CharacterEventCallback OnCharacterEvent;
public ShouldExitEventLoopCallback OnShouldExitEventLoop;
public CloseRequestedCallback OnCloseRequested;
}
}

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

@ -6,7 +6,10 @@ namespace Avalonia.Windowing.Bindings
public class EventsLoop : IDisposable
{
[DllImport("winit_wrapper")]
private static extern IntPtr winit_events_loop_new(out IntPtr eventsLoopProxyHandle);
private static extern IntPtr winit_events_loop_new();
[DllImport("winit_wrapper")]
private static extern IntPtr winit_events_loop_proxy_new(IntPtr eventsLoopHandle);
[DllImport("winit_wrapper")]
private static extern void winit_events_loop_destroy(IntPtr handle);
@ -19,6 +22,7 @@ namespace Avalonia.Windowing.Bindings
);
public IntPtr Handle { get; private set; }
private readonly EventsLoopProxy _eventsLoopProxy;
private readonly EventNotifier _notifier;
@ -28,11 +32,12 @@ namespace Avalonia.Windowing.Bindings
public event AwakenedEventCallback OnAwakened;
public event ResizeEventCallback OnResized;
public event ShouldExitEventLoopCallback OnShouldExitEventLoop;
public event CloseRequestedCallback OnCloseRequested;
public EventsLoop()
{
Handle = winit_events_loop_new(out var elpHandle);
_eventsLoopProxy = new EventsLoopProxy(elpHandle);
Handle = winit_events_loop_new();
_eventsLoopProxy = new EventsLoopProxy(winit_events_loop_proxy_new(Handle));
_notifier = new EventNotifier()
{
OnMouseEvent = (windowId, mouseEvent) => OnMouseEvent?.Invoke(windowId, mouseEvent),
@ -40,7 +45,8 @@ namespace Avalonia.Windowing.Bindings
OnCharacterEvent = (windowId, characterEvent) => OnCharacterEvent?.Invoke(windowId, characterEvent),
OnResized = (windowId, resizeEvent) => OnResized?.Invoke(windowId, resizeEvent),
OnAwakened = () => OnAwakened?.Invoke(),
OnShouldExitEventLoop = (windowId) => (byte)OnShouldExitEventLoop?.Invoke(windowId)
OnShouldExitEventLoop = (windowId) => (byte)OnShouldExitEventLoop?.Invoke(windowId),
OnCloseRequested = (windowId) => OnCloseRequested?.Invoke(windowId)
};
}

17
src/Avalonia.Windowing/WIndowingPlatform.cs

@ -44,14 +44,29 @@ namespace Avalonia.Windowing
_eventsLoop.OnAwakened += _eventsLoop_Awakened;
_eventsLoop.OnResized += _eventsLoop_Resized;
_eventsLoop.OnShouldExitEventLoop += _eventsLoop_OnShouldExitEventLoop;
_eventsLoop.OnCloseRequested += _eventsLoop_OnCloseRequested;
_windows = new Dictionary<WindowId, WindowImpl>();
}
void _eventsLoop_OnCloseRequested(WindowId windowId)
{
if (_windows.ContainsKey(windowId))
{
if (!_windows[windowId].OnCloseRequested())
{
_windows[windowId].Dispose();
}
}
}
byte _eventsLoop_OnShouldExitEventLoop(WindowId windowId)
{
if (_windows.ContainsKey(windowId))
{
_windows[windowId].OnClosed();
_windows.Remove(windowId);
}
return _windows.Any() ? (byte)0 : (byte)1;
}

10
src/Avalonia.Windowing/WindowImpl.cs

@ -319,5 +319,15 @@ namespace Avalonia.Windowing
gpuCtx.ResizeContext(ClientSize.Width, ClientSize.Height);
}
}
public void OnClosed()
{
Closed?.Invoke();
}
public bool OnCloseRequested()
{
return (bool)Closing?.Invoke();
}
}
}
Loading…
Cancel
Save