diff --git a/native/Avalonia.Native/src/OSX/StorageProvider.mm b/native/Avalonia.Native/src/OSX/StorageProvider.mm index 570281fdfd..e0a471a4f3 100644 --- a/native/Avalonia.Native/src/OSX/StorageProvider.mm +++ b/native/Avalonia.Native/src/OSX/StorageProvider.mm @@ -148,8 +148,23 @@ public: [fileUri stopAccessingSecurityScopedResource]; } } + + static NSWindow* GetEffectiveNSWindow(IAvnTopLevel* topLevel) + { + auto windowHolder = dynamic_cast(topLevel); + if (windowHolder != nullptr) + return windowHolder->GetNSWindow(); + + auto viewHolder = dynamic_cast(topLevel); + if (viewHolder != nullptr) { + auto view = (NSView*)viewHolder->GetNSView(); + return [view window]; + } + + return nullptr; + } - virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle, + virtual void SelectFolderDialog (IAvnTopLevel* parentTopLevel, IAvnSystemDialogEvents* events, bool allowMultiple, const char* title, @@ -176,6 +191,8 @@ public: panel.directoryURL = [NSURL URLWithString:directoryString]; } + auto parentWindow = GetEffectiveNSWindow(parentTopLevel); + auto handler = ^(NSModalResponse result) { if(result == NSFileHandlingPanelOKButton) { @@ -188,10 +205,9 @@ public: [panel orderOut:panel]; - if(parentWindowHandle != nullptr) + if (parentWindow != nullptr) { - auto windowHolder = dynamic_cast(parentWindowHandle); - [windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()]; + [parentWindow makeKeyAndOrderFront:parentWindow]; } return; @@ -202,11 +218,9 @@ public: }; - if(parentWindowHandle != nullptr) + if (parentWindow != nullptr) { - auto windowBase = dynamic_cast(parentWindowHandle); - - [panel beginSheetModalForWindow:windowBase->GetNSWindow() completionHandler:handler]; + [panel beginSheetModalForWindow:parentWindow completionHandler:handler]; } else { @@ -215,7 +229,7 @@ public: } } - virtual void OpenFileDialog (IAvnWindow* parentWindowHandle, + virtual void OpenFileDialog (IAvnTopLevel* parentTopLevel, IAvnSystemDialogEvents* events, bool allowMultiple, const char* title, @@ -249,6 +263,8 @@ public: panel.directoryURL = [NSURL URLWithString:directoryString]; } + auto parentWindow = GetEffectiveNSWindow(parentTopLevel); + auto handler = ^(NSModalResponse result) { if(result == NSFileHandlingPanelOKButton) { @@ -261,10 +277,9 @@ public: [panel orderOut:panel]; - if(parentWindowHandle != nullptr) + if (parentWindow != nullptr) { - auto windowHolder = dynamic_cast(parentWindowHandle); - [windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()]; + [parentWindow makeKeyAndOrderFront:parentWindow]; } return; @@ -275,11 +290,9 @@ public: }; - if(parentWindowHandle != nullptr) + if (parentWindow != nullptr) { - auto windowHolder = dynamic_cast(parentWindowHandle); - - [panel beginSheetModalForWindow:windowHolder->GetNSWindow() completionHandler:handler]; + [panel beginSheetModalForWindow:parentWindow completionHandler:handler]; } else { @@ -288,7 +301,7 @@ public: } } - virtual void SaveFileDialog (IAvnWindow* parentWindowHandle, + virtual void SaveFileDialog (IAvnTopLevel* parentTopLevel, IAvnSystemDialogEvents* events, const char* title, const char* initialDirectory, @@ -319,6 +332,8 @@ public: panel.directoryURL = [NSURL URLWithString:directoryString]; } + auto parentWindow = GetEffectiveNSWindow(parentTopLevel); + auto handler = ^(NSModalResponse result) { int selectedIndex = -1; if (panel.accessoryView != nil) @@ -339,10 +354,9 @@ public: [panel orderOut:panel]; - if(parentWindowHandle != nullptr) + if (parentWindow != nullptr) { - auto windowHolder = dynamic_cast(parentWindowHandle); - [windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()]; + [parentWindow makeKeyAndOrderFront:parentWindow]; } return; @@ -352,11 +366,9 @@ public: }; - if(parentWindowHandle != nullptr) + if (parentWindow != nullptr) { - auto windowBase = dynamic_cast(parentWindowHandle); - - [panel beginSheetModalForWindow:windowBase->GetNSWindow() completionHandler:handler]; + [panel beginSheetModalForWindow:parentWindow completionHandler:handler]; } else { diff --git a/src/Avalonia.Native/StorageProviderApi.cs b/src/Avalonia.Native/StorageProviderApi.cs index 819623c0da..1a8fc12de4 100644 --- a/src/Avalonia.Native/StorageProviderApi.cs +++ b/src/Avalonia.Native/StorageProviderApi.cs @@ -158,7 +158,7 @@ internal class StorageProviderApi(IAvnStorageProvider native, bool sandboxEnable var (items, _) = await OpenDialogAsync(events => { - _native.OpenFileDialog((IAvnWindow?)topLevel?.Native, + _native.OpenFileDialog(topLevel?.Native, events, options.AllowMultiple.AsComBool(), options.Title ?? string.Empty, @@ -177,7 +177,7 @@ internal class StorageProviderApi(IAvnStorageProvider native, bool sandboxEnable var (items, selectedFilterIndex) = await OpenDialogAsync(events => { - _native.SaveFileDialog((IAvnWindow?)topLevel?.Native, + _native.SaveFileDialog(topLevel?.Native, events, options.Title ?? string.Empty, suggestedDirectory, @@ -201,7 +201,7 @@ internal class StorageProviderApi(IAvnStorageProvider native, bool sandboxEnable var (items, _) = await OpenDialogAsync(events => { - _native.SelectFolderDialog((IAvnWindow?)topLevel?.Native, + _native.SelectFolderDialog(topLevel?.Native, events, options.AllowMultiple.AsComBool(), options.Title ?? "", diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl index a224eeea45..6a3781ed89 100644 --- a/src/Avalonia.Native/avn.idl +++ b/src/Avalonia.Native/avn.idl @@ -938,13 +938,13 @@ interface IAvnSystemDialogEvents : IUnknown [uuid(4d7a47db-a944-4061-abe7-62cb6aa0ffd5)] interface IAvnStorageProvider : IUnknown { - void SelectFolderDialog(IAvnWindow* parentWindowHandle, + void SelectFolderDialog(IAvnTopLevel* parentTopLevel, IAvnSystemDialogEvents* events, bool allowMultiple, [const] char* title, [const] char* initialPath); - void OpenFileDialog(IAvnWindow* parentWindowHandle, + void OpenFileDialog(IAvnTopLevel* parentTopLevel, IAvnSystemDialogEvents* events, bool allowMultiple, [const] char* title, @@ -952,7 +952,7 @@ interface IAvnStorageProvider : IUnknown [const] char* initialFile, IAvnFilePickerFileTypes* filters); - void SaveFileDialog(IAvnWindow* parentWindowHandle, + void SaveFileDialog(IAvnTopLevel* parentTopLevel, IAvnSystemDialogEvents* events, [const] char* title, [const] char* initialDirectory,