-
Notifications
You must be signed in to change notification settings - Fork 28.8k
[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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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" ] | ||
} |
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 |
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; | ||
|
||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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_ |
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 |
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_ |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.