@@ -204,11 +204,18 @@ class FlutterHtmlKeyboardEvent {
204204// [dispatchKeyData] as given in the constructor. Some key data might be
205205// dispatched asynchronously.
206206class KeyboardConverter {
207- KeyboardConverter (this .dispatchKeyData , {this .onMacOs = false });
207+ KeyboardConverter (this .performDispatchKeyData , {this .onMacOs = false });
208208
209- final DispatchKeyData dispatchKeyData ;
209+ final DispatchKeyData performDispatchKeyData ;
210210 final bool onMacOs;
211211
212+ // The `performDispatchKeyData` wrapped with tracking logic.
213+ //
214+ // It is non-null only during `handleEvent`. All events during `handleEvent`
215+ // should be dispatched with `_dispatchKeyData`, others with
216+ // `performDispatchKeyData`.
217+ DispatchKeyData ? _dispatchKeyData;
218+
212219 bool _disposed = false ;
213220 void dispose () {
214221 _disposed = true ;
@@ -294,7 +301,9 @@ class KeyboardConverter {
294301 Future <void >.delayed (duration).then <void >((_) {
295302 if (! canceled && ! _disposed) {
296303 callback ();
297- dispatchKeyData (getData ());
304+ // This dispatch is performed asynchronously, therefore should not use
305+ // `_dispatchKeyData`.
306+ performDispatchKeyData (getData ());
298307 }
299308 });
300309 return () { canceled = true ; };
@@ -335,17 +344,7 @@ class KeyboardConverter {
335344 _keyGuards.remove (physicalKey)? .call ();
336345 }
337346
338- // Parse the HTML event, update states, and dispatch Flutter key data through
339- // [dispatchKeyData].
340- //
341- // * The method might dispatch some synthesized key data first to update states,
342- // results discarded.
343- // * Then it dispatches exactly one non-synthesized key data that corresponds
344- // to the `event`, i.e. the primary key data. If this dispatching returns
345- // true, then this event will be invoked `preventDefault`.
346- // * Some key data might be synthesized to update states after the main key
347- // data. They are always scheduled asynchronously with results discarded.
348- void handleEvent (FlutterHtmlKeyboardEvent event) {
347+ void _handleEvent (FlutterHtmlKeyboardEvent event) {
349348 final Duration timeStamp = _eventTimeStampToDuration (event.timeStamp! );
350349
351350 final String eventKey = event.key! ;
@@ -411,7 +410,6 @@ class KeyboardConverter {
411410 // a currently pressed one, usually indicating multiple keyboards are
412411 // pressing keys with the same physical key, or the up event was lost
413412 // during a loss of focus. The down event is ignored.
414- dispatchKeyData (_emptyKeyData);
415413 event.preventDefault ();
416414 return ;
417415 }
@@ -425,7 +423,6 @@ class KeyboardConverter {
425423 if (lastLogicalRecord == null ) {
426424 // The physical key has been released before. It indicates multiple
427425 // keyboards pressed keys with the same physical key. Ignore the up event.
428- dispatchKeyData (_emptyKeyData);
429426 event.preventDefault ();
430427 return ;
431428 }
@@ -465,7 +462,7 @@ class KeyboardConverter {
465462 if (logicalRecord != logicalKey)
466463 return false ;
467464
468- dispatchKeyData (ui.KeyData (
465+ _dispatchKeyData ! (ui.KeyData (
469466 timeStamp: timeStamp,
470467 type: ui.KeyEventType .up,
471468 physical: physicalKey,
@@ -497,9 +494,36 @@ class KeyboardConverter {
497494 synthesized: false ,
498495 );
499496
500- final bool primaryHandled = dispatchKeyData (keyData);
497+ final bool primaryHandled = _dispatchKeyData ! (keyData);
501498 if (primaryHandled) {
502499 event.preventDefault ();
503500 }
504501 }
502+
503+ // Parse the HTML event, update states, and dispatch Flutter key data through
504+ // [performDispatchKeyData].
505+ //
506+ // * The method might dispatch some synthesized key data first to update states,
507+ // results discarded.
508+ // * Then it dispatches exactly one non-synthesized key data that corresponds
509+ // to the `event`, i.e. the primary key data. If this dispatching returns
510+ // true, then this event will be invoked `preventDefault`.
511+ // * Some key data might be synthesized to update states after the main key
512+ // data. They are always scheduled asynchronously with results discarded.
513+ void handleEvent (FlutterHtmlKeyboardEvent event) {
514+ assert (_dispatchKeyData == null );
515+ bool sentAnyEvents = false ;
516+ _dispatchKeyData = (ui.KeyData data) {
517+ sentAnyEvents = true ;
518+ return performDispatchKeyData (data);
519+ };
520+ try {
521+ _handleEvent (event);
522+ } finally {
523+ if (! sentAnyEvents) {
524+ _dispatchKeyData !(_emptyKeyData);
525+ }
526+ _dispatchKeyData = null ;
527+ }
528+ }
505529}
0 commit comments