Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[engine] prototype sync text input model. #167015

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions 18 engine/src/flutter/common/input/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2013 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("//flutter/common/config.gni")
import("//flutter/shell/config.gni")
import("//flutter/testing/testing.gni")

source_set("input") {
sources = [
"text_input_connection.cc",
"text_input_connection.h",
]

deps = [ "//flutter/fml" ]

public_configs = [ "//flutter:config" ]
}
11 changes: 11 additions & 0 deletions 11 engine/src/flutter/common/input/text_input_connection.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2013 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.

#include "flutter/common/input/text_input_connection.h"

namespace flutter {

//

} // namespace flutter
44 changes: 44 additions & 0 deletions 44 engine/src/flutter/common/input/text_input_connection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2013 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.

#ifndef FLUTTER_COMMON_INPUT_TEXT_INPUT_CONNECTION_H_
#define FLUTTER_COMMON_INPUT_TEXT_INPUT_CONNECTION_H_

#include <string>
#include "fml/closure.h"

namespace flutter {

class TextInputConnection {
public:
TextInputConnection() = default;

virtual ~TextInputConnection() {}

virtual std::string GetCurrentText() = 0;

virtual void SetCurrentText(std::string_view text) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know if we would suffer any performance overhead by calling this from framework side to read and write to the state in embedding? probably fine for iOS, but I am more worry about android since everything need to go through jni. thus serialization

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah serialization is a problem. For text input you might still adopt a dual source of truth/diff based approach.

For semantics, either way you are serializing.


virtual void SetUpdateCallback(fml::closure callback) {}

TextInputConnection(const TextInputConnection&) = delete;
TextInputConnection& operator=(const TextInputConnection&) = delete;
};

class TextInputConnectionFactory {
public:
TextInputConnectionFactory() = default;

virtual ~TextInputConnectionFactory() {}

virtual std::shared_ptr<TextInputConnection> CreateTextInputConnection() = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume we would need to provide implementation that convert the call into embedder.h api?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah you could have a generic EmbedderTextInputConnectionFactory that would be backed by callbacks provided in embedder.h


TextInputConnectionFactory(const TextInputConnectionFactory&) = delete;
TextInputConnectionFactory& operator=(const TextInputConnectionFactory&) =
delete;
};

} // namespace flutter

