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( ...@@ -628,6 +628,12 @@ bool ArcImeService::SetCompositionFromExistingText(
return false; 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, bool ArcImeService::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) { const gfx::Range& range) {
base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count", base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count",
......
...@@ -149,6 +149,7 @@ class ArcImeService : public KeyedService, ...@@ -149,6 +149,7 @@ class ArcImeService : public KeyedService,
bool SetCompositionFromExistingText( bool SetCompositionFromExistingText(
const gfx::Range& range, const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override; const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text, bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override; const gfx::Range& range) override;
......
...@@ -324,6 +324,12 @@ bool TextInput::SetCompositionFromExistingText( ...@@ -324,6 +324,12 @@ bool TextInput::SetCompositionFromExistingText(
return false; 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 // TODO(crbug.com/1091088) Implement setAutocorrectRange
bool TextInput::SetAutocorrectRange(const base::string16& autocorrect_text, bool TextInput::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) { const gfx::Range& range) {
......
...@@ -140,6 +140,7 @@ class TextInput : public ui::TextInputClient, ...@@ -140,6 +140,7 @@ class TextInput : public ui::TextInputClient,
bool SetCompositionFromExistingText( bool SetCompositionFromExistingText(
const gfx::Range& range, const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override; const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text, bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override; const gfx::Range& range) override;
......
...@@ -1464,6 +1464,12 @@ bool RenderWidgetHostViewAura::SetCompositionFromExistingText( ...@@ -1464,6 +1464,12 @@ bool RenderWidgetHostViewAura::SetCompositionFromExistingText(
#endif #endif
#if defined(OS_CHROMEOS) #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( bool RenderWidgetHostViewAura::SetAutocorrectRange(
const base::string16& autocorrect_text, const base::string16& autocorrect_text,
const gfx::Range& range) { const gfx::Range& range) {
......
...@@ -231,7 +231,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura ...@@ -231,7 +231,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
#endif #endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// Set the autocorrect range gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text, bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override; const gfx::Range& range) override;
#endif #endif
......
...@@ -153,6 +153,10 @@ bool DummyTextInputClient::SetCompositionFromExistingText( ...@@ -153,6 +153,10 @@ bool DummyTextInputClient::SetCompositionFromExistingText(
#endif #endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
gfx::Rect DummyTextInputClient::GetAutocorrectCharacterBounds() const {
return gfx::Rect();
}
bool DummyTextInputClient::SetAutocorrectRange( bool DummyTextInputClient::SetAutocorrectRange(
const base::string16& autocorrect_text, const base::string16& autocorrect_text,
const gfx::Range& range) { const gfx::Range& range) {
......
...@@ -63,6 +63,8 @@ class DummyTextInputClient : public TextInputClient { ...@@ -63,6 +63,8 @@ class DummyTextInputClient : public TextInputClient {
#endif #endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
gfx::Rect GetAutocorrectCharacterBounds() const override;
// Set the autocorrect range // Set the autocorrect range
bool SetAutocorrectRange(const base::string16& autocorrect_text, bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override; const gfx::Range& range) override;
......
...@@ -227,6 +227,12 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { ...@@ -227,6 +227,12 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient {
#endif #endif
#if defined(OS_CHROMEOS) #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 // Set the autocorrect range and return if it has been set correctly as a
// boolean value. // boolean value.
virtual bool SetAutocorrectRange(const base::string16& autocorrect_text, virtual bool SetAutocorrectRange(const base::string16& autocorrect_text,
......
...@@ -172,6 +172,11 @@ bool PrefixSelector::SetCompositionFromExistingText( ...@@ -172,6 +172,11 @@ bool PrefixSelector::SetCompositionFromExistingText(
#endif #endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
gfx::Rect PrefixSelector::GetAutocorrectCharacterBounds() const {
NOTIMPLEMENTED_LOG_ONCE();
return gfx::Rect();
}
bool PrefixSelector::SetAutocorrectRange(const base::string16& autocorrect_text, bool PrefixSelector::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) { const gfx::Range& range) {
// TODO(crbug.com/1091088) Implement setAutocorrectRange. // TODO(crbug.com/1091088) Implement setAutocorrectRange.
......
...@@ -83,6 +83,7 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient { ...@@ -83,6 +83,7 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
#endif #endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text, bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override; const gfx::Range& range) override;
#endif #endif
......
...@@ -1846,12 +1846,26 @@ bool Textfield::SetCompositionFromExistingText( ...@@ -1846,12 +1846,26 @@ bool Textfield::SetCompositionFromExistingText(
#endif #endif
#if defined(OS_CHROMEOS) #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, bool Textfield::SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) { const gfx::Range& range) {
base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count", base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count",
TextInputClient::SubClass::kTextField); TextInputClient::SubClass::kTextField);
// TODO(crbug.com/1091088) Implement autocorrect range textfield handling. model_->SetAutocorrectRange(autocorrect_text, range);
return false; return true;
} }
#endif #endif
......
...@@ -408,6 +408,7 @@ class VIEWS_EXPORT Textfield : public View, ...@@ -408,6 +408,7 @@ class VIEWS_EXPORT Textfield : public View,
#endif #endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const base::string16& autocorrect_text, bool SetAutocorrectRange(const base::string16& autocorrect_text,
const gfx::Range& range) override; const gfx::Range& range) override;
#endif #endif
......
...@@ -753,6 +753,33 @@ void TextfieldModel::SetCompositionText( ...@@ -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) { void TextfieldModel::SetCompositionFromExistingText(const gfx::Range& range) {
if (range.is_empty() || !gfx::Range(0, text().length()).Contains(range)) { if (range.is_empty() || !gfx::Range(0, text().length()).Contains(range)) {
ClearComposition(); ClearComposition();
......
...@@ -233,6 +233,17 @@ class VIEWS_EXPORT TextfieldModel { ...@@ -233,6 +233,17 @@ class VIEWS_EXPORT TextfieldModel {
// composition text. // composition text.
void SetCompositionText(const ui::CompositionText& composition); 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. // Puts the text in the specified range into composition mode.
// This method should not be called with composition text or an invalid range. // 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 // The provided range is checked against the string's length, if |range| is
...@@ -321,9 +332,16 @@ class VIEWS_EXPORT TextfieldModel { ...@@ -321,9 +332,16 @@ class VIEWS_EXPORT TextfieldModel {
// The stylized text, cursor, selection, and the visual layout model. // The stylized text, cursor, selection, and the visual layout model.
std::unique_ptr<gfx::RenderText> render_text_; std::unique_ptr<gfx::RenderText> render_text_;
// The composition range.
gfx::Range 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 // 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. // newest ones are at the back of the list.
using EditHistory = std::list<std::unique_ptr<internal::Edit>>; using EditHistory = std::list<std::unique_ptr<internal::Edit>>;
......
...@@ -3050,6 +3050,73 @@ TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) { ...@@ -3050,6 +3050,73 @@ TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
// - rects[6] == rects[7] // - 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 // The word we select by double clicking should remain selected regardless of
// where we drag the mouse afterwards without releasing the left button. // where we drag the mouse afterwards without releasing the left button.
TEST_F(TextfieldTest, KeepInitiallySelectedWord) { 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