From ce3b07fe5d9ea88e2fb583eed50ddc233c6a64a5 Mon Sep 17 00:00:00 2001 From: Louise Hsu Date: Wed, 1 Nov 2023 10:40:08 -0700 Subject: [PATCH 1/4] move pointer_interceptor to sub folder --- .../pointer_interceptor/.gitignore | 74 ++++++ .../pointer_interceptor/.metadata | 10 + .../pointer_interceptor/AUTHORS | 7 + .../pointer_interceptor/CHANGELOG.md | 64 +++++ .../pointer_interceptor/LICENSE | 25 ++ .../pointer_interceptor/README.md | 103 ++++++++ .../doc/img/affected-areas.png | Bin 0 -> 15011 bytes .../doc/img/fixed-areas.png | Bin 0 -> 17538 bytes .../pointer_interceptor/example/.gitignore | 46 ++++ .../pointer_interceptor/example/.metadata | 10 + .../pointer_interceptor/example/README.md | 17 ++ .../example/integration_test/widget_test.dart | 179 ++++++++++++++ .../pointer_interceptor/example/lib/main.dart | 219 ++++++++++++++++++ .../pointer_interceptor/example/pubspec.yaml | 28 +++ .../example/test_driver/integration_test.dart | 7 + .../example/web/favicon.png | Bin 0 -> 917 bytes .../example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../example/web/index.html | 48 ++++ .../example/web/manifest.json | 23 ++ .../lib/pointer_interceptor.dart | 7 + .../pointer_interceptor/lib/src/mobile.dart | 34 +++ .../pointer_interceptor/lib/src/web.dart | 93 ++++++++ .../pointer_interceptor/pubspec.yaml | 21 ++ .../pointer_interceptor/test/README.md | 5 + .../test/tests_exist_elsewhere_test.dart | 16 ++ 26 files changed, 1036 insertions(+) create mode 100644 packages/pointer_interceptor/pointer_interceptor/.gitignore create mode 100644 packages/pointer_interceptor/pointer_interceptor/.metadata create mode 100644 packages/pointer_interceptor/pointer_interceptor/AUTHORS create mode 100644 packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md create mode 100644 packages/pointer_interceptor/pointer_interceptor/LICENSE create mode 100644 packages/pointer_interceptor/pointer_interceptor/README.md create mode 100644 packages/pointer_interceptor/pointer_interceptor/doc/img/affected-areas.png create mode 100644 packages/pointer_interceptor/pointer_interceptor/doc/img/fixed-areas.png create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/.gitignore create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/.metadata create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/README.md create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/integration_test/widget_test.dart create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/lib/main.dart create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/test_driver/integration_test.dart create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/web/favicon.png create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/web/icons/Icon-192.png create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/web/icons/Icon-512.png create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/web/index.html create mode 100644 packages/pointer_interceptor/pointer_interceptor/example/web/manifest.json create mode 100644 packages/pointer_interceptor/pointer_interceptor/lib/pointer_interceptor.dart create mode 100644 packages/pointer_interceptor/pointer_interceptor/lib/src/mobile.dart create mode 100644 packages/pointer_interceptor/pointer_interceptor/lib/src/web.dart create mode 100644 packages/pointer_interceptor/pointer_interceptor/pubspec.yaml create mode 100644 packages/pointer_interceptor/pointer_interceptor/test/README.md create mode 100644 packages/pointer_interceptor/pointer_interceptor/test/tests_exist_elsewhere_test.dart diff --git a/packages/pointer_interceptor/pointer_interceptor/.gitignore b/packages/pointer_interceptor/pointer_interceptor/.gitignore new file mode 100644 index 00000000000..1985397a2cb --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/.gitignore @@ -0,0 +1,74 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 diff --git a/packages/pointer_interceptor/pointer_interceptor/.metadata b/packages/pointer_interceptor/pointer_interceptor/.metadata new file mode 100644 index 00000000000..b5330742eed --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: e6bd95bc5caa5e34c5b0285a559673984374b7ea + channel: master + +project_type: package diff --git a/packages/pointer_interceptor/pointer_interceptor/AUTHORS b/packages/pointer_interceptor/pointer_interceptor/AUTHORS new file mode 100644 index 00000000000..eb34297f179 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/AUTHORS @@ -0,0 +1,7 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +The Chromium Authors diff --git a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md new file mode 100644 index 00000000000..3a66b061ff7 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md @@ -0,0 +1,64 @@ +## 0.9.3+6 + +* Migrates to `dart:ui_web` APIs. +* Updates minimum supported SDK version to Flutter 3.13.0/Dart 3.1.0. + +## 0.9.3+5 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. +* Aligns Dart and Flutter SDK constraints. + +## 0.9.3+4 + +* Removes const keyword from PointerInterceptor's constructor. +* Updates minimum Flutter version to 3.0. + +## 0.9.3+3 + +* Fixes lint warnings. + +## 0.9.3+2 + +* (Temporarily) helps tests introduced in prior version to pass in `stable`. + (This will be removed when `master` rolls to `stable`) +* Updates README to reference the correct github URL. + +## 0.9.3+1 + +* Updates example code and integration tests to accomodate hit-testing changes in the Flutter web engine. + +## 0.9.3 + +* Require minimal version of flutter SDK to be `2.10` + +## 0.9.2 + +* Marked `PointerInterceptor` as invisible, so it can be optimized by the engine. +* (Version Retracted. This attempted to use an API from Flutter `2.10` in earlier versions of Flutter. Fixed in v0.9.3) + +## 0.9.1 + +* Removed `android` and `ios` directories from `example`, as the example doesn't + build for those platforms. +* Added `intercepting` field to allow for conditional pointer interception + +## 0.9.0+1 + +* Change sizing of HtmlElementView so it works well when slotted. + +## 0.9.0 + +* Migrates to null safety. + +## 0.8.0+2 + +* Use `ElevatedButton` instead of the deprecated `RaisedButton` in example and docs. + +## 0.8.0+1 + +* Update README.md so images render in pub.dev + +## 0.8.0 + +* Initial release of the `PointerInterceptor` widget. diff --git a/packages/pointer_interceptor/pointer_interceptor/LICENSE b/packages/pointer_interceptor/pointer_interceptor/LICENSE new file mode 100644 index 00000000000..c6823b81eb8 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/pointer_interceptor/pointer_interceptor/README.md b/packages/pointer_interceptor/pointer_interceptor/README.md new file mode 100644 index 00000000000..6da163fc5d1 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/README.md @@ -0,0 +1,103 @@ +# pointer_interceptor + +`PointerInterceptor` is a widget that prevents mouse events (in web) from being captured by an underlying [`HtmlElementView`](https://api.flutter.dev/flutter/widgets/HtmlElementView-class.html). + +You can use this widget in a cross-platform app freely. In mobile, where the issue that this plugin fixes does not exist, the widget acts as a pass-through of its `children`, without adding anything to the render tree. + +## What is the problem? + +When overlaying Flutter widgets on top of `HtmlElementView` widgets that respond to mouse gestures (handle clicks, for example), the clicks will be consumed by the `HtmlElementView`, and not relayed to Flutter. + +The result is that Flutter widget's `onTap` (and other) handlers won't fire as expected, but they'll affect the underlying webview. + +|The problem...| +|:-:| +|![Depiction of problematic areas](https://raw.githubusercontent.com/flutter/packages/main/packages/pointer_interceptor/doc/img/affected-areas.png)| +|_In the dashed areas, mouse events won't work as expected. The `HtmlElementView` will consume them before Flutter sees them._| + + +## How does this work? + +`PointerInterceptor` creates a platform view consisting of an empty HTML element. The element has the size of its `child` widget, and is inserted in the layer tree _behind_ its child in paint order. + +This empty platform view doesn't do anything with mouse events, other than preventing them from reaching other platform views underneath it. + +This gives an opportunity to the Flutter framework to handle the click, as expected: + +|The solution...| +|:-:| +|![Depiction of the solution](https://raw.githubusercontent.com/flutter/packages/main/packages/pointer_interceptor/doc/img/fixed-areas.png)| +|_Each `PointerInterceptor` (green) renders between Flutter widgets and the underlying `HtmlElementView`. Mouse events now can't reach the background HtmlElementView, and work as expected._| + +## How to use + +Some common scenarios where this widget may come in handy: + +* [FAB](https://api.flutter.dev/flutter/material/FloatingActionButton-class.html) unclickable in an app that renders a full-screen background Map +* Custom Play/Pause buttons on top of a video element don't work +* Drawer contents not interactive when it overlaps an iframe element +* ... + +All the cases above have in common that they attempt to render Flutter widgets *on top* of platform views that handle pointer events. + +There's two ways that the `PointerInterceptor` widget can be used to solve the problems above: + +1. Wrapping your button element directly (FAB, Custom Play/Pause button...): + + ```dart + PointerInterceptor( + child: ElevatedButton(...), + ) + ``` + +2. As a root container for a "layout" element, wrapping a bunch of other elements (like a Drawer): + + ```dart + Scaffold( + ... + drawer: PointerInterceptor( + child: Drawer( + child: ... + ), + ), + ... + ) + ``` + +### `intercepting` + +A common use of the `PointerInterceptor` widget is to block clicks only under +certain conditions (`isVideoShowing`, `isPanelOpen`...). + +The `intercepting` property allows the `PointerInterceptor` widget to render +itself (or not) depending on a boolean value, instead of having to manually +write an `if/else` on the Flutter App widget tree, so code like this: + + ```dart + if (someCondition) { + return PointerInterceptor( + child: ElevatedButton(...), + ) + } else { + return ElevatedButton(...), + } + ``` + +can be rewritten as: + + ```dart + return PointerInterceptor( + intercepting: someCondition, + child: ElevatedButton(...), + ) + ``` + +Note: when `intercepting` is false, the `PointerInterceptor` will not render +_anything_ in flutter, and just return its `child`. The code is exactly +equivalent to the example above. + +### `debug` + +The `PointerInterceptor` widget has a `debug` property, that will render it visibly on the screen (similar to the images above). + +This may be useful to see what the widget is actually covering when used as a layout element. diff --git a/packages/pointer_interceptor/pointer_interceptor/doc/img/affected-areas.png b/packages/pointer_interceptor/pointer_interceptor/doc/img/affected-areas.png new file mode 100644 index 0000000000000000000000000000000000000000..40592db6d2b6a2e45c4d0653c39f6ac184b63298 GIT binary patch literal 15011 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 literal 0 HcmV?d00001 diff --git a/packages/pointer_interceptor/pointer_interceptor/doc/img/fixed-areas.png b/packages/pointer_interceptor/pointer_interceptor/doc/img/fixed-areas.png new file mode 100644 index 0000000000000000000000000000000000000000..489d376660b481246cf2802eac5a26db0a882888 GIT binary patch literal 17538 zcmc$`g;yL+@GiUyfyD_B92N-fB)Gdsf5^)N=-$f+0APp(;KO?f_&M?=A|MtBT}p|_Uy^=;En0-vSS?>QU8kb&x9`_X$dphvn_+jpq9touBzz=1 zihC-DA)6uFBsD7D`9Z?69MylO-_5=o{Xa1K_yPRp$~1K;8Op@V+5*$%L^yTaMU}3c z^!#c#fU}3yaZ5U-(?wavK>Tl7-a`U*snlPFhIj!CZNU90e23#59Ux$zOsTg>3WUXHA}^Xf;QjaMl6 z!HdDSL^LH^{Q8nt%+Ek1u*TuPNAj`&h#By4YO@Rjd&eLACZTxj;tbQ*lXgCy6Emg{ z6}Yg;lMwUevhwc2* zi?v5rqJ8AfzUs|0HD>7RiC-7*hy5hW)OYXL-WMa;bdJFJ7)3YZk?k8~J~r>(x;Jc2 zs>42Mb`BAFJy%@w@AAb`vf`a;z{PyoEz|^wNIq@ihN8`1rNg@Q#*5^kXAG!-^ywcC zIKwQt!M0m?c}@z`D#*n7Z=R{Vf2!B>s>|uFU04-Un7#{%NRHjDI8g)}SrGBaT;F=; zDP%PQ>Z{xpKf7mmz$hvC!>4zIguV_zxMGC&elL6+%M!Uhd#kiSuD)9rai$u%d$i0O zYfG(uK#52B(d3>#ops;n*9M4F`j}FDG=$spb zItx9^6Mc6d*WSeQ?);)k$Z2S!?AT&62@Y`Gg(!bnhQ5ww9tF!bZ}Z8__TnHARiI_3 zAnbJjKwEcUipMDukFmgFa#pHCCBlmihc4eTGbo@#C5DoqZypICy6QyKxl3n5`y3(M ze`-j!cIV}VGIi#DviF?O&~FTiG2jEkqV1H}Q9KF+j4O8j!5LwLACtdu9-TX%6$**K z@B`?jct=7&Pv*^_M<(1D$7d3SAeWjAzZbo?DLaBSjKSm6AFX$WjeRz2l|Ik>M#=hI zHr8SN(&mM8wKX_XxObu6YdTn*D|cVCt>f^DKSB73_`hZH_)4#77LGC5n6_L%UNYps(Bs z%4Rx8Db#|JQC@^;-$HEa1wJ44V6*;K+(6 zhs-fGYe=ppwp{voRpGS?;em%-2DOKe)1`S;^$hV_2d@yX59Kp`QRs?%RXd-lPczHD z1PEeA(hwZ?nH3(aN$$R}G(?%nniT3HcHDUU^tDn6(zn;uEUkul)DZ)xCikoJjzxzA zMcp;!jJ$Oprvv?=H&eyL)BXHaebBmaYpTohpHn0fw~w64+vTGQzVZ@0e{8OmjSaXV)uX-YrS z>)&W{`Vw(H+m8nRU389f^6&m8{0LF3cyuPB%9V$t{hJ-{N-_6>et}8>Z)M#K>*i*) zze!FUF4_z}Bj{jue!0YS3RfDy@q0O@#GqzKUKaW9v`&!Pr%lFzO{CBGurdAKOt2w! zr_EZ~0o^ouy((e!xEPsDEU$8)#_tZD+v&*HS}2+nQdjFUPs*rbGk=d=Kn#{ej*H

#kG8Z3*8ltPRr8JN-{mcN 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%0DGdFW))E`Y|}5?e51M|bK|!7dpm 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 Docs > Testing & debugging > Integration testing](https://flutter.dev/docs/testing/integration-tests). diff --git a/packages/pointer_interceptor/pointer_interceptor/example/integration_test/widget_test.dart b/packages/pointer_interceptor/pointer_interceptor/example/integration_test/widget_test.dart new file mode 100644 index 00000000000..c8d5d6f52b7 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/example/integration_test/widget_test.dart @@ -0,0 +1,179 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_print + +import 'dart:html' as html; + +// Imports the Flutter Driver API. +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:pointer_interceptor_example/main.dart' as app; + +final Finder nonClickableButtonFinder = + find.byKey(const Key('transparent-button')); +final Finder clickableWrappedButtonFinder = + find.byKey(const Key('wrapped-transparent-button')); +final Finder clickableButtonFinder = find.byKey(const Key('clickable-button')); +final Finder backgroundFinder = + find.byKey(const ValueKey('background-widget')); + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('Without semantics', () { + testWidgets( + 'on wrapped elements, the browser does not hit the background-html-view', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + final html.Element element = + _getHtmlElementAtCenter(clickableButtonFinder, tester); + + expect(element.id, isNot('background-html-view')); + }, semanticsEnabled: false); + + testWidgets( + 'on wrapped elements with intercepting set to false, the browser hits the background-html-view', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + final html.Element element = + _getHtmlElementAtCenter(clickableWrappedButtonFinder, tester); + + expect(element.id, 'background-html-view'); + }, semanticsEnabled: false); + + testWidgets( + 'on unwrapped elements, the browser hits the background-html-view', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + final html.Element element = + _getHtmlElementAtCenter(nonClickableButtonFinder, tester); + + expect(element.id, 'background-html-view'); + }, semanticsEnabled: false); + + testWidgets('on background directly', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + final html.Element element = + _getHtmlElementAt(tester.getTopLeft(backgroundFinder)); + + expect(element.id, 'background-html-view'); + }, semanticsEnabled: false); + }); + + group('With semantics', () { + testWidgets('finds semantics of wrapped widgets', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + if (!_newSemanticsAvailable()) { + print('Skipping test: Needs flutter > 2.10'); + return; + } + + final html.Element element = + _getHtmlElementAtCenter(clickableButtonFinder, tester); + + expect(element.tagName.toLowerCase(), 'flt-semantics'); + expect(element.getAttribute('aria-label'), 'Works As Expected'); + }); + + testWidgets( + 'finds semantics of wrapped widgets with intercepting set to false', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + if (!_newSemanticsAvailable()) { + print('Skipping test: Needs flutter > 2.10'); + return; + } + + final html.Element element = + _getHtmlElementAtCenter(clickableWrappedButtonFinder, tester); + + expect(element.tagName.toLowerCase(), 'flt-semantics'); + expect(element.getAttribute('aria-label'), + 'Never calls onPressed transparent'); + }); + + testWidgets('finds semantics of unwrapped elements', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + if (!_newSemanticsAvailable()) { + print('Skipping test: Needs flutter > 2.10'); + return; + } + + final html.Element element = + _getHtmlElementAtCenter(nonClickableButtonFinder, tester); + + expect(element.tagName.toLowerCase(), 'flt-semantics'); + expect(element.getAttribute('aria-label'), 'Never calls onPressed'); + }); + + // Notice that, when hit-testing the background platform view, instead of + // finding a semantics node, the platform view itself is found. This is + // because the platform view does not add interactive semantics nodes into + // the framework's semantics tree. Instead, its semantics is determined by + // the HTML content of the platform view itself. Flutter's semantics tree + // simply allows the hit test to land on the platform view by making itself + // hit test transparent. + testWidgets('on background directly', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + final html.Element element = + _getHtmlElementAt(tester.getTopLeft(backgroundFinder)); + + expect(element.id, 'background-html-view'); + }); + }); +} + +// Calls [_getHtmlElementAt] passing it the center of the widget identified by +// the `finder`. +html.Element _getHtmlElementAtCenter(Finder finder, WidgetTester tester) { + final Offset point = tester.getCenter(finder); + return _getHtmlElementAt(point); +} + +// Locates the DOM element at the given `point` using `elementFromPoint`. +// +// `elementFromPoint` is an approximate proxy for a hit test, although it's +// sensitive to the presence of shadow roots and browser quirks (not all +// browsers agree on what it should return in all situations). Since this test +// runs only in Chromium, it relies on Chromium's behavior. +html.Element _getHtmlElementAt(Offset point) { + // Probe at the shadow so the browser reports semantics nodes in addition to + // platform view elements. If probed from `html.document` the browser hides + // the contents of as an implementation detail. + final html.ShadowRoot glassPaneShadow = + html.document.querySelector('flt-glass-pane')!.shadowRoot!; + return glassPaneShadow.elementFromPoint(point.dx.toInt(), point.dy.toInt())!; +} + +// TODO(dit): Remove this after flutter master (2.13) lands into stable. +// This detects that we can do new semantics assertions by looking at the 'id' +// attribute on flt-semantics elements (it is now set in 2.13 and up). +bool _newSemanticsAvailable() { + final html.ShadowRoot glassPaneShadow = + html.document.querySelector('flt-glass-pane')!.shadowRoot!; + final List elements = + glassPaneShadow.querySelectorAll('flt-semantics[id]'); + return elements.isNotEmpty; +} diff --git a/packages/pointer_interceptor/pointer_interceptor/example/lib/main.dart b/packages/pointer_interceptor/pointer_interceptor/example/lib/main.dart new file mode 100644 index 00000000000..74f632a6023 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/example/lib/main.dart @@ -0,0 +1,219 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore: avoid_web_libraries_in_flutter +import 'dart:html' as html; +import 'dart:ui_web' as ui_web; + +import 'package:flutter/material.dart'; +import 'package:pointer_interceptor/pointer_interceptor.dart'; + +const String _htmlElementViewType = '_htmlElementViewType'; +const double _videoWidth = 640; +const double _videoHeight = 480; + +/// The html.Element that will be rendered underneath the flutter UI. +html.Element htmlElement = html.DivElement() + ..style.width = '100%' + ..style.height = '100%' + ..style.backgroundColor = '#fabada' + ..style.cursor = 'auto' + ..id = 'background-html-view'; + +// See other examples commented out below... + +// html.Element htmlElement = html.VideoElement() +// ..style.width = '100%' +// ..style.height = '100%' +// ..style.cursor = 'auto' +// ..style.backgroundColor = 'black' +// ..id = 'background-html-view' +// ..src = 'https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4' +// ..poster = 'https://peach.blender.org/wp-content/uploads/title_anouncement.jpg?x11217' +// ..controls = true; + +// html.Element htmlElement = html.IFrameElement() +// ..width = '100%' +// ..height = '100%' +// ..id = 'background-html-view' +// ..src = 'https://www.youtube.com/embed/IyFZznAk69U' +// ..style.border = 'none'; + +void main() { + ui_web.platformViewRegistry.registerViewFactory( + _htmlElementViewType, + (int viewId) => htmlElement, + ); + + runApp(const MyApp()); +} + +/// Main app +class MyApp extends StatelessWidget { + /// Creates main app. + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + title: 'Stopping Clicks with some DOM', + home: MyHomePage(), + ); + } +} + +/// First page +class MyHomePage extends StatefulWidget { + /// Creates first page. + const MyHomePage({super.key}); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + String _lastClick = 'none'; + + void _clickedOn(String key) { + setState(() { + _lastClick = key; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('PointerInterceptor demo'), + actions: [ + PointerInterceptor( + // debug: true, + child: IconButton( + icon: const Icon(Icons.add_alert), + tooltip: 'AppBar Icon', + onPressed: () { + _clickedOn('appbar-icon'); + }, + ), + ), + ], + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Last click on: $_lastClick', + key: const Key('last-clicked'), + ), + Container( + color: Colors.black, + width: _videoWidth, + height: _videoHeight, + child: Stack( + alignment: Alignment.center, + children: [ + HtmlElement( + key: const ValueKey('background-widget'), + onClick: () { + _clickedOn('html-element'); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + key: const Key('transparent-button'), + child: const Text('Never calls onPressed'), + onPressed: () { + _clickedOn('transparent-button'); + }, + ), + PointerInterceptor( + intercepting: false, + child: ElevatedButton( + key: const Key('wrapped-transparent-button'), + child: + const Text('Never calls onPressed transparent'), + onPressed: () { + _clickedOn('wrapped-transparent-button'); + }, + ), + ), + PointerInterceptor( + child: ElevatedButton( + key: const Key('clickable-button'), + child: const Text('Works As Expected'), + onPressed: () { + _clickedOn('clickable-button'); + }, + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + floatingActionButton: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PointerInterceptor( + // debug: true, + child: FloatingActionButton( + child: const Icon(Icons.navigation), + onPressed: () { + _clickedOn('fab-1'); + }, + ), + ), + ], + ), + drawer: Drawer( + child: PointerInterceptor( + // debug: true, // Enable this to "see" the interceptor covering the column. + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ListTile( + title: const Text('Item 1'), + onTap: () { + _clickedOn('drawer-item-1'); + }, + ), + ListTile( + title: const Text('Item 2'), + onTap: () { + _clickedOn('drawer-item-2'); + }, + ), + ], + ), + ), + ), + ); + } +} + +/// Initialize the videoPlayer, then render the corresponding view... +class HtmlElement extends StatelessWidget { + /// Constructor + const HtmlElement({super.key, required this.onClick}); + + /// A function to run when the element is clicked + final VoidCallback onClick; + + @override + Widget build(BuildContext context) { + htmlElement.onClick.listen((_) { + onClick(); + }); + + return const HtmlElementView( + viewType: _htmlElementViewType, + ); + } +} diff --git a/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml new file mode 100644 index 00000000000..9f8b29e288b --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml @@ -0,0 +1,28 @@ +name: pointer_interceptor_example +description: An example app for the pointer_interceptor package. +publish_to: 'none' +version: 1.0.0 + +environment: + sdk: ">=3.1.0 <4.0.0" + flutter: ">=3.13.0" + +dependencies: + flutter: + sdk: flutter + pointer_interceptor: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true diff --git a/packages/pointer_interceptor/pointer_interceptor/example/test_driver/integration_test.dart b/packages/pointer_interceptor/pointer_interceptor/example/test_driver/integration_test.dart new file mode 100644 index 00000000000..f26b6a310cf --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() async => integrationDriver(); diff --git a/packages/pointer_interceptor/pointer_interceptor/example/web/favicon.png b/packages/pointer_interceptor/pointer_interceptor/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/packages/pointer_interceptor/pointer_interceptor/example/web/icons/Icon-192.png b/packages/pointer_interceptor/pointer_interceptor/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/packages/pointer_interceptor/pointer_interceptor/example/web/icons/Icon-512.png b/packages/pointer_interceptor/pointer_interceptor/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/packages/pointer_interceptor/pointer_interceptor/example/web/index.html b/packages/pointer_interceptor/pointer_interceptor/example/web/index.html new file mode 100644 index 00000000000..a53f5677b57 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/example/web/index.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/packages/pointer_interceptor/pointer_interceptor/example/web/manifest.json b/packages/pointer_interceptor/pointer_interceptor/example/web/manifest.json new file mode 100644 index 00000000000..8c012917dab --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/packages/pointer_interceptor/pointer_interceptor/lib/pointer_interceptor.dart b/packages/pointer_interceptor/pointer_interceptor/lib/pointer_interceptor.dart new file mode 100644 index 00000000000..4ca1499d3bd --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/lib/pointer_interceptor.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +library pointer_interceptor; + +export 'src/mobile.dart' if (dart.library.html) 'src/web.dart'; diff --git a/packages/pointer_interceptor/pointer_interceptor/lib/src/mobile.dart b/packages/pointer_interceptor/pointer_interceptor/lib/src/mobile.dart new file mode 100644 index 00000000000..8d645ffbcfe --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/lib/src/mobile.dart @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/widgets.dart'; + +/// A [Widget] that prevents clicks from being swallowed by [HtmlElementView]s. +class PointerInterceptor extends StatelessWidget { + /// Create a `PointerInterceptor` wrapping a `child`. + // ignore: prefer_const_constructors_in_immutables + PointerInterceptor({ + required this.child, + this.intercepting = true, + this.debug = false, + super.key, + }); + + /// The `Widget` that is being wrapped by this `PointerInterceptor`. + final Widget child; + + /// Whether or not this `PointerInterceptor` should intercept pointer events. + final bool intercepting; + + /// When true, the widget renders with a semi-transparent red background, for debug purposes. + /// + /// This is useful when rendering this as a "layout" widget, like the root child + /// of a `Drawer`. + final bool debug; + + @override + Widget build(BuildContext context) { + return child; + } +} diff --git a/packages/pointer_interceptor/pointer_interceptor/lib/src/web.dart b/packages/pointer_interceptor/pointer_interceptor/lib/src/web.dart new file mode 100644 index 00000000000..e0dbcf904ff --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/lib/src/web.dart @@ -0,0 +1,93 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore: avoid_web_libraries_in_flutter +import 'dart:html' as html; +import 'dart:ui_web' as ui_web; + +import 'package:flutter/widgets.dart'; + +const String _viewType = '__webPointerInterceptorViewType__'; +const String _debug = 'debug__'; + +// Computes a "view type" for different configurations of the widget. +String _getViewType({bool debug = false}) { + return debug ? _viewType + _debug : _viewType; +} + +// Registers a viewFactory for this widget. +void _registerFactory({bool debug = false}) { + final String viewType = _getViewType(debug: debug); + ui_web.platformViewRegistry.registerViewFactory(viewType, (int viewId) { + final html.Element htmlElement = html.DivElement() + ..style.width = '100%' + ..style.height = '100%'; + if (debug) { + htmlElement.style.backgroundColor = 'rgba(255, 0, 0, .5)'; + } + return htmlElement; + }, isVisible: false); +} + +/// The web implementation of the `PointerInterceptor` widget. +/// +/// A `Widget` that prevents clicks from being swallowed by [HtmlElementView]s. +class PointerInterceptor extends StatelessWidget { + /// Creates a PointerInterceptor for the web. + PointerInterceptor({ + required this.child, + this.intercepting = true, + this.debug = false, + super.key, + }) { + if (!_registered) { + _register(); + } + } + + /// The `Widget` that is being wrapped by this `PointerInterceptor`. + final Widget child; + + /// Whether or not this `PointerInterceptor` should intercept pointer events. + final bool intercepting; + + /// When true, the widget renders with a semi-transparent red background, for debug purposes. + /// + /// This is useful when rendering this as a "layout" widget, like the root child + /// of a [Drawer]. + final bool debug; + + // Keeps track if this widget has already registered its view factories or not. + static bool _registered = false; + + // Registers the view factories for the interceptor widgets. + static void _register() { + assert(!_registered); + + _registerFactory(); + _registerFactory(debug: true); + + _registered = true; + } + + @override + Widget build(BuildContext context) { + if (!intercepting) { + return child; + } + + final String viewType = _getViewType(debug: debug); + return Stack( + alignment: Alignment.center, + children: [ + Positioned.fill( + child: HtmlElementView( + viewType: viewType, + ), + ), + child, + ], + ); + } +} diff --git a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml new file mode 100644 index 00000000000..3dba03b703b --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml @@ -0,0 +1,21 @@ +name: pointer_interceptor +description: A widget to prevent clicks from being swallowed by underlying HtmlElementViews on the web. +repository: https://github.com/flutter/packages/tree/main/packages/pointer_interceptor +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pointer_interceptor%22 +version: 0.9.3+6 + +environment: + sdk: ">=3.1.0 <4.0.0" + flutter: ">=3.13.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +topics: + - web + - widgets diff --git a/packages/pointer_interceptor/pointer_interceptor/test/README.md b/packages/pointer_interceptor/pointer_interceptor/test/README.md new file mode 100644 index 00000000000..7c5b4ad682b --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/test/README.md @@ -0,0 +1,5 @@ +## test + +This package uses integration tests for testing. + +See `example/README.md` for more info. diff --git a/packages/pointer_interceptor/pointer_interceptor/test/tests_exist_elsewhere_test.dart b/packages/pointer_interceptor/pointer_interceptor/test/tests_exist_elsewhere_test.dart new file mode 100644 index 00000000000..cc32e6c72f1 --- /dev/null +++ b/packages/pointer_interceptor/pointer_interceptor/test/tests_exist_elsewhere_test.dart @@ -0,0 +1,16 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_print + +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('Tell the user where to find the real tests', () { + print('---'); + print('This package uses integration_test for its tests.'); + print('See `example/README.md` for more info.'); + print('---'); + }); +} From 3ebf7ff5276324ca233affe5b7da661cf8fe50da Mon Sep 17 00:00:00 2001 From: Louise Hsu Date: Wed, 1 Nov 2023 10:45:02 -0700 Subject: [PATCH 2/4] update versioning --- packages/pointer_interceptor/.gitignore | 74 ------ packages/pointer_interceptor/.metadata | 10 - packages/pointer_interceptor/AUTHORS | 7 - packages/pointer_interceptor/CHANGELOG.md | 64 ----- packages/pointer_interceptor/LICENSE | 25 -- packages/pointer_interceptor/README.md | 103 -------- .../doc/img/affected-areas.png | Bin 15011 -> 0 bytes .../doc/img/fixed-areas.png | Bin 17538 -> 0 bytes .../pointer_interceptor/example/.gitignore | 46 ---- .../pointer_interceptor/example/.metadata | 10 - .../pointer_interceptor/example/README.md | 17 -- .../example/integration_test/widget_test.dart | 179 -------------- .../pointer_interceptor/example/lib/main.dart | 219 ------------------ .../pointer_interceptor/example/pubspec.yaml | 28 --- .../example/test_driver/integration_test.dart | 7 - .../example/web/favicon.png | Bin 917 -> 0 bytes .../example/web/icons/Icon-192.png | Bin 5292 -> 0 bytes .../example/web/icons/Icon-512.png | Bin 8252 -> 0 bytes .../example/web/index.html | 48 ---- .../example/web/manifest.json | 23 -- .../lib/pointer_interceptor.dart | 7 - .../pointer_interceptor/lib/src/mobile.dart | 34 --- packages/pointer_interceptor/lib/src/web.dart | 93 -------- .../pointer_interceptor/CHANGELOG.md | 4 + .../pointer_interceptor/pubspec.yaml | 2 +- packages/pointer_interceptor/pubspec.yaml | 21 -- packages/pointer_interceptor/test/README.md | 5 - .../test/tests_exist_elsewhere_test.dart | 16 -- 28 files changed, 5 insertions(+), 1037 deletions(-) delete mode 100644 packages/pointer_interceptor/.gitignore delete mode 100644 packages/pointer_interceptor/.metadata delete mode 100644 packages/pointer_interceptor/AUTHORS delete mode 100644 packages/pointer_interceptor/CHANGELOG.md delete mode 100644 packages/pointer_interceptor/LICENSE delete mode 100644 packages/pointer_interceptor/README.md delete mode 100644 packages/pointer_interceptor/doc/img/affected-areas.png delete mode 100644 packages/pointer_interceptor/doc/img/fixed-areas.png delete mode 100644 packages/pointer_interceptor/example/.gitignore delete mode 100644 packages/pointer_interceptor/example/.metadata delete mode 100644 packages/pointer_interceptor/example/README.md delete mode 100644 packages/pointer_interceptor/example/integration_test/widget_test.dart delete mode 100644 packages/pointer_interceptor/example/lib/main.dart delete mode 100644 packages/pointer_interceptor/example/pubspec.yaml delete mode 100644 packages/pointer_interceptor/example/test_driver/integration_test.dart delete mode 100644 packages/pointer_interceptor/example/web/favicon.png delete mode 100644 packages/pointer_interceptor/example/web/icons/Icon-192.png delete mode 100644 packages/pointer_interceptor/example/web/icons/Icon-512.png delete mode 100644 packages/pointer_interceptor/example/web/index.html delete mode 100644 packages/pointer_interceptor/example/web/manifest.json delete mode 100644 packages/pointer_interceptor/lib/pointer_interceptor.dart delete mode 100644 packages/pointer_interceptor/lib/src/mobile.dart delete mode 100644 packages/pointer_interceptor/lib/src/web.dart delete mode 100644 packages/pointer_interceptor/pubspec.yaml delete mode 100644 packages/pointer_interceptor/test/README.md delete mode 100644 packages/pointer_interceptor/test/tests_exist_elsewhere_test.dart diff --git a/packages/pointer_interceptor/.gitignore b/packages/pointer_interceptor/.gitignore deleted file mode 100644 index 1985397a2cb..00000000000 --- a/packages/pointer_interceptor/.gitignore +++ /dev/null @@ -1,74 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 diff --git a/packages/pointer_interceptor/.metadata b/packages/pointer_interceptor/.metadata deleted file mode 100644 index b5330742eed..00000000000 --- a/packages/pointer_interceptor/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: e6bd95bc5caa5e34c5b0285a559673984374b7ea - channel: master - -project_type: package diff --git a/packages/pointer_interceptor/AUTHORS b/packages/pointer_interceptor/AUTHORS deleted file mode 100644 index eb34297f179..00000000000 --- a/packages/pointer_interceptor/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -# Below is a list of people and organizations that have contributed -# to the Flutter project. Names should be added to the list like so: -# -# Name/Organization - -Google Inc. -The Chromium Authors diff --git a/packages/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/CHANGELOG.md deleted file mode 100644 index 3a66b061ff7..00000000000 --- a/packages/pointer_interceptor/CHANGELOG.md +++ /dev/null @@ -1,64 +0,0 @@ -## 0.9.3+6 - -* Migrates to `dart:ui_web` APIs. -* Updates minimum supported SDK version to Flutter 3.13.0/Dart 3.1.0. - -## 0.9.3+5 - -* Adds pub topics to package metadata. -* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. -* Aligns Dart and Flutter SDK constraints. - -## 0.9.3+4 - -* Removes const keyword from PointerInterceptor's constructor. -* Updates minimum Flutter version to 3.0. - -## 0.9.3+3 - -* Fixes lint warnings. - -## 0.9.3+2 - -* (Temporarily) helps tests introduced in prior version to pass in `stable`. - (This will be removed when `master` rolls to `stable`) -* Updates README to reference the correct github URL. - -## 0.9.3+1 - -* Updates example code and integration tests to accomodate hit-testing changes in the Flutter web engine. - -## 0.9.3 - -* Require minimal version of flutter SDK to be `2.10` - -## 0.9.2 - -* Marked `PointerInterceptor` as invisible, so it can be optimized by the engine. -* (Version Retracted. This attempted to use an API from Flutter `2.10` in earlier versions of Flutter. Fixed in v0.9.3) - -## 0.9.1 - -* Removed `android` and `ios` directories from `example`, as the example doesn't - build for those platforms. -* Added `intercepting` field to allow for conditional pointer interception - -## 0.9.0+1 - -* Change sizing of HtmlElementView so it works well when slotted. - -## 0.9.0 - -* Migrates to null safety. - -## 0.8.0+2 - -* Use `ElevatedButton` instead of the deprecated `RaisedButton` in example and docs. - -## 0.8.0+1 - -* Update README.md so images render in pub.dev - -## 0.8.0 - -* Initial release of the `PointerInterceptor` widget. diff --git a/packages/pointer_interceptor/LICENSE b/packages/pointer_interceptor/LICENSE deleted file mode 100644 index c6823b81eb8..00000000000 --- a/packages/pointer_interceptor/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright 2013 The Flutter Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/pointer_interceptor/README.md b/packages/pointer_interceptor/README.md deleted file mode 100644 index 6da163fc5d1..00000000000 --- a/packages/pointer_interceptor/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# pointer_interceptor - -`PointerInterceptor` is a widget that prevents mouse events (in web) from being captured by an underlying [`HtmlElementView`](https://api.flutter.dev/flutter/widgets/HtmlElementView-class.html). - -You can use this widget in a cross-platform app freely. In mobile, where the issue that this plugin fixes does not exist, the widget acts as a pass-through of its `children`, without adding anything to the render tree. - -## What is the problem? - -When overlaying Flutter widgets on top of `HtmlElementView` widgets that respond to mouse gestures (handle clicks, for example), the clicks will be consumed by the `HtmlElementView`, and not relayed to Flutter. - -The result is that Flutter widget's `onTap` (and other) handlers won't fire as expected, but they'll affect the underlying webview. - -|The problem...| -|:-:| -|![Depiction of problematic areas](https://raw.githubusercontent.com/flutter/packages/main/packages/pointer_interceptor/doc/img/affected-areas.png)| -|_In the dashed areas, mouse events won't work as expected. The `HtmlElementView` will consume them before Flutter sees them._| - - -## How does this work? - -`PointerInterceptor` creates a platform view consisting of an empty HTML element. The element has the size of its `child` widget, and is inserted in the layer tree _behind_ its child in paint order. - -This empty platform view doesn't do anything with mouse events, other than preventing them from reaching other platform views underneath it. - -This gives an opportunity to the Flutter framework to handle the click, as expected: - -|The solution...| -|:-:| -|![Depiction of the solution](https://raw.githubusercontent.com/flutter/packages/main/packages/pointer_interceptor/doc/img/fixed-areas.png)| -|_Each `PointerInterceptor` (green) renders between Flutter widgets and the underlying `HtmlElementView`. Mouse events now can't reach the background HtmlElementView, and work as expected._| - -## How to use - -Some common scenarios where this widget may come in handy: - -* [FAB](https://api.flutter.dev/flutter/material/FloatingActionButton-class.html) unclickable in an app that renders a full-screen background Map -* Custom Play/Pause buttons on top of a video element don't work -* Drawer contents not interactive when it overlaps an iframe element -* ... - -All the cases above have in common that they attempt to render Flutter widgets *on top* of platform views that handle pointer events. - -There's two ways that the `PointerInterceptor` widget can be used to solve the problems above: - -1. Wrapping your button element directly (FAB, Custom Play/Pause button...): - - ```dart - PointerInterceptor( - child: ElevatedButton(...), - ) - ``` - -2. As a root container for a "layout" element, wrapping a bunch of other elements (like a Drawer): - - ```dart - Scaffold( - ... - drawer: PointerInterceptor( - child: Drawer( - child: ... - ), - ), - ... - ) - ``` - -### `intercepting` - -A common use of the `PointerInterceptor` widget is to block clicks only under -certain conditions (`isVideoShowing`, `isPanelOpen`...). - -The `intercepting` property allows the `PointerInterceptor` widget to render -itself (or not) depending on a boolean value, instead of having to manually -write an `if/else` on the Flutter App widget tree, so code like this: - - ```dart - if (someCondition) { - return PointerInterceptor( - child: ElevatedButton(...), - ) - } else { - return ElevatedButton(...), - } - ``` - -can be rewritten as: - - ```dart - return PointerInterceptor( - intercepting: someCondition, - child: ElevatedButton(...), - ) - ``` - -Note: when `intercepting` is false, the `PointerInterceptor` will not render -_anything_ in flutter, and just return its `child`. The code is exactly -equivalent to the example above. - -### `debug` - -The `PointerInterceptor` widget has a `debug` property, that will render it visibly on the screen (similar to the images above). - -This may be useful to see what the widget is actually covering when used as a layout element. diff --git a/packages/pointer_interceptor/doc/img/affected-areas.png b/packages/pointer_interceptor/doc/img/affected-areas.png deleted file mode 100644 index 40592db6d2b6a2e45c4d0653c39f6ac184b63298..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15011 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 diff --git a/packages/pointer_interceptor/doc/img/fixed-areas.png b/packages/pointer_interceptor/doc/img/fixed-areas.png deleted file mode 100644 index 489d376660b481246cf2802eac5a26db0a882888..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17538 zcmc$`g;yL+@GiUyfyD_B92N-fB)Gdsf5^)N=-$f+0APp(;KO?f_&M?=A|MtBT}p|_Uy^=;En0-vSS?>QU8kb&x9`_X$dphvn_+jpq9touBzz=1 zihC-DA)6uFBsD7D`9Z?69MylO-_5=o{Xa1K_yPRp$~1K;8Op@V+5*$%L^yTaMU}3c z^!#c#fU}3yaZ5U-(?wavK>Tl7-a`U*snlPFhIj!CZNU90e23#59Ux$zOsTg>3WUXHA}^Xf;QjaMl6 z!HdDSL^LH^{Q8nt%+Ek1u*TuPNAj`&h#By4YO@Rjd&eLACZTxj;tbQ*lXgCy6Emg{ z6}Yg;lMwUevhwc2* zi?v5rqJ8AfzUs|0HD>7RiC-7*hy5hW)OYXL-WMa;bdJFJ7)3YZk?k8~J~r>(x;Jc2 zs>42Mb`BAFJy%@w@AAb`vf`a;z{PyoEz|^wNIq@ihN8`1rNg@Q#*5^kXAG!-^ywcC zIKwQt!M0m?c}@z`D#*n7Z=R{Vf2!B>s>|uFU04-Un7#{%NRHjDI8g)}SrGBaT;F=; zDP%PQ>Z{xpKf7mmz$hvC!>4zIguV_zxMGC&elL6+%M!Uhd#kiSuD)9rai$u%d$i0O zYfG(uK#52B(d3>#ops;n*9M4F`j}FDG=$spb zItx9^6Mc6d*WSeQ?);)k$Z2S!?AT&62@Y`Gg(!bnhQ5ww9tF!bZ}Z8__TnHARiI_3 zAnbJjKwEcUipMDukFmgFa#pHCCBlmihc4eTGbo@#C5DoqZypICy6QyKxl3n5`y3(M ze`-j!cIV}VGIi#DviF?O&~FTiG2jEkqV1H}Q9KF+j4O8j!5LwLACtdu9-TX%6$**K z@B`?jct=7&Pv*^_M<(1D$7d3SAeWjAzZbo?DLaBSjKSm6AFX$WjeRz2l|Ik>M#=hI zHr8SN(&mM8wKX_XxObu6YdTn*D|cVCt>f^DKSB73_`hZH_)4#77LGC5n6_L%UNYps(Bs z%4Rx8Db#|JQC@^;-$HEa1wJ44V6*;K+(6 zhs-fGYe=ppwp{voRpGS?;em%-2DOKe)1`S;^$hV_2d@yX59Kp`QRs?%RXd-lPczHD z1PEeA(hwZ?nH3(aN$$R}G(?%nniT3HcHDUU^tDn6(zn;uEUkul)DZ)xCikoJjzxzA zMcp;!jJ$Oprvv?=H&eyL)BXHaebBmaYpTohpHn0fw~w64+vTGQzVZ@0e{8OmjSaXV)uX-YrS z>)&W{`Vw(H+m8nRU389f^6&m8{0LF3cyuPB%9V$t{hJ-{N-_6>et}8>Z)M#K>*i*) zze!FUF4_z}Bj{jue!0YS3RfDy@q0O@#GqzKUKaW9v`&!Pr%lFzO{CBGurdAKOt2w! zr_EZ~0o^ouy((e!xEPsDEU$8)#_tZD+v&*HS}2+nQdjFUPs*rbGk=d=Kn#{ej*H

#kG8Z3*8ltPRr8JN-{mcN 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%0DGdFW))E`Y|}5?e51M|bK|!7dpm zAZ)jPX?Pu%bsN2sJ}B>8f06|{g>0Hu&{7CA^{FWY0)+97k&b{ooyk|Em1Dx5h1_DY z_l2Yb*q-L_T`%or?29K)Lh%+DXWLxe)o82BNs?ANeSfN%3t_VIKAo#GG#b~I|Lj+) za5yLpCxVxiu(98IcaEd8Z4Dcy>x#rWbT$+YGG}{4lJo;7b|a> zVYWNVYY+XkcYZiwSsgL_phG8~i{RnWGuM~>I}rIQ!czoAY^=S*^UrS4NiNg!V(-~U z+r6{DAMRa3ciquxNnU$n7*SoK0~R>Ft!;92D;yA*!=WEv-UqQ*IA?z}5vrj!Y1?mo z2!eqz??N9nj}hXB<>mlZcjx+$2g+fi8;)C>9t0cfeg)L7U6!q_H3AO3)_c&vnXIX3 zfG}Vthsjj>lj;t=eRmqFc!EEyuWxaq|)g7Cm|IstaoBrDP!dwN%XO zM9$`svK0o`R2c4g$@ah1r3=ImL&;Q;b9}zuT!mNh`|X)$cAlIV(vLHP+u4MG58oiz zeaVBa>ahno)% zAwSx7d2na7P)-nwizzACM4ByD5qzUS5hM=rjt3o5GCcI4 z6A*j5Y#@;{r8yO8Sd*3~tx5~xqk3f|WSxKBz5COZsa|KV_~1piAw84k%d>!CO*s zjxd&9lcm7F$4DSplq@(}An0A$rCfbHIpoA)u#e)NvzZ$M!`6#JKx`wX$mAi&xONVX zUg%JC1HU$x%z3=eCq5r*TyC8Sf_KEV5hG$Q0VdO0lqiBNSfp6?!aRX4oI%So#(u=DExejAA_yIel2 zx~k0n+A@gS74Urv%qqr8IJ~y4n7ApHgo5-PR~y;FYb(pzBIEDFMqE8_xJv# zIVGPJ?2iUqi(uWw7vkz?cu;n%xg|5#KMhwWbiGbH4MPjEEgqUqGZp-Fyz%v%US}*R zzClk+=pw3rgZaMY-j^OC`FXo9bjmdRotnemvvhGr?-bKMd`Ug}Bd_9qkjzz&C~5nO z*(y`zy&3|`?O^Hp2VbfRU15f5?g}9O?4y;bSoFTds$@Fu5v615Jth){ zk7=6E`XlsHA&@=xl~MDEJ$^A=-0sjtd$&)6DVO<}Jz9XdhK?)F1ye{|@bD(5S~uyf zvH{t=ckyl8wXjEYS-0_N2_3x3+~zJ88pun#2rgo5GjpUoK17-auxNLO99#5YX2x`R zRPp4>*acyL7G``30Ol43DOSuREB#2ZCOxxXrb{utZGEDYM<=qNu4nY+sswyGzWlIWV#O0&oHBt?>n$V$TThy_1zRd|a@aqaq))0E$TknM$GO-rU} z{QfWZ1M;5gZtK`hrp6x7Jv49-cHPUy3BOTY{|Ub34bQWXtLBvZKUZwRXSUWBQ@)WRe`DSDxrv(nV)uxcAZ18M>e?WR5W4$BJWM9KMm2ch7+L}{QO8wS$C;#f(bq>|n_uH(@UA8*9 zCT=kPg$#}@KyV2Q7<2ZD9tHfB`sBnG@lqOW0sH3rLi2dgzw3y9FwR_|7Z6^jhRTDDsJhevWD-%WfNDZI{^(#GA$(aYoaNyAI+I1`7M{9=omu=M-g z_ki#}rJX~lw4*v*cl`P(ld9UwJWI<)HFXu4OdNhZeYN9zx}+|c0C!zqZA71w-X*>fEOcx>*@$3^zvcy2`iD}?mo~uC}?-ft|>*c>5!MR>4$Xf46sL5gp z#r91@AC%c;%0+($lQ#^9U1MaS@t@0mb|*#G#k~z@GyozF_cS!Pm3d=tKX2!G+u=r4 zUtV1>h@T%t+ z=9(^W=6HPYO-UZ1bUf76u4?Dfav>IeOAnw)W#OM9bClJ*w%EtL!(t#ei(0-{xvpp= zg(ga&^C7wo#_2HacjqIU@l8rCa!WFq&G9bBj~mMd2KOG^un5?e%1CcSm4O~ngp`?h&&e_j=w#@pmGDr0bC90cf`jVS7ABo~xRaa+ z;3>N>A(6yBHWjG$?kr}n!lKKOTPIngujEzc^vUgIeD##p#!uRTru|v*spWI$+I_>| zaq~rFZ#ZCC?r_drO7M1mmG(vx2VzX6er;rOw}c5%SjMRHL^OE1cd+-3O^~?y1cT;r z*}>$w6J5&Y^c|wFw_7B(bpiJ8j-}Uovbds(dgX88>-yjZ=LJ+bp@< z8SWJip+xKmJq6@!ywJaIQa@Gga{2mu*kV{y@a4SLM~13Ei>)h_K&Ll(4uW^`Lw?qg z_JP|{u4RBKC1e*9m14Lb4l614wFxb`yvv zDcQnknUIFj(qmH8k5rT}Q2E@`Ibvjg6 z29&`Ov)g)o?dW+=(opZ-KSd)?@v_&)?ku1~piyIbvs3OO;}`n&U~o4T7i?Hx_4=@9 z1P4|r_a>;RBp?cXjQNa)H2x*UDLF)&McmGin)r+7VEMpsO!i+*G1dJR=vDdm!Mvdv z|Gwlof3!XY9by6$Ll5&?2}v(s-aZ9a@$?vr>Llzu>@;dlA2vB^jKzNBa+D z8Rq95O|`7&3y+)G{lLSZdIu0}ME}GJAweF5!Xi@uz&HrX8Siv~+knZA?H4yA(h!MR z^+CagzdVQ#4696n2-ao@$zm72)jYRrRzhGc82IfoAf~Dei9iqT4Wi_7nhkloj*)Jo z{!%n6hdO6Hay@U$piZ+xo0~m&H5{&>l^RhUdZo#ef}ax_-?h1&i+Yu#g<GmvMR@@rtR>vMnFX1W*>LDvaYCd6xhj&jp_d1xyEiS5B(h- z`x*Mht*~jSq}!*VK8xZD&mhNngffB_=db6LTZ~MpT=&z4QuU7cStHf!(^BXHEs}8# zmxS8`>FN-YhL`dPd8)1>mJFq+#SA%fQpvSAv~{?PZ}@KK0jn(yy6ZG}QrdCIq+|}Q zPOSWYw7!73`7q9*9}SN5 zo}G^kuJVo%#CPIHxX&k}kWgcJJC6*PCGk+HkILaK{lj2_cMiD&ESViV@}oE<2*W0u zl}@|X%Tyww?=}QNa7JnKA{5JW1ig>{93&TR^=$126*fFm*i-wQ{I!G+{?dN@t-yU% zc}5QF?}vl&U*(5?@6_WqW~7_m%!$Xcl%-<6R$k#G&ScO&To08~O*5bIMC0{3j3U`B7WBCjYkiJXYM;R}OdFUY>2iUwDYeLb^6gSP z#1_igfr(u_{z_L3IqIJ4I*`TAF!pn_UHtr65EB(C(nHw&4wf0^kYS8rz2K$0GKH!+t+71;u< zNuA!?ay(|jls>z!4fPpgZhtZzt?_*>f-RFy!%}Xif0d(64V-ETznvvG9n_vNePiHc z3prR?xSdHk)sZz4*aiSihI1t4Q7Pygtd(<_lAcEcLeLXeuZEU*5Z`Pp5vQizVkVow zi(<@-`+8_Lno|?0)Wy2!HM)!p3;T>Mu{i3T$yS6T?0xaadY)c-jxFkTJR%DlEg79R zX)V{#HR|*7SKZm+vpgT0U9!jLy9H(Agmp`tmQVHozWeN1vebbW|Ef1#eHaG^*oHEJ zWsYg2_N#H;*~v+v-#;!02SaL~syV5ZLRaQJsC|AOp*K#ayl%KC*{ZnSnj=XHX?K>$ zX-Bi~%jXOn?&t>R?MMl>&}ElNz#Zu67k3{jsRmBkCsw#B)5-YMS6A`7MjUD+Kg>l$ zM{@)@SJ%4}>1=A$FWB0|0=bhXkfgQFH(TiqsB1iZ(Jw`-92gb|)^E(s%4wJX5MAc$ z3Z8uwu6kie>3Eij?yL2qOrg_#qh-9Dj+73n{~-$-R3py7=AhGiK4T9{`}VT&jK#S2 zO!I(zuRD~+d+&tO=cl{g{+?YlJo$qJm9xePwJR9E zfuiGRsV1_}X860Av%e~*WW(gpPzHH+g8tY#RoPMmD?T*;>2hWHbA2(Y8SeMz&$=2U zyv4bpnto`r4UQq!(o)QPhnHW;1xrWUfBtt8D53pKqjd@O=Q=Oo|1ofzIx*bCVxG@Q3eYv+-d$G4N0Ge-cDy7eKA6-B-FTz z#UwvUoui4YnebE%jEyvn2-?Z2Hw@V|#{cY)jLd+n$+FCiz{O+?SBQZBz}{LsZHCma zE8{%w4;sgk+IPIAl-y9oBX=khrnsHI|CWW=KV;VY;Cc2cx>vTl(OogZ2i67q`HC)3PL1N3Rudr|T<(|fggMZkh6#OtsmVyQK zzoi*JK82dGU-N#QJl__`G;Giv_3U3FZ2MDq9VhR}f+@XtG$tbJO;H=-K)j!tMeI#c z;jKX9(J!g*rD@<#OH5x!XF$nu8KF>rT3_X<^Cn>TFBXqxCwv6){9DpcUuwhzC^5Ny zx~Em7+_%v9kS;|@i;>PTJTNZZtMZS(Q19TNkLp$h%og7eGD%hOWd?HNAhiRIe=`ga z<1@x7?}*b+X$BY1XNpT?d^Thn#aF)G|x#Hk3N!ymBp^k&5vG3F|OXjpI!W-|-@}4DHInC2k?% zGi!?Cvv%|>=ccLEAq52Q6Cse1Ji1^1V$X{SNrSR<j8#VK4zfD=xiaJ?Wvs6HcO7)Uw z<_(lA-~U(k#Q7KZ50@Rzb80JxLN*XfOSv zsOcc>fK*p{XYpDwM<~;xf78B40AY#Yos>9rz@3ng%ZH`VtvVK;=X|TfurB#RH+2Q* z;~x_>UQN&zW)a5fR|WJSnaWw^48`8{{@LC;uu4s8}wBwg?3MPOr z_0IHYDfSMgl+t!PW~dHMTJ~FD&$q6VoyHvv8zh?%xDinx!ZABY_ckCzEll$avKwar zE&PUBzujbY{}*YT`uoCui1m%_MYmjtZABjmuIO;D~B$zq<69 zF2uQtjO)i2??c_12s;OhsU~-2?jVi(e;L<7Zut0K@sdM~Y{JYTyLXqa)=El*YKpw0 z=<##Y^+z9JB_ZK5czn(Bxi&`2@v{FthX8sWVX&eO-!qzlprTHA#du80@%S~!W4twD zL#!ddz^7PPJgTZ?7Adk~%@SZ3(Fk)qH<4X}@X50@hsFRXsT8KzKwD9qW+B^TNtDY8 z1h=nj^?-z6@W9?j%Of!Xpv6^dW)!7ZlCS}t3YONb{QkfAsG;zat~EL#;%+3}0U%O2 zKO+Z2mP@B!A}jI!GMA=p**D1`x{pcW*>wUH2%Iq#c#O{|;GUeA-W~)U@bjTmyZxe} zWMk9Q`p|$42>CSiF>lN;{3koweKWj$j!jRm8ep3Dh@8Vk0Rpm=oVdCm{^)HL=u>6Y z5IUTM-VK@aclp?GTk;yY$ip6qUJs9laShF{L`S6{kekd(G>tdz24cTw0r)O@W7HC+ zq1}IjO!W-uF^wL==8Pg^{7?PK6TrqlU2(VoVzV(I60Sg}v8``Eud*|M=op%GIzliD zFck5B-_uiT7NpC;TyaQlDO?d}ru^>Sw~1?7x;_$Y`Tn^x5L0hdV%Q>+|2PbBrSJR# z{F3*`1aA^pKqfMD>^LYAk@*Jh!k{;^xsL7Ep^{(0cCX?&8fZ{ zuD47e*y|1kNh1Al4=XvIcVa{DQn(F-zrla+)#|d@C`>=|DRGT}B{@W`%j4Ow7eC>& z&ev`F;HO9Z>tyz!9br|`ElX!yde%0vA07H=4$|xH?hW`CiGd$?Zaz9SCy~cdj4ua? zZ#-Dv1?heNeH$V-zJKC#Jg%J7g2$&o;AWNKjJ(`5ZEVH7gYgtoZ~wf%b?V~g@K6!b z*0y%ik!;A=5OTj#-ZzLUne~{T^{pT&J>cn~(zq}7W-4U79*R*7H->Cs{cq7Rb(dejU^0Z`vv$;D)e~j&bS_#wGHm@^uBJV)PLXb zo4L)OP_jB8o#9Q{i|&jr3%}Nwdad2vo?Xm!gW{Yu2M89XDGtQE(8$wq%VN)C*ygyn z_!XoFrySZJOU$2HsOtH~O*fneJnFbWg?apzW6XD74W{NF&F+7-?mCaHno&wC+`nVr zpbWzGTYaqHsDHS8q?n#tdEkr0=!K6+O}qT~N$gzBbbC zJnJf%-x&KtiTJvTlHuwGY zLtTFyqAg8-`-VQ?6NsB}qp>-i)KS|JO!^eD(j`WZ{v19GGlxpCh-S*t=4^kVJ8oKmZ~2)OXAEdV})L9q2zi__Stk+Lsf5v zA3Y%9c-M{>Ml!}8IqaGW1lV9x!P!Tqj?Uv1Ypk7%K_|q3K^#xpV;i>I9k$l*w`W5q zTawO8?Db~_UDnOvS$pF?eGbg_o_y{p2e)5S+s!W5tS!8i*Z8c4-{U;tSQhdpc8ATi zBu2-(@HbxWb3<(YxR%TruQN1pDX!j8(T#Tb$I(8~hHBkLoS@?`HQ#In9JK0nBU7&i ze8R^wuA|IfRsC~!4((UqJ&jgyTLQA>QzkqEdCP6Xy_SwV9s6ABTW>k*4Oh)dIO{|e zGy_R8?id0FoGD$8|L}NvuVKq5a)RFobU+i6tpPF9BfMP-DdUgqI*}@QM_Rg0xH@TP zlcubG`3y2G7d!!ckTyO)s#e<*576Vhbvx6UgYeHbPWMNh2u0P-)jjpOzO>$Bp5lL+ijcBOE z1VkO4IKN3+h(|L4}Q;~1T%^&7YTm7Jtf@qSkox_0* z>{w$uOE)ux*Wfx67XDh^13?XcSkL##Y>vRtD1&bkd8%9qZopntAoDp(85=ay`q_`; z*Zi(}dMan`)K2x{T4# zE8V_8RPX!I&q`A+xmr@${~FEHP3~<9yw*zYrkhWPdeZY=M$+@(>t~eHY3Eec!oLrq z>t-)U|2mO490G%aW96-evn}u9>D$Nst-SJZh48lVhIasgdX%xwO(LR!jMiH!39h>& zWk(Deq{+7-2%WkkW>6Ix`!&D?cDGj^8pO*$L*+#2pL%%WGQw#QUlrbU*pN>fvHWeH=6!!wHG(6M! zg_ksyZ4Vtj8GI*@&b*^FZuP-Lj5yjibL*+F@afdv?SsHFMU;w6kcl}FYU}gtKZ5Pr^Jx1;X!bUy*+kz>UeL(#4XsGp)Ze21@O&eW z_oMPF+InNZ|5vSpqX#L*uvDWe+Fb1 zHYX&Xywol~_ALeOH~Fep>SS=9bRIlPH3fP$b9ZcY)K^=iEyMhAaBOxeet{gVaLlm& zvfH`>F<&T5!n=$^TWqp(sRVvQU2w038vL4AduFb~NA918OzYkE^{&TX4Qk|$J)W*S z*6Cg-vI9Is8O83zZ+X@!p9I&jS7z>c-0t0GmvA*Bi{+X#C!*z4!@HNz<&0}6+YZkS zJjh&v!n<-FeO=s9c+FPaFY2>!M;9)Z2o8vkS&;LszQ4?vHSTcCB-dL_i|=c^h4NbF zF6;LTvotHesq(lT-OZ&z>ZM&0?7<{NE9!5Gz4#w1YKeIFBpTKoh9V872-~_w@-HP- zZM%vCCnDNY{CA)D!erianDSpbT9Xj7YD&DOuCr;+HHXZ2*H>S%!>Rw#=xM&p94rx3 z++0iC-idmrMd|JSGaY}8y*BY{CipN%%+Iyz;l1I zwqXKjRg)Lz_W-7AIu@0Ab+r{}c#houVG>yVDQ#B0#(UN-ii(QLW;I`-zfb&tZ;xgY zP{;Ochg{a|E@GDL1`9B6=WHfYtMC~exs{k^@&GiT#M=xUo@<%^ zQh7T6hBOLr_ysLz!BuksIAjiKTl}K}%!xPibx)hk@iEQ!@8Ny(1zacUTr!QX_Qq6| zm3y<}CyVXGZ=HRNJqpT8o1Lo;j4GQCfbBHbYLtb+SVi}!K_j0OYeZO%?sh!MdEMpv zs}lp(sA8BOaJVZHAZAe9?!tf8=Lw>Y98y0_-g%=0gC*}YQ4`gU;Cn+0fR$1WTg|cQ zD%8ANP6u9cq9_r?%JB5y_~CHrm{m8N%x(cv%lB`Y#ppj*ul_$QkBwSd;D7KS*LS>6 zja6S@)I05T`ah^py_zW|!8^-z@m;E~3Kfgvy)G%8_n|$lo+NGlPD(XgfB@0kIOG=J zNv)(d@9I)IYE-%J99D?lyVU=yO44S8Xg&=SU7#p&RFjRyerJ_;U2AnwRZ$U5(f72N z&a<~WS#EHCeb`s=^}XZ_q#j!w8SL=7n;uT0x0uQk{|}UY@L_@<_f6QGcW66CFpEkt zOK#lzmW`aB2nGJo;O!AtK7%Vxfon6cV2g;yIdt9gm@%Ex4(!pPuiapYJ(kIvQdVA` zP(%_P_s%;pt~3cPrj$+o=Hby|S%XjaS;qDHV2aIBbxSgTWOz8wqK*vkaka(>Hq&D- zO)2*F!CU4Q7KAqGFhDHn;SmNea7pId8;E%HBpDPGH1$j_&J54@4wpp*WWVG61C<PF z1H%zCG&In4h1b9STly_o>4Z=MVVYj5>|JYfqwjzn1m>h}0Twl?^(#xD1m2|8T(gKr z$R0qct!}Jt!KG{I>Fa*ZWJ!a14!KLi9pQbMJ(kw+J{U@0=Fa;(g8uyp#plS+-7r^9 zkrnplH91jnqhLXcX$sG)F-|quOn$G%PjOIV=LSw|3P?jh9BY~=_t@B&^X-yZxe|`W zTK_?*q=VpyzZbE zG1Y(pKLI3MfDcu<1^~ye3yX^-IBjunf3OrIhfyI0wcp{?)Ya+i;U-0JMcyHmP`Dg2 zhKOo_ZaubiO2ugBAN-MgW^FCfhZFyS~uW(OjeaTG&*>tO!x=R30D#kYVd_*vf9i|KBuFiQ~R!mQ1f4IT@~q z=iqt^Km~>EjvW@pwFj61<#c061oaO=&;VMhdswLmQM`GwVQhlt5ch-8DxIMjk_}Dp z%hdYEeer#lFw_(P0QT^|{{m2Gn55EaIIPpu)g?;#L=1P$)GjH#5UiDo0*Dkl0!@gF)c+A+*jLx*WBt+#a$jO3q3(FqB|JZfxvisN z-a8l~;(^R8Ns8`wbn1>gB3BSQSD1_oP#(}%!>TEKeO2!7>Fu6{&m@|MnP;hCSc6VRT0oo z`RCFH0iUqeh6bIvUGseuzYkUp03^PBd&;gKrn?c=} z$9{c1#|+7{k|Xy zO9SaJ#S&0anFjEW0gnMx=5Qy4`8Ukw?c292b2pRxVugR(wrvSNjF8D3&YWOT6x+b) z2uKG$vAci~TRLg7yuFDV=yI?)2~fsa5LgTLZDrvL-~mv?^r9!L19^}hogeEK&>?gI zonQ?FfMVAL(qXLw7KUv7f(C#Daj1t(Oj%HdnYKU+IpVNg3-cLg6|ik;-$fZ{6=2kp z5z{vqNhhi8TF}J-FF5E8@%AZ*00X8vSSJxDyDI=>JE+M0f$&{?aHy*?Y3;Y5*(tSaeLa@Hm95siMIjrUB?I0|gq%WE#kFU|C?K$NI)VI&@F; zGb|X}!C@fEz@anfc;Ui@eIjQpk3OkwWM>-a20qZ*0DptQ<3N^!sf2wxF;F@Icseba zfuh}CI%dtIzZx|8jRta50|q>DwBn7}Mg#rTfB}#GYS8328pu%%^lQxn3ogbP4HylK zObwv__I0ro68Cwx1(~tqVw}-{(ZI;n0Jg{b>iPv9eJ#}FGa4`&82K77YaS!N4vhpx z14E(#10F-7c2lU)z{uBt0gsViheiUUfg#a=0goY3yD8LYVB~ASfXB$MLnDFFz>sLb zfX9%i-4tpxF!D8Ez+>dsp^?C7U`RAzz+*_%ZVELT82K77;4$*+&`4l3FeDl<;4vg> zH-#DvjC>6k@EG}ZXe2Ni7!nN_@E8)cn?j8SM!p9AKiV Docs > Testing & debugging > Integration testing](https://flutter.dev/docs/testing/integration-tests). diff --git a/packages/pointer_interceptor/example/integration_test/widget_test.dart b/packages/pointer_interceptor/example/integration_test/widget_test.dart deleted file mode 100644 index c8d5d6f52b7..00000000000 --- a/packages/pointer_interceptor/example/integration_test/widget_test.dart +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: avoid_print - -import 'dart:html' as html; - -// Imports the Flutter Driver API. -import 'package:flutter/src/widgets/framework.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; - -import 'package:pointer_interceptor_example/main.dart' as app; - -final Finder nonClickableButtonFinder = - find.byKey(const Key('transparent-button')); -final Finder clickableWrappedButtonFinder = - find.byKey(const Key('wrapped-transparent-button')); -final Finder clickableButtonFinder = find.byKey(const Key('clickable-button')); -final Finder backgroundFinder = - find.byKey(const ValueKey('background-widget')); - -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - group('Without semantics', () { - testWidgets( - 'on wrapped elements, the browser does not hit the background-html-view', - (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - final html.Element element = - _getHtmlElementAtCenter(clickableButtonFinder, tester); - - expect(element.id, isNot('background-html-view')); - }, semanticsEnabled: false); - - testWidgets( - 'on wrapped elements with intercepting set to false, the browser hits the background-html-view', - (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - final html.Element element = - _getHtmlElementAtCenter(clickableWrappedButtonFinder, tester); - - expect(element.id, 'background-html-view'); - }, semanticsEnabled: false); - - testWidgets( - 'on unwrapped elements, the browser hits the background-html-view', - (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - final html.Element element = - _getHtmlElementAtCenter(nonClickableButtonFinder, tester); - - expect(element.id, 'background-html-view'); - }, semanticsEnabled: false); - - testWidgets('on background directly', (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - final html.Element element = - _getHtmlElementAt(tester.getTopLeft(backgroundFinder)); - - expect(element.id, 'background-html-view'); - }, semanticsEnabled: false); - }); - - group('With semantics', () { - testWidgets('finds semantics of wrapped widgets', - (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - if (!_newSemanticsAvailable()) { - print('Skipping test: Needs flutter > 2.10'); - return; - } - - final html.Element element = - _getHtmlElementAtCenter(clickableButtonFinder, tester); - - expect(element.tagName.toLowerCase(), 'flt-semantics'); - expect(element.getAttribute('aria-label'), 'Works As Expected'); - }); - - testWidgets( - 'finds semantics of wrapped widgets with intercepting set to false', - (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - if (!_newSemanticsAvailable()) { - print('Skipping test: Needs flutter > 2.10'); - return; - } - - final html.Element element = - _getHtmlElementAtCenter(clickableWrappedButtonFinder, tester); - - expect(element.tagName.toLowerCase(), 'flt-semantics'); - expect(element.getAttribute('aria-label'), - 'Never calls onPressed transparent'); - }); - - testWidgets('finds semantics of unwrapped elements', - (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - if (!_newSemanticsAvailable()) { - print('Skipping test: Needs flutter > 2.10'); - return; - } - - final html.Element element = - _getHtmlElementAtCenter(nonClickableButtonFinder, tester); - - expect(element.tagName.toLowerCase(), 'flt-semantics'); - expect(element.getAttribute('aria-label'), 'Never calls onPressed'); - }); - - // Notice that, when hit-testing the background platform view, instead of - // finding a semantics node, the platform view itself is found. This is - // because the platform view does not add interactive semantics nodes into - // the framework's semantics tree. Instead, its semantics is determined by - // the HTML content of the platform view itself. Flutter's semantics tree - // simply allows the hit test to land on the platform view by making itself - // hit test transparent. - testWidgets('on background directly', (WidgetTester tester) async { - app.main(); - await tester.pumpAndSettle(); - - final html.Element element = - _getHtmlElementAt(tester.getTopLeft(backgroundFinder)); - - expect(element.id, 'background-html-view'); - }); - }); -} - -// Calls [_getHtmlElementAt] passing it the center of the widget identified by -// the `finder`. -html.Element _getHtmlElementAtCenter(Finder finder, WidgetTester tester) { - final Offset point = tester.getCenter(finder); - return _getHtmlElementAt(point); -} - -// Locates the DOM element at the given `point` using `elementFromPoint`. -// -// `elementFromPoint` is an approximate proxy for a hit test, although it's -// sensitive to the presence of shadow roots and browser quirks (not all -// browsers agree on what it should return in all situations). Since this test -// runs only in Chromium, it relies on Chromium's behavior. -html.Element _getHtmlElementAt(Offset point) { - // Probe at the shadow so the browser reports semantics nodes in addition to - // platform view elements. If probed from `html.document` the browser hides - // the contents of as an implementation detail. - final html.ShadowRoot glassPaneShadow = - html.document.querySelector('flt-glass-pane')!.shadowRoot!; - return glassPaneShadow.elementFromPoint(point.dx.toInt(), point.dy.toInt())!; -} - -// TODO(dit): Remove this after flutter master (2.13) lands into stable. -// This detects that we can do new semantics assertions by looking at the 'id' -// attribute on flt-semantics elements (it is now set in 2.13 and up). -bool _newSemanticsAvailable() { - final html.ShadowRoot glassPaneShadow = - html.document.querySelector('flt-glass-pane')!.shadowRoot!; - final List elements = - glassPaneShadow.querySelectorAll('flt-semantics[id]'); - return elements.isNotEmpty; -} diff --git a/packages/pointer_interceptor/example/lib/main.dart b/packages/pointer_interceptor/example/lib/main.dart deleted file mode 100644 index 74f632a6023..00000000000 --- a/packages/pointer_interceptor/example/lib/main.dart +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore: avoid_web_libraries_in_flutter -import 'dart:html' as html; -import 'dart:ui_web' as ui_web; - -import 'package:flutter/material.dart'; -import 'package:pointer_interceptor/pointer_interceptor.dart'; - -const String _htmlElementViewType = '_htmlElementViewType'; -const double _videoWidth = 640; -const double _videoHeight = 480; - -/// The html.Element that will be rendered underneath the flutter UI. -html.Element htmlElement = html.DivElement() - ..style.width = '100%' - ..style.height = '100%' - ..style.backgroundColor = '#fabada' - ..style.cursor = 'auto' - ..id = 'background-html-view'; - -// See other examples commented out below... - -// html.Element htmlElement = html.VideoElement() -// ..style.width = '100%' -// ..style.height = '100%' -// ..style.cursor = 'auto' -// ..style.backgroundColor = 'black' -// ..id = 'background-html-view' -// ..src = 'https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4' -// ..poster = 'https://peach.blender.org/wp-content/uploads/title_anouncement.jpg?x11217' -// ..controls = true; - -// html.Element htmlElement = html.IFrameElement() -// ..width = '100%' -// ..height = '100%' -// ..id = 'background-html-view' -// ..src = 'https://www.youtube.com/embed/IyFZznAk69U' -// ..style.border = 'none'; - -void main() { - ui_web.platformViewRegistry.registerViewFactory( - _htmlElementViewType, - (int viewId) => htmlElement, - ); - - runApp(const MyApp()); -} - -/// Main app -class MyApp extends StatelessWidget { - /// Creates main app. - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return const MaterialApp( - title: 'Stopping Clicks with some DOM', - home: MyHomePage(), - ); - } -} - -/// First page -class MyHomePage extends StatefulWidget { - /// Creates first page. - const MyHomePage({super.key}); - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - String _lastClick = 'none'; - - void _clickedOn(String key) { - setState(() { - _lastClick = key; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('PointerInterceptor demo'), - actions: [ - PointerInterceptor( - // debug: true, - child: IconButton( - icon: const Icon(Icons.add_alert), - tooltip: 'AppBar Icon', - onPressed: () { - _clickedOn('appbar-icon'); - }, - ), - ), - ], - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Last click on: $_lastClick', - key: const Key('last-clicked'), - ), - Container( - color: Colors.black, - width: _videoWidth, - height: _videoHeight, - child: Stack( - alignment: Alignment.center, - children: [ - HtmlElement( - key: const ValueKey('background-widget'), - onClick: () { - _clickedOn('html-element'); - }, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ElevatedButton( - key: const Key('transparent-button'), - child: const Text('Never calls onPressed'), - onPressed: () { - _clickedOn('transparent-button'); - }, - ), - PointerInterceptor( - intercepting: false, - child: ElevatedButton( - key: const Key('wrapped-transparent-button'), - child: - const Text('Never calls onPressed transparent'), - onPressed: () { - _clickedOn('wrapped-transparent-button'); - }, - ), - ), - PointerInterceptor( - child: ElevatedButton( - key: const Key('clickable-button'), - child: const Text('Works As Expected'), - onPressed: () { - _clickedOn('clickable-button'); - }, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - floatingActionButton: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - PointerInterceptor( - // debug: true, - child: FloatingActionButton( - child: const Icon(Icons.navigation), - onPressed: () { - _clickedOn('fab-1'); - }, - ), - ), - ], - ), - drawer: Drawer( - child: PointerInterceptor( - // debug: true, // Enable this to "see" the interceptor covering the column. - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ListTile( - title: const Text('Item 1'), - onTap: () { - _clickedOn('drawer-item-1'); - }, - ), - ListTile( - title: const Text('Item 2'), - onTap: () { - _clickedOn('drawer-item-2'); - }, - ), - ], - ), - ), - ), - ); - } -} - -/// Initialize the videoPlayer, then render the corresponding view... -class HtmlElement extends StatelessWidget { - /// Constructor - const HtmlElement({super.key, required this.onClick}); - - /// A function to run when the element is clicked - final VoidCallback onClick; - - @override - Widget build(BuildContext context) { - htmlElement.onClick.listen((_) { - onClick(); - }); - - return const HtmlElementView( - viewType: _htmlElementViewType, - ); - } -} diff --git a/packages/pointer_interceptor/example/pubspec.yaml b/packages/pointer_interceptor/example/pubspec.yaml deleted file mode 100644 index 9f8b29e288b..00000000000 --- a/packages/pointer_interceptor/example/pubspec.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: pointer_interceptor_example -description: An example app for the pointer_interceptor package. -publish_to: 'none' -version: 1.0.0 - -environment: - sdk: ">=3.1.0 <4.0.0" - flutter: ">=3.13.0" - -dependencies: - flutter: - sdk: flutter - pointer_interceptor: - path: ../ - -dev_dependencies: - flutter_test: - sdk: flutter - integration_test: - sdk: flutter - -# The following section is specific to Flutter. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true diff --git a/packages/pointer_interceptor/example/test_driver/integration_test.dart b/packages/pointer_interceptor/example/test_driver/integration_test.dart deleted file mode 100644 index f26b6a310cf..00000000000 --- a/packages/pointer_interceptor/example/test_driver/integration_test.dart +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:integration_test/integration_test_driver.dart'; - -Future main() async => integrationDriver(); diff --git a/packages/pointer_interceptor/example/web/favicon.png b/packages/pointer_interceptor/example/web/favicon.png deleted file mode 100644 index 8aaa46ac1ae21512746f852a42ba87e4165dfdd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM diff --git a/packages/pointer_interceptor/example/web/icons/Icon-192.png b/packages/pointer_interceptor/example/web/icons/Icon-192.png deleted file mode 100644 index b749bfef07473333cf1dd31e9eed89862a5d52aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5292 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 diff --git a/packages/pointer_interceptor/example/web/icons/Icon-512.png b/packages/pointer_interceptor/example/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48dff1169879ba46840804b412fe02fefd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8252 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 diff --git a/packages/pointer_interceptor/example/web/index.html b/packages/pointer_interceptor/example/web/index.html deleted file mode 100644 index a53f5677b57..00000000000 --- a/packages/pointer_interceptor/example/web/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - example - - - - - - - - diff --git a/packages/pointer_interceptor/example/web/manifest.json b/packages/pointer_interceptor/example/web/manifest.json deleted file mode 100644 index 8c012917dab..00000000000 --- a/packages/pointer_interceptor/example/web/manifest.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} diff --git a/packages/pointer_interceptor/lib/pointer_interceptor.dart b/packages/pointer_interceptor/lib/pointer_interceptor.dart deleted file mode 100644 index 4ca1499d3bd..00000000000 --- a/packages/pointer_interceptor/lib/pointer_interceptor.dart +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -library pointer_interceptor; - -export 'src/mobile.dart' if (dart.library.html) 'src/web.dart'; diff --git a/packages/pointer_interceptor/lib/src/mobile.dart b/packages/pointer_interceptor/lib/src/mobile.dart deleted file mode 100644 index 8d645ffbcfe..00000000000 --- a/packages/pointer_interceptor/lib/src/mobile.dart +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -/// A [Widget] that prevents clicks from being swallowed by [HtmlElementView]s. -class PointerInterceptor extends StatelessWidget { - /// Create a `PointerInterceptor` wrapping a `child`. - // ignore: prefer_const_constructors_in_immutables - PointerInterceptor({ - required this.child, - this.intercepting = true, - this.debug = false, - super.key, - }); - - /// The `Widget` that is being wrapped by this `PointerInterceptor`. - final Widget child; - - /// Whether or not this `PointerInterceptor` should intercept pointer events. - final bool intercepting; - - /// When true, the widget renders with a semi-transparent red background, for debug purposes. - /// - /// This is useful when rendering this as a "layout" widget, like the root child - /// of a `Drawer`. - final bool debug; - - @override - Widget build(BuildContext context) { - return child; - } -} diff --git a/packages/pointer_interceptor/lib/src/web.dart b/packages/pointer_interceptor/lib/src/web.dart deleted file mode 100644 index e0dbcf904ff..00000000000 --- a/packages/pointer_interceptor/lib/src/web.dart +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore: avoid_web_libraries_in_flutter -import 'dart:html' as html; -import 'dart:ui_web' as ui_web; - -import 'package:flutter/widgets.dart'; - -const String _viewType = '__webPointerInterceptorViewType__'; -const String _debug = 'debug__'; - -// Computes a "view type" for different configurations of the widget. -String _getViewType({bool debug = false}) { - return debug ? _viewType + _debug : _viewType; -} - -// Registers a viewFactory for this widget. -void _registerFactory({bool debug = false}) { - final String viewType = _getViewType(debug: debug); - ui_web.platformViewRegistry.registerViewFactory(viewType, (int viewId) { - final html.Element htmlElement = html.DivElement() - ..style.width = '100%' - ..style.height = '100%'; - if (debug) { - htmlElement.style.backgroundColor = 'rgba(255, 0, 0, .5)'; - } - return htmlElement; - }, isVisible: false); -} - -/// The web implementation of the `PointerInterceptor` widget. -/// -/// A `Widget` that prevents clicks from being swallowed by [HtmlElementView]s. -class PointerInterceptor extends StatelessWidget { - /// Creates a PointerInterceptor for the web. - PointerInterceptor({ - required this.child, - this.intercepting = true, - this.debug = false, - super.key, - }) { - if (!_registered) { - _register(); - } - } - - /// The `Widget` that is being wrapped by this `PointerInterceptor`. - final Widget child; - - /// Whether or not this `PointerInterceptor` should intercept pointer events. - final bool intercepting; - - /// When true, the widget renders with a semi-transparent red background, for debug purposes. - /// - /// This is useful when rendering this as a "layout" widget, like the root child - /// of a [Drawer]. - final bool debug; - - // Keeps track if this widget has already registered its view factories or not. - static bool _registered = false; - - // Registers the view factories for the interceptor widgets. - static void _register() { - assert(!_registered); - - _registerFactory(); - _registerFactory(debug: true); - - _registered = true; - } - - @override - Widget build(BuildContext context) { - if (!intercepting) { - return child; - } - - final String viewType = _getViewType(debug: debug); - return Stack( - alignment: Alignment.center, - children: [ - Positioned.fill( - child: HtmlElementView( - viewType: viewType, - ), - ), - child, - ], - ); - } -} diff --git a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md index 3a66b061ff7..075832d18f4 100644 --- a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md +++ b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.3+7 + +* Move pointer_interceptor to subfolder + ## 0.9.3+6 * Migrates to `dart:ui_web` APIs. diff --git a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml index 3dba03b703b..697b544d98a 100644 --- a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml @@ -2,7 +2,7 @@ name: pointer_interceptor description: A widget to prevent clicks from being swallowed by underlying HtmlElementViews on the web. repository: https://github.com/flutter/packages/tree/main/packages/pointer_interceptor issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pointer_interceptor%22 -version: 0.9.3+6 +version: 0.9.3+7 environment: sdk: ">=3.1.0 <4.0.0" diff --git a/packages/pointer_interceptor/pubspec.yaml b/packages/pointer_interceptor/pubspec.yaml deleted file mode 100644 index 3dba03b703b..00000000000 --- a/packages/pointer_interceptor/pubspec.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: pointer_interceptor -description: A widget to prevent clicks from being swallowed by underlying HtmlElementViews on the web. -repository: https://github.com/flutter/packages/tree/main/packages/pointer_interceptor -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pointer_interceptor%22 -version: 0.9.3+6 - -environment: - sdk: ">=3.1.0 <4.0.0" - flutter: ">=3.13.0" - -dependencies: - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - -topics: - - web - - widgets diff --git a/packages/pointer_interceptor/test/README.md b/packages/pointer_interceptor/test/README.md deleted file mode 100644 index 7c5b4ad682b..00000000000 --- a/packages/pointer_interceptor/test/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## test - -This package uses integration tests for testing. - -See `example/README.md` for more info. diff --git a/packages/pointer_interceptor/test/tests_exist_elsewhere_test.dart b/packages/pointer_interceptor/test/tests_exist_elsewhere_test.dart deleted file mode 100644 index cc32e6c72f1..00000000000 --- a/packages/pointer_interceptor/test/tests_exist_elsewhere_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: avoid_print - -import 'package:flutter_test/flutter_test.dart'; - -void main() { - test('Tell the user where to find the real tests', () { - print('---'); - print('This package uses integration_test for its tests.'); - print('See `example/README.md` for more info.'); - print('---'); - }); -} From 3d4cd7b3fac7deccd10f5f9d77c54534dc52b7ef Mon Sep 17 00:00:00 2001 From: Louise Hsu Date: Wed, 1 Nov 2023 10:55:50 -0700 Subject: [PATCH 3/4] typos --- packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md | 2 +- packages/pointer_interceptor/pointer_interceptor/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md index 075832d18f4..ec035567f32 100644 --- a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md +++ b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.9.3+7 -* Move pointer_interceptor to subfolder +* Moved pointer_interceptor to subfolder. ## 0.9.3+6 diff --git a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml index 697b544d98a..63bfccb5392 100644 --- a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml @@ -1,6 +1,6 @@ name: pointer_interceptor description: A widget to prevent clicks from being swallowed by underlying HtmlElementViews on the web. -repository: https://github.com/flutter/packages/tree/main/packages/pointer_interceptor +repository: https://github.com/flutter/packages/tree/main/packages/pointer_interceptor/pointer_interceptor issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pointer_interceptor%22 version: 0.9.3+7 From cf5259934a54d1a61d6170ce69c6c0ceab6d5503 Mon Sep 17 00:00:00 2001 From: Louise Hsu Date: Tue, 7 Nov 2023 10:43:31 -0800 Subject: [PATCH 4/4] update changelog --- packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md index ec035567f32..b6d9709b6f0 100644 --- a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md +++ b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.9.3+7 -* Moved pointer_interceptor to subfolder. +* Updates metadata to point to new source folder ## 0.9.3+6