#endif // FLUTTER_COMMON_INPUT_TEXT_INPUT_CONNECTION_H_
3 changes: 3 additions & 0 deletions 3 engine/src/flutter/lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ source_set("ui") {
"dart_ui.h",
"dart_wrapper.h",
"floating_point.h",
"input/text_input_model.cc",
"input/text_input_model.h",
"io_manager.cc",
"io_manager.h",
"isolate_name_server/isolate_name_server.cc",
Expand Down Expand Up @@ -177,6 +179,7 @@ source_set("ui") {
"//flutter/assets",
"//flutter/common",
"//flutter/common/graphics",
"//flutter/common/input",
"//flutter/display_list",
"//flutter/fml",
"//flutter/impeller/runtime_stage",
Expand Down
8 changes: 7 additions & 1 deletion 8 engine/src/flutter/lib/ui/dart_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "flutter/lib/ui/compositing/scene.h"
#include "flutter/lib/ui/compositing/scene_builder.h"
#include "flutter/lib/ui/dart_runtime_hooks.h"
#include "flutter/lib/ui/input/text_input_model.h"
#include "flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h"
#include "flutter/lib/ui/painting/canvas.h"
#include "flutter/lib/ui/painting/codec.h"
Expand Down Expand Up @@ -81,6 +82,7 @@ typedef CanvasPath Path;
V(RSuperellipse::Create) \
V(SceneBuilder::Create) \
V(SemanticsUpdateBuilder::Create) \
V(UiTextInputModel::Create) \
/* Other */ \
V(FontCollection::LoadFontFromList) \
V(ImageDescriptor::initEncoded) \
Expand Down Expand Up @@ -311,7 +313,11 @@ typedef CanvasPath Path;
V(SemanticsUpdateBuilder, updateCustomAction) \
V(SemanticsUpdateBuilder, updateNode) \
V(SemanticsUpdate, dispose) \
V(Vertices, dispose)
V(Vertices, dispose) \
V(UiTextInputModel, getCurrentText) \
V(UiTextInputModel, setCurrentText) \
V(UiTextInputModel, setUpdateCallback) \
V(UiTextInputModel, dispose)

#define FFI_FUNCTION_INSERT(FUNCTION) \
g_function_dispatchers.insert(std::make_pair( \
Expand Down
55 changes: 55 additions & 0 deletions 55 engine/src/flutter/lib/ui/input/text_input_model.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

// Copyright 2013 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.

#include "flutter/lib/ui/input/text_input_model.h"
#include "dart_api.h"
#include "lib/ui/ui_dart_state.h"

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, UiTextInputModel);

// static
void UiTextInputModel::Create(Dart_Handle wrapper) {
UIDartState::ThrowIfUIOperationsProhibited();
fml::RefPtr<UiTextInputModel> res = fml::MakeRefCounted<UiTextInputModel>();
res->AssociateWithDartWrapper(wrapper);
}

UiTextInputModel::UiTextInputModel() {
connection_ = UIDartState::Current()
->GetTextInputConnectionFactory()
.CreateTextInputConnection();
}

Dart_Handle UiTextInputModel::getCurrentText() {
auto text = connection_->GetCurrentText();
return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(text.data()),
text.size());
}

void UiTextInputModel::setCurrentText(const std::string& value) {
connection_->SetCurrentText(value);
}

void UiTextInputModel::setUpdateCallback(Dart_Handle callback) {
update_callback_.Set(tonic::DartState::Current(), callback);

connection_->SetUpdateCallback([&] {
std::shared_ptr<tonic::DartState> dart_state =
update_callback_.dart_state().lock();
if (!dart_state) {
return;
}
tonic::DartState::Scope scope(dart_state);
tonic::DartInvoke(update_callback_.value(), {});
});
}

void UiTextInputModel::dispose() {
//
}

} // namespace flutter
45 changes: 45 additions & 0 deletions 45 engine/src/flutter/lib/ui/input/text_input_model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2013 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.

#ifndef FLUTTER_LIB_UI_INPUT_TEXT_INPUT_MODEL_H_
#define FLUTTER_LIB_UI_INPUT_TEXT_INPUT_MODEL_H_

#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/dart/runtime/include/dart_api.h"

namespace flutter {

class UiTextInputModel : public RefCountedDartWrappable<UiTextInputModel> {
DEFINE_WRAPPERTYPEINFO();
FML_FRIEND_MAKE_REF_COUNTED(UiTextInputModel);

public:
UiTextInputModel();

~UiTextInputModel() = default;

static void Create(Dart_Handle wrapper);

Dart_Handle getCurrentText();

void setCurrentText(const std::string& value);

void setUpdateCallback(Dart_Handle callback);

void dispose();

private:
std::shared_ptr<TextInputConnection> connection_;
tonic::DartPersistentValue update_callback_;

UiTextInputModel(const UiTextInputModel&) = delete;
UiTextInputModel(UiTextInputModel&&) = delete;
UiTextInputModel& operator=(const UiTextInputModel&) = delete;
UiTextInputModel& operator=(UiTextInputModel&&) = delete;
};

} // namespace flutter

#endif // FLUTTER_LIB_UI_INPUT_TEXT_INPUT_MODEL_H_
44 changes: 44 additions & 0 deletions 44 engine/src/flutter/lib/ui/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3784,3 +3784,47 @@ FutureOr<void> _sendFontChangeMessage() async {

@Native<Void Function(Handle, Handle, Handle)>(symbol: 'FontCollection::LoadFontFromList')
external void _loadFontFromList(Uint8List list, _Callback<void> callback, String fontFamily);

///
///

base class TextInputModel extends NativeFieldWrapperClass1 {
static TextInputModel create() {
return TextInputModel._();
}

TextInputModel._() {
_constructor();
}

String getCurrentText() {
return _getCurrentText();
}

void setCurrentText(String value) {
_setCurrentText(value);
}

void dispose() {
_dispose();
}

void setUpdateCallback(void Function() cb) {
_setUpdateCallback(cb);
}

@Native<Void Function(Handle)>(symbol: 'UiTextInputModel::Create')
external void _constructor();

@Native<Handle Function(Pointer<Void>)>(symbol: 'UiTextInputModel::getCurrentText')
external String _getCurrentText();

@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'UiTextInputModel::setCurrentText')
external void _setCurrentText(String value);

@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'UiTextInputModel::setUpdateCallback')
external void _setUpdateCallback(void Function() cb);

@Native<Void Function(Pointer<Void>)>(symbol: 'UiTextInputModel::dispose')
external void _dispose();
}
7 changes: 7 additions & 0 deletions 7 engine/src/flutter/lib/ui/ui_dart_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <utility>

