From 624727fd4e1cc486151e2c7cd746ebe8119ca3cc Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Wed, 19 Oct 2022 16:50:55 +0200 Subject: [PATCH] Added windowType, windowAlphaValue, windowStyleMask, windowTitlebarSeparatorStyle, windowFrame for MacOS InAppBrowserSettings --- CHANGELOG.md | 1 + .../lib/src/exchangeable_enum_generator.dart | 8 +- .../ios/Flutter/flutter_export_environment.sh | 4 +- .../lib/in_app_browser_example.screen.dart | 11 +- .../macos/Runner/DebugProfile.entitlements | 4 + example/macos/Runner/Release.entitlements | 4 + .../in_app_browser_settings.dart | 46 ++- .../in_app_browser_settings.g.dart | 58 +++- .../in_app_webview_settings.g.dart | 4 + lib/src/types/main.dart | 3 + .../types/webview_render_process_action.dart | 3 - lib/src/types/window_style_mask.dart | 126 +++++++++ lib/src/types/window_style_mask.g.dart | 265 ++++++++++++++++++ .../window_titlebar_separator_style.dart | 30 ++ .../window_titlebar_separator_style.g.dart | 139 +++++++++ lib/src/types/window_type.dart | 22 ++ lib/src/types/window_type.g.dart | 95 +++++++ .../InAppBrowser/InAppBrowserManager.swift | 6 +- .../InAppBrowser/InAppBrowserSettings.swift | 55 ++++ .../InAppBrowser/InAppBrowserWindow.swift | 28 +- .../Types/InAppBrowserWindowType.swift | 13 + 21 files changed, 910 insertions(+), 15 deletions(-) create mode 100644 lib/src/types/window_style_mask.dart create mode 100644 lib/src/types/window_style_mask.g.dart create mode 100644 lib/src/types/window_titlebar_separator_style.dart create mode 100644 lib/src/types/window_titlebar_separator_style.g.dart create mode 100644 lib/src/types/window_type.dart create mode 100644 lib/src/types/window_type.g.dart create mode 100644 macos/Classes/Types/InAppBrowserWindowType.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b2b34b8..f9007b37 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 6.0.0-beta.3 - Added MacOS support +- Added `windowType`, `windowAlphaValue`, `windowStyleMask`, `windowTitlebarSeparatorStyle`, `windowFrame` for MacOS `InAppBrowserSettings` - Added `PrintJobInfo.printer` - Added `getContentWidth` WebView method diff --git a/dev_packages/generators/lib/src/exchangeable_enum_generator.dart b/dev_packages/generators/lib/src/exchangeable_enum_generator.dart index 70724983..d5632d8d 100644 --- a/dev_packages/generators/lib/src/exchangeable_enum_generator.dart +++ b/dev_packages/generators/lib/src/exchangeable_enum_generator.dart @@ -284,7 +284,13 @@ class ExchangeableEnumGenerator if (annotation.read("bitwiseOrOperator").boolValue) { classBuffer.writeln( - "$extClassName operator |($extClassName value) => $extClassName._internal(value.toValue() | _value, value.toNativeValue() | _nativeValue);"); + "$extClassName operator |($extClassName value) => $extClassName._internal(value.toValue() | _value, "); + if (Util.typeIsNullable(enumNativeValue.type)) { + classBuffer.write("value.toNativeValue() != null && _nativeValue != null ? value.toNativeValue()! | _nativeValue! : _nativeValue"); + } else { + classBuffer.write("value.toNativeValue() | _nativeValue"); + } + classBuffer.write(");"); } if (annotation.read("toStringMethod").boolValue && (!visitor.methods.containsKey("toString") || diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 03bce7c9..9e98dd5e 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -3,11 +3,11 @@ export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/2.10.4" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_TARGET=integration_test/webview_flutter_test.dart" +export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" -export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" +export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" diff --git a/example/lib/in_app_browser_example.screen.dart b/example/lib/in_app_browser_example.screen.dart index cc626d76..76da9d8d 100755 --- a/example/lib/in_app_browser_example.screen.dart +++ b/example/lib/in_app_browser_example.screen.dart @@ -26,6 +26,12 @@ class MyInAppBrowser extends InAppBrowser { pullToRefreshController?.endRefreshing(); } + @override + Future onPermissionRequest(request) async { + return PermissionResponse( + resources: request.resources, action: PermissionResponseAction.GRANT); + } + @override void onLoadError(url, code, message) { pullToRefreshController?.endRefreshing(); @@ -106,9 +112,8 @@ class _InAppBrowserExampleScreenState extends State { URLRequest(url: Uri.parse("https://flutter.dev")), settings: InAppBrowserClassSettings( browserSettings: InAppBrowserSettings( - toolbarTopBackgroundColor: Colors.blue, - presentationStyle: ModalPresentationStyle.POPOVER - ), + toolbarTopBackgroundColor: Colors.blue, + presentationStyle: ModalPresentationStyle.POPOVER), webViewSettings: InAppWebViewSettings( useShouldOverrideUrlLoading: true, useOnLoadResource: true, diff --git a/example/macos/Runner/DebugProfile.entitlements b/example/macos/Runner/DebugProfile.entitlements index f7ba7c9b..9f2a6f04 100644 --- a/example/macos/Runner/DebugProfile.entitlements +++ b/example/macos/Runner/DebugProfile.entitlements @@ -6,6 +6,10 @@ com.apple.security.cs.allow-jit + com.apple.security.device.audio-input + + com.apple.security.device.camera + com.apple.security.files.user-selected.read-write com.apple.security.network.client diff --git a/example/macos/Runner/Release.entitlements b/example/macos/Runner/Release.entitlements index 8ed2e121..40c55dbc 100644 --- a/example/macos/Runner/Release.entitlements +++ b/example/macos/Runner/Release.entitlements @@ -4,6 +4,10 @@ com.apple.security.app-sandbox + com.apple.security.device.audio-input + + com.apple.security.device.camera + com.apple.security.files.user-selected.read-write com.apple.security.network.client diff --git a/lib/src/in_app_browser/in_app_browser_settings.dart b/lib/src/in_app_browser/in_app_browser_settings.dart index f0bfc15f..c89336ac 100755 --- a/lib/src/in_app_browser/in_app_browser_settings.dart +++ b/lib/src/in_app_browser/in_app_browser_settings.dart @@ -4,8 +4,12 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_inappwebview/src/types/main.dart'; import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart'; +import '../types/in_app_webview_rect.dart'; import '../types/modal_presentation_style.dart'; import '../types/modal_transition_style.dart'; +import '../types/window_style_mask.dart'; +import '../types/window_titlebar_separator_style.dart'; +import '../types/window_type.dart'; import '../util.dart'; import '../in_app_webview/in_app_webview_settings.dart'; @@ -230,6 +234,41 @@ class InAppBrowserSettings_ ///- iOS ModalTransitionStyle_? transitionStyle; + ///How the browser window should be added to the main window. + ///The default value is [WindowType.CHILD]. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + WindowType_? windowType; + + ///The window’s alpha value. + ///The default value is `1.0`. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + double? windowAlphaValue; + + ///Flags that describe the window’s current style, such as if it’s resizable or in full-screen mode. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + WindowStyleMask_? windowStyleMask; + + ///The type of separator that the app displays between the title bar and content of a window. + /// + ///**NOTE for MacOS**: available on MacOS 11.0+. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + WindowTitlebarSeparatorStyle_? windowTitlebarSeparatorStyle; + + ///Sets the origin and size of the window’s frame rectangle according to a given frame rectangle, + ///thereby setting its position and size onscreen. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + InAppWebViewRect_? windowFrame; + InAppBrowserSettings_( {this.hidden = false, this.hideToolbarTop = false, @@ -250,7 +289,12 @@ class InAppBrowserSettings_ this.toolbarTopFixedTitle, this.closeOnCannotGoBack = true, this.allowGoBackWithBackButton = true, - this.shouldCloseOnBackButtonPressed = false}); + this.shouldCloseOnBackButtonPressed = false, + this.windowType, + this.windowAlphaValue = 1.0, + this.windowStyleMask, + this.windowTitlebarSeparatorStyle, + this.windowFrame}); @override @ExchangeableObjectMethod(ignore: true) diff --git a/lib/src/in_app_browser/in_app_browser_settings.g.dart b/lib/src/in_app_browser/in_app_browser_settings.g.dart index 7d89a162..ad4d8747 100644 --- a/lib/src/in_app_browser/in_app_browser_settings.g.dart +++ b/lib/src/in_app_browser/in_app_browser_settings.g.dart @@ -146,6 +146,41 @@ class InAppBrowserSettings ///**Supported Platforms/Implementations**: ///- iOS ModalTransitionStyle? transitionStyle; + + ///How the browser window should be added to the main window. + ///The default value is [WindowType.CHILD]. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + WindowType? windowType; + + ///The window’s alpha value. + ///The default value is `1.0`. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + double? windowAlphaValue; + + ///Flags that describe the window’s current style, such as if it’s resizable or in full-screen mode. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + WindowStyleMask? windowStyleMask; + + ///The type of separator that the app displays between the title bar and content of a window. + /// + ///**NOTE for MacOS**: available on MacOS 11.0+. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + WindowTitlebarSeparatorStyle? windowTitlebarSeparatorStyle; + + ///Sets the origin and size of the window’s frame rectangle according to a given frame rectangle, + ///thereby setting its position and size onscreen. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + InAppWebViewRect? windowFrame; InAppBrowserSettings( {this.hidden = false, this.hideToolbarTop = false, @@ -166,7 +201,12 @@ class InAppBrowserSettings this.closeButtonCaption, this.closeButtonColor, this.presentationStyle = ModalPresentationStyle.FULL_SCREEN, - this.transitionStyle = ModalTransitionStyle.COVER_VERTICAL}); + this.transitionStyle = ModalTransitionStyle.COVER_VERTICAL, + this.windowType, + this.windowAlphaValue = 1.0, + this.windowStyleMask, + this.windowTitlebarSeparatorStyle, + this.windowFrame}); ///Gets a possible [InAppBrowserSettings] instance from a [Map] value. static InAppBrowserSettings? fromMap(Map? map) { @@ -192,6 +232,13 @@ class InAppBrowserSettings closeButtonColor: map['closeButtonColor'] != null ? UtilColor.fromStringRepresentation(map['closeButtonColor']) : null, + windowType: WindowType.fromNativeValue(map['windowType']), + windowStyleMask: WindowStyleMask.fromNativeValue(map['windowStyleMask']), + windowTitlebarSeparatorStyle: + WindowTitlebarSeparatorStyle.fromNativeValue( + map['windowTitlebarSeparatorStyle']), + windowFrame: + InAppWebViewRect.fromMap(map['windowFrame']?.cast()), ); instance.hidden = map['hidden']; instance.hideToolbarTop = map['hideToolbarTop']; @@ -212,6 +259,7 @@ class InAppBrowserSettings ModalPresentationStyle.fromNativeValue(map['presentationStyle']); instance.transitionStyle = ModalTransitionStyle.fromNativeValue(map['transitionStyle']); + instance.windowAlphaValue = map['windowAlphaValue']; return instance; } @@ -239,6 +287,12 @@ class InAppBrowserSettings "closeButtonColor": closeButtonColor?.toHex(), "presentationStyle": presentationStyle?.toNativeValue(), "transitionStyle": transitionStyle?.toNativeValue(), + "windowType": windowType?.toNativeValue(), + "windowAlphaValue": windowAlphaValue, + "windowStyleMask": windowStyleMask?.toNativeValue(), + "windowTitlebarSeparatorStyle": + windowTitlebarSeparatorStyle?.toNativeValue(), + "windowFrame": windowFrame?.toMap(), }; } @@ -254,6 +308,6 @@ class InAppBrowserSettings @override String toString() { - return 'InAppBrowserSettings{hidden: $hidden, hideToolbarTop: $hideToolbarTop, toolbarTopBackgroundColor: $toolbarTopBackgroundColor, hideUrlBar: $hideUrlBar, hideProgressBar: $hideProgressBar, hideTitleBar: $hideTitleBar, toolbarTopFixedTitle: $toolbarTopFixedTitle, closeOnCannotGoBack: $closeOnCannotGoBack, allowGoBackWithBackButton: $allowGoBackWithBackButton, shouldCloseOnBackButtonPressed: $shouldCloseOnBackButtonPressed, toolbarTopTranslucent: $toolbarTopTranslucent, toolbarTopBarTintColor: $toolbarTopBarTintColor, toolbarTopTintColor: $toolbarTopTintColor, hideToolbarBottom: $hideToolbarBottom, toolbarBottomBackgroundColor: $toolbarBottomBackgroundColor, toolbarBottomTintColor: $toolbarBottomTintColor, toolbarBottomTranslucent: $toolbarBottomTranslucent, closeButtonCaption: $closeButtonCaption, closeButtonColor: $closeButtonColor, presentationStyle: $presentationStyle, transitionStyle: $transitionStyle}'; + return 'InAppBrowserSettings{hidden: $hidden, hideToolbarTop: $hideToolbarTop, toolbarTopBackgroundColor: $toolbarTopBackgroundColor, hideUrlBar: $hideUrlBar, hideProgressBar: $hideProgressBar, hideTitleBar: $hideTitleBar, toolbarTopFixedTitle: $toolbarTopFixedTitle, closeOnCannotGoBack: $closeOnCannotGoBack, allowGoBackWithBackButton: $allowGoBackWithBackButton, shouldCloseOnBackButtonPressed: $shouldCloseOnBackButtonPressed, toolbarTopTranslucent: $toolbarTopTranslucent, toolbarTopBarTintColor: $toolbarTopBarTintColor, toolbarTopTintColor: $toolbarTopTintColor, hideToolbarBottom: $hideToolbarBottom, toolbarBottomBackgroundColor: $toolbarBottomBackgroundColor, toolbarBottomTintColor: $toolbarBottomTintColor, toolbarBottomTranslucent: $toolbarBottomTranslucent, closeButtonCaption: $closeButtonCaption, closeButtonColor: $closeButtonColor, presentationStyle: $presentationStyle, transitionStyle: $transitionStyle, windowType: $windowType, windowAlphaValue: $windowAlphaValue, windowStyleMask: $windowStyleMask, windowTitlebarSeparatorStyle: $windowTitlebarSeparatorStyle, windowFrame: $windowFrame}'; } } diff --git a/lib/src/in_app_webview/in_app_webview_settings.g.dart b/lib/src/in_app_webview/in_app_webview_settings.g.dart index 9217f382..fa542184 100644 --- a/lib/src/in_app_webview/in_app_webview_settings.g.dart +++ b/lib/src/in_app_webview/in_app_webview_settings.g.dart @@ -1014,6 +1014,10 @@ class InAppWebViewSettings { ///- [InAppWebViewController.getScrollY] ///- [InAppWebViewController.scrollTo] ///- [InAppWebViewController.scrollBy] + ///- [InAppWebViewController.getContentHeight] + ///- [InAppWebViewController.getContentWidth] + ///- [InAppWebViewController.canScrollVertically] + ///- [InAppWebViewController.canScrollHorizontally] /// ///Settings affected: ///- [WebView.initialUserScripts] diff --git a/lib/src/types/main.dart b/lib/src/types/main.dart index b427d132..28ff5f51 100644 --- a/lib/src/types/main.dart +++ b/lib/src/types/main.dart @@ -212,3 +212,6 @@ export 'print_job_page_order.dart' show PrintJobPageOrder; export 'print_job_pagination_mode.dart' show PrintJobPaginationMode; export 'print_job_disposition.dart' show PrintJobDisposition; export 'printer.dart' show Printer; +export 'window_type.dart' show WindowType; +export 'window_style_mask.dart' show WindowStyleMask; +export 'window_titlebar_separator_style.dart' show WindowTitlebarSeparatorStyle; \ No newline at end of file diff --git a/lib/src/types/webview_render_process_action.dart b/lib/src/types/webview_render_process_action.dart index 79df074f..233cd6e0 100644 --- a/lib/src/types/webview_render_process_action.dart +++ b/lib/src/types/webview_render_process_action.dart @@ -12,9 +12,6 @@ class WebViewRenderProcessAction_ { final int _value; const WebViewRenderProcessAction_._internal(this._value); - ///Gets [int] value. - int toValue() => _value; - ///Cause this renderer to terminate. static const TERMINATE = const WebViewRenderProcessAction_._internal(0); } diff --git a/lib/src/types/window_style_mask.dart b/lib/src/types/window_style_mask.dart new file mode 100644 index 00000000..c957a5ca --- /dev/null +++ b/lib/src/types/window_style_mask.dart @@ -0,0 +1,126 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart'; + +part 'window_style_mask.g.dart'; + +///Class that represents the flags that describe the browser window’s current style, such as if it’s resizable or in full-screen mode. +@ExchangeableEnum(bitwiseOrOperator: true) +class WindowStyleMask_ { + // ignore: unused_field + final int _value; + // ignore: unused_field + final int? _nativeValue = null; + const WindowStyleMask_._internal(this._value); + + ///The window displays none of the usual peripheral elements. Useful only for display or caching purposes. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 0, + apiName: "NSWindow.StyleMask.borderless", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644698-borderless" + ) + ]) + static const BORDERLESS = const WindowStyleMask_._internal(0); + + ///The window displays a title bar. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 1, + apiName: "NSWindow.StyleMask.titled", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644724-titled" + ) + ]) + static const TITLED = const WindowStyleMask_._internal(1); + + ///The window displays a close button. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 2, + apiName: "NSWindow.StyleMask.closable", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644610-closable" + ) + ]) + static const CLOSABLE = const WindowStyleMask_._internal(2); + + ///The window displays a minimize button. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 4, + apiName: "NSWindow.StyleMask.miniaturizable", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644650-miniaturizable" + ) + ]) + static const MINIATURIZABLE = const WindowStyleMask_._internal(4); + + ///The window can be resized by the user. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 8, + apiName: "NSWindow.StyleMask.miniaturizable", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644717-resizable" + ) + ]) + static const RESIZABLE = const WindowStyleMask_._internal(8); + + ///The window can appear full screen. A fullscreen window does not draw its title bar, and may have special handling for its toolbar. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 16384, + apiName: "NSWindow.StyleMask.fullScreen", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644530-fullscreen" + ) + ]) + static const FULLSCREEN = const WindowStyleMask_._internal(16384); + + ///When set, the window’s contentView consumes the full size of the window. + ///Although you can combine this constant with other window style masks, it is respected only for windows with a title bar. + ///Note that using this mask opts in to layer-backing. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 32768, + apiName: "NSWindow.StyleMask.fullSizeContentView", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644646-fullsizecontentview" + ) + ]) + static const FULL_SIZE_CONTENT_VIEW = const WindowStyleMask_._internal(32768); + + ///The window is a panel. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 16, + apiName: "NSWindow.StyleMask.utilityWindow", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644672-utilitywindow" + ) + ]) + static const UTILITY_WINDOW = const WindowStyleMask_._internal(16); + + ///The window is a document-modal panel. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 64, + apiName: "NSWindow.StyleMask.docModalWindow", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644253-docmodalwindow" + ) + ]) + static const DOC_MODAL_WINDOW = const WindowStyleMask_._internal(64); + + ///The window is a panel that does not activate the owning app. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 128, + apiName: "NSWindow.StyleMask.nonactivatingPanel", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644696-nonactivatingpanel" + ) + ]) + static const NONACTIVATING_PANEL = const WindowStyleMask_._internal(128); + + ///The window is a HUD panel. + @EnumSupportedPlatforms(platforms: [ + EnumMacOSPlatform( + value: 8192, + apiName: "NSWindow.StyleMask.hudWindow", + apiUrl: "https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644653-hudwindow" + ) + ]) + static const HUD_WINDOW = const WindowStyleMask_._internal(8192); +} \ No newline at end of file diff --git a/lib/src/types/window_style_mask.g.dart b/lib/src/types/window_style_mask.g.dart new file mode 100644 index 00000000..9375237e --- /dev/null +++ b/lib/src/types/window_style_mask.g.dart @@ -0,0 +1,265 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'window_style_mask.dart'; + +// ************************************************************************** +// ExchangeableEnumGenerator +// ************************************************************************** + +///Class that represents the flags that describe the browser window’s current style, such as if it’s resizable or in full-screen mode. +class WindowStyleMask { + final int _value; + final int? _nativeValue; + const WindowStyleMask._internal(this._value, this._nativeValue); +// ignore: unused_element + factory WindowStyleMask._internalMultiPlatform( + int value, Function nativeValue) => + WindowStyleMask._internal(value, nativeValue()); + + ///The window displays none of the usual peripheral elements. Useful only for display or caching purposes. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.borderless](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644698-borderless)) + static final BORDERLESS = WindowStyleMask._internalMultiPlatform(0, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 0; + default: + break; + } + return null; + }); + + ///The window displays a title bar. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.titled](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644724-titled)) + static final TITLED = WindowStyleMask._internalMultiPlatform(1, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 1; + default: + break; + } + return null; + }); + + ///The window displays a close button. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.closable](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644610-closable)) + static final CLOSABLE = WindowStyleMask._internalMultiPlatform(2, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 2; + default: + break; + } + return null; + }); + + ///The window displays a minimize button. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.miniaturizable](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644650-miniaturizable)) + static final MINIATURIZABLE = WindowStyleMask._internalMultiPlatform(4, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 4; + default: + break; + } + return null; + }); + + ///The window can be resized by the user. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.miniaturizable](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644717-resizable)) + static final RESIZABLE = WindowStyleMask._internalMultiPlatform(8, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 8; + default: + break; + } + return null; + }); + + ///The window can appear full screen. A fullscreen window does not draw its title bar, and may have special handling for its toolbar. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.fullScreen](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644530-fullscreen)) + static final FULLSCREEN = WindowStyleMask._internalMultiPlatform(16384, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 16384; + default: + break; + } + return null; + }); + + ///When set, the window’s contentView consumes the full size of the window. + ///Although you can combine this constant with other window style masks, it is respected only for windows with a title bar. + ///Note that using this mask opts in to layer-backing. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.fullSizeContentView](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644646-fullsizecontentview)) + static final FULL_SIZE_CONTENT_VIEW = + WindowStyleMask._internalMultiPlatform(32768, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 32768; + default: + break; + } + return null; + }); + + ///The window is a panel. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.utilityWindow](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644672-utilitywindow)) + static final UTILITY_WINDOW = WindowStyleMask._internalMultiPlatform(16, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 16; + default: + break; + } + return null; + }); + + ///The window is a document-modal panel. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.docModalWindow](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644253-docmodalwindow)) + static final DOC_MODAL_WINDOW = + WindowStyleMask._internalMultiPlatform(64, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 64; + default: + break; + } + return null; + }); + + ///The window is a panel that does not activate the owning app. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.nonactivatingPanel](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644696-nonactivatingpanel)) + static final NONACTIVATING_PANEL = + WindowStyleMask._internalMultiPlatform(128, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 128; + default: + break; + } + return null; + }); + + ///The window is a HUD panel. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS ([Official API - NSWindow.StyleMask.hudWindow](https://developer.apple.com/documentation/appkit/nswindow/stylemask/1644653-hudwindow)) + static final HUD_WINDOW = WindowStyleMask._internalMultiPlatform(8192, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 8192; + default: + break; + } + return null; + }); + + ///Set of all values of [WindowStyleMask]. + static final Set values = [ + WindowStyleMask.BORDERLESS, + WindowStyleMask.TITLED, + WindowStyleMask.CLOSABLE, + WindowStyleMask.MINIATURIZABLE, + WindowStyleMask.RESIZABLE, + WindowStyleMask.FULLSCREEN, + WindowStyleMask.FULL_SIZE_CONTENT_VIEW, + WindowStyleMask.UTILITY_WINDOW, + WindowStyleMask.DOC_MODAL_WINDOW, + WindowStyleMask.NONACTIVATING_PANEL, + WindowStyleMask.HUD_WINDOW, + ].toSet(); + + ///Gets a possible [WindowStyleMask] instance from [int] value. + static WindowStyleMask? fromValue(int? value) { + if (value != null) { + try { + return WindowStyleMask.values + .firstWhere((element) => element.toValue() == value); + } catch (e) { + return WindowStyleMask._internal(value, value); + } + } + return null; + } + + ///Gets a possible [WindowStyleMask] instance from a native value. + static WindowStyleMask? fromNativeValue(int? value) { + if (value != null) { + try { + return WindowStyleMask.values + .firstWhere((element) => element.toNativeValue() == value); + } catch (e) { + return WindowStyleMask._internal(value, value); + } + } + return null; + } + + ///Gets [int] value. + int toValue() => _value; + + ///Gets [int?] native value. + int? toNativeValue() => _nativeValue; + + @override + int get hashCode => _value.hashCode; + + @override + bool operator ==(value) => value == _value; + + WindowStyleMask operator |(WindowStyleMask value) => + WindowStyleMask._internal( + value.toValue() | _value, + value.toNativeValue() != null && _nativeValue != null + ? value.toNativeValue()! | _nativeValue! + : _nativeValue); + @override + String toString() { + switch (_value) { + case 0: + return 'BORDERLESS'; + case 1: + return 'TITLED'; + case 2: + return 'CLOSABLE'; + case 4: + return 'MINIATURIZABLE'; + case 8: + return 'RESIZABLE'; + case 16384: + return 'FULLSCREEN'; + case 32768: + return 'FULL_SIZE_CONTENT_VIEW'; + case 16: + return 'UTILITY_WINDOW'; + case 64: + return 'DOC_MODAL_WINDOW'; + case 128: + return 'NONACTIVATING_PANEL'; + case 8192: + return 'HUD_WINDOW'; + } + return _value.toString(); + } +} diff --git a/lib/src/types/window_titlebar_separator_style.dart b/lib/src/types/window_titlebar_separator_style.dart new file mode 100644 index 00000000..bbe87aad --- /dev/null +++ b/lib/src/types/window_titlebar_separator_style.dart @@ -0,0 +1,30 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart'; + +part 'window_titlebar_separator_style.g.dart'; + +///Class that represents the type of separator that the app displays between the title bar and content of a browser window. +@ExchangeableEnum() +class WindowTitlebarSeparatorStyle_ { + // ignore: unused_field + final int _value; + // ignore: unused_field + final int? _nativeValue = null; + const WindowTitlebarSeparatorStyle_._internal(this._value); + + ///A style indicating that the system determines the type of separator. + @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 0)]) + static const AUTOMATIC = const WindowTitlebarSeparatorStyle_._internal(0); + + ///A style indicating that the title bar separator is a line. + @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 1)]) + static const NONE = const WindowTitlebarSeparatorStyle_._internal(1); + + ///A style indicating that there’s no title bar separator. + @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 2)]) + static const LINE = const WindowTitlebarSeparatorStyle_._internal(2); + + ///A style indicating that the title bar separator is a shadow. + @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 3)]) + static const SHADOW = const WindowTitlebarSeparatorStyle_._internal(3); +} \ No newline at end of file diff --git a/lib/src/types/window_titlebar_separator_style.g.dart b/lib/src/types/window_titlebar_separator_style.g.dart new file mode 100644 index 00000000..eed2a058 --- /dev/null +++ b/lib/src/types/window_titlebar_separator_style.g.dart @@ -0,0 +1,139 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'window_titlebar_separator_style.dart'; + +// ************************************************************************** +// ExchangeableEnumGenerator +// ************************************************************************** + +///Class that represents the type of separator that the app displays between the title bar and content of a browser window. +class WindowTitlebarSeparatorStyle { + final int _value; + final int? _nativeValue; + const WindowTitlebarSeparatorStyle._internal(this._value, this._nativeValue); +// ignore: unused_element + factory WindowTitlebarSeparatorStyle._internalMultiPlatform( + int value, Function nativeValue) => + WindowTitlebarSeparatorStyle._internal(value, nativeValue()); + + ///A style indicating that the system determines the type of separator. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + static final AUTOMATIC = + WindowTitlebarSeparatorStyle._internalMultiPlatform(0, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 0; + default: + break; + } + return null; + }); + + ///A style indicating that the title bar separator is a line. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + static final NONE = + WindowTitlebarSeparatorStyle._internalMultiPlatform(1, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 1; + default: + break; + } + return null; + }); + + ///A style indicating that there’s no title bar separator. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + static final LINE = + WindowTitlebarSeparatorStyle._internalMultiPlatform(2, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 2; + default: + break; + } + return null; + }); + + ///A style indicating that the title bar separator is a shadow. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + static final SHADOW = + WindowTitlebarSeparatorStyle._internalMultiPlatform(3, () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 3; + default: + break; + } + return null; + }); + + ///Set of all values of [WindowTitlebarSeparatorStyle]. + static final Set values = [ + WindowTitlebarSeparatorStyle.AUTOMATIC, + WindowTitlebarSeparatorStyle.NONE, + WindowTitlebarSeparatorStyle.LINE, + WindowTitlebarSeparatorStyle.SHADOW, + ].toSet(); + + ///Gets a possible [WindowTitlebarSeparatorStyle] instance from [int] value. + static WindowTitlebarSeparatorStyle? fromValue(int? value) { + if (value != null) { + try { + return WindowTitlebarSeparatorStyle.values + .firstWhere((element) => element.toValue() == value); + } catch (e) { + return null; + } + } + return null; + } + + ///Gets a possible [WindowTitlebarSeparatorStyle] instance from a native value. + static WindowTitlebarSeparatorStyle? fromNativeValue(int? value) { + if (value != null) { + try { + return WindowTitlebarSeparatorStyle.values + .firstWhere((element) => element.toNativeValue() == value); + } catch (e) { + return null; + } + } + return null; + } + + ///Gets [int] value. + int toValue() => _value; + + ///Gets [int?] native value. + int? toNativeValue() => _nativeValue; + + @override + int get hashCode => _value.hashCode; + + @override + bool operator ==(value) => value == _value; + + @override + String toString() { + switch (_value) { + case 0: + return 'AUTOMATIC'; + case 1: + return 'NONE'; + case 2: + return 'LINE'; + case 3: + return 'SHADOW'; + } + return _value.toString(); + } +} diff --git a/lib/src/types/window_type.dart b/lib/src/types/window_type.dart new file mode 100644 index 00000000..fe502bba --- /dev/null +++ b/lib/src/types/window_type.dart @@ -0,0 +1,22 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_inappwebview_internal_annotations/flutter_inappwebview_internal_annotations.dart'; + +part 'window_type.g.dart'; + +///Class that represents how a browser window should be added to the main window. +@ExchangeableEnum() +class WindowType_ { + // ignore: unused_field + final String _value; + + const WindowType_._internal(this._value); + + ///Adds the new browser window as a child window of the main window. + @EnumSupportedPlatforms(platforms: [EnumMacOSPlatform(value: 'CHILD')]) + static const CHILD = const WindowType_._internal('CHILD'); + + ///Adds the new browser window as a new tab in a tabbed window of the main window. + @EnumSupportedPlatforms( + platforms: [EnumMacOSPlatform(value: 'TABBED', available: "10.12+")]) + static const TABBED = const WindowType_._internal('TABBED'); +} diff --git a/lib/src/types/window_type.g.dart b/lib/src/types/window_type.g.dart new file mode 100644 index 00000000..958e9198 --- /dev/null +++ b/lib/src/types/window_type.g.dart @@ -0,0 +1,95 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'window_type.dart'; + +// ************************************************************************** +// ExchangeableEnumGenerator +// ************************************************************************** + +///Class that represents how a browser window should be added to the main window. +class WindowType { + final String _value; + final String _nativeValue; + const WindowType._internal(this._value, this._nativeValue); +// ignore: unused_element + factory WindowType._internalMultiPlatform( + String value, Function nativeValue) => + WindowType._internal(value, nativeValue()); + + ///Adds the new browser window as a child window of the main window. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS + static final CHILD = WindowType._internalMultiPlatform('CHILD', () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 'CHILD'; + default: + break; + } + return null; + }); + + ///Adds the new browser window as a new tab in a tabbed window of the main window. + /// + ///**Supported Platforms/Implementations**: + ///- MacOS 10.12++ + static final TABBED = WindowType._internalMultiPlatform('TABBED', () { + switch (defaultTargetPlatform) { + case TargetPlatform.macOS: + return 'TABBED'; + default: + break; + } + return null; + }); + + ///Set of all values of [WindowType]. + static final Set values = [ + WindowType.CHILD, + WindowType.TABBED, + ].toSet(); + + ///Gets a possible [WindowType] instance from [String] value. + static WindowType? fromValue(String? value) { + if (value != null) { + try { + return WindowType.values + .firstWhere((element) => element.toValue() == value); + } catch (e) { + return null; + } + } + return null; + } + + ///Gets a possible [WindowType] instance from a native value. + static WindowType? fromNativeValue(String? value) { + if (value != null) { + try { + return WindowType.values + .firstWhere((element) => element.toNativeValue() == value); + } catch (e) { + return null; + } + } + return null; + } + + ///Gets [String] value. + String toValue() => _value; + + ///Gets [String] native value. + String toNativeValue() => _nativeValue; + + @override + int get hashCode => _value.hashCode; + + @override + bool operator ==(value) => value == _value; + + @override + String toString() { + return _value; + } +} diff --git a/macos/Classes/InAppBrowser/InAppBrowserManager.swift b/macos/Classes/InAppBrowser/InAppBrowserManager.swift index 892e8fa2..fdc8ee5f 100755 --- a/macos/Classes/InAppBrowser/InAppBrowserManager.swift +++ b/macos/Classes/InAppBrowser/InAppBrowserManager.swift @@ -79,7 +79,11 @@ public class InAppBrowserManager: ChannelDelegate { window.contentViewController = webViewController window.prepare() - NSApplication.shared.mainWindow?.addChildWindow(window, ordered: .above) + if #available(macOS 10.12, *), browserSettings.windowType == .tabbed { + NSApplication.shared.mainWindow?.addTabbedWindow(window, ordered: .above) + } else { + NSApplication.shared.mainWindow?.addChildWindow(window, ordered: .above) + } if browserSettings.hidden { window.hide() diff --git a/macos/Classes/InAppBrowser/InAppBrowserSettings.swift b/macos/Classes/InAppBrowser/InAppBrowserSettings.swift index 91acead9..f2c8ab22 100755 --- a/macos/Classes/InAppBrowser/InAppBrowserSettings.swift +++ b/macos/Classes/InAppBrowser/InAppBrowserSettings.swift @@ -16,19 +16,74 @@ public class InAppBrowserSettings: ISettings { var hideUrlBar = false var hideProgressBar = false var toolbarTopFixedTitle: String? + var windowType = InAppBrowserWindowType.child + var windowAlphaValue = 1.0 + var _windowStyleMask: NSNumber? + var windowStyleMask: NSWindow.StyleMask? { + get { + return _windowStyleMask != nil ? + NSWindow.StyleMask.init(rawValue: _windowStyleMask!.uintValue) : + nil + } + set { + if let newValue = newValue { + _windowStyleMask = NSNumber.init(value: newValue.rawValue) + } else { + _windowStyleMask = nil + } + } + } + var _windowTitlebarSeparatorStyle: NSNumber? + @available(macOS 11.0, *) + var windowTitlebarSeparatorStyle: NSTitlebarSeparatorStyle? { + get { + return _windowTitlebarSeparatorStyle != nil ? + NSTitlebarSeparatorStyle.init(rawValue: _windowTitlebarSeparatorStyle!.intValue) : + nil + } + set { + if let newValue = newValue { + _windowTitlebarSeparatorStyle = NSNumber.init(value: newValue.rawValue) + } else { + _windowTitlebarSeparatorStyle = nil + } + } + } + var windowFrame: NSRect? override init(){ super.init() } + override func parse(settings: [String: Any?]) -> InAppBrowserSettings { + let _ = super.parse(settings: settings) + if let windowType = settings["windowType"] as? String { + self.windowType = InAppBrowserWindowType.init(rawValue: windowType) ?? InAppBrowserWindowType.child + } + if let windowFrame = settings["windowFrame"] as? [String:Double] { + self.windowFrame = NSRect(x: windowFrame["x"]!, + y: windowFrame["y"]!, + width: windowFrame["width"]!, + height: windowFrame["height"]!) + } + return self + } + override func getRealSettings(obj: InAppBrowserWebViewController?) -> [String: Any?] { var realOptions: [String: Any?] = toMap() + realOptions["windowType"] = windowType.rawValue if let inAppBrowserWebViewController = obj { realOptions["hidden"] = inAppBrowserWebViewController.isHidden realOptions["hideUrlBar"] = inAppBrowserWebViewController.window?.searchBar?.isHidden realOptions["hideProgressBar"] = inAppBrowserWebViewController.progressBar.isHidden realOptions["hideToolbarTop"] = !(inAppBrowserWebViewController.window?.toolbar?.isVisible ?? true) realOptions["toolbarTopBackgroundColor"] = inAppBrowserWebViewController.window?.backgroundColor.hexString + realOptions["windowAlphaValue"] = inAppBrowserWebViewController.window?.alphaValue + realOptions["windowStyleMask"] = inAppBrowserWebViewController.window?.styleMask.rawValue + if #available(macOS 11.0, *) { + realOptions["windowTitlebarSeparatorStyle"] = inAppBrowserWebViewController.window?.titlebarSeparatorStyle.rawValue + } + realOptions["windowFrame"] = inAppBrowserWebViewController.window?.frame.toMap() } return realOptions } diff --git a/macos/Classes/InAppBrowser/InAppBrowserWindow.swift b/macos/Classes/InAppBrowser/InAppBrowserWindow.swift index 1b74dbe9..d01d7bf5 100644 --- a/macos/Classes/InAppBrowser/InAppBrowserWindow.swift +++ b/macos/Classes/InAppBrowser/InAppBrowserWindow.swift @@ -49,8 +49,14 @@ public class InAppBrowserWindow : NSWindow, NSWindowDelegate, NSToolbarDelegate, public func prepare() { title = "" + collectionBehavior = .fullScreenPrimary delegate = self + NotificationCenter.default.addObserver(self, + selector: #selector(onMainWindowClose(_:)), + name: NSWindow.willCloseNotification, + object: NSApplication.shared.mainWindow) + if #available(macOS 10.13, *) { let windowToolbar = NSToolbar() windowToolbar.delegate = self @@ -142,6 +148,16 @@ public class InAppBrowserWindow : NSWindow, NSWindowDelegate, NSToolbarDelegate, else { toolbar?.isVisible = false } + if #available(macOS 11.0, *), let windowTitlebarSeparatorStyle = browserSettings.windowTitlebarSeparatorStyle { + titlebarSeparatorStyle = windowTitlebarSeparatorStyle + } + alphaValue = browserSettings.windowAlphaValue + if let windowStyleMask = browserSettings.windowStyleMask { + styleMask = windowStyleMask + } + if let windowFrame = browserSettings.windowFrame { + setFrame(windowFrame, display: true) + } } } @@ -208,7 +224,11 @@ public class InAppBrowserWindow : NSWindow, NSWindowDelegate, NSToolbarDelegate, } public func show() { - if !(NSApplication.shared.mainWindow?.childWindows?.contains(self) ?? false) { + if #available(macOS 10.12, *), + !(NSApplication.shared.mainWindow?.tabbedWindows?.contains(self) ?? false), + browserSettings?.windowType == .tabbed { + NSApplication.shared.mainWindow?.addTabbedWindow(self, ordered: .above) + } else if !(NSApplication.shared.mainWindow?.childWindows?.contains(self) ?? false) { NSApplication.shared.mainWindow?.addChildWindow(self, ordered: .above) } else { orderFront(self) @@ -241,7 +261,6 @@ public class InAppBrowserWindow : NSWindow, NSWindowDelegate, NSToolbarDelegate, backgroundColor = nil } } - browserSettings = newSettings } @@ -249,6 +268,11 @@ public class InAppBrowserWindow : NSWindow, NSWindowDelegate, NSToolbarDelegate, dispose() } + @objc func onMainWindowClose(_ notification: Notification) { + close() + } + + public func dispose() { delegate = nil if let webViewController = contentViewController as? InAppBrowserWebViewController { diff --git a/macos/Classes/Types/InAppBrowserWindowType.swift b/macos/Classes/Types/InAppBrowserWindowType.swift new file mode 100644 index 00000000..9ab3f3d8 --- /dev/null +++ b/macos/Classes/Types/InAppBrowserWindowType.swift @@ -0,0 +1,13 @@ +// +// InAppBrowserWindowType.swift +// flutter_inappwebview +// +// Created by Lorenzo Pichilli on 19/10/22. +// + +import Foundation + +public enum InAppBrowserWindowType: String { + case child = "CHILD" + case tabbed = "TABBED" +}