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 CharacterEventCallback(WindowId windowId, CharacterEvent characterEvent);
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);
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct EventNotifier public struct EventNotifier
@ -20,5 +21,6 @@ namespace Avalonia.Windowing.Bindings
public KeyboardEventCallback OnKeyboardEvent; public KeyboardEventCallback OnKeyboardEvent;
public CharacterEventCallback OnCharacterEvent; public CharacterEventCallback OnCharacterEvent;
public ShouldExitEventLoopCallback OnShouldExitEventLoop; 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 public class EventsLoop : IDisposable
{ {
[DllImport("winit_wrapper")] [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")] [DllImport("winit_wrapper")]
private static extern void winit_events_loop_destroy(IntPtr handle); private static extern void winit_events_loop_destroy(IntPtr handle);
@ -19,6 +22,7 @@ namespace Avalonia.Windowing.Bindings
); );
public IntPtr Handle { get; private set; } public IntPtr Handle { get; private set; }
private readonly EventsLoopProxy _eventsLoopProxy; private readonly EventsLoopProxy _eventsLoopProxy;
private readonly EventNotifier _notifier; private readonly EventNotifier _notifier;
@ -28,11 +32,12 @@ namespace Avalonia.Windowing.Bindings
public event AwakenedEventCallback OnAwakened; public event AwakenedEventCallback OnAwakened;
public event ResizeEventCallback OnResized; public event ResizeEventCallback OnResized;
public event ShouldExitEventLoopCallback OnShouldExitEventLoop; public event ShouldExitEventLoopCallback OnShouldExitEventLoop;
public event CloseRequestedCallback OnCloseRequested;
public EventsLoop() public EventsLoop()
{ {
Handle = winit_events_loop_new(out var elpHandle); Handle = winit_events_loop_new();
_eventsLoopProxy = new EventsLoopProxy(elpHandle); _eventsLoopProxy = new EventsLoopProxy(winit_events_loop_proxy_new(Handle));
_notifier = new EventNotifier() _notifier = new EventNotifier()
{ {
OnMouseEvent = (windowId, mouseEvent) => OnMouseEvent?.Invoke(windowId, mouseEvent), OnMouseEvent = (windowId, mouseEvent) => OnMouseEvent?.Invoke(windowId, mouseEvent),
@ -40,7 +45,8 @@ namespace Avalonia.Windowing.Bindings
OnCharacterEvent = (windowId, characterEvent) => OnCharacterEvent?.Invoke(windowId, characterEvent), OnCharacterEvent = (windowId, characterEvent) => OnCharacterEvent?.Invoke(windowId, characterEvent),
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)
}; };
} }

17
src/Avalonia.Windowing/WIndowingPlatform.cs

@ -44,14 +44,29 @@ namespace Avalonia.Windowing
_eventsLoop.OnAwakened += _eventsLoop_Awakened; _eventsLoop.OnAwakened += _eventsLoop_Awakened;
_eventsLoop.OnResized += _eventsLoop_Resized; _eventsLoop.OnResized += _eventsLoop_Resized;
_eventsLoop.OnShouldExitEventLoop += _eventsLoop_OnShouldExitEventLoop; _eventsLoop.OnShouldExitEventLoop += _eventsLoop_OnShouldExitEventLoop;
_eventsLoop.OnCloseRequested += _eventsLoop_OnCloseRequested;
_windows = new Dictionary<WindowId, WindowImpl>(); _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) byte _eventsLoop_OnShouldExitEventLoop(WindowId windowId)
{ {
if (_windows.ContainsKey(windowId)) if (_windows.ContainsKey(windowId))
{
_windows[windowId].OnClosed();
_windows.Remove(windowId); _windows.Remove(windowId);
}
return _windows.Any() ? (byte)0 : (byte)1; 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); gpuCtx.ResizeContext(ClientSize.Width, ClientSize.Height);
} }
} }
public void OnClosed()
{
Closed?.Invoke();
}
public bool OnCloseRequested()
{
return (bool)Closing?.Invoke();
}
} }
} }
Loading…
Cancel
Save