#include "flutter/common/input/text_input_connection.h"
#include "flutter/fml/message_loop.h"
#include "flutter/lib/ui/window/platform_configuration.h"
#include "flutter/lib/ui/window/platform_message.h"
Expand All @@ -26,6 +27,7 @@ UIDartState::Context::Context(
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<ImageDecoder> image_decoder,
fml::WeakPtr<ImageGeneratorRegistry> image_generator_registry,
std::shared_ptr<TextInputConnectionFactory> text_input_connection_factory,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
bool deterministic_rendering_enabled,
Expand All @@ -39,6 +41,7 @@ UIDartState::Context::Context(
unref_queue(std::move(unref_queue)),
image_decoder(std::move(image_decoder)),
image_generator_registry(std::move(image_generator_registry)),
text_input_connection_factory(std::move(text_input_connection_factory)),
advisory_script_uri(std::move(advisory_script_uri)),
advisory_script_entrypoint(std::move(advisory_script_entrypoint)),
deterministic_rendering_enabled(deterministic_rendering_enabled),
Expand Down Expand Up @@ -247,4 +250,8 @@ Dart_Isolate UIDartState::CreatePlatformIsolate(Dart_Handle entry_point,
return nullptr;
}

TextInputConnectionFactory& UIDartState::GetTextInputConnectionFactory() const {
return *context_.text_input_connection_factory;
}

} // namespace flutter
7 changes: 7 additions & 0 deletions 7 engine/src/flutter/lib/ui/ui_dart_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string>
#include <utility>

#include "flutter/common/input/text_input_connection.h"
#include "flutter/common/settings.h"
#include "flutter/common/task_runners.h"
#include "flutter/fml/build_config.h"
Expand Down Expand Up @@ -50,6 +51,8 @@ class UIDartState : public tonic::DartState {
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<ImageDecoder> image_decoder,
fml::WeakPtr<ImageGeneratorRegistry> image_generator_registry,
std::shared_ptr<TextInputConnectionFactory>
text_input_connection_factory,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
bool deterministic_rendering_enabled,
Expand Down Expand Up @@ -83,6 +86,8 @@ class UIDartState : public tonic::DartState {
/// can then be used for image decoding.
fml::WeakPtr<ImageGeneratorRegistry> image_generator_registry;

std::shared_ptr<TextInputConnectionFactory> text_input_connection_factory;

/// The advisory script URI (only used for debugging). This does not affect
/// the code being run in the isolate in any way.
std::string advisory_script_uri;
Expand Down Expand Up @@ -148,6 +153,8 @@ class UIDartState : public tonic::DartState {

fml::WeakPtr<ImageGeneratorRegistry> GetImageGeneratorRegistry() const;

TextInputConnectionFactory& GetTextInputConnectionFactory() const;

std::shared_ptr<IsolateNameServer> GetIsolateNameServer() const;

tonic::DartErrorHandleType GetLastError();
Expand Down
1 change: 1 addition & 0 deletions 1 engine/src/flutter/runtime/runtime_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ std::unique_ptr<RuntimeController> RuntimeController::Spawn(
context_.unref_queue,
std::move(image_decoder),
std::move(image_generator_registry),
context_.text_input_connection_factory,
advisory_script_uri,
advisory_script_entrypoint,
context_.deterministic_rendering_enabled,
Expand Down
2 changes: 2 additions & 0 deletions 2 engine/src/flutter/shell/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ source_set("common") {
"//flutter/assets",
"//flutter/common",
"//flutter/common/graphics",
"//flutter/common/input",
"//flutter/flow",
"//flutter/fml",
"//flutter/lib/ui",
Expand Down Expand Up @@ -334,6 +335,7 @@ if (enable_unittests) {
":shell_unittests_fixtures",
"//flutter/assets",
"//flutter/common/graphics",
"//flutter/common/input",
"//flutter/display_list/testing:display_list_testing",
"//flutter/shell/common:base64",
"//flutter/shell/profiling:profiling_unittests",
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.