1. 01 Apr, 2021 1 commit
  2. 04 Mar, 2021 1 commit
  3. 04 Feb, 2021 1 commit
  4. 19 Oct, 2020 1 commit
    • Greg Spencer's avatar
      Mark keys that match a shortcut, but have no action defined as "not handled". (#67359) · 8c03ff8c
      Greg Spencer authored
      - - When I added notification of key events before processing them as text, it made it so that shortcut key bindings like the spacebar would prevent spaces from being inserted into text fields, which is obviously not desirable (and so that change was reverted). At the same time, we do want to make it possible to override key events so that they can do things like intercept a tab key or arrow keys that change the focus.
      
      This PR changes the behavior of the Shortcuts widget so that if it has a shortcut defined, but no action is bound to the intent, then instead of responding that the key is "handled", it responds as if nothing handled it. This allows the engine to continue to process the key as text entry.
      
      This PR includes:
      
      - Modification of the callback type for key handlers to return a KeyEventResult instead of a bool, so that we can return more information (i.e. the extra state of "stop propagation").
      - Modification of the ActionDispatcher.invokeAction contract to require that Action.isEnabled return true before calling it. It will now assert if the action isn't enabled when invokeAction is called. This is to allow optimization of the number of calls to isEnabled, since the shortcuts widget now wants to know if the action was enabled before deciding to either handle the key or to return ignored.
      - Modification to ShortcutManager.handleKeypress to return KeyEventResult.ignored for keys which don't have an enabled action associated with them.
      - Adds an attribute to DoNothingAction that allows it to mark a key as not handled, even though it does have an action associated with it. This will allow disabling of a shortcut for a subtree.
      8c03ff8c
  5. 13 Oct, 2020 1 commit
  6. 11 Jun, 2020 1 commit
  7. 01 May, 2020 1 commit
    • Greg Spencer's avatar
      Add `ExcludeFocus` widget, and a way to prevent focusability for a subtree. (#55756) · fdc4d21b
      Greg Spencer authored
      This adds an ExcludeFocus widget that prevents widgets in a subtree from having or obtaining focus. It also adds the ability for a FocusNode to conditionally prevent its children from being focusable when it isn't focusable (i.e. when canRequestFocus is false).
      
      It does this by adding an descendantsAreFocusable attribute to the FocusNode, which, when false, prevents the descendants of the node from being focusable (and removes focus from them if they are currently focused).
      fdc4d21b
  8. 27 Apr, 2020 1 commit
  9. 10 Apr, 2020 1 commit
    • Greg Spencer's avatar
      Fix initial value for highlight mode on desktop platforms. (#54306) · c7b10df7
      Greg Spencer authored
      This fixes the initial value of FocusManager.highlightMode so that it gets initialized correctly on desktop platforms.
      
      My recent update of this code (#52990) broke things so that the highlight mode never changed from the initial default of touch, which meant that focus highlights didn't show unless you set FocusManager.highlightStrategy to something (even automatic, the default: setting it caused the mode to be updated).
      c7b10df7
  10. 04 Apr, 2020 1 commit
  11. 27 Feb, 2020 1 commit
    • Greg Spencer's avatar
      Change Focus.unfocus to take a disposition for where the focus… (#50831) · d4226566
      Greg Spencer authored
      When Focus.unfocus is called, the caller usually just thinks about wanting to remove focus from the node, but really, unfocus is a request to automatically pass the focus to another (hopefully useful) node.
      
      This PR removes the focusPrevious flag from unfocus, and replaces it with a disposition enum that indicates where the focus should go from here.
      
      The other value of the UnfocusDisposition enum is UnfocusDisposition.scope.
      
      UnfocusDisposition.previouslyFocusedChild is closest to what focusPrevious used to do: focus the nearest enclosing scope and use its focusedChild field to walk down the tree, finding the leaf focusedChild. This PR modifies it slightly so that it walks up to the nearest focusable enclosing scope before trying to focus the children. This change addresses #48903
      
      A new mode: UnfocusDisposition.scope will focus the nearest focusable enclosing scope of this node without trying to use the FocusScopeNode.focusedChild value to descend to the leaf focused child. This is useful as a default for both text field finalization and for what happens when canRequestFocus is set to false. It allows the scope to stay focused so that nextFocus/previousFocus still work as expected, but removes the focus from primary focus.
      
      In addition to those changes, unfocus called on a FocuScope that wasn't the primary focus used to unfocus the primary focus instead. I removed that behavior, since it was buggy: if the primary focus was inside of a child scope, and you called unfocus on the parent scope, then the child scope could have focused another of its children instead, leaving the scope that you called unfocus on with hasFocus returning true still. If you want to remove the focus from the primary focus instead of the scope, that's easy enough to do: just call primaryFocus.unfocus().
      
      Fixes #48903
      d4226566
  12. 13 Feb, 2020 1 commit
  13. 10 Feb, 2020 1 commit
  14. 13 Jan, 2020 1 commit
    • Greg Spencer's avatar
      Allow requestFocus on an unattached FocusNode to create a deferred focus request (#48589) · 6495d377
      Greg Spencer authored
      This changes the behavior of requestFocus when it is called on a FocusNode that does not yet have a parent, so that it defers requesting focus until it receives a parent. Before this change, calling requestFocus before it had a parent was a no-op.
      
      This allows scenarios where a widget is newly added and wishes to immediately request the focus. Previously, it was very hard to make that work because requesting focus before the widget's focus node had a parent was ignored, so the developer had to wait until two frames later to request focus (one for the widget's node to be added to the focus tree, and one to request the focus).
      
      Now, in order to have a widget be focused when initially added, you just need to call requestFocus on its node when you create it, and as soon as it is added, it will automatically request focus.
      
      This is different from the autofocus attribute on the Focus widget, because it unconditionally requests focus when added (autofocus will only request focus if nothing else in the scope has focus).
      6495d377
  15. 03 Dec, 2019 1 commit
    • Greg Spencer's avatar
      Clean up some things I noticed while doing another change (#45658) · 37f86c31
      Greg Spencer authored
      This fixes some minor things I noticed while doing another change.
      
      - Uncomments an old test that wants to be run, but can't be, and marked it as "skipped", so that the code won't rot anymore.
      - Added the focus state to the short string version of a FocusNode
      - Added a missing piece of information to findAncestorWidgetOfExactType
      37f86c31
  16. 27 Nov, 2019 1 commit
    • Ian Hickson's avatar
      License update (#45373) · 449f4a66
      Ian Hickson authored
      * Update project.pbxproj files to say Flutter rather than Chromium
      
      Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright.
      
      * Update the copyright notice checker to require a standard notice on all files
      
      * Update copyrights on Dart files. (This was a mechanical commit.)
      
      * Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine.
      
      Some were already marked "The Flutter Authors", not clear why. Their
      dates have been normalized. Some were missing the blank line after the
      license. Some were randomly different in trivial ways for no apparent
      reason (e.g. missing the trailing period).
      
      * Clean up the copyrights in non-Dart files. (Manual edits.)
      
      Also, make sure templates don't have copyrights.
      
      * Fix some more ORGANIZATIONNAMEs
      449f4a66
  17. 01 Nov, 2019 1 commit
    • Greg Spencer's avatar
      Add convenience accessor for primaryFocus (#43859) · 3a30722f
      Greg Spencer authored
      This adds accessors for WidgetsBinding.instance.focusManager and WidgetsBinding.instance.focusManager.primaryFocus so that they can be more easily found in IDEs and accessed.
      
      This adds a top level getter for WidgetsBinding.instance.focusManager.primaryFocus called primaryFocus, and a static accessor FocusManager.instance that returns WidgetsBinding.instance.focusManager.
      3a30722f
  18. 30 Oct, 2019 1 commit
  19. 28 Oct, 2019 2 commits
  20. 23 Oct, 2019 2 commits
  21. 18 Oct, 2019 1 commit
    • Greg Spencer's avatar
      Wire up canRequestFocus and skipTraversal in FocusScopeNode (#43013) · 560873af
      Greg Spencer authored
      This adds a canRequestFocus and skipTraversal argument to FocusScope and FocusScopeNode, so that a scope can prevent being traversed.
      
      This allows a fix for a problem in the gallery where the focus while traversing the list of items would sometimes appear to disappear, since it would be focusing things that were in the backdrop that were part of the tree, but were not visible.
      
      Related Issues
      Fixes #42955
      560873af
  22. 15 Oct, 2019 1 commit
    • Greg Spencer's avatar
      Optimize focus operations by caching descendants and ancestors. (#42683) · 134ac429
      Greg Spencer authored
      This optimizes certain paths in the FocusManager, FocusNode, and FocusScopeNode classes in order to fix a regression in stock_animation_open_first_frame_average when I added more focus nodes to the tree to do focus traversal.
      
      Mainly I removed some remaining sync* iterators, and also started caching the computation of descendants and ancestors, since those are iterated over fairly often.
      
      This improves stock_animation_open_first_frame_average by about 2.8% overall (so about half of a 4.9% regression, both averaged over 10 runs).
      
      Addresses #42564
      134ac429
  23. 14 Oct, 2019 1 commit
    • Greg Spencer's avatar
      Fix route focusing and autofocus when reparenting focus nodes. (#42554) · e2c5fd6c
      Greg Spencer authored
      This fixes a problem with reparenting of focus nodes where it would remove the node from the scope's focused children when reparented, even if it was being reparented to another place under the same scope. This only occurred if the scope in question didn't have focus.
      
      This caused nodes to not get autofocused when they were a child of another node within the scope, and were reparented, and then the scope was given focus (as when a route is pushed).
      
      This keeps the node in the scope's child list where it was if the node is reparented under a parent within the same scope.
      
      - Added a test that tries to autofocus a TextField when the route is pushed and there is another 
        FocusNode above the text field. This was how this was first noticed: the autofocus got ignored in 
        this configuration.
      
      - Added a test to focus_manager_test that tests for the specific case of reparenting a node when 
        it's in the focused children of the scope.
      e2c5fd6c
  24. 26 Sep, 2019 1 commit
    • Greg Spencer's avatar
      Added proper focus handling when pushing and popping routes (#40166) · 1a7bb1f5
      Greg Spencer authored
      The proposed change will change focus handling when pushing and popping routes so that the FocusScopeNode for the route receives focus when pushed, and that the FocusScopeNode in the navigator receives focus when the route is popped.
      
      This means that the last setFirstFocus call on the scope is used to determine which control actually receives focus. When the focus scope receives focus, it traverses its children, trying to find a non-scope node that is the "first focus" of itself or a child node.
      
      This is a breaking change, because the focus behavior has changed. If you push a route after this change, and had a 'first focus' set on a widget via FocusScopeNode.setFirstFocus, it won't currently receive focus immediately, but after this change it will. Similarly, if you pop a route after this change, the focus will go back to where it was before the route was pushed, which is correct, but different from what happens now.
      1a7bb1f5
  25. 24 Sep, 2019 1 commit
    • Greg Spencer's avatar
      Add fake keyboard key generation to the testing framework (#40706) · 0e6cb28d
      Greg Spencer authored
      There were four or five different implementations in various tests for sendFakeKeyEvent, which roughly all did the same thing. I was going to add yet another one, and decided that it needed to be generalized and centralized. This replaces those instances with something that just takes a LogicalKeyboardKey so that it's self-documenting, and can be used with multiple platforms.
      
      This adds two functions to widget tester: sendKeyDownEvent and sendKeyUpEvent which simulate key up/down from a physical keyboard. It also adds global functions simulateKeyDownEvent and simulateKeyUpEvent that can be called without a widget tester. All are async functions protected by the async guard.
      0e6cb28d
  26. 04 Sep, 2019 1 commit
  27. 21 Aug, 2019 2 commits
  28. 16 Aug, 2019 1 commit
    • Greg Spencer's avatar
      Automatic focus highlight mode for FocusManager (#37825) · a11d7314
      Greg Spencer authored
      This adds a FocusHighlightMode to the FocusManager that switches based on the type of input that has recently been received. The initial value is based on the platform, but is updated as soon as user input is received. There is also a FocusHighlightStrategy enum so that the developer can change the strategy to a fixed value if needed.
      
      The default is to automatically detect the mode based on the last type of user input. If they use a mouse or keyboard, it shows the focus highlights. If they use a touch interface, then the highlights disappear. This is consistent with the way that Android and Chrome work. The controls still receive focus, only the display of the highlight changes.
      
      Text fields show the focus highlight regardless of the focus highlight mode.
      a11d7314
  29. 12 Aug, 2019 1 commit
  30. 09 Aug, 2019 2 commits
  31. 28 May, 2019 1 commit
  32. 21 May, 2019 1 commit
  33. 01 May, 2019 1 commit
    • Greg Spencer's avatar
      Change unfocus to unfocus the entire chain, Fix setFirstFocus (#31909) · be75fb36
      Greg Spencer authored
      In #31614, I added an unfocus() to FocusNodes to allow giving up of focus, but it only worked on the primary focus. This changes that so that it will unfocus the entire chain, not just the primary focus. Now, if you call unfocus() on a FocusNode or FocusScopeNode, and their hasFocus returns true, then after calling unfocus(), it will return false. Before this change, it would only do that if hasPrimaryFocus was also true.
      
      This also fixes a bug in the way setFirstFocus was implemented, making it conform more to the behavior of the previous implementation. It has simplified logic in reparent, and in when it requests focus for scope nodes that have had setFirstFocus called on them.
      be75fb36
  34. 25 Apr, 2019 1 commit
    • Greg Spencer's avatar
      [Re-Land] Implement focus traversal for desktop platforms. (#31614) · 7775c237
      Greg Spencer authored
      This re-lands the Focus changes in #30040. Correctness changes in routes.dart, and removes the automatic requesting of focus on reparent when there is no current focus, which caused undesirable selections.
      
      Addresses #11344, #1608, #13264, and #1678
      Fixes #30084
      Fixes #26704
      7775c237
  35. 23 Apr, 2019 1 commit
  36. 22 Apr, 2019 1 commit
    • Greg Spencer's avatar
      Implement focus traversal for desktop platforms, shoehorn edition. (#30040) · 4218c0bc
      Greg Spencer authored
      Implements focus traversal for desktop platforms, including re-implementing the existing focus manager and focus tree.
      
      This implements a Focus widget that can be put into a widget tree to allow input focus to be given to a particular part of a widget tree.
      
      It incorporates with the existing FocusScope and FocusNode infrastructure, and has minimal breakage to the API, although FocusScope.reparentIfNeeded is removed, replaced by a call to FocusAttachment.reparent(), so this is a breaking change:
      
      FocusScopeNodes must now be attached to the focus tree using FocusScopeNode.attach, which takes a context and an optional onKey callback, and returns a FocusAttachment that should be kept by the widget that hosts the FocusScopeNode. This is necessary because of the need to make sure that the focus tree reflects the widget hierarchy.
      
      Callers that used to call FocusScope(context).reparentIfNeeded in their build method will call reparent  on a FocusAttachment instead, which they will obtain by calling FocusScopeNode.attach in their initState method. Widgets that own FocusNodes will need to call dispose on the focus node in their dispose method.
      
      Addresses #11344, #1608, #13264, and #1678
      Fixes #30084
      Fixes #26704
      4218c0bc