Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Explain the "patching" protocol in KeyMessageManager.keyMessageHandler and add an example #105280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

dkwingsmt
Copy link
Contributor

@dkwingsmt dkwingsmt commented Jun 3, 2022

This PR rewrites the documentation of KeyMessageManager.keyMessageHandler, explains how to properly "patch" the handler, and adds an example that uses it.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • 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.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard bot added d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos documentation framework flutter/packages/flutter repository. See also f: labels. c: contributor-productivity Team-specific productivity, code health, technical debt. labels Jun 3, 2022
@dkwingsmt dkwingsmt marked this pull request as draft June 3, 2022 01:38
@dkwingsmt dkwingsmt added a: text input Entering text in a text field or keyboard related problems a: desktop Running on desktop labels Jun 3, 2022
@dkwingsmt dkwingsmt changed the title Explain KeyMessageManager.keyMessageHandler and add an example Explain the "patching" protocol in KeyMessageManager.keyMessageHandler and add an example Jun 3, 2022
@matthew-carroll
Copy link
Contributor

@dkwingsmt looking at KeyMessage, which has a List of KeyEvent and a single RawKeyEvent, how is a client expected to differentiate between key up and key down events? In fact, how can there be multiple KeyEvents for a single RawKeyEvent?

@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Jun 5, 2022

how is a client expected to differentiate between key up and key down events

The short answer is, you only use either the stream of RawKeyEvents or the stream of KeyEvents. Within each individual stream, the state of the key should be easily understandable.

To handle both at the same time, check out the introduction to Event Results updated in this PR, as well as FocusManager._handleKeyMessage.

how can there be multiple KeyEvents for a single RawKeyEvent?

It is due to the new event model adopted by KeyEvent, and this can occur in many scenarios.

One of them, for example, is modifier synchronization. If you press AltLeft when Flutter is on focus, switch away, release the key, and switch back (which happens for Alt-Tab), Flutter will not receive a native event of key up, but the key is released by ground truth.

In the RawKeyEvent model, Flutter events are mapped from native events one-to-one, which means Flutter never dispatches the AltLeft up event. The keyboard state is updated to the ground truth at the next event nonetheless, but silently.

