Skip to content

Commit d8a3b06

Browse files
authored
[Embedder] Send key data through message channel (flutter#29795)
This PR changes how embedder API's SendKeyData sends ui.KeyData to the framework. The packets are now sent over the existing platform messenger, reusing the entirety of its code path and functionalities while keeping the embedder API unchanged
1 parent 5727fc1 commit d8a3b06

26 files changed

+228
-298
lines changed

lib/ui/hooks.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ void _dispatchPointerDataPacket(ByteData packet) {
8888
PlatformDispatcher.instance._dispatchPointerDataPacket(packet);
8989
}
9090

91-
@pragma('vm:entry-point')
92-
void _dispatchKeyData(ByteData packet, int responseId) {
93-
PlatformDispatcher.instance._dispatchKeyData(packet, responseId);
94-
}
95-
9691
@pragma('vm:entry-point')
9792
void _dispatchSemanticsAction(int id, int action, ByteData? args) {
9893
PlatformDispatcher.instance._dispatchSemanticsAction(id, action, args);

lib/ui/platform_dispatcher.dart

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ typedef TimingsCallback = void Function(List<FrameTiming> timings);
2828
/// Signature for [PlatformDispatcher.onPointerDataPacket].
2929
typedef PointerDataPacketCallback = void Function(PointerDataPacket packet);
3030

31-
// Signature for the response to KeyDataCallback.
32-
typedef _KeyDataResponseCallback = void Function(int responseId, bool handled);
33-
3431
/// Signature for [PlatformDispatcher.onKeyData].
3532
///
3633
/// The callback should return true if the key event has been handled by the
@@ -59,6 +56,11 @@ typedef PlatformConfigurationChangedCallback = void Function(PlatformConfigurati
5956
// A gesture setting value that indicates it has not been set by the engine.
6057
const double _kUnsetGestureSetting = -1.0;
6158

59+
// A message channel to receive KeyData from the platform.
60+
//
61+
// See embedder.cc::kFlutterKeyDataChannel for more information.
62+
const String _kFlutterKeyDataChannel = 'flutter/keydata';
63+
6264
/// Platform event dispatcher singleton.
6365
///
6466
/// The most basic interface to the host operating system's interface.
@@ -349,9 +351,19 @@ class PlatformDispatcher {
349351
return PointerDataPacket(data: data);
350352
}
351353

352-
/// Called by [_dispatchKeyData].
353-
void _respondToKeyData(int responseId, bool handled)
354-
native 'PlatformConfiguration_respondToKeyData';
354+
static ChannelCallback _keyDataListener(KeyDataCallback onKeyData, Zone zone) =>
355+
(ByteData? packet, PlatformMessageResponseCallback callback) {
356+
_invoke1<KeyData>(
357+
(KeyData keyData) {
358+
final bool handled = onKeyData(keyData);
359+
final Uint8List response = Uint8List(1);
360+
response[0] = handled ? 1 : 0;
361+
callback(response.buffer.asByteData());
362+
},
363+
zone,
364+
_unpackKeyData(packet!),
365+
);
366+
};
355367

356368
/// A callback that is invoked when key data is available.
357369
///
@@ -362,22 +374,13 @@ class PlatformDispatcher {
362374
/// framework and should not be propagated further.
363375
KeyDataCallback? get onKeyData => _onKeyData;
364376
KeyDataCallback? _onKeyData;
365-
Zone _onKeyDataZone = Zone.root;
366377
set onKeyData(KeyDataCallback? callback) {
367378
_onKeyData = callback;
368-
_onKeyDataZone = Zone.current;
369-
}
370-
371-
// Called from the engine, via hooks.dart
372-
void _dispatchKeyData(ByteData packet, int responseId) {
373-
_invoke2<KeyData, _KeyDataResponseCallback>(
374-
(KeyData data, _KeyDataResponseCallback callback) {
375-
callback(responseId, onKeyData != null && onKeyData!(data));
376-
},
377-
_onKeyDataZone,
378-
_unpackKeyData(packet),
379-
_respondToKeyData,
380-
);
379+
if (callback != null) {
380+
channelBuffers.setListener(_kFlutterKeyDataChannel, _keyDataListener(callback, Zone.current));
381+
} else {
382+
channelBuffers.clearListener(_kFlutterKeyDataChannel);
383+
}
381384
}
382385

383386
// If this value changes, update the encoding code in the following files:

lib/ui/window/platform_configuration.cc

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,6 @@ void GetPersistentIsolateData(Dart_NativeArguments args) {
181181
persistent_isolate_data->GetSize()));
182182
}
183183

184-
void RespondToKeyData(Dart_Handle window, int response_id, bool handled) {
185-
UIDartState::Current()->platform_configuration()->CompleteKeyDataResponse(
186-
response_id, handled);
187-
}
188-
189-
void _RespondToKeyData(Dart_NativeArguments args) {
190-
tonic::DartCallStatic(&RespondToKeyData, args);
191-
}
192-
193184
Dart_Handle ToByteData(const fml::Mapping& buffer) {
194185
return tonic::DartByteData::Create(buffer.GetMapping(), buffer.GetSize());
195186
}
@@ -360,13 +351,6 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id,
360351
args_handle}));
361352
}
362353

