Commit f7c2bc27 authored by Keith Lee's avatar Keith Lee Committed by Commit Bot

Implement SetAutocorrectRange and GetAutocorrectCharacterBounds function for Textfields.

The GetAutocorrectCharacterBounds function returns the location of the autocorrect word as a gfx::Rect object.

Change-Id: I214e8eb506b9456114496b71be87dd0a61bf38e0
Bug: 1108170
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2251638Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Reviewed-by: default avatarDarren Shen <shend@chromium.org>
Commit-Queue: Keith Lee <keithlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792056}
parent a49b7e13
......@@ -628,6 +628,12 @@ bool ArcImeService::SetCompositionFromExistingText(
return false;
}
gfx::Rect ArcImeService::GetAutocorrectCharacterBounds() const {
// TODO(https://crbug.com/952757): Implement this method.
NOTIMPLEMENTED_LOG_ONCE();
return gfx::Rect();
}
bool ArcImeService::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) {
base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count",
......
......@@ -149,6 +149,7 @@ class ArcImeService : public KeyedService,
bool SetCompositionFromExistingText(
const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override;
......
......@@ -324,6 +324,12 @@ bool TextInput::SetCompositionFromExistingText(
return false;
}
gfx::Rect TextInput::GetAutocorrectCharacterBounds() const {
// TODO(https://crbug.com/952757): Implement this method.
NOTIMPLEMENTED_LOG_ONCE();
return gfx::Rect();
}
// TODO(crbug.com/1091088) Implement setAutocorrectRange
bool TextInput::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) {
......
......@@ -140,6 +140,7 @@ class TextInput : public ui::TextInputClient,
bool SetCompositionFromExistingText(
const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override;
......
......@@ -1464,6 +1464,12 @@ bool RenderWidgetHostViewAura::SetCompositionFromExistingText(
#endif
#if defined(OS_CHROMEOS)
gfx::Rect RenderWidgetHostViewAura::GetAutocorrectCharacterBounds() const {
// TODO(crbug.com/1108170): Implement this function, since we need this
// for autocorrect on websites to work.
return gfx::Rect();
}
bool RenderWidgetHostViewAura::SetAutocorrectRange(
const base::string16& autocorrect_text,
const gfx::Range& range) {
......
......@@ -231,7 +231,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
#endif
#if defined(OS_CHROMEOS)
// Set the autocorrect range
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override;
#endif
......
......@@ -153,6 +153,10 @@ bool DummyTextInputClient::SetCompositionFromExistingText(
#endif
#if defined(OS_CHROMEOS)
gfx::Rect DummyTextInputClient::GetAutocorrectCharacterBounds() const {
return gfx::Rect();
}
bool DummyTextInputClient::SetAutocorrectRange(
const base::string16& autocorrect_text,
const gfx::Range& range) {
......
......@@ -63,6 +63,8 @@ class DummyTextInputClient : public TextInputClient {
#endif
#if defined(OS_CHROMEOS)
gfx::Rect GetAutocorrectCharacterBounds() const override;
// Set the autocorrect range
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override;
......
......@@ -227,6 +227,12 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient {
#endif
#if defined(OS_CHROMEOS)
// Return the location of the autocorrect range as a gfx::Rect object.
// If gfx::Rect is empty, then the autocorrect character bounds have not been
// set.
// These bounds are in screen coordinates.
virtual gfx::Rect GetAutocorrectCharacterBounds() const = 0;
// Set the autocorrect range and return if it has been set correctly as a
// boolean value.
virtual bool SetAutocorrectRange(const base::string16& autocorrect_text,
......
......@@ -172,6 +172,11 @@ bool PrefixSelector::SetCompositionFromExistingText(
#endif
#if defined(OS_CHROMEOS)
gfx::Rect PrefixSelector::GetAutocorrectCharacterBounds() const {
NOTIMPLEMENTED_LOG_ONCE();
return gfx::Rect();
}
bool PrefixSelector::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) {
// TODO(crbug.com/1091088) Implement setAutocorrectRange.
......
......@@ -83,6 +83,7 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
#endif
#if defined(OS_CHROMEOS)
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override;
#endif
......
......@@ -1846,12 +1846,26 @@ bool Textfield::SetCompositionFromExistingText(
#endif
#if defined(OS_CHROMEOS)
gfx::Rect Textfield::GetAutocorrectCharacterBounds() const {
gfx::Range autocorrect_range = model_->autocorrect_range();
if (autocorrect_range.is_empty())
return gfx::Rect();
gfx::RenderText* render_text = GetRenderText();
const gfx::SelectionModel caret(autocorrect_range, gfx::CURSOR_BACKWARD);
gfx::Rect rect;
rect = render_text->GetCursorBounds(caret, false);
ConvertRectToScreen(this, &rect);
return rect;
}
bool Textfield::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) {
base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count",
TextInputClient::SubClass::kTextField);
// TODO(crbug.com/1091088) Implement autocorrect range textfield handling.
return false;
model_->SetAutocorrectRange(autocorrect_text, range);
return true;
}
#endif
......
......@@ -408,6 +408,7 @@ class VIEWS_EXPORT Textfield : public View,
#endif
#if defined(OS_CHROMEOS)
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override;
#endif
......
......@@ -753,6 +753,33 @@ void TextfieldModel::SetCompositionText(
}
}
#if defined(OS_CHROMEOS)
bool TextfieldModel::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& autocorrect_range) {
// TODO(crbug.com/1108170): Use original text to create the Undo window.
original_text_ = render_text_->GetTextFromRange(autocorrect_range);
uint32_t autocorrect_range_start = autocorrect_range.start();
// TODO(crbug.com/1108170): Update the autocorrect range when the composition
// changes for ChromeOS. The current autocorrect_range_ does not get updated
// when composition changes or more text is committed.
autocorrect_range_ =
gfx::Range(autocorrect_range_start,
autocorrect_text.length() + autocorrect_range_start);
base::string16 before_text =
render_text_->GetTextFromRange(gfx::Range(0, autocorrect_range.start()));
base::string16 after_text = render_text_->GetTextFromRange(gfx::Range(
autocorrect_range.end(),
std::max(autocorrect_range.end(),
static_cast<uint32_t>(render_text_->text().length()))));
base::string16 new_text =
before_text.append(autocorrect_text).append(after_text);
SetRenderTextText(new_text);
return true;
}
#endif
void TextfieldModel::SetCompositionFromExistingText(const gfx::Range& range) {
if (range.is_empty() || !gfx::Range(0, text().length()).Contains(range)) {
ClearComposition();
......
......@@ -233,6 +233,17 @@ class VIEWS_EXPORT TextfieldModel {
// composition text.
void SetCompositionText(const ui::CompositionText& composition);
#if defined(OS_CHROMEOS)
// Return the text range corresponding to the autocorrected text.
const gfx::Range& autocorrect_range() const { return autocorrect_range_; }
// Replace the text in the specified range with the autocorrect text and
// store necessary metadata (The size of the new text + the original text)
// to be able to undo this change if needed.
bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range);
#endif
// Puts the text in the specified range into composition mode.
// This method should not be called with composition text or an invalid range.
// The provided range is checked against the string's length, if |range| is
......@@ -321,9 +332,16 @@ class VIEWS_EXPORT TextfieldModel {
// The stylized text, cursor, selection, and the visual layout model.
std::unique_ptr<gfx::RenderText> render_text_;
// The composition range.
gfx::Range composition_range_;
#if defined(OS_CHROMEOS)
gfx::Range autocorrect_range_;
// Original text is the text that was replaced by the autocorrect feature.
// This should be restored if the Undo button corresponding to the Autocorrect
// window is pressed.
base::string16 original_text_;
#endif
// The list of Edits. The oldest Edits are at the front of the list, and the
// newest ones are at the back of the list.
using EditHistory = std::list<std::unique_ptr<internal::Edit>>;
......
......@@ -3050,6 +3050,73 @@ TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
// - rects[6] == rects[7]
}
#if defined(OS_CHROMEOS)
TEST_F(TextfieldTest, SetAutocorrectRangeTextWithNoInitalText) {
InitTextfield();
ui::TextInputClient* client = textfield_;
client->SetAutocorrectRange(ASCIIToUTF16("text replacement"),
gfx::Range(0, 0));
base::string16 text;
client->GetTextFromRange(gfx::Range(0, 16), &text);
EXPECT_EQ(text, UTF8ToUTF16("text replacement"));
}
TEST_F(TextfieldTest, SetAutocorrectRangeText) {
InitTextfield();
ui::TextInputClient* client = textfield_;
ui::CompositionText composition;
composition.text = UTF8ToUTF16("Initial txt");
client->SetCompositionText(composition);
client->SetAutocorrectRange(ASCIIToUTF16("text replacement"),
gfx::Range(8, 11));
base::string16 text;
client->GetTextFromRange(gfx::Range(0, 24), &text);
EXPECT_EQ(text, UTF8ToUTF16("Initial text replacement"));
}
TEST_F(TextfieldTest, SetAutocorrectRangeExplicitlySet) {
InitTextfield();
ui::TextInputClient* client = textfield_;
client->InsertText(UTF8ToUTF16("Initial txt"));
client->SetAutocorrectRange(ASCIIToUTF16("text replacement"),
gfx::Range(8, 11));
base::string16 text;
client->GetTextFromRange(gfx::Range(0, 24), &text);
EXPECT_EQ(text, UTF8ToUTF16("Initial text replacement"));
}
TEST_F(TextfieldTest, GetAutocorrectCharacterBoundsTest) {
InitTextfield();
ui::TextInputClient* client = textfield_;
client->InsertText(UTF8ToUTF16("hello placeholder text"));
client->SetAutocorrectRange(ASCIIToUTF16("longlonglongtext"),
gfx::Range(3, 10));
gfx::Rect rectForLongText = client->GetAutocorrectCharacterBounds();
// Clear the text
client->DeleteRange(gfx::Range(0, 99));
client->InsertText(UTF8ToUTF16("hello placeholder text"));
client->SetAutocorrectRange(ASCIIToUTF16("short"), gfx::Range(3, 10));
gfx::Rect rectForShortText = client->GetAutocorrectCharacterBounds();
EXPECT_LT(rectForShortText.x(), rectForLongText.x());
EXPECT_EQ(rectForShortText.y(), rectForLongText.y());
EXPECT_EQ(rectForShortText.height(), rectForLongText.height());
// TODO(crbug.com/1108170): Investigate why the rectangle width is wrong.
// The value seems to be wrong due to the incorrect value being returned from
// RenderText::GetCursorBounds(). Unfortuantly, that is tricky to fix, since
// RenderText is used in other parts of the codebase.
// When fixed, the following EXPECT statement should pass.
// EXPECT_LT(rectForShortText.width(), rectForLongText.width());
}
// TODO(crbug.com/1108170): Add a test to check that when the composition /
// surrounding text is updated, the AutocorrectRange is updated accordingly.
#endif // OS_CHROMEOS
// The word we select by double clicking should remain selected regardless of
// where we drag the mouse afterwards without releasing the left button.
TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment