window_size_channel.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import 'dart:async';
  15. import 'dart:ui';
  16. import 'package:flutter/services.dart';
  17. import 'platform_window.dart';
  18. import 'screen.dart';
  19. /// The name of the plugin's platform channel.
  20. const String _windowSizeChannelName = 'flutter/windowsize';
  21. /// The method name to request information about the available screens.
  22. ///
  23. /// Returns a list of screen info maps; see keys below.
  24. const String _getScreenListMethod = 'getScreenList';
  25. /// The method name to request information about the window containing the
  26. /// Flutter instance.
  27. ///
  28. /// Returns a list of window info maps; see keys below.
  29. const String _getWindowInfoMethod = 'getWindowInfo';
  30. /// The method name to set the frame of a window.
  31. ///
  32. /// Takes a frame array, as documented for the value of _frameKey.
  33. const String _setWindowFrameMethod = 'setWindowFrame';
  34. /// The method name to set the minimum size of a window.
  35. ///
  36. /// Takes a window size array, with the value is a list of two doubles:
  37. /// [width, height].
  38. ///
  39. /// A value of zero for width or height is to be interpreted as
  40. /// unconstrained in that dimension.
  41. const String _setWindowMinimumSizeMethod = 'setWindowMinimumSize';
  42. /// The method name to set the maximum size of a window.
  43. ///
  44. /// Takes a window size array, with the value is a list of two doubles:
  45. /// [width, height].
  46. ///
  47. /// A value of `-1` for width or height is to be interpreted as
  48. /// unconstrained in that dimension.
  49. const String _setWindowMaximumSizeMethod = 'setWindowMaximumSize';
  50. /// The method name to set the window title of a window.
  51. const String _setWindowTitleMethod = 'setWindowTitle';
  52. /// The method name to set the window title's represented URL.
  53. ///
  54. /// Only implemented for macOS. If the URL is a file URL, the
  55. /// window shows an icon in its title bar.
  56. const String _setWindowTitleRepresentedUrlMethod =
  57. 'setWindowTitleRepresentedUrl';
  58. /// The method name to get the minimum size of a window.
  59. ///
  60. /// Returns a window size array, with the value is a list of two doubles:
  61. /// [width, height].
  62. ///
  63. /// A value of zero for width or height is to be interpreted as
  64. /// unconstrained in that dimension.
  65. const String _getWindowMinimumSizeMethod = 'getWindowMinimumSize';
  66. /// The method name to get the maximum size of a window.
  67. ///
  68. /// Returns a window size array, with the value is a list of two doubles:
  69. /// [width, height].
  70. ///
  71. /// A value of `-1` for width or height is to be interpreted as
  72. /// unconstrained in that dimension.
  73. const String _getWindowMaximumSizeMethod = 'getWindowMaximumSize';
  74. /// The method name to set the window visibility.
  75. ///
  76. /// The argument will be a boolean controlling whether or not the window should
  77. /// be visible.
  78. const String _setWindowVisibilityMethod = 'setWindowVisibility';
  79. // Keys for screen and window maps returned by _getScreenListMethod.
  80. /// The frame of a screen or window. The value is a list of four doubles:
  81. /// [left, top, width, height]
  82. const String _frameKey = 'frame';
  83. /// The frame of a screen available for use by applications. The value format
  84. /// is the same as _frameKey's.
  85. ///
  86. /// Only used for screens.
  87. const String _visibleFrameKey = 'visibleFrame';
  88. /// The scale factor for a screen or window, as a double.
  89. ///
  90. /// This is the number of pixels per screen coordinate, and thus the ratio
  91. /// between sizes as seen by Flutter and sizes in native screen coordinates.
  92. const String _scaleFactorKey = 'scaleFactor';
  93. /// The screen containing this window, if any. The value is a screen map, or
  94. /// null if the window is not visible on a screen.
  95. ///
  96. /// Only used for windows.
  97. ///
  98. /// If a window is on multiple screens, it is up to the platform to decide which
  99. /// screen to report.
  100. const String _screenKey = 'screen';
  101. /// A singleton object that handles the interaction with the platform channel.
  102. class WindowSizeChannel {
  103. /// Private constructor.
  104. WindowSizeChannel._();
  105. final MethodChannel _platformChannel =
  106. const MethodChannel(_windowSizeChannelName);
  107. /// The static instance of the menu channel.
  108. static final WindowSizeChannel instance = new WindowSizeChannel._();
  109. /// Returns a list of screens.
  110. Future<List<Screen>> getScreenList() async {
  111. final screenList = <Screen>[];
  112. final response = await _platformChannel.invokeMethod(_getScreenListMethod);
  113. for (final screenInfo in response) {
  114. screenList.add(_screenFromInfoMap(screenInfo));
  115. }
  116. return screenList;
  117. }
  118. /// Returns information about the window containing this Flutter instance.
  119. Future<PlatformWindow> getWindowInfo() async {
  120. final response = await _platformChannel.invokeMethod(_getWindowInfoMethod);
  121. final screenInfo = response[_screenKey];
  122. final screen = screenInfo == null ? null : _screenFromInfoMap(screenInfo);
  123. return PlatformWindow(_rectFromLTWHList(response[_frameKey].cast<double>()),
  124. response[_scaleFactorKey], screen);
  125. }
  126. /// Sets the frame of the window containing this Flutter instance, in
  127. /// screen coordinates.
  128. ///
  129. /// The platform may adjust the frame as necessary if the provided frame would
  130. /// cause significant usability issues (e.g., a window with no visible portion
  131. /// that can be used to move the window).
  132. void setWindowFrame(Rect frame) async {
  133. assert(!frame.isEmpty, 'Cannot set window frame to an empty rect.');
  134. assert(frame.isFinite, 'Cannot set window frame to a non-finite rect.');
  135. await _platformChannel.invokeMethod(_setWindowFrameMethod,
  136. [frame.left, frame.top, frame.width, frame.height]);
  137. }
  138. /// Sets the minimum size of the window containing this Flutter instance.
  139. void setWindowMinSize(Size size) async {
  140. await _platformChannel
  141. .invokeMethod(_setWindowMinimumSizeMethod, [size.width, size.height]);
  142. }
  143. /// Sets the visibility of the window.
  144. void setWindowVisibility({required bool visible}) async {
  145. await _platformChannel.invokeMethod(_setWindowVisibilityMethod, visible);
  146. }
  147. // Window maximum size unconstrained is passed over the channel as -1.
  148. double _channelRepresentationForMaxDimension(double size) {
  149. return size == double.infinity ? -1 : size;
  150. }
  151. /// Sets the maximum size of the window containing this Flutter instance.
  152. void setWindowMaxSize(Size size) async {
  153. await _platformChannel.invokeMethod(_setWindowMaximumSizeMethod, [
  154. _channelRepresentationForMaxDimension(size.width),
  155. _channelRepresentationForMaxDimension(size.height),
  156. ]);
  157. }
  158. /// Sets the title of the window containing this Flutter instance.
  159. void setWindowTitle(String title) async {
  160. await _platformChannel.invokeMapMethod(_setWindowTitleMethod, title);
  161. }
  162. /// Sets the title's represented URL of the window containing this Flutter instance.
  163. void setWindowTitleRepresentedUrl(Uri file) async {
  164. await _platformChannel.invokeMapMethod(
  165. _setWindowTitleRepresentedUrlMethod, file.toString());
  166. }
  167. /// Gets the minimum size of the window containing this Flutter instance.
  168. Future<Size> getWindowMinSize() async {
  169. final response =
  170. await _platformChannel.invokeMethod(_getWindowMinimumSizeMethod);
  171. return _sizeFromWHList(List<double>.from(response.cast<double>()));
  172. }
  173. // Window maximum size unconstrained is passed over the channel as -1.
  174. double _maxDimensionFromChannelRepresentation(double size) {
  175. return size == -1 ? double.infinity : size;
  176. }
  177. /// Gets the maximum size of the window containing this Flutter instance.
  178. Future<Size> getWindowMaxSize() async {
  179. final response =
  180. await _platformChannel.invokeMethod(_getWindowMaximumSizeMethod);
  181. return _sizeFromWHList(
  182. List<double>.from(
  183. response.cast<double>().map(_maxDimensionFromChannelRepresentation),
  184. ),
  185. );
  186. }
  187. /// Given an array of the form [left, top, width, height], return the
  188. /// corresponding [Rect].
  189. ///
  190. /// Used for frame deserialization in the platform channel.
  191. Rect _rectFromLTWHList(List<double> ltwh) {
  192. return Rect.fromLTWH(ltwh[0], ltwh[1], ltwh[2], ltwh[3]);
  193. }
  194. /// Given an array of the form [width, height], return the corresponding
  195. /// [Size].
  196. ///
  197. /// Used for window size deserialization in the platform channel.
  198. Size _sizeFromWHList(List<double> wh) {
  199. return Size(wh[0], wh[1]);
  200. }
  201. /// Given a map of information about a screen, return the corresponding
  202. /// [Screen] object.
  203. ///
  204. /// Used for screen deserialization in the platform channel.
  205. Screen _screenFromInfoMap(Map<dynamic, dynamic> map) {
  206. return Screen(
  207. _rectFromLTWHList(map[_frameKey].cast<double>()),
  208. _rectFromLTWHList(map[_visibleFrameKey].cast<double>()),
  209. map[_scaleFactorKey]);
  210. }
  211. }