363-
uint64_t PlatformConfiguration::RegisterKeyDataResponse(
364-
KeyDataResponse callback) {
365-
uint64_t response_id = next_key_response_id_++;
366-
pending_key_responses_[response_id] = std::move(callback);
367-
return response_id;
368-
}
369-
370354
void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime,
371355
uint64_t frame_number) {
372356
std::shared_ptr<tonic::DartState> dart_state =
@@ -444,27 +428,6 @@ void PlatformConfiguration::CompletePlatformMessageResponse(
444428
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
445429
}
446430

447-
void PlatformConfiguration::CompleteKeyDataResponse(uint64_t response_id,
448-
bool handled) {
449-
if (response_id == 0) {
450-
return;
451-
}
452-
auto it = pending_key_responses_.find(response_id);
453-
FML_DCHECK(it != pending_key_responses_.end());
454-
if (it == pending_key_responses_.end()) {
455-
return;
456-
}
457-
KeyDataResponse callback = std::move(it->second);
458-
pending_key_responses_.erase(it);
459-
// The key result callback must be called on the platform thread. This is
460-
// mainly because iOS needs to block the platform message loop with a nested
461-
// loop to respond to key events synchronously, and if the callback is called
462-
// from another thread, it won't stop the nested message loop, causing a
463-
// deadlock.
464-
UIDartState::Current()->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
465-
[handled, callback]() { callback(handled); });
466-
}
467-
468431
Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) {
469432
std::vector<std::string> supportedLocales =
470433
tonic::DartConverter<std::vector<std::string>>::FromDart(
@@ -495,7 +458,6 @@ void PlatformConfiguration::RegisterNatives(
495458
true},
496459
{"PlatformConfiguration_respondToPlatformMessage",
497460
_RespondToPlatformMessage, 3, true},
498-
{"PlatformConfiguration_respondToKeyData", _RespondToKeyData, 3, true},
499461
{"PlatformConfiguration_render", Render, 3, true},
500462
{"PlatformConfiguration_updateSemantics", UpdateSemantics, 2, true},
501463
{"PlatformConfiguration_setIsolateDebugName", SetIsolateDebugName, 2,

lib/ui/window/platform_configuration.h

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ class FontCollection;
2323
class PlatformMessage;
2424
class Scene;
2525

26-
typedef std::function<void(bool /* handled */)> KeyDataResponse;
27-
2826
//--------------------------------------------------------------------------
2927
/// @brief An enum for defining the different kinds of accessibility features
3028
/// that can be enabled by the platform.
@@ -327,24 +325,6 @@ class PlatformConfiguration final {
327325
SemanticsAction action,
328326
fml::MallocMapping args);
329327

330-
//----------------------------------------------------------------------------
331-
/// @brief Registers a callback to be invoked when the framework has
332-
/// decided whether to handle an event. This callback originates
333-
/// in the platform view and has been forwarded through the engine
334-
/// to here.
335-
///
336-
/// This method will move and store the `callback`, associate it
337-
/// with a self-incrementing identifier, the response ID, then
338-
/// return the ID, which is typically used by
339-
/// Window::DispatchKeyDataPacket.
340-
///
341-
/// @param[in] callback The callback to be registered.
342-
///
343-
/// @return The response ID to be associated with the callback. Using this
344-
/// ID in CompleteKeyDataResponse will invoke the callback.
345-
///
346-
uint64_t RegisterKeyDataResponse(KeyDataResponse callback);
347-
348328
//----------------------------------------------------------------------------
349329
/// @brief Notifies the framework that it is time to begin working on a
350330
/// new frame previously scheduled via a call to
@@ -439,21 +419,6 @@ class PlatformConfiguration final {
439419
///
440420
void CompletePlatformMessageEmptyResponse(int response_id);
441421

442-
//----------------------------------------------------------------------------
443-
/// @brief Responds to a previously registered key data message from the
444-
/// framework to the engine.
445-
///
446-
/// For each response_id, this method should be called exactly
447-
/// once. Responding to a response_id that has not been registered
448-
/// or has been invoked will lead to a fatal error.
449-
///
450-
/// @param[in] response_id The unique id that identifies the original platform
451-
/// message to respond to, created by
452-
/// RegisterKeyDataResponse.
453-
/// @param[in] handled Whether the key data is handled.
454-
///
455-
void CompleteKeyDataResponse(uint64_t response_id, bool handled);
456-
457422
private:
458423
PlatformConfigurationClient* client_;
459424
tonic::DartPersistentValue update_locales_;
@@ -462,7 +427,6 @@ class PlatformConfiguration final {
462427
tonic::DartPersistentValue update_semantics_enabled_;
463428
tonic::DartPersistentValue update_accessibility_features_;
464429
tonic::DartPersistentValue dispatch_platform_message_;
465-
tonic::DartPersistentValue dispatch_key_message_;
466430
tonic::DartPersistentValue dispatch_semantics_action_;
467431
tonic::DartPersistentValue begin_frame_;
468432
tonic::DartPersistentValue draw_frame_;
@@ -474,10 +438,6 @@ class PlatformConfiguration final {
474438
int next_response_id_ = 1;
475439
std::unordered_map<int, fml::RefPtr<PlatformMessageResponse>>
476440
pending_responses_;
477-
478-
// ID starts at 1 because an ID of 0 indicates that no response is expected.
479-
uint64_t next_key_response_id_ = 1;
480-
std::unordered_map<uint64_t, KeyDataResponse> pending_key_responses_;
481441
};
482442

483443
} // namespace flutter

lib/ui/window/window.cc

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,6 @@ void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
3636
library_.value(), "_dispatchPointerDataPacket", {data_handle}));
3737
}
3838

39-
void Window::DispatchKeyDataPacket(const KeyDataPacket& packet,
40-
uint64_t response_id) {
41-
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
42-
if (!dart_state) {
43-
return;
44-
}
45-
tonic::DartState::Scope scope(dart_state);
46-
47-
const std::vector<uint8_t>& buffer = packet.data();
48-
Dart_Handle data_handle =
49-
tonic::DartByteData::Create(buffer.data(), buffer.size());
50-
if (Dart_IsError(data_handle)) {
51-
return;
52-
}
53-
tonic::LogIfError(
54-
tonic::DartInvokeField(library_.value(), "_dispatchKeyData",
55-
{data_handle, tonic::ToDart(response_id)}));
56-
}
57-
5839
void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
5940
viewport_metrics_ = metrics;
6041

lib/ui/window/window.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,6 @@ class Window final {
3131
// Dispatch a packet to the framework that indicates one or a few pointer
3232
// events.
3333
void DispatchPointerDataPacket(const PointerDataPacket& packet);
34-
// Dispatch a packet to the framework that indicates a key event.
35-
//
36-
// The `response_id` is used to label the response of whether the key event
37-
// is handled by the framework, typically the return value of
38-
// PlatformConfiguration::RegisterKeyDataResponse.
39-
// It should be used later in
40-
// PlatformConfiguration::CompleteKeyDataResponse.
41-
void DispatchKeyDataPacket(const KeyDataPacket& packet, uint64_t response_id);
4234
void UpdateWindowMetrics(const ViewportMetrics& metrics);
4335

4436
private:

runtime/runtime_controller.cc

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -238,20 +238,6 @@ bool RuntimeController::DispatchPointerDataPacket(
238238
return false;
239239
}
240240

241-
bool RuntimeController::DispatchKeyDataPacket(const KeyDataPacket& packet,
242-
KeyDataResponse callback) {
243-
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
244-
TRACE_EVENT1("flutter", "RuntimeController::DispatchKeyDataPacket", "mode",
245-
"basic");
246-
uint64_t response_id =
247-
platform_configuration->RegisterKeyDataResponse(std::move(callback));
248-
platform_configuration->get_window(0)->DispatchKeyDataPacket(packet,
249-
response_id);
250-
return true;
251-
}
252-
return false;
253-
}
254-
255241
bool RuntimeController::DispatchSemanticsAction(int32_t id,
256242
SemanticsAction action,
257243
fml::MallocMapping args) {

runtime/runtime_controller.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -385,20 +385,6 @@ class RuntimeController : public PlatformConfigurationClient {
385385
///
386386
bool DispatchPointerDataPacket(const PointerDataPacket& packet);
387387

388-
//----------------------------------------------------------------------------
389-
/// @brief Dispatch the specified pointer data message to the running
390-
/// root isolate.
391-
///
392-
/// @param[in] packet The key data message to dispatch to the isolate.
393-
/// @param[in] callback Called when the framework has decided whether
394-
/// to handle this key data.
395-
///
396-
/// @return If the key data message was dispatched. This may fail is
397-
/// an isolate is not running.
398-
///
399-
bool DispatchKeyDataPacket(const KeyDataPacket& packet,
400-
KeyDataResponse callback);
401-
402388
//----------------------------------------------------------------------------
403389
/// @brief Dispatch the semantics action to the specified accessibility
404390
/// node.

shell/common/engine.cc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,6 @@ void Engine::DispatchPointerDataPacket(
434434
pointer_data_dispatcher_->DispatchPacket(std::move(packet), trace_flow_id);
435435
}
436436

437-
void Engine::DispatchKeyDataPacket(std::unique_ptr<KeyDataPacket> packet,
438-
KeyDataResponse callback) {
439-
TRACE_EVENT0("flutter", "Engine::DispatchKeyDataPacket");
440-
if (runtime_controller_) {
441-
runtime_controller_->DispatchKeyDataPacket(*packet, std::move(callback));
442-
}
443-
}
444-
445437
void Engine::DispatchSemanticsAction(int id,
446438
SemanticsAction action,
447439
fml::MallocMapping args) {

shell/common/engine.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -735,21 +735,6 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
735735
void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet,
736736
uint64_t trace_flow_id);
737737

738-
//----------------------------------------------------------------------------
739-
/// @brief Notifies the engine that the embedder has sent it a key data
740-
/// packet. A key data packet contains one key event. This call
741-
/// originates in the platform view and the shell has forwarded
742-
/// the same to the engine on the UI task runner here. The engine
743-
/// will decide whether to handle this event, and send the
744-
/// result using `callback`, which will be called exactly once.
745-
///
746-
/// @param[in] packet The key data packet.
747-
/// @param[in] callback Called when the framework has decided whether
748-
/// to handle this key data.
749-
///
750-
void DispatchKeyDataPacket(std::unique_ptr<KeyDataPacket> packet,
751-
KeyDataResponse callback);
752-
753738
//----------------------------------------------------------------------------
754739
/// @brief Notifies the engine that the embedder encountered an
755740
/// accessibility related action on the specified node. This call

shell/common/platform_view.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,6 @@ void PlatformView::DispatchPointerDataPacket(
3939
pointer_data_packet_converter_.Convert(std::move(packet)));
4040
}
4141

42-
void PlatformView::DispatchKeyDataPacket(std::unique_ptr<KeyDataPacket> packet,
43-
KeyDataResponse callback) {
44-
delegate_.OnPlatformViewDispatchKeyDataPacket(std::move(packet),
45-
std::move(callback));
46-
}
47-
4842
void PlatformView::DispatchSemanticsAction(int32_t id,
4943
SemanticsAction action,
5044
fml::MallocMapping args) {

shell/common/platform_view.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -127,20 +127,6 @@ class PlatformView {
127127
virtual void OnPlatformViewDispatchPointerDataPacket(
128128
std::unique_ptr<PointerDataPacket> packet) = 0;
129129

130-
//--------------------------------------------------------------------------
131-
/// @brief Notifies the delegate that the platform view has encountered
132-
/// a key event. This key event and the callback needs to be
133-
/// forwarded to the running root isolate hosted by the engine
134-
/// on the UI thread.
135-
///
136-
/// @param[in] packet The key data packet containing one key event.
137-
/// @param[in] callback Called when the framework has decided whether
138-
/// to handle this key data.
139-
///
140-
virtual void OnPlatformViewDispatchKeyDataPacket(
141-
std::unique_ptr<KeyDataPacket> packet,
142-
std::function<void(bool /* handled */)> callback) = 0;
143-
144130
//--------------------------------------------------------------------------
145131
/// @brief Notifies the delegate that the platform view has encountered
146132
/// an accessibility related action on the specified node. This
@@ -591,17 +577,6 @@ class PlatformView {
591577
///
592578
void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet);
593579

594-
//----------------------------------------------------------------------------
595-
/// @brief Dispatches key events from the embedder to the framework. Each
596-
/// key data packet contains one physical event and multiple
597-
/// logical key events. Each call to this method wakes up the UI
598-
/// thread.
599-
///
600-
/// @param[in] packet The key data packet to dispatch to the framework.
601-
///
602-
void DispatchKeyDataPacket(std::unique_ptr<KeyDataPacket> packet,
603-
Delegate::KeyDataResponse callback);
604-
605580
//--------------------------------------------------------------------------
606581
/// @brief Used by the embedder to specify a texture that it wants the
607582
/// rasterizer to composite within the Flutter layer tree. All

0 commit comments

Comments
 (0)