In the KeyEvent model, Flutter events are mapped from state changes. There will be no silent state changes. Whether the KeyEvent can be mapped a real event is indicated by synthesized. So while the keyboard state is still only updated to the ground truth at the next event (we will likely improve this in #99330), immediately before that real event Flutter will dispatch a sythesized AltLeft key up event.

To summarize what happens,

Ground truth:           AltLeft down       (AltLeft released elsewhere)       KeyA down

RawKeyEvent events:     AltLeft down                                          KeyA down
RawKeyboard state:        AltLeft pressed                                       AltLeft released

KeyEvent events:        AltLeft down                                          AltLeft up*, KeyA down
HardwareKeyboard state:   AltLeft pressed                                       AltLeft released

* Synthesized.

And it is needed to pack the RawKeyEvent and KeyEvents for this native event in one object, even though it looks confusing, just in case the developer would like to calculate the aggregated event result for the native event, which you can find out in FocusManager._handleKeyMessage.

@matthew-carroll
Copy link
Contributor

Is there a reason that only a single RawKeyEvent is provided, but possibly many KeyEvents?

You mentioned the synthesized property on KeyEvent. With that property, why is RawKeyEvent required? If synthesized is false on KeyEvent, doesn't that represent a "raw key event"?

@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Jun 6, 2022

Every native event corresponds to one RawKeyEvent. Every native event can spawn zero to multiple KeyEvents. The reason has been explained above.

RawKeyEvent is only provided for backward compatibility, and will be deprecated in the future. The HardwareKeyboard system is intended as a breaking change. The current condition where two sets of APIs are provided in parallel is temporary.

There are quite a few things we'd like to break with this new keyboard system, not only the event object, but also types (RawKeyEvent doesn't support repeat types), keys (there are new rules to forge logical keys in certain corner cases), APIs (the locked modes, mostly how CapsLock's state is represented), and work in progress, character, and the name (we no longer provide RawKeyEventData, and even the non-synthesized events might not be that "raw".) Moreover, there are some bugs that are hard to fix without ditching some guarantees we assured in the documentation of the old system. Among others.

@goderbauer
Copy link
Member

(triage) @dkwingsmt Do you still have plans for this PR?

@matthew-carroll
Copy link
Contributor

FYI @dkwingsmt - Despite us not ending up using this in super_editor, I do plain to use this capability to show popup indications for what the user presses, so that devs can debug their keyboard behavior. So I do think there are use-cases for this, and a public example is a good idea.

@dkwingsmt
Copy link
Contributor Author

Thanks for letting me know! Yeah I was hesitating of committing to this since I couldn't think of more usage.

@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Jul 13, 2022

Let me add some tests and I'll land this PR.

@dkwingsmt dkwingsmt force-pushed the explain-key-event-manager-key-message-handler branch from f5c404b to 77ec229 Compare July 18, 2022 23:00
@dkwingsmt dkwingsmt marked this pull request as ready for review July 19, 2022 02:29
@dkwingsmt dkwingsmt requested a review from gspencergoog July 19, 2022 02:29
@dkwingsmt
Copy link
Contributor Author

cc @matthew-carroll
I'd appreciate if you can take a look and see if the docs make sense. :)

Comment on lines 8 to 12
// This example app demonstrates a use case of patching
// `KeyEventManager.keyMessageHandler`: be notified of key events that are not
// handled by any focus handlers (such as shortcuts).
//
// See [KeyEventManager.keyMessageHandler].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't link in the IDE, so you don't need the []

Also, Because we don't want to maintain two copies of the description that can get out
of date, we tend not to put detailed descriptions here, other that to say what it is
attached to. So, I'd change this to:

Suggested change
// This example app demonstrates a use case of patching
// `KeyEventManager.keyMessageHandler`: be notified of key events that are not
// handled by any focus handlers (such as shortcuts).
//
// See [KeyEventManager.keyMessageHandler].
/// Flutter code sample for [KeyEventManager.keyMessageHandler].

dkwingsmt and others added 4 commits July 20, 2022 07:21
…b.com:dkwingsmt/flutter into explain-key-event-manager-key-message-handler
@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Jul 20, 2022

@gspencergoog I've applied most suggestions, with one question left. Unfortunately we can't link widget layer symbols in hardware_keyboard.dart, such as Shortcuts, since we can't import it... until dart-lang/sdk#49073 is implemented.

),
);

class FallbackDemo extends StatefulWidget {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the term "fallback" mean in terms of a key handler example?

}

