diff --git a/plugins/window_size/.gitignore b/plugins/window_size/.gitignore new file mode 100644 index 000000000..93d2a1eae --- /dev/null +++ b/plugins/window_size/.gitignore @@ -0,0 +1,2 @@ +.packages +pubspec.lock diff --git a/plugins/window_size/analysis_options.yaml b/plugins/window_size/analysis_options.yaml new file mode 100644 index 000000000..f04c6cf0f --- /dev/null +++ b/plugins/window_size/analysis_options.yaml @@ -0,0 +1 @@ +include: ../../analysis_options.yaml diff --git a/plugins/window_size/common/channel_constants.cc b/plugins/window_size/common/channel_constants.cc new file mode 100644 index 000000000..5caa0a8bc --- /dev/null +++ b/plugins/window_size/common/channel_constants.cc @@ -0,0 +1,29 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "plugins/window_size/common/channel_constants.h" + +namespace plugins_window_size { + +const char kChannelName[] = "flutter/windowsize"; + +const char kGetScreenListMethod[] = "getScreenList"; +const char kGetWindowInfoMethod[] = "getWindowInfo"; +const char kSetWindowFrameMethod[] = "setWindowFrame"; + +const char kFrameKey[] = "frame"; +const char kVisibleFrameKey[] = "visibleFrame"; +const char kScaleFactorKey[] = "scaleFactor"; +const char kScreenKey[] = "screen"; + +} // namespace plugins_window_size diff --git a/plugins/window_size/common/channel_constants.h b/plugins/window_size/common/channel_constants.h new file mode 100644 index 000000000..684b23a3b --- /dev/null +++ b/plugins/window_size/common/channel_constants.h @@ -0,0 +1,70 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef PLUGINS_WINDOW_SIZE_COMMON_CHANNEL_CONSTANTS_H_ +#define PLUGINS_WINDOW_SIZE_COMMON_CHANNEL_CONSTANTS_H_ + +namespace plugins_window_size { + +// This file contains constants used in the platform channel, which are shared +// across all native platform implementations. + +// The name of the plugin's platform channel. +extern const char kChannelName[]; + +// The method name to request information about the available screens. +// +// Returns a list of screen info maps; see keys below. +extern const char kGetScreenListMethod[]; + +// The method name to request information about the window containing the +// Flutter instance. +// +// Returns a list of window info maps; see keys below. +extern const char kGetWindowInfoMethod[]; + +// The method name to set the frame of a window. +// +// Takes a frame array, as documented for the value of kFrameKey. +extern const char kSetWindowFrameMethod[]; + +// Keys for screen and window maps returned by kGetScreenListMethod. + +// The frame of a screen or window. The value is an array of four doubles: +// [left, top, width, height] +extern const char kFrameKey[]; + +// The frame of a screen available for use by applications. The value format +// is the same as kFrameKey's. +// +// Only used for screens. +extern const char kVisibleFrameKey[]; + +// The scale factor for a screen or window, as a double. +// +// This is the number of pixels per screen coordinate, and thus the ratio +// between sizes as seen by Flutter and sizes in native screen coordinates. +extern const char kScaleFactorKey[]; + +// The screen containing this window, if any. The value is a screen map, or null +// if the window is not visible on a screen. +// +// Only used for windows. +// +// If a window is on multiple screens, it is up to the platform to decide which +// screen to report. +extern const char kScreenKey[]; + +} // namespace plugins_window_size + +#endif // PLUGINS_WINDOW_SIZE_COMMON_CHANNEL_CONSTANTS_H_ diff --git a/plugins/window_size/lib/src/platform_window.dart b/plugins/window_size/lib/src/platform_window.dart new file mode 100644 index 000000000..dded87cfa --- /dev/null +++ b/plugins/window_size/lib/src/platform_window.dart @@ -0,0 +1,35 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import 'dart:ui'; + +import 'screen.dart'; + +/// Represents a window, containing information about its size, position, and +/// properties. +/// +/// TODO: Evaluate how to reconcile this with the highly mobile-centric Window +/// class in dart::ui +class PlatformWindow { + /// Create a new window. + PlatformWindow(this.frame, this.scaleFactor, this.screen); + + /// The frame of the screen, in screen coordinates. + final Rect frame; + + /// The number of pixels per screen coordinate for this screen. + final double scaleFactor; + + /// The (or a) screen containing this window, if any. + final Screen screen; +} diff --git a/plugins/window_size/lib/src/screen.dart b/plugins/window_size/lib/src/screen.dart new file mode 100644 index 000000000..ca7c27ef4 --- /dev/null +++ b/plugins/window_size/lib/src/screen.dart @@ -0,0 +1,31 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import 'dart:ui'; + +/// Represents a screen, containing information about its size, position, and +/// properties. +class Screen { + /// Create a new screen. + Screen(this.frame, this.visibleFrame, this.scaleFactor); + + /// The frame of the screen, in screen coordinates. + final Rect frame; + + /// The portion of the screen's frame that is available for use by application + /// windows. E.g., on macOS, this excludes the menu bar. + final Rect visibleFrame; + + /// The number of pixels per screen coordinate for this screen. + final double scaleFactor; +} diff --git a/plugins/window_size/lib/src/window_size_channel.dart b/plugins/window_size/lib/src/window_size_channel.dart new file mode 100644 index 000000000..a25a18be2 --- /dev/null +++ b/plugins/window_size/lib/src/window_size_channel.dart @@ -0,0 +1,113 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter/services.dart'; + +import 'platform_window.dart'; +import 'screen.dart'; + +// Plugin channel constants. See common/channel_constants.h for details. +const String _windowSizeChannelName = 'flutter/windowsize'; +const String _getScreenListMethod = 'getScreenList'; +const String _getCurrentScreenMethod = 'getCurrentScreen'; +const String _getWindowInfoMethod = 'getWindowInfo'; +const String _setWindowFrameMethod = 'setWindowFrame'; +const String _frameKey = 'frame'; +const String _visibleFrameKey = 'visibleFrame'; +const String _scaleFactorKey = 'scaleFactor'; +const String _screenKey = 'screen'; + +/// A singleton object that handles the interaction with the platform channel. +class WindowSizeChannel { + /// Private constructor. + WindowSizeChannel._(); + + final MethodChannel _platformChannel = + const MethodChannel(_windowSizeChannelName); + + /// The static instance of the menu channel. + static final WindowSizeChannel instance = new WindowSizeChannel._(); + + /// Returns a list of screens. + Future> getScreenList() async { + try { + final screenList = []; + final response = + await _platformChannel.invokeMethod(_getScreenListMethod); + + for (final screenInfo in response) { + screenList.add(_screenFromInfoMap(screenInfo)); + } + return screenList; + } on PlatformException catch (e) { + print('Platform exception getting screen list: ${e.message}'); + } + return []; + } + + /// Returns information about the window containing this Flutter instance. + Future getWindowInfo() async { + try { + final response = + await _platformChannel.invokeMethod(_getWindowInfoMethod); + + return PlatformWindow( + _rectFromLTWHList(response[_frameKey].cast()), + response[_scaleFactorKey], + _screenFromInfoMap(response[_screenKey])); + } on PlatformException catch (e) { + print('Platform exception getting window info: ${e.message}'); + } + return null; + } + + /// Sets the frame of the window containing this Flutter instance, in + /// screen coordinates. + /// + /// The platform may adjust the frame as necessary if the provided frame would + /// cause significant usability issues (e.g., a window with no visible portion + /// that can be used to move the window). + void setWindowFrame(Rect frame) async { + try { + await _platformChannel.invokeMethod(_setWindowFrameMethod, + [frame.left, frame.top, frame.width, frame.height]); + } on PlatformException catch (e) { + print('Platform exception setting window frame: ${e.message}'); + } + } + + /// Given an array of the form [left, top, width, height], return the + /// corresponding [Rect]. + /// + /// Used for frame deserialization in the platform channel. + Rect _rectFromLTWHList(List ltwh) { + return Rect.fromLTWH(ltwh[0], ltwh[1], ltwh[2], ltwh[3]); + } + + /// Given a map of information about a screen, return the corresponding + /// [Screen] object, or null. + /// + /// Used for screen deserialization in the platform channel. + Screen _screenFromInfoMap(Map map) { + if (map == null) { + return null; + } + return Screen( + _rectFromLTWHList(map[_frameKey].cast()), + _rectFromLTWHList(map[_visibleFrameKey].cast()), + map[_scaleFactorKey]); + } +} diff --git a/plugins/window_size/lib/src/window_size_utils.dart b/plugins/window_size/lib/src/window_size_utils.dart new file mode 100644 index 000000000..122d7dbe5 --- /dev/null +++ b/plugins/window_size/lib/src/window_size_utils.dart @@ -0,0 +1,51 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import 'dart:async'; +import 'dart:ui'; + +import 'platform_window.dart'; +import 'screen.dart'; +import 'window_size_channel.dart'; + +/// Returns a list of [Screen]s for the current screen configuration. +/// +/// It is possible for this list to be empty, if the machine is running in +/// a headless mode. +Future> getScreenList() async { + return await WindowSizeChannel.instance.getScreenList(); +} + +/// Returns the [Screen] showing the window that contains this Flutter instance. +/// +/// If the window is not being displayed, returns null. If the window is being +/// displayed on multiple screens, the platform can return any of those screens. +Future getCurrentScreen() async { + final windowInfo = await WindowSizeChannel.instance.getWindowInfo(); + return windowInfo.screen; +} + +/// Returns information about the window containing this Flutter instance. +Future getWindowInfo() async { + return await WindowSizeChannel.instance.getWindowInfo(); +} + +/// Sets the frame of the window containing this Flutter instance, in +/// screen coordinates. +/// +/// The platform may adjust the frame as necessary if the provided frame would +/// cause significant usability issues (e.g., a window with no visible portion +/// that can be used to move the window). +void setWindowFrame(Rect frame) async { + WindowSizeChannel.instance.setWindowFrame(frame); +} diff --git a/plugins/window_size/lib/window_size.dart b/plugins/window_size/lib/window_size.dart new file mode 100644 index 000000000..e038f960f --- /dev/null +++ b/plugins/window_size/lib/window_size.dart @@ -0,0 +1,16 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +export 'src/platform_window.dart'; +export 'src/screen.dart'; +export 'src/window_size_utils.dart'; diff --git a/plugins/window_size/macos/FLEWindowSizePlugin.h b/plugins/window_size/macos/FLEWindowSizePlugin.h new file mode 100644 index 000000000..6190b224a --- /dev/null +++ b/plugins/window_size/macos/FLEWindowSizePlugin.h @@ -0,0 +1,25 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import + +/** + * A FlutterPlugin to manage macOS's shared NSColorPanel singleton. + * Responsible for managing the panel's display state and sending selected color data to Flutter. + */ +@interface FLEWindowSizePlugin : NSObject + +@end diff --git a/plugins/window_size/macos/FLEWindowSizePlugin.mm b/plugins/window_size/macos/FLEWindowSizePlugin.mm new file mode 100644 index 000000000..e11979e17 --- /dev/null +++ b/plugins/window_size/macos/FLEWindowSizePlugin.mm @@ -0,0 +1,141 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FLEWindowSizePlugin.h" + +#import + +#include "plugins/window_size/common/channel_constants.h" + +/** + * Returns the max Y coordinate across all screens. + */ +CGFloat GetMaxScreenY() { + CGFloat maxY = 0; + for (NSScreen *screen in [NSScreen screens]) { + maxY = MAX(maxY, CGRectGetMaxY(screen.frame)); + } + return maxY; +} + +/** + * Given |frame| in screen coordinates, returns a frame flipped relative to + * GetMaxScreenY(). + */ +NSRect GetFlippedRect(NSRect frame) { + CGFloat maxY = GetMaxScreenY(); + return NSMakeRect(frame.origin.x, maxY - frame.origin.y - frame.size.height, frame.size.width, + frame.size.height); +} + +@interface FLEWindowSizePlugin () +/** + * Extracts information from |screen| and returns the serialiable form expected + * by the platform channel. + */ +- (NSDictionary *)platformChannelRepresentationForScreen:(NSScreen *)screen; + +/** + * Extracts information from |window| and returns the serialiable form expected + * by the platform channel. + */ +- (NSDictionary *)platformChannelRepresentationForWindow:(NSWindow *)window; + +/** + * Returns the serialiable form of |frame| expected by the platform channel. + */ +- (NSArray *)platformChannelRepresentationForFrame:(NSRect)frame; + +@end + +@implementation FLEWindowSizePlugin { + // The channel used to communicate with Flutter. + FlutterMethodChannel *_channel; + // The view displaying Flutter content. + NSView *_flutterView; +} + ++ (void)registerWithRegistrar:(id)registrar { + FlutterMethodChannel *channel = + [FlutterMethodChannel methodChannelWithName:@(plugins_window_size::kChannelName) + binaryMessenger:registrar.messenger]; + FLEWindowSizePlugin *instance = [[FLEWindowSizePlugin alloc] initWithChannel:channel + view:registrar.view]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (instancetype)initWithChannel:(FlutterMethodChannel *)channel view:(NSView *)view { + self = [super init]; + if (self) { + _channel = channel; + _flutterView = view; + } + return self; +} + +/** + * Handles platform messages generated by the Flutter framework on the color + * panel channel. + */ +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + id methodResult = nil; + if ([call.method isEqualToString:@(plugins_window_size::kGetScreenListMethod)]) { + NSMutableArray *screenList = + [NSMutableArray arrayWithCapacity:[NSScreen screens].count]; + for (NSScreen *screen in [NSScreen screens]) { + [screenList addObject:[self platformChannelRepresentationForScreen:screen]]; + } + methodResult = screenList; + } else if ([call.method isEqualToString:@(plugins_window_size::kGetWindowInfoMethod)]) { + methodResult = [self platformChannelRepresentationForWindow:_flutterView.window]; + } else if ([call.method isEqualToString:@(plugins_window_size::kSetWindowFrameMethod)]) { + NSArray *arguments = call.arguments; + [_flutterView.window + setFrame:GetFlippedRect(NSMakeRect(arguments[0].doubleValue, arguments[1].doubleValue, + arguments[2].doubleValue, arguments[3].doubleValue)) + display:YES]; + methodResult = nil; + } else { + methodResult = FlutterMethodNotImplemented; + } + result(methodResult); +} + +#pragma mark - Private methods + +- (NSDictionary *)platformChannelRepresentationForScreen:(NSScreen *)screen { + return @{ + @(plugins_window_size::kFrameKey) : + [self platformChannelRepresentationForFrame:GetFlippedRect(screen.frame)], + @(plugins_window_size::kVisibleFrameKey) : + [self platformChannelRepresentationForFrame:GetFlippedRect(screen.visibleFrame)], + @(plugins_window_size::kScaleFactorKey) : @(screen.backingScaleFactor), + }; +} + +- (NSDictionary *)platformChannelRepresentationForWindow:(NSWindow *)window { + return @{ + @(plugins_window_size::kFrameKey) : + [self platformChannelRepresentationForFrame:GetFlippedRect(window.frame)], + @(plugins_window_size::kScreenKey) : + [self platformChannelRepresentationForScreen:window.screen], + @(plugins_window_size::kScaleFactorKey) : @(window.backingScaleFactor), + }; +} + +- (NSArray *)platformChannelRepresentationForFrame:(NSRect)frame { + return @[ @(frame.origin.x), @(frame.origin.y), @(frame.size.width), @(frame.size.height) ]; +} + +@end diff --git a/plugins/window_size/macos/FlutterEmbedderWindowSize.h b/plugins/window_size/macos/FlutterEmbedderWindowSize.h new file mode 100644 index 000000000..507d179c7 --- /dev/null +++ b/plugins/window_size/macos/FlutterEmbedderWindowSize.h @@ -0,0 +1,15 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FLEWindowSizePlugin.h" diff --git a/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.pbxproj b/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.pbxproj new file mode 100644 index 000000000..738007304 --- /dev/null +++ b/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.pbxproj @@ -0,0 +1,397 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 3329FFD020C9D284002E5F16 /* FlutterEmbedderWindowSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 3329FFCF20C9D25C002E5F16 /* FlutterEmbedderWindowSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 332A46CE20C9D15C00C30EB9 /* FLEWindowSizePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 332A46CC20C9D15C00C30EB9 /* FLEWindowSizePlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 332A46CF20C9D15C00C30EB9 /* FLEWindowSizePlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 332A46CD20C9D15C00C30EB9 /* FLEWindowSizePlugin.mm */; }; + 332A46D520C9D18000C30EB9 /* channel_constants.cc in Sources */ = {isa = PBXBuildFile; fileRef = 332A46D320C9D18000C30EB9 /* channel_constants.cc */; }; + 3378246F20D3758700909728 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3378246E20D3758700909728 /* AppKit.framework */; }; + 33D1A0FD221487DE006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A0FC221487DE006C7A3E /* FlutterMacOS.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33D1A0F4221487AF006C7A3E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3329FFD820C9D496002E5F16 /* SharedFlutterFramework.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 1E2492471FCF585600DD3BBB; + remoteInfo = "Fetch Shared Flutter Framework"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 3329FFCF20C9D25C002E5F16 /* FlutterEmbedderWindowSize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlutterEmbedderWindowSize.h; sourceTree = ""; }; + 3329FFD820C9D496002E5F16 /* SharedFlutterFramework.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SharedFlutterFramework.xcodeproj; path = ../../common/macos/SharedFlutterFramework.xcodeproj; sourceTree = ""; }; + 332A46C120C9CFE600C30EB9 /* FlutterEmbedderWindowSize.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FlutterEmbedderWindowSize.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 332A46C520C9CFE600C30EB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 332A46CC20C9D15C00C30EB9 /* FLEWindowSizePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEWindowSizePlugin.h; sourceTree = ""; }; + 332A46CD20C9D15C00C30EB9 /* FLEWindowSizePlugin.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FLEWindowSizePlugin.mm; sourceTree = ""; }; + 332A46D320C9D18000C30EB9 /* channel_constants.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = channel_constants.cc; sourceTree = ""; }; + 332A46D420C9D18000C30EB9 /* channel_constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = channel_constants.h; sourceTree = ""; }; + 3378246E20D3758700909728 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 33D1A0FC221487DE006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = ../../../../flutter_framework/FlutterMacOS.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 332A46BD20C9CFE600C30EB9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3378246F20D3758700909728 /* AppKit.framework in Frameworks */, + 33D1A0FD221487DE006C7A3E /* FlutterMacOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3329FFD920C9D496002E5F16 /* Products */ = { + isa = PBXGroup; + children = ( + ); + name = Products; + sourceTree = ""; + }; + 332A46B720C9CFE600C30EB9 = { + isa = PBXGroup; + children = ( + 3329FFCF20C9D25C002E5F16 /* FlutterEmbedderWindowSize.h */, + 332A46CC20C9D15C00C30EB9 /* FLEWindowSizePlugin.h */, + 332A46CD20C9D15C00C30EB9 /* FLEWindowSizePlugin.mm */, + 332A46D220C9D18000C30EB9 /* common */, + 332A46C520C9CFE600C30EB9 /* Info.plist */, + 332A46C220C9CFE600C30EB9 /* Products */, + 3329FFD820C9D496002E5F16 /* SharedFlutterFramework.xcodeproj */, + 3378246B20D3758100909728 /* Frameworks */, + ); + sourceTree = ""; + }; + 332A46C220C9CFE600C30EB9 /* Products */ = { + isa = PBXGroup; + children = ( + 332A46C120C9CFE600C30EB9 /* FlutterEmbedderWindowSize.framework */, + ); + name = Products; + sourceTree = ""; + }; + 332A46D220C9D18000C30EB9 /* common */ = { + isa = PBXGroup; + children = ( + 332A46D320C9D18000C30EB9 /* channel_constants.cc */, + 332A46D420C9D18000C30EB9 /* channel_constants.h */, + ); + name = common; + path = ../common; + sourceTree = ""; + }; + 3378246B20D3758100909728 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 33D1A0FC221487DE006C7A3E /* FlutterMacOS.framework */, + 3378246E20D3758700909728 /* AppKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 332A46BE20C9CFE600C30EB9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3329FFD020C9D284002E5F16 /* FlutterEmbedderWindowSize.h in Headers */, + 332A46CE20C9D15C00C30EB9 /* FLEWindowSizePlugin.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 332A46C020C9CFE600C30EB9 /* FlutterEmbedderWindowSize */ = { + isa = PBXNativeTarget; + buildConfigurationList = 332A46C920C9CFE600C30EB9 /* Build configuration list for PBXNativeTarget "FlutterEmbedderWindowSize" */; + buildPhases = ( + 332A46BC20C9CFE600C30EB9 /* Sources */, + 332A46BD20C9CFE600C30EB9 /* Frameworks */, + 332A46BE20C9CFE600C30EB9 /* Headers */, + 332A46BF20C9CFE600C30EB9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 33D1A0F5221487AF006C7A3E /* PBXTargetDependency */, + ); + name = FlutterEmbedderWindowSize; + productName = FlutterEmbedderWindowSize; + productReference = 332A46C120C9CFE600C30EB9 /* FlutterEmbedderWindowSize.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 332A46B820C9CFE600C30EB9 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "Google LLC"; + TargetAttributes = { + 332A46C020C9CFE600C30EB9 = { + CreatedOnToolsVersion = 9.3.1; + }; + }; + }; + buildConfigurationList = 332A46BB20C9CFE600C30EB9 /* Build configuration list for PBXProject "FlutterEmbedderWindowSize" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 332A46B720C9CFE600C30EB9; + productRefGroup = 332A46C220C9CFE600C30EB9 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 3329FFD920C9D496002E5F16 /* Products */; + ProjectRef = 3329FFD820C9D496002E5F16 /* SharedFlutterFramework.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 332A46C020C9CFE600C30EB9 /* FlutterEmbedderWindowSize */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 332A46BF20C9CFE600C30EB9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 332A46BC20C9CFE600C30EB9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 332A46CF20C9D15C00C30EB9 /* FLEWindowSizePlugin.mm in Sources */, + 332A46D520C9D18000C30EB9 /* channel_constants.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33D1A0F5221487AF006C7A3E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Fetch Shared Flutter Framework"; + targetProxy = 33D1A0F4221487AF006C7A3E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 332A46C720C9CFE600C30EB9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + FDE_ROOT = $PROJECT_DIR/../../..; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 332A46C820C9CFE600C30EB9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FDE_ROOT = $PROJECT_DIR/../../..; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 332A46CA20C9CFE600C30EB9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = $FDE_ROOT/../flutter_framework; + FRAMEWORK_VERSION = A; + HEADER_SEARCH_PATHS = ../../..; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.google.FlutterEmbedderWindowSize; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 332A46CB20C9CFE600C30EB9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = $FDE_ROOT/../flutter_framework; + FRAMEWORK_VERSION = A; + HEADER_SEARCH_PATHS = ../../..; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.google.FlutterEmbedderWindowSize; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 332A46BB20C9CFE600C30EB9 /* Build configuration list for PBXProject "FlutterEmbedderWindowSize" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 332A46C720C9CFE600C30EB9 /* Debug */, + 332A46C820C9CFE600C30EB9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 332A46C920C9CFE600C30EB9 /* Build configuration list for PBXNativeTarget "FlutterEmbedderWindowSize" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 332A46CA20C9CFE600C30EB9 /* Debug */, + 332A46CB20C9CFE600C30EB9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 332A46B820C9CFE600C30EB9 /* Project object */; +} diff --git a/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..efc54300c --- /dev/null +++ b/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/plugins/window_size/macos/Info.plist b/plugins/window_size/macos/Info.plist new file mode 100644 index 000000000..1007fd9dd --- /dev/null +++ b/plugins/window_size/macos/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/plugins/window_size/pubspec.yaml b/plugins/window_size/pubspec.yaml new file mode 100644 index 000000000..be8fd7f6f --- /dev/null +++ b/plugins/window_size/pubspec.yaml @@ -0,0 +1,8 @@ +name: window_size +description: Window resizing for desktop Flutter +dependencies: + flutter: + sdk: flutter + +environment: + sdk: '<3.0.0' diff --git a/testbed/lib/main.dart b/testbed/lib/main.dart index f70d89ca1..03c5666f2 100644 --- a/testbed/lib/main.dart +++ b/testbed/lib/main.dart @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. import 'dart:io' show Platform; +import 'dart:math' as math; import 'package:flutter/foundation.dart' show debugDefaultTargetPlatformOverride; @@ -21,11 +22,30 @@ import 'package:color_panel/color_panel.dart'; import 'package:example_flutter/keyboard_test_page.dart'; import 'package:file_chooser/file_chooser.dart' as file_chooser; import 'package:menubar/menubar.dart'; +import 'package:window_size/window_size.dart' as window_size; void main() { // Desktop platforms are not recognized as valid targets by // Flutter; force a specific target to prevent exceptions. debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia; + + // Try to resize and reposition the window to be half the width and height + // of its screen, centered horizontally and shifted up from center. + if (Platform.isMacOS) { + window_size.getWindowInfo().then((window) { + if (window.screen != null) { + final screenFrame = window.screen.visibleFrame; + final width = math.max((screenFrame.width / 2).roundToDouble(), 640.0); + final height = + math.max((screenFrame.height / 2).roundToDouble(), 480.0); + final left = ((screenFrame.width - width) / 2).roundToDouble(); + final top = ((screenFrame.height - height) / 3).roundToDouble(); + final frame = Rect.fromLTWH(left, top, width, height); + window_size.setWindowFrame(frame); + } + }); + } + runApp(new MyApp()); } diff --git a/testbed/macos/PluginRegistrant.m b/testbed/macos/PluginRegistrant.m index e68da6770..e5ba2c5bd 100644 --- a/testbed/macos/PluginRegistrant.m +++ b/testbed/macos/PluginRegistrant.m @@ -21,6 +21,7 @@ #import #import #import +#import @implementation PluginRegistrant @@ -28,6 +29,7 @@ + (void)registerWithRegistry:(NSObject*)registry { [FLEColorPanelPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLEColorPanelPlugin"]]; [FLEFileChooserPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLEFileChooserPlugin"]]; [FLEMenubarPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLEMenubarPlugin"]]; + [FLEWindowSizePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLEWindowSizePlugin"]]; } @end diff --git a/testbed/macos/Runner.xcodeproj/project.pbxproj b/testbed/macos/Runner.xcodeproj/project.pbxproj index 90ccfccb2..34d1e014e 100644 --- a/testbed/macos/Runner.xcodeproj/project.pbxproj +++ b/testbed/macos/Runner.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 33CC111E2044C6BF0003C045 /* ShellScript */, ); dependencies = ( - 33D1A0EC22148486006C7A3E /* PBXTargetDependency */, ); name = "Build Flutter Bundle"; productName = FLX; @@ -25,6 +24,8 @@ 3329005320D2EC9E002E5F16 /* FlutterEmbedderFileChooser.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 3329004F20D2EC7C002E5F16 /* FlutterEmbedderFileChooser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3329009620D84F99002E5F16 /* FlutterEmbedderMenubar.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 3329009320D84F6E002E5F16 /* FlutterEmbedderMenubar.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3329FFFF20C9F5D9002E5F16 /* FlutterEmbedderColorPanel.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 3329FFFB20C9F5AC002E5F16 /* FlutterEmbedderColorPanel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3399D4652277B94E009A79C7 /* FlutterEmbedderWindowSize.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3399D4642277B915009A79C7 /* FlutterEmbedderWindowSize.framework */; }; + 3399D4662277B95B009A79C7 /* FlutterEmbedderWindowSize.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 3399D4642277B915009A79C7 /* FlutterEmbedderWindowSize.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 33A2DE652267798600914F77 /* PluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 33A2DE642267798600914F77 /* PluginRegistrant.m */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -36,9 +37,6 @@ 33E98C0521824E4000EB88EF /* FlutterEmbedderMenubar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3329009320D84F6E002E5F16 /* FlutterEmbedderMenubar.framework */; }; 33E98C0721824E4800EB88EF /* FlutterEmbedderFileChooser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3329004F20D2EC7C002E5F16 /* FlutterEmbedderFileChooser.framework */; }; 33E98C0821824E4C00EB88EF /* FlutterEmbedderColorPanel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3329FFFB20C9F5AC002E5F16 /* FlutterEmbedderColorPanel.framework */; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004394FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -84,6 +82,20 @@ remoteGlobalIDString = 332A46C020C9CFE600C30EB9; remoteInfo = FlutterEmbedderColorPanel; }; + 3399D4632277B915009A79C7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3399D45E2277B915009A79C7 /* FlutterEmbedderWindowSize.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 332A46C120C9CFE600C30EB9; + remoteInfo = FlutterEmbedderWindowSize; + }; + 3399D4672277BA0B009A79C7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3399D45E2277B915009A79C7 /* FlutterEmbedderWindowSize.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 332A46C020C9CFE600C30EB9; + remoteInfo = FlutterEmbedderWindowSize; + }; 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 33CC10E52044A3C60003C045 /* Project object */; @@ -100,6 +112,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 3399D4662277B95B009A79C7 /* FlutterEmbedderWindowSize.framework in Bundle Framework */, 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */, 3329009620D84F99002E5F16 /* FlutterEmbedderMenubar.framework in Bundle Framework */, 3329005320D2EC9E002E5F16 /* FlutterEmbedderFileChooser.framework in Bundle Framework */, @@ -114,6 +127,8 @@ 3329004920D2EC7C002E5F16 /* FlutterEmbedderFileChooser.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FlutterEmbedderFileChooser.xcodeproj; path = ../../plugins/file_chooser/macos/FlutterEmbedderFileChooser.xcodeproj; sourceTree = ""; }; 3329008D20D84F6E002E5F16 /* FlutterEmbedderMenubar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FlutterEmbedderMenubar.xcodeproj; path = ../../plugins/menubar/macos/FlutterEmbedderMenubar.xcodeproj; sourceTree = ""; }; 3329FFF520C9F5AC002E5F16 /* FlutterEmbedderColorPanel.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FlutterEmbedderColorPanel.xcodeproj; path = ../../plugins/color_panel/macos/FlutterEmbedderColorPanel.xcodeproj; sourceTree = ""; }; + 3399D4442277B840009A79C7 /* Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 3399D45E2277B915009A79C7 /* FlutterEmbedderWindowSize.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FlutterEmbedderWindowSize.xcodeproj; path = ../../plugins/window_size/macos/FlutterEmbedderWindowSize.xcodeproj; sourceTree = ""; }; 33A2DE632267798600914F77 /* PluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginRegistrant.h; sourceTree = ""; }; 33A2DE642267798600914F77 /* PluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PluginRegistrant.m; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* Testbed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Testbed.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -125,6 +140,8 @@ 33CC11162044C3600003C045 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 33CC112C20461AD40003C045 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = ../build/flutter_assets; sourceTree = ""; }; 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = ../flutter_framework/FlutterMacOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -135,6 +152,7 @@ 33E98C0821824E4C00EB88EF /* FlutterEmbedderColorPanel.framework in Frameworks */, 33E98C0721824E4800EB88EF /* FlutterEmbedderFileChooser.framework in Frameworks */, 33E98C0521824E4000EB88EF /* FlutterEmbedderMenubar.framework in Frameworks */, + 3399D4652277B94E009A79C7 /* FlutterEmbedderWindowSize.framework in Frameworks */, 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -166,6 +184,24 @@ name = Products; sourceTree = ""; }; + 3399D4432277B6F6009A79C7 /* Configs */ = { + isa = PBXGroup; + children = ( + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 3399D4442277B840009A79C7 /* Generated.xcconfig */, + ); + name = Configs; + sourceTree = ""; + }; + 3399D45F2277B915009A79C7 /* Products */ = { + isa = PBXGroup; + children = ( + 3399D4642277B915009A79C7 /* FlutterEmbedderWindowSize.framework */, + ); + name = Products; + sourceTree = ""; + }; 33CC10E42044A3C60003C045 = { isa = PBXGroup; children = ( @@ -175,11 +211,13 @@ 33A2DE642267798600914F77 /* PluginRegistrant.m */, 33CC11162044C3600003C045 /* Runner-Bridging-Header.h */, 33CC11242044D66E0003C045 /* Resources */, + 3399D4432277B6F6009A79C7 /* Configs */, 33D1A10222148A83006C7A3E /* Frameworks */, 33CC10EE2044A3C60003C045 /* Products */, 3329FFF520C9F5AC002E5F16 /* FlutterEmbedderColorPanel.xcodeproj */, 3329004920D2EC7C002E5F16 /* FlutterEmbedderFileChooser.xcodeproj */, 3329008D20D84F6E002E5F16 /* FlutterEmbedderMenubar.xcodeproj */, + 3399D45E2277B915009A79C7 /* FlutterEmbedderWindowSize.xcodeproj */, ); sourceTree = ""; }; @@ -202,15 +240,6 @@ name = Resources; sourceTree = ""; }; - D76E93BA226BCA8F00F7932B /* Configs */ = { - isa = PBXGroup; - children = ( - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - ); - name = "Configs"; - sourceTree = ""; - }; 33D1A10222148A83006C7A3E /* Frameworks */ = { isa = PBXGroup; children = ( @@ -234,14 +263,14 @@ buildRules = ( ); dependencies = ( - 33D1A0EA2214847F006C7A3E /* PBXTargetDependency */, 33CC11202044C79F0003C045 /* PBXTargetDependency */, 3329FFFE20C9F5CF002E5F16 /* PBXTargetDependency */, 3329005220D2EC90002E5F16 /* PBXTargetDependency */, 3329009520D84F84002E5F16 /* PBXTargetDependency */, + 3399D4682277BA0B009A79C7 /* PBXTargetDependency */, ); name = Runner; - productName = "Testbed"; + productName = Testbed; productReference = 33CC10ED2044A3C60003C045 /* Testbed.app */; productType = "com.apple.product-type.application"; }; @@ -290,6 +319,10 @@ ProductGroup = 3329008E20D84F6E002E5F16 /* Products */; ProjectRef = 3329008D20D84F6E002E5F16 /* FlutterEmbedderMenubar.xcodeproj */; }, + { + ProductGroup = 3399D45F2277B915009A79C7 /* Products */; + ProjectRef = 3399D45E2277B915009A79C7 /* FlutterEmbedderWindowSize.xcodeproj */; + }, ); projectRoot = ""; targets = ( @@ -321,6 +354,13 @@ remoteRef = 3329FFFA20C9F5AC002E5F16 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 3399D4642277B915009A79C7 /* FlutterEmbedderWindowSize.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = FlutterEmbedderWindowSize.framework; + remoteRef = 3399D4632277B915009A79C7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ @@ -381,6 +421,11 @@ name = FlutterEmbedderColorPanel; targetProxy = 3329FFFD20C9F5CF002E5F16 /* PBXContainerItemProxy */; }; + 3399D4682277BA0B009A79C7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FlutterEmbedderWindowSize; + targetProxy = 3399D4672277BA0B009A79C7 /* PBXContainerItemProxy */; + }; 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 33CC111A2044C6BA0003C045 /* Build Flutter Bundle */; @@ -569,22 +614,6 @@ }; name = Release; }; - 33D1A0E622148440006C7A3E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33D1A0E722148440006C7A3E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -615,15 +644,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 33D1A0E522148440006C7A3E /* Build configuration list for PBXAggregateTarget "Fetch Flutter Framework" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33D1A0E622148440006C7A3E /* Debug */, - 33D1A0E722148440006C7A3E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; diff --git a/testbed/pubspec.yaml b/testbed/pubspec.yaml index 1111bea12..d911710c6 100644 --- a/testbed/pubspec.yaml +++ b/testbed/pubspec.yaml @@ -17,6 +17,8 @@ dependencies: path: ../plugins/file_chooser menubar: path: ../plugins/menubar + window_size: + path: ../plugins/window_size dev_dependencies: flutter_test: