Feat: Add brightness export from widgets.dart
fixes: #169294
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
This PR adds a `RawMenuAnchor()` widget to widgets.dart. The purpose of
this widget is to provide a menu primitive for the Material and
Cupertino libraries (and others) to build upon. Additionally, this PR
makes MenuController an inherited widget to simplify nested access to
the menu (e.g. if you want to launch a context menu from a deeply-nested
widget).
This PR:
* Centralizes core menu logic to a private class,` _RawMenuAnchor()`,
* Provides the internals for interacting with menus:
* TapRegion interop
* DismissMenuAction handler
* Close on scroll/resize
* Focus traversal information, if applicable
* Subclasses override `_open`, `_close`, `_isOpen`, `_buildAnchor`, and
`_menuScopeNode`
* State is accessible by descendents via
`MenuController.maybeOf(context)._anchor`
* Adds 2 public constructors, backed by a `_RawMenuAnchor()` that
contains shared logic.
* `RawMenuAnchor()`
* Users build the overlay from scratch.
* Provides anchor/overlay position information and TapRegionGroupId to
builder
* Does not provide FocusScope management.
* `RawMenuAnchorGroup()`
* A primitive for menus that do not have overlays (menu bars).
* This was previously called RawMenuAnchor.node(), but @dkwingsmt made a
good case for splitting out the constructor.
<s>Documentation examples have been added, and can be viewed at
https://menu-anchor.web.app/</s>
<s>https://github.com/user-attachments/assets/25d35f23-2aad-4d07-9172-5c3fd65d53cf</s>
@dkwingsmt
List which issues are fixed by this PR.
https://github.com/flutter/flutter/pull/143712
Some issues that need to be addressed:
Semantics:
<img width="1027" alt="image"
src="https://github.com/user-attachments/assets/d69661c9-8435-4d9c-b200-474968cb57eb">
I'm basing the menu semantics off of the comment
[here](ef3ca70db2/lib/web_ui/lib/src/engine/semantics/semantics.dart (L382)),
but I'm unsure whether the route should be given a name. There is no
menubar/menu/menuitem role in Flutter, so I'm assuming the menu should
be composed of nested dialogs
<s>Unlike the menubar pattern from
[W3C](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-navigation/),
the RawMenuAnchor
- does not close on tab/shift-tab. I left this behavior out of the menu
so that users could customize tab behavior, but I'm not opinionated
either way
- does not open on ArrowUp/ArrowDown, because this could interfere with
user focus behavior in unconventional menu setups (e.g. a vertical
menu).
- does not automatically focus the first item in a menu overlay when
activated via enter/spacebar, but does focus the first item when
horizontal traversal opens a submenu. Automatically focusing the first
item whenever an overlay opens interferes with hover traversal, and I
couldn't think of a good way to only focus the first item when an
overlay is triggered via enter/spacebar.
- doesn't focus disabled items (I wasn't sure how to address this
without editing MenuItemButton)
While it is possible to nest menus -- for example, a dropdown anchor
within a full-app context menu area -- nested menus behave as a single
group. I was considering adding an additional parameter that separates
nested root menus from their parents, and am interested to hear your
feedback.</s>
*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
---------
Co-authored-by: Bruno Leroux <bruno.leroux@gmail.com>
Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>
This is the initial work for the upcoming Widget Preview functionality.
The `WidgetPreview` class allows for users to specify overrides and
details to apply to its child `Widget`. Initially, this includes:
- Setting arbitrary width and height constraints to mimic changes in
device resolution
- Custom text scaling factors
The `Preview` class is an annotation used to identify top-level, public
functions as widget previews
Inspired by the review on #146182.
This PR adds boundary feature to the drag gestures, including `MultiDragGestureRecognizer` and `DragGestureRecognizer`. The `GestureDetector` widget will also benefit from this.
## Description
This adds `find.backButton()` in the Common Finders to allow finding different types of standard UI elements. It works by attaching a key made from an enum value in a new enum called `StandardComponentType` to all of the standard widgets that perform the associated function.
I also substituted the finder in several places where it is useful in tests.
This allows writing tests that want to find the "back" button without having to know exactly which icon the back button uses under what circumstances. To do it correctly is actually quite complicated, since there are several adaptations that occur (based on platform, and whether it is web or not).
## Tests
- Added tests.
A sliver that shows its [child] when the user scrolls forward and hides it when the user scrolls backwards. Similar headers can be found in Google Photos and Facebook.
This sliver is preferable to the general purpose SliverPersistentHeader for its relatively narrow use case because there's no need to create a SliverPersistentHeaderDelegate or to predict the header's size.
https://github.com/flutter/flutter/assets/1377460/82b67dfb-5d38-4adf-9415-fc8527d0eb9f
A sliver that is pinned to the start of its `CustomScrollView` and reacts to scrolling by resizing between the intrinsic sizes of its min and max extent prototypes.
The minimum and maximum sizes of this sliver are defined by `minExtentPrototype` and `maxExtentPrototype`, a pair of widgets that are laid out once. You can use `SizedBox` widgets to define the size limits.
This sliver is preferable to the general purpose `SliverPersistentHeader` for its relatively narrow use case because there's no need to create a `SliverPersistentHeaderDelegate` or to predict the header's minimum or maximum size.
The sample shows how this sliver's two extent prototype properties can be used to create a resizing header whose minimum and maximum sizes match small and large configurations of the same header widget.
https://github.com/flutter/flutter/assets/1377460/fa7ced98-9d92-4d13-b093-50392118c213
Related sliver utility PRs: https://github.com/flutter/flutter/pull/143538, https://github.com/flutter/flutter/pull/143196, https://github.com/flutter/flutter/pull/127340.
Reverts: flutter/flutter#148238
Initiated by: zanderso
Reason for reverting: Failures in post submit https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8748025189669617649/+/u/run_test.dart_for_web_canvaskit_tests_shard_and_subshard_3/stdout
Original PR Author: justinmc
Reviewed By: {hellohuanlin}
This change reverts the following previous change:
Reland of https://github.com/flutter/flutter/pull/143002, which was reverted in https://github.com/flutter/flutter/pull/148237 due to unresolved docs references. Not sure why those weren't caught in presubmit.
```
dartdoc:stdout: Generating docs for package flutter...
dartdoc:stderr: error: unresolved doc reference [TextInput.showSystemContextMenu]
dartdoc:stderr: from widgets.MediaQueryData.supportsShowingSystemContextMenu: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/widgets/media_query.dart:579:14)
dartdoc:stderr: in documentation inherited from widgets.MediaQueryData.supportsShowingSystemContextMenu: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/widgets/media_query.dart:579:14)
dartdoc:stderr: error: unresolved doc reference [showSystemContextMenu]
dartdoc:stderr: from services.SystemContextMenuController.hide: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/services/text_input.dart:2554:16)
dartdoc:stderr: error: unresolved doc reference [hideSystemContextMenu]
dartdoc:stderr: from services.SystemContextMenuController.show: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/services/text_input.dart:2509:16)
```
It's now possible to use the native-rendered text selection context menu on iOS. This sacrifices customizability in exchange for avoiding showing a notification when the user presses "Paste". It's off by default, but to enable, see the example system_context_menu.0.dart.
Reverts: flutter/flutter#143002
Initiated by: cbracken
Reason for reverting: unresolved docs links. See failure here: https://ci.chromium.org/ui/p/flutter/builders/prod/Linux%20docs_test/16540/overview
```
dartdoc:stdout: Generating docs for package flutter...
dartdoc:stderr: error: unresolved doc reference [TextInput.showSystemContextMenu]
dartdoc:stderr: from widgets.MediaQueryData.supportsShowingSystemContextMenu: (file:///b/s/w/ir/x/w/flutter/packages/flutt
Original PR Author: justinmc
Reviewed By: {Renzo-Olivares, hellohuanlin}
This change reverts the following previous change:
In order to work around the fact that iOS 15 shows a notification on pressing Flutter's paste button (https://github.com/flutter/flutter/issues/103163), this PR allows showing the iOS system context menu in text fields.
<img width="385" alt="Screenshot 2024-02-06 at 11 52 25 AM" src="https://github.com/flutter/flutter/assets/389558/d82e18ee-b8a3-4082-9225-cf47fa7f3674">
It is currently opt-in, which a user would typically do like this (also in example system_context_menu.0.dart):
```dart
contextMenuBuilder: (BuildContext context, EditableTextState editableTextState) {
// If supported, show the system context menu.
if (SystemContextMenu.isSupported(context)) {
return SystemContextMenu.editableText(
editableTextState: editableTextState,
);
}
// Otherwise, show the flutter-rendered context menu for the current
// platform.
return AdaptiveTextSelectionToolbar.editableText(
editableTextState: editableTextState,
);
},
```
Requires engine PR https://github.com/flutter/engine/pull/50095.
## API changes
### SystemContextMenu
A widget that shows the system context menu when built, and removes it when disposed. The main high-level way that most users would use this PR. Only works on later versions of iOS.
### SystemContextMenuController
Used under the hood to hide and show a system context menu. There can only be one visible at a time.
### MediaQuery.supportsShowingSystemContextMenu
Sent by the iOS embedder to tell the framework whether or not the platform supports showing the system context menu. That way the framework, or Flutter developers, can decide to show a different menu.
### `flutter/platform ContextMenu.showSystemContextMenu`
Sent by the framework to show the menu at a given `targetRect`, which is the current selection rect.
### `flutter/platform ContextMenu.hideSystemContextMenu`
Sent by the framework to hide the menu. Typically not needed, because the platform will hide the menu when the user taps outside of it and after the user presses a button, but it handles edge cases where the user programmatically rebuilds the context menu, for example.
### `flutter/platform System.onDismissSystemContextMenu`
Sent by the iOS embedder to indicate that the system context menu has been hidden by the system, such as when the user taps outside of the menu. This is useful when there are multiple instances of SystemContextMenu, such as with multiple text fields.
It's now possible to use the native-rendered text selection context menu on iOS. This sacrifices customizability in exchange for avoiding showing a notification when the user presses "Paste". It's off by default, but to enable, see the example system_context_menu.0.dart.
This cleans up a few sliver classes, like moving RenderSliverVariedExtentList to the rendering layer (it was in the widgets layer), and moving SliverVariedExtentList to live with its sibling subclasses, SliverFixedExtentList, SliverList, and so on.
I moved these while working on SliverTree, so figure I should break out into a separate change.
SliverTree and SliverCarousel (both inbound in separate changes) will also be subclasses of RenderSliverFixedExtentBoxAdaptor, organizing them together felt easier to work with.
Related to https://github.com/flutter/flutter/issues/114299 and https://github.com/flutter/flutter/issues/125980
Fixes#138270.
Moves the majority of the logic of MaterialStateProperties down to the widgets layer, then has the existing Material classes pull from the widgets versions.
Reverts flutter/flutter#125927
context: b/300804374
Looks like a g3 fix might involve changing the names of widget on the customer app, and I am not sure if that would be the right approach forward. Putting up a revert to be safe for now.
Fixes https://github.com/flutter/flutter/issues/113431
Currently we only support specifying all slivers to have the same extent.
This patch introduces an `itemExtentBuilder` property for `ListView`, allowing the slivers to have different extents while still having scrolling performance, especially when the scroll position changes drastically(such as scrolling by the scrollbar or controller.jumpTo()).
@Piinks Hi, Any thoughts about this? :)
This PR aims to support Android's predictive back gesture when popping the entire Flutter app. Predictive route transitions between routes inside of a Flutter app will come later.
<img width="200" src="https://user-images.githubusercontent.com/389558/217918109-945febaa-9086-41cc-a476-1a189c7831d8.gif" />
### Trying it out
If you want to try this feature yourself, here are the necessary steps:
1. Run Android 33 or above.
1. Enable the feature flag for predictive back on the device under "Developer
options".
1. Create a Flutter project, or clone [my example project](https://github.com/justinmc/flutter_predictive_back_examples).
1. Set `android:enableOnBackInvokedCallback="true"` in
android/app/src/main/AndroidManifest.xml (already done in the example project).
1. Check out this branch.
1. Run the app. Perform a back gesture (swipe from the left side of the
screen).
You should see the predictive back animation like in the animation above and be able to commit or cancel it.
### go_router support
go_router works with predictive back out of the box because it uses a Navigator internally that dispatches NavigationNotifications!
~~go_router can be supported by adding a listener to the router and updating SystemNavigator.setFrameworkHandlesBack.~~
Similar to with nested Navigators, nested go_routers is supported by using a PopScope widget.
<details>
<summary>Full example of nested go_routers</summary>
```dart
// Copyright 2014 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:go_router/go_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
void main() => runApp(_MyApp());
class _MyApp extends StatelessWidget {
final GoRouter router = GoRouter(
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) => _HomePage(),
),
GoRoute(
path: '/nested_navigators',
builder: (BuildContext context, GoRouterState state) => _NestedGoRoutersPage(),
),
],
);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: router,
);
}
}
class _HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Nested Navigators Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Home Page'),
const Text('A system back gesture here will exit the app.'),
const SizedBox(height: 20.0),
ListTile(
title: const Text('Nested go_router route'),
subtitle: const Text('This route has another go_router in addition to the one used with MaterialApp above.'),
onTap: () {
context.push('/nested_navigators');
},
),
],
),
),
);
}
}
class _NestedGoRoutersPage extends StatefulWidget {
@override
State<_NestedGoRoutersPage> createState() => _NestedGoRoutersPageState();
}
class _NestedGoRoutersPageState extends State<_NestedGoRoutersPage> {
late final GoRouter _router;
final GlobalKey<NavigatorState> _nestedNavigatorKey = GlobalKey<NavigatorState>();
// If the nested navigator has routes that can be popped, then we want to
// block the root navigator from handling the pop so that the nested navigator
// can handle it instead.
bool get _popEnabled {
// canPop will throw an error if called before build. Is this the best way
// to avoid that?
return _nestedNavigatorKey.currentState == null ? true : !_router.canPop();
}
void _onRouterChanged() {
// Here the _router reports the location correctly, but canPop is still out
// of date. Hence the post frame callback.
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
setState(() {});
});
}
@override
void initState() {
super.initState();
final BuildContext rootContext = context;
_router = GoRouter(
navigatorKey: _nestedNavigatorKey,
routes: [
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) => _LinksPage(
title: 'Nested once - home route',
backgroundColor: Colors.indigo,
onBack: () {
rootContext.pop();
},
buttons: <Widget>[
TextButton(
onPressed: () {
context.push('/two');
},
child: const Text('Go to another route in this nested Navigator'),
),
],
),
),
GoRoute(
path: '/two',
builder: (BuildContext context, GoRouterState state) => _LinksPage(
backgroundColor: Colors.indigo.withBlue(255),
title: 'Nested once - page two',
),
),
],
);
_router.addListener(_onRouterChanged);
}
@override
void dispose() {
_router.removeListener(_onRouterChanged);
super.dispose();
}
@override
Widget build(BuildContext context) {
return PopScope(
popEnabled: _popEnabled,
onPopped: (bool success) {
if (success) {
return;
}
_router.pop();
},
child: Router<Object>.withConfig(
restorationScopeId: 'router-2',
config: _router,
),
);
}
}
class _LinksPage extends StatelessWidget {
const _LinksPage ({
required this.backgroundColor,
this.buttons = const <Widget>[],
this.onBack,
required this.title,
});
final Color backgroundColor;
final List<Widget> buttons;
final VoidCallback? onBack;
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(title),
//const Text('A system back here will go back to Nested Navigators Page One'),
...buttons,
TextButton(
onPressed: onBack ?? () {
context.pop();
},
child: const Text('Go back'),
),
],
),
),
);
}
}
```
</details>
### Resources
Fixes https://github.com/flutter/flutter/issues/109513
Depends on engine PR https://github.com/flutter/engine/pull/39208✔️
Design doc: https://docs.google.com/document/d/1BGCWy1_LRrXEB6qeqTAKlk-U2CZlKJ5xI97g45U7azk/edit#
Migration guide: https://github.com/flutter/website/pull/8952
This change enables Flutter to generate multiple Scenes to be rendered into separate FlutterViews from a single widget tree. Each Scene is described by a separate render tree, which are all associated with the single widget tree.
This PR implements the framework-side mechanisms to describe the content to be rendered into multiple views. Separate engine-side changes are necessary to provide these views to the framework and to draw the framework-generated Scene into them.
## Summary of changes
The details of this change are described in [flutter.dev/go/multiple-views](https://flutter.dev/go/multiple-views). Below is a high-level summary organized by layers.
### Rendering layer changes
* The `RendererBinding` no longer owns a single `renderView`. In fact, it doesn't OWN any `RenderView`s at all anymore. Instead, it offers an API (`addRenderView`/`removeRenderView`) to add and remove `RenderView`s that then will be MANAGED by the binding. The `RenderView` itself is now owned by a higher-level abstraction (e.g. the `RawView` Element of the widgets layer, see below), who is also in charge of adding it to the binding. When added, the binding will interact with the `RenderView` to produce a frame (e.g. by calling `compositeFrame` on it) and to perform hit tests for incoming pointer events. Multiple `RenderView`s can be added to the binding (typically one per `FlutterView`) to produce multiple Scenes.
* Instead of owning a single `pipelineOwner`, the `RendererBinding` now owns the root of the `PipelineOwner` tree (exposed as `rootPipelineOwner` on the binding). Each `PipelineOwner` in that tree (except for the root) typically manages its own render tree typically rooted in one of the `RenderView`s mentioned in the previous bullet. During frame production, the binding will instruct each `PipelineOwner` of that tree to flush layout, paint, semantics etc. A higher-level abstraction (e.g. the widgets layer, see below) is in charge of adding `PipelineOwner`s to this tree.
* Backwards compatibility: The old `renderView` and `pipelineOwner` properties of the `RendererBinding` are retained, but marked as deprecated. Care has been taken to keep their original behavior for the deprecation period, i.e. if you just call `runApp`, the render tree bootstrapped by this call is rooted in the deprecated `RendererBinding.renderView` and managed by the deprecated `RendererBinding.pipelineOwner`.
### Widgets layer changes
* The `WidgetsBinding` no longer attaches the widget tree to an existing render tree. Instead, it bootstraps a stand-alone widget tree that is not backed by a render tree. For this, `RenderObjectToWidgetAdapter` has been replaced by `RootWidget`.
* Multiple render trees can be bootstrapped and attached to the widget tree with the help of the `View` widget, which internally is backed by a `RawView` widget. Configured with a `FlutterView` to render into, the `RawView` creates a new `PipelineOwner` and a new `RenderView` for the new render tree. It adds the new `RenderView` to the `RendererBinding` and its `PipelineOwner` to the pipeline owner tree.
* The `View` widget can only appear in certain well-defined locations in the widget tree since it bootstraps a new render tree and does not insert a `RenderObject` into an ancestor. However, almost all Elements expect that their children insert `RenderObject`s, otherwise they will not function properly. To produce a good error message when the `View` widget is used in an illegal location, the `debugMustInsertRenderObjectIntoSlot` method has been added to Element, where a child can ask whether a given slot must insert a RenderObject into its ancestor or not. In practice, the `View` widget can be used as a child of the `RootWidget`, inside the `view` slot of the `ViewAnchor` (see below) and inside a `ViewCollection` (see below). In those locations, the `View` widget may be wrapped in other non-RenderObjectWidgets (e.g. InheritedWidgets).
* The new `ViewAnchor` can be used to create a side-view inside a parent `View`. The `child` of the `ViewAnchor` widget renders into the parent `View` as usual, but the `view` slot can take on another `View` widget, which has access to all inherited widgets above the `ViewAnchor`. Metaphorically speaking, the view is anchored to the location of the `ViewAnchor` in the widget tree.
* The new `ViewCollection` widget allows for multiple sibling views as it takes a list of `View`s as children. It can be used in all the places that accept a `View` widget.
## Google3
As of July 5, 2023 this change passed a TAP global presubmit (TGP) in google3: tap/OCL:544707016:BASE:545809771:1688597935864:e43dd651
## Note to reviewers
This change is big (sorry). I suggest focusing the initial review on the changes inside of `packages/flutter` first. The majority of the changes describe above are implemented in (listed in suggested review order):
* `rendering/binding.dart`
* `widgets/binding.dart`
* `widgets/view.dart`
* `widgets/framework.dart`
All other changes included in the PR are basically the fallout of what's implemented in those files. Also note that a lot of the lines added in this PR are documentation and tests.
I am also very happy to walk reviewers through the code in person or via video call, if that is helpful.
I appreciate any feedback.
## Feedback to address before submitting ("TODO")
This is a second attempt to merge #107269. Currently I've fixed two of the issues:
1. Fixed horizontal scrollview by using a switch statement to consider vertical/horizontal case.
2. Fixed issue of `paintExtent` not being the right extent for painting. Rather using a `scrollExtent` for the main axis length of the decoration box and painting it offsetted by the `scrollOffset`.
3. If the sliver child has inifinite scrollExtent, then we only draw the decoration down to the bottom of the `cacheExtent`. The developer is expected to ensure that the border does not creep up above the cache area.
This PR includes a test that checks that the correct rectangle is drawn at a certain scrollOffset for both the horizontal and vertical case which should be sufficient for checking that `SliverDecoration` works properly now.
Fixes https://github.com/flutter/flutter/issues/107498.
* Revert "Revert "Add support for double tap and drag for text selection (#109573)" (#117497)"
This reverts commit 39fa0117a919bd401c4c8734c97ddb46fbc45cb7.
* Allow TapAndDragGestureRecognizer to accept pointer events from any devices -- the TapGestureRecognizer it replaces was previously doing this
Co-authored-by: Renzo Olivares <roliv@google.com>
* Replace PanGestureRecognizer in TextSelection with TapAndDragGestureRecognizer
* add tracking of _DragState to new tap_and_drag recognizer and remove some legacy double tap code from text_selection.dart and add logs"
* add dragTapCount, a tap count that is persistent for an entire drag and is set to null on drag end vs the regular tap count which is reset on a timer
* basic double tap to drag functionality and add a local dragTapCount in text_selection.dart to use with the timer callback
* Add offsetFromOrigin and localOffsetFromOrigin to DragUpdateDetails similar to LongPressMoveUpdateDetails, eliminates the need to hold the state of lastDragStartDetails
* make a generic baselongpressgesturerecognizer
* Revert "make a generic baselongpressgesturerecognizer"
This reverts commit aad8f7433bd01e4cd016d527af832c3b1f15fac5.
* rename tap_and_drag to selection_recognizers
* add mixin for consecutivetap
* tap and long press gesture recognizer
* Revert "Revert "make a generic baselongpressgesturerecognizer""
This reverts commit 181350c36718f644eada3e45c1b7b5939f90a340.
* Revert "Revert "Revert "make a generic baselongpressgesturerecognizer"""
This reverts commit 4d69775967858dfd66dd9429e1713da598908a85.
* Add support for secondary button clicks on drag gesture recognizer and separate drag end and tap up callback
* get test running
* rename tapCount to consecutiveTapCount
* dispose timer properly
* add some comments to tests
* Add comments
* Make ConsecutiveTapMixin private and move logic to increment tap count into mixin
* stop tracking pointer when gesture is rejected and detect drags on touch devices
* onCancel for TapAndDrag
* have the TapAndDragGestureRecognizer handle tap downs and tap ups on touch and mouse devices
* add drag to move cursor for android and iOS, and pointer device kind to DragUpdateDetails
* get tests running
* refactor TapAndDragGestureRecognizer moving some logic into _check methods
* Handle cancel properly on TapAndDragGestureRecognizer, having both onTapCancel and onDragCancel, also fix tests
* Fix test mouse drag selects and cannot drag cursor, save _initialPosition based on dragStartBehavior (either on tapDown or dragStart)
* determine if drag has a sufficient global distance to accept and fix some cancel behavior, making _checkCancel clearer
* give up pointer on drag end
* properly stop tracking pointer, fixes test for right click on Apple and non-apple platforms
* clean up some comments from last commit
* remove drag on touch for now
* fix Can select text by dragging with a mouse due to dragStart only being fired on the first PointerMoveEvent, the previous pan gesture recognizer would fire both dragStart and dragUpdate
* Revert "fix Can select text by dragging with a mouse due to dragStart only being fired on the first PointerMoveEvent, the previous pan gesture recognizer would fire both dragStart and dragUpdate"
This reverts commit 124dc79bc3389672c76d7c014ce04edab297abc6.
* correctly use _initialPosition for checkStart and call _checkUpdate after _checkStart if localDelta is not zero
* updates
* fix double tap chains
* Add docs
* Address analyzer
* more analyzer, only issues left are with print statements
* add deadlineTimer to fix conflict with ForcePressGestureRecognizer
* Revert "add deadlineTimer to fix conflict with ForcePressGestureRecognizer"
This reverts commit 3b29ddfff4cde4845edd481ecefb789fea2a0781.
* remove unecessary changes to tests
* secondaryButton should not drag
* Revert "Revert "add deadlineTimer to fix conflict with ForcePressGestureRecognizer""
This reverts commit 0a008f029f5796acd48c17c1897c0b700d5ef3a7.
* updates
* Revert "updates"
This reverts commit 4803b8443a2b67f0b8d29e9a01f712dfcb0f588c.
* Revert "Revert "Revert "add deadlineTimer to fix conflict with ForcePressGestureRecognizer"""
This reverts commit 79251a7af88d5dbb1460a960afc77e65dea18bff.
* fix shift + tap + drag tests, this was happening because a double tap + drag was being registered and not a single tap, added a duration to pumpAndSettle to fix this
* remove TapAndLongPressGestureRecognizer
* fix cupertino text field tests related to shift + tap + drag
* deadline timer try 2
* more logs
* Should reset taps when tap cancel is called, and should wait until gesture is accepted to initiate a drag
* should clear _down and _up when gesture is rejected
* remove erroneous log
* fix selectable text double tap chains test
* dont restart timer until tap up
* reset consecutiveTapCount on drag end
* fix selectableText test
* fix material text field tests
* reject TapAndDragGestureRecognizer when it is neither a tap nor a drag
* remove prints
* clean up
* shift aware
* clean up
* fix cupertino test
* fix text field focus tests
* Add 100ms delay to cupertino test, to prevent a double tap
* clean up test comments
* add comment to test
* uncomment test
* remove longpress changes
* Fix drag on mobile
* remove debug
* Fix drag to move cursor on iOS
* left over from drag fix
* add tests for drag on touch devices
* add test for double tap + drag mouse devices
* add tests
* Fix bug where initialPosition was used before it was set
* Address some review comments and fix issue where if double tap was held too long then long press gesture recognizer would take over
* remove _isDoubleTap flag since it is no longer needed due to previous commit
* Add docs for onTapCancel and onDragCancel
* analyzer fixes
* Do not test selection handles on macOS, since macOS does not support touch
* Add assert for dragStartBehavior
* add double tap + drag tests to cupertino
* use kDoubleTapTimeout instead of const Duration(milliseconds: 300) for readability
* analyzer issues
* update docs
* update more docs
* address comments
* more doc updates
* fix docs
* unused import
* fix docs
* Add more tests
* Add more tests and reject a tap up if we have exceeded the tap tolerance
* updates
* Address comments
* fix test naming
* update documentation
* move selection_recognizers to selection_gestures
* fix analyzer
* fix analyzer
* keysPressedOnDown instead of isShiftPressed
* update docs
* update docs
* Add drag update throttle to TapAndDragGestureRecognizer
* update comments
* missed from merge
* Replace _ConsecutiveTapMixin with _TapStatusTrackerMixin
* updates
* correctly cancel tap when when past tap tolerance with new implementation
* Should call tap and drag cancel if we are giving up a pointer without succesfully tracking a PointerUpEvent
* comments
* move pastTapTolerance to tap tracker
* move pastTapTolerance to tap tracker
* clean up check for nulls and remove use of consecutiveTapCountWhileDragging
* move call to super.acceptGesture to top
* remove print
* clean up
* Fix tests where both PanGestureRecognizer and TapAndDragGestureRecognizer lost
* clean up
* _GestureState -> _DragState
* more docs clean up
* more clean up
* Add onSecondaryTapCancel
* Add docs
* more docs
* Fix broken isPointerAllowed when attempting a right click drag - the _initialButtons is never reset
* revert debug flag
* make primaryPointer private
* Add support for upper count limit in TapAndDragGestureRecognizer, the tap counter should not be allowed to grow infinitely unless that is desired
* fix analyzer
* Use new TapDrag details objects and callbacks
* clean up docs
* clean up and add test for upperLimit
* Add docs for TapAndDragGestureRecognizer and remove some ambiguity of onStart onUpdate and onEnd parameters
* Address review comments
* analyzer fixes
* Call cancel before rejecting the gesture so we can still access _initialButtons
* Recognizer should reject any pointer differing from the original
* Revert "Recognizer should reject any pointer differing from the original"
This reverts commit afd9807480bd11e119bdd2b7d520631511973bab.
* Address reviewer comments
* Correct cancel behavior
* Fix consecutive tap + drag because _dragStart state was not being set when consecutive tap is greater than one
* Add more tests
* Add documentation on behavior with TapGestureRecognizer and DragGestureRecognizer
* more docs
* more docs
* remove comments
* updates
* fix multiple pointer behavior
* only handle the primary pointer
* Clean up dangerous assumptions in gesture details objects
* forgot from rebase
* update docs
* updates
* Clean up some redundant code
* remove whitespace
* fix tests as a result of #115849
* update test docs
* Fix same test from last commit for material variants
* More clean up of redundant code and update docs
* Clean up didStopTrackingLastPointer and untie TapAndDragGestureRecognizer cancel behavior from TapStatusTrackerMixin.currentUp state
* untie pastTapTolerance
* updates
* Add slopTolerance
* update docs
* Have secondary tap handled by TapGestureRecognizer
* update docs
* fix analyzer and address comments
* Add more docs
* Update cancel behavior tol not call on tap cancel when a drag has been accepted
* Change cancel behavior to only cancel if the tap down callback has been sent and merge tapcancel and dragcancel
* update docs;
* Rename selection_gestures to tap_and_drag_gestures
* Address some reviewer comments
* make deadline and slopTolerance private
* updates
* updates
* Address review comments
* remove _initialButtons
* fix docs
* trackTrap -> trackTap
* fix analyzer
* Add test to verify that tap up is called when recognizer accepts before handleEvent is called
* implement Diagnosticable for Details objects;
* sentTapDown == wonArenaForPrimaryPointer, so the implementation now only uses sentTapDown
* Count user tap up immediately and do not wait to win the arena
* Do not need to call super from TapAndDragGestureRecognizer.acceptGesture anymore because mixin implementation is gone
* Do not start selection drag on Android, iOS, and Fuchshsia touch devices if renderEditable does not have focus, this fixes many scubas
* Address reviewer comments
* fix test
* TapAndDragGestureRecognizer should wait for other recognizer to lose before winning the arena
* Address review comments
* Dont check for drag if the start was already found
* Only check for a drag if it has not already been found"
* fix from rebase
Co-authored-by: Renzo Olivares <roliv@google.com>
* Reland "Inject current `FlutterView` into tree and make available via `View.of(context)` (#116924)"
This reverts commit 9102f2fe0bd26db6074ac4a17785296cd341ecb9.
* remove window placeholder
* Can show context menus anywhere in the app, not just on text.
* Unifies all desktop/mobile context menus to go through one class (ContextMenuController).
* All context menus are now just plain widgets that can be fully customized.
* Existing default context menus can be customized and reused.