From 5aa219be00c9776b7462114b16932319cee0dcd9 Mon Sep 17 00:00:00 2001 From: WojciechKrysiak Date: Mon, 13 Aug 2018 07:23:04 +0200 Subject: [PATCH] Fix windows for Mono.Mac (#1804) - handle closing - handle showing dialogs --- src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs | 25 +++++++--- src/OSX/Avalonia.MonoMac/WindowImpl.cs | 58 +++++++++++++++------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs b/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs index 89cef59b53..e7d82ae25e 100644 --- a/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs +++ b/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs @@ -14,6 +14,8 @@ namespace Avalonia.MonoMac private readonly ManagedWindowResizeDragHelper _managedDrag; public CustomWindow Window { get; private set; } + private bool _closed; + public WindowBaseImpl() { _managedDrag = new ManagedWindowResizeDragHelper(this, _ => { }, ResizeForManagedDrag); @@ -78,9 +80,8 @@ namespace Avalonia.MonoMac public override void WillClose(global::MonoMac.Foundation.NSNotification notification) { - _impl.Window.Dispose(); - _impl.Window = null; - _impl.Dispose(); + _impl._closed = true; + _impl.Closed?.Invoke(); } public override CGRect WillUseStandardFrame(NSWindow window, CGRect newFrame) @@ -94,8 +95,19 @@ namespace Avalonia.MonoMac { return true; } + + public override void DidResize(NSNotification notification) + { + _impl.OnResized(); + } } + /// + /// As you can't combine NSWindowDelegate overrides and events this is a workaround + /// + protected virtual void OnResized() + { + } public Point Position { @@ -185,12 +197,11 @@ namespace Avalonia.MonoMac return cocoaScreenPoint.ConvertPointY().ToAvaloniaPoint(); } - - public override void Dispose() { - Window?.Close(); - Window?.Dispose(); + if (!_closed) + Window.Close(); + Window.Dispose(); base.Dispose(); } } diff --git a/src/OSX/Avalonia.MonoMac/WindowImpl.cs b/src/OSX/Avalonia.MonoMac/WindowImpl.cs index 3900af8709..89b5550688 100644 --- a/src/OSX/Avalonia.MonoMac/WindowImpl.cs +++ b/src/OSX/Avalonia.MonoMac/WindowImpl.cs @@ -26,18 +26,19 @@ namespace Avalonia.MonoMac }); Window.SetCanBecomeKeyAndMain(); - - Window.DidResize += delegate - { - var windowState = Window.IsMiniaturized ? WindowState.Minimized - : (IsZoomed ? WindowState.Maximized : WindowState.Normal); + } - if (windowState != _lastWindowState) - { - _lastWindowState = windowState; - WindowStateChanged?.Invoke(windowState); - } - }; + + protected override void OnResized() + { + var windowState = Window.IsMiniaturized ? WindowState.Minimized + : (IsZoomed ? WindowState.Maximized : WindowState.Normal); + + if (windowState != _lastWindowState) + { + _lastWindowState = windowState; + WindowStateChanged?.Invoke(windowState); + } } public WindowState WindowState @@ -129,24 +130,47 @@ namespace Avalonia.MonoMac class ModalDisposable : IDisposable { readonly WindowImpl _impl; + readonly IntPtr _modalSession; + bool disposed; - public ModalDisposable(WindowImpl impl) + public ModalDisposable(WindowImpl impl, IntPtr modalSession) { _impl = impl; + _modalSession = modalSession; + } + + public void Continue() + { + if (disposed) + return; + + var response = (NSRunResponse)NSApplication.SharedApplication.RunModalSession(_modalSession); + if (response == NSRunResponse.Continues) + { + Dispatcher.UIThread.Post(Continue, DispatcherPriority.ContextIdle); + } + else + { + Logging.Logger.Log(Logging.LogEventLevel.Debug, "MonoMac", this, "Modal session ended"); + } } public void Dispose() { + Logging.Logger.Log(Logging.LogEventLevel.Debug, "MonoMac", this, "ModalDisposable disposed"); _impl.Window.OrderOut(_impl.Window); + NSApplication.SharedApplication.EndModalSession(_modalSession); + disposed = true; } } public IDisposable ShowDialog() { - //TODO: Investigate how to return immediately. - // May be add some magic to our run loop or something - NSApplication.SharedApplication.RunModalForWindow(Window); - return new ModalDisposable(this); + var session = NSApplication.SharedApplication.BeginModalSession(Window); + var disposable = new ModalDisposable(this, session); + Dispatcher.UIThread.Post(disposable.Continue, DispatcherPriority.ContextIdle); + + return disposable; } } -} \ No newline at end of file +}