/// A node used by [FallbackKeyEventRegistrar] to register fallback key handlers.
class FallbackFocusNode {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A FocusNode isn't actually required to implement a custom key handler, right? If not, I think the focus configuration that's done in this demo is probably distracting from the root interactions that allow developers to receive key events from the manager.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

// This example app demonstrates a use case of patching
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would include a description for at least one hypothetical use-case where a developer would want to patch key handling. If you can think of more then one, then I'd mention multiple use-cases. Examples help a lot with gaining context for an example that a developer is about to read.

Copy link
Contributor Author

@dkwingsmt dkwingsmt Jul 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really can't think of any, because if there was a usage that was easy to explain and not possible with the current keyboard API, I would have thought about a new API to support it. Even the usage you mentioned, "show popup indications for what the user presses", should be possible with HardwareKeyboard.instance.addHandler. I will add more documentation to the other methods though. Thanks for your feedback.

Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32384589-a60f0e74-c078-11e7-9bc1-e5b5287aea9d

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 26, 2022
@auto-submit auto-submit bot merged commit 4056d3f into flutter:master Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
stuartmorgan-g pushed a commit to flutter/plugins that referenced this pull request Jul 27, 2022
* 2142b2e Roll Flutter Engine from cd7e2ec4037b to c31036f2381c (1 revision) (flutter/flutter#108299)

* 178e444 Revert "Add optional flag to determine assertiveness level in aria announcement for flutter web" (flutter/flutter#108262)

* 8a7b359 flutter update-packages --force-upgrade + analyzer fix (flutter/flutter#108198)

* b3f5d3f Roll Flutter Engine from c31036f2381c to 54b0ac3059bf (1 revision) (flutter/flutter#108302)

* 2f4299a [flutter_tools] Remove unused parameter when connected DAP to VM Service (flutter/flutter#108285)

* e74b9b5 Migrate InputDecorator to Material 3 (flutter/flutter#107943)

* e3b851a Fix Tamil DateTime representation of AM/PM (flutter/flutter#108185)

* 43d6e2b Roll Flutter Engine from 54b0ac3059bf to 705072522c00 (4 revisions) (flutter/flutter#108308)

* 6929ad1 Roll Flutter Engine from 705072522c00 to 3964cf62cdf8 (1 revision) (flutter/flutter#108316)

* 5f67b47 [iOS] Update template icons (flutter/flutter#107873)

* 606954d Added iconSize parameter in ButtonStyle (flutter/flutter#108268)

* b3814c7 Roll Flutter Engine from 3964cf62cdf8 to 7f8925b1f6f3 (2 revisions) (flutter/flutter#108320)

* ca6cecf Upgrade Gradle and AGP versions to 7.5/7.2 and migrate examples/tests (flutter/flutter#108197)

* d155bc1 Revert "Upgrade Gradle and AGP versions to 7.5/7.2 and migrate examples/tests (#108197)" (flutter/flutter#108349)

* 4056d3f Explain the "patching" protocol in `KeyMessageManager.keyMessageHandler` and add an example (flutter/flutter#105280)

* b035ef1 [flutter_tools] Remove more shuffles (flutter/flutter#107759)

* be14858 Roll Flutter Engine from 7f8925b1f6f3 to 8eca26d130a2 (1 revision) (flutter/flutter#108326)

* 3eb638f Roll Flutter Engine from 8eca26d130a2 to f1f9b4de82b6 (5 revisions) (flutter/flutter#108350)

* 401b556 Roll Flutter Engine from f1f9b4de82b6 to 11d927ac3e9b (2 revisions) (flutter/flutter#108353)

* 925bee9 Roll Flutter Engine from 11d927ac3e9b to 5dcaeae6561b (1 revision) (flutter/flutter#108356)

* 5d31b07 [flutter_tools] [dap] Ensure DAP sends app.stop/app.detach during terminate (flutter/flutter#108310)

* c8b5d10 Roll Flutter Engine from 5dcaeae6561b to 89e117b89c63 (1 revision) (flutter/flutter#108367)

* e3d08fb Hide the debug banner in the PopupMenuButton example (flutter/flutter#108324)
camsim99 pushed a commit to camsim99/flutter that referenced this pull request Aug 10, 2022
yutaaraki-toydium pushed a commit to yutaaraki-toydium/plugins that referenced this pull request Aug 12, 2022
* 2142b2e Roll Flutter Engine from cd7e2ec4037b to c31036f2381c (1 revision) (flutter/flutter#108299)

* 178e444 Revert "Add optional flag to determine assertiveness level in aria announcement for flutter web" (flutter/flutter#108262)

* 8a7b359 flutter update-packages --force-upgrade + analyzer fix (flutter/flutter#108198)

* b3f5d3f Roll Flutter Engine from c31036f2381c to 54b0ac3059bf (1 revision) (flutter/flutter#108302)

* 2f4299a [flutter_tools] Remove unused parameter when connected DAP to VM Service (flutter/flutter#108285)

* e74b9b5 Migrate InputDecorator to Material 3 (flutter/flutter#107943)

* e3b851a Fix Tamil DateTime representation of AM/PM (flutter/flutter#108185)

* 43d6e2b Roll Flutter Engine from 54b0ac3059bf to 705072522c00 (4 revisions) (flutter/flutter#108308)

* 6929ad1 Roll Flutter Engine from 705072522c00 to 3964cf62cdf8 (1 revision) (flutter/flutter#108316)

* 5f67b47 [iOS] Update template icons (flutter/flutter#107873)

* 606954d Added iconSize parameter in ButtonStyle (flutter/flutter#108268)

* b3814c7 Roll Flutter Engine from 3964cf62cdf8 to 7f8925b1f6f3 (2 revisions) (flutter/flutter#108320)

* ca6cecf Upgrade Gradle and AGP versions to 7.5/7.2 and migrate examples/tests (flutter/flutter#108197)

* d155bc1 Revert "Upgrade Gradle and AGP versions to 7.5/7.2 and migrate examples/tests (#108197)" (flutter/flutter#108349)

* 4056d3f Explain the "patching" protocol in `KeyMessageManager.keyMessageHandler` and add an example (flutter/flutter#105280)

* b035ef1 [flutter_tools] Remove more shuffles (flutter/flutter#107759)

* be14858 Roll Flutter Engine from 7f8925b1f6f3 to 8eca26d130a2 (1 revision) (flutter/flutter#108326)

* 3eb638f Roll Flutter Engine from 8eca26d130a2 to f1f9b4de82b6 (5 revisions) (flutter/flutter#108350)

* 401b556 Roll Flutter Engine from f1f9b4de82b6 to 11d927ac3e9b (2 revisions) (flutter/flutter#108353)

* 925bee9 Roll Flutter Engine from 11d927ac3e9b to 5dcaeae6561b (1 revision) (flutter/flutter#108356)

* 5d31b07 [flutter_tools] [dap] Ensure DAP sends app.stop/app.detach during terminate (flutter/flutter#108310)

* c8b5d10 Roll Flutter Engine from 5dcaeae6561b to 89e117b89c63 (1 revision) (flutter/flutter#108367)

* e3d08fb Hide the debug banner in the PopupMenuButton example (flutter/flutter#108324)
mauricioluz pushed a commit to mauricioluz/plugins that referenced this pull request Jan 26, 2023
* 2142b2e Roll Flutter Engine from cd7e2ec4037b to c31036f2381c (1 revision) (flutter/flutter#108299)

* 178e444 Revert "Add optional flag to determine assertiveness level in aria announcement for flutter web" (flutter/flutter#108262)

* 8a7b359 flutter update-packages --force-upgrade + analyzer fix (flutter/flutter#108198)

* b3f5d3f Roll Flutter Engine from c31036f2381c to 54b0ac3059bf (1 revision) (flutter/flutter#108302)

* 2f4299a [flutter_tools] Remove unused parameter when connected DAP to VM Service (flutter/flutter#108285)

* e74b9b5 Migrate InputDecorator to Material 3 (flutter/flutter#107943)

* e3b851a Fix Tamil DateTime representation of AM/PM (flutter/flutter#108185)

* 43d6e2b Roll Flutter Engine from 54b0ac3059bf to 705072522c00 (4 revisions) (flutter/flutter#108308)

* 6929ad1 Roll Flutter Engine from 705072522c00 to 3964cf62cdf8 (1 revision) (flutter/flutter#108316)

* 5f67b47 [iOS] Update template icons (flutter/flutter#107873)

* 606954d Added iconSize parameter in ButtonStyle (flutter/flutter#108268)

* b3814c7 Roll Flutter Engine from 3964cf62cdf8 to 7f8925b1f6f3 (2 revisions) (flutter/flutter#108320)

* ca6cecf Upgrade Gradle and AGP versions to 7.5/7.2 and migrate examples/tests (flutter/flutter#108197)

* d155bc1 Revert "Upgrade Gradle and AGP versions to 7.5/7.2 and migrate examples/tests (#108197)" (flutter/flutter#108349)

* 4056d3f Explain the "patching" protocol in `KeyMessageManager.keyMessageHandler` and add an example (flutter/flutter#105280)

* b035ef1 [flutter_tools] Remove more shuffles (flutter/flutter#107759)

* be14858 Roll Flutter Engine from 7f8925b1f6f3 to 8eca26d130a2 (1 revision) (flutter/flutter#108326)

* 3eb638f Roll Flutter Engine from 8eca26d130a2 to f1f9b4de82b6 (5 revisions) (flutter/flutter#108350)

* 401b556 Roll Flutter Engine from f1f9b4de82b6 to 11d927ac3e9b (2 revisions) (flutter/flutter#108353)

* 925bee9 Roll Flutter Engine from 11d927ac3e9b to 5dcaeae6561b (1 revision) (flutter/flutter#108356)

* 5d31b07 [flutter_tools] [dap] Ensure DAP sends app.stop/app.detach during terminate (flutter/flutter#108310)

* c8b5d10 Roll Flutter Engine from 5dcaeae6561b to 89e117b89c63 (1 revision) (flutter/flutter#108367)

* e3d08fb Hide the debug banner in the PopupMenuButton example (flutter/flutter#108324)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: desktop Running on desktop a: text input Entering text in a text field or keyboard related problems autosubmit Merge PR when tree becomes green via auto submit App c: contributor-productivity Team-specific productivity, code health, technical debt. d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants