summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsuzhe@google.com <suzhe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-22 00:51:22 +0000
committersuzhe@google.com <suzhe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-22 00:51:22 +0000
commit48b4f7b21180a14660f7e8a6df1b17cdd25eab1b (patch)
treea31287a0da6bb04519294f9e944c0892d2b9e45f
parent96886fddb95f9f0516652f07a9efd8ab16df40cc (diff)
downloadchromium_src-48b4f7b21180a14660f7e8a6df1b17cdd25eab1b.zip
chromium_src-48b4f7b21180a14660f7e8a6df1b17cdd25eab1b.tar.gz
chromium_src-48b4f7b21180a14660f7e8a6df1b17cdd25eab1b.tar.bz2
Make predictive instant suggest work with IME composition.
This CL enables predictive isntant suggest even when an IME composition text is available. But it won't be converted into inline autocomplete automatically, which conflicts with IME composition. This approach doesn't work for Mac port, which displays predictive isntant suggest in the same way as inline autocomplete. BUG=64983 TEST=See bug report. Review URL: http://codereview.chromium.org/6075004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69909 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit.cc11
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc59
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.h15
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_win.cc20
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_win.h3
-rw-r--r--chrome/browser/ui/views/location_bar/location_bar_view.cc3
6 files changed, 94 insertions, 17 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc
index dffc2be..68cdc82 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit.cc
@@ -178,9 +178,16 @@ void AutocompleteEditModel::GetDataForURLExport(GURL* url,
}
bool AutocompleteEditModel::UseVerbatimInstant() {
+#if defined(OS_MACOSX)
+ // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView,
+ // so that we can display instant suggest along with composition text.
const AutocompleteInput& input = popup_->autocomplete_controller()->input();
- if (input.initial_prevent_inline_autocomplete() ||
- view_->DeleteAtEndPressed() || (popup_->selected_line() != 0))
+ if (input.initial_prevent_inline_autocomplete())
+ return true;
+#endif
+
+ if (view_->DeleteAtEndPressed() || (popup_->selected_line() != 0) ||
+ just_deleted_text_)
return true;
std::wstring::size_type start, end;
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
index d8eca8d..e450e70 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
@@ -186,6 +186,11 @@ AutocompleteEditViewGtk::AutocompleteEditViewGtk(
selection_suggested_(false),
delete_was_pressed_(false),
delete_at_end_pressed_(false),
+ handling_key_press_(false),
+ content_maybe_changed_by_key_press_(false),
+#if GTK_CHECK_VERSION(2, 20, 0)
+ preedit_size_before_change_(0),
+#endif
going_to_focus_(NULL) {
model_->SetPopupModel(popup_view_->GetModel());
}
@@ -684,6 +689,12 @@ void AutocompleteEditViewGtk::OnRevertTemporaryText() {
}
void AutocompleteEditViewGtk::OnBeforePossibleChange() {
+ // This method will be called in HandleKeyPress() method just before
+ // handling a key press event. So we should prevent it from being called
+ // when handling the key press event.
+ if (handling_key_press_)
+ return;
+
// If this change is caused by a paste clipboard action and all text is
// selected, then call model_->on_paste_replacing_all() to prevent inline
// autocomplete.
@@ -696,10 +707,21 @@ void AutocompleteEditViewGtk::OnBeforePossibleChange() {
// Record our state.
text_before_change_ = GetText();
sel_before_change_ = GetSelection();
+#if GTK_CHECK_VERSION(2, 20, 0)
+ preedit_size_before_change_ = preedit_.size();
+#endif
}
// TODO(deanm): This is mostly stolen from Windows, and will need some work.
bool AutocompleteEditViewGtk::OnAfterPossibleChange() {
+ // This method will be called in HandleKeyPress() method just after
+ // handling a key press event. So we should prevent it from being called
+ // when handling the key press event.
+ if (handling_key_press_) {
+ content_maybe_changed_by_key_press_ = true;
+ return false;
+ }
+
// If the change is caused by an Enter key press event, and the event was not
// handled by IME, then it's an unexpected change and shall be reverted here.
// {Start|Finish}UpdatingHighlightedText() are called here to prevent the
@@ -720,6 +742,10 @@ bool AutocompleteEditViewGtk::OnAfterPossibleChange() {
// See if the text or selection have changed since OnBeforePossibleChange().
std::wstring new_text(GetText());
text_changed_ = (new_text != text_before_change_);
+#if GTK_CHECK_VERSION(2, 20, 0)
+ text_changed_ =
+ text_changed_ || (preedit_.size() != preedit_size_before_change_);
+#endif
if (text_changed_)
AdjustTextJustification();
@@ -1020,11 +1046,19 @@ gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget,
// Reset |text_changed_| before passing the key event on to the text view.
text_changed_ = false;
+ OnBeforePossibleChange();
+ handling_key_press_ = true;
+ content_maybe_changed_by_key_press_ = false;
+
// Call the default handler, so that IME can work as normal.
// New line characters will be filtered out by our "insert-text"
// signal handler attached to |text_buffer_| object.
gboolean result = klass->key_press_event(widget, event);
+ handling_key_press_ = false;
+ if (content_maybe_changed_by_key_press_)
+ OnAfterPossibleChange();
+
// Set |tab_was_pressed_| to false, to make sure Tab to search behavior can
// only be triggered by pressing Tab key.
tab_was_pressed_ = false;
@@ -1707,18 +1741,27 @@ AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() {
mark = gtk_text_buffer_get_insert(text_buffer_);
gtk_text_buffer_get_iter_at_mark(text_buffer_, &insert, mark);
+ gint start_offset = gtk_text_iter_get_offset(&start);
+ gint end_offset = gtk_text_iter_get_offset(&insert);
+
#if GTK_CHECK_VERSION(2, 20, 0)
// Nothing should be selected when we are in the middle of composition.
- DCHECK(preedit_.empty() || gtk_text_iter_equal(&start, &insert));
+ DCHECK(preedit_.empty() || start_offset == end_offset);
+ if (!preedit_.empty()) {
+ start_offset += preedit_.size();
+ end_offset += preedit_.size();
+ }
#endif
- return CharRange(gtk_text_iter_get_offset(&start),
- gtk_text_iter_get_offset(&insert));
+ return CharRange(start_offset, end_offset);
}
void AutocompleteEditViewGtk::ItersFromCharRange(const CharRange& range,
GtkTextIter* iter_min,
GtkTextIter* iter_max) {
+#if GTK_CHECK_VERSION(2, 20, 0)
+ DCHECK(preedit_.empty());
+#endif
gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min);
gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max);
}
@@ -1742,8 +1785,10 @@ void AutocompleteEditViewGtk::EmphasizeURLComponents() {
// a part of the text content inside GtkTextView. And it's ok to simply return
// in this case, as this method will be called again when the preedit string
// gets committed.
- if (preedit_.size())
+ if (preedit_.size()) {
+ strikethrough_ = CharRange();
return;
+ }
#endif
// See whether the contents are a URL with a non-empty host portion, which we
// should emphasize. To check for a URL, rather than using the type returned
@@ -1811,7 +1856,11 @@ void AutocompleteEditViewGtk::SetInstantSuggestion(
gtk_widget_hide(instant_view_);
} else {
if (InstantController::IsEnabled(model_->profile(),
- InstantController::PREDICTIVE_TYPE)) {
+ InstantController::PREDICTIVE_TYPE)
+#if GTK_CHECK_VERSION(2, 20, 0)
+ && preedit_.empty()
+#endif
+ ) {
instant_animation_->set_delegate(this);
instant_animation_->Start();
}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
index 66c7541..dc09d91 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h
@@ -488,9 +488,24 @@ class AutocompleteEditViewGtk : public AutocompleteEditView,
// Was the delete key pressed with an empty selection at the end of the edit?
bool delete_at_end_pressed_;
+ // Indicates if we are handling a key press event.
+ bool handling_key_press_;
+
+ // Indicates if omnibox's content maybe changed by a key press event, so that
+ // we need to call OnAfterPossibleChange() after handling the event.
+ // This flag should be set for changes directly caused by a key press event,
+ // including changes to content text, selection range and preedit string.
+ // Changes caused by function calls like SetUserText() should not affect this
+ // flag.
+ bool content_maybe_changed_by_key_press_;
+
#if GTK_CHECK_VERSION(2, 20, 0)
// Stores the text being composed by the input method.
std::wstring preedit_;
+
+ // Tracking preedit state before and after a possible change. We don't need to
+ // track preedit_'s content, as it'll be treated as part of text content.
+ size_t preedit_size_before_change_;
#endif
// The view that is going to be focused next. Only valid while handling
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
index bd6b50e..284f30c 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
@@ -711,14 +711,6 @@ void AutocompleteEditViewWin::UpdatePopup() {
return;
}
- // Figure out whether the user is trying to compose something in an IME.
- bool ime_composing = false;
- HIMC context = ImmGetContext(m_hWnd);
- if (context) {
- ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
- ImmReleaseContext(m_hWnd, context);
- }
-
// Don't inline autocomplete when:
// * The user is deleting text
// * The caret/selection isn't at the end of the text
@@ -727,7 +719,7 @@ void AutocompleteEditViewWin::UpdatePopup() {
CHARRANGE sel;
GetSel(sel);
model_->StartAutocomplete(sel.cpMax != sel.cpMin,
- (sel.cpMax < GetTextLength()) || ime_composing);
+ (sel.cpMax < GetTextLength()) || IsImeComposing());
}
void AutocompleteEditViewWin::ClosePopup() {
@@ -2593,3 +2585,13 @@ int AutocompleteEditViewWin::WidthNeededToDisplay(const std::wstring& text) {
// PosFromChar(i) might return 0 when i is greater than 1.
return font_.GetStringWidth(text) + GetHorizontalMargin();
}
+
+bool AutocompleteEditViewWin::IsImeComposing() const {
+ bool ime_composing = false;
+ HIMC context = ImmGetContext(m_hWnd);
+ if (context) {
+ ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
+ ImmReleaseContext(m_hWnd, context);
+ }
+ return ime_composing;
+}
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
index 904b9cd..0773843 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
@@ -213,6 +213,9 @@ class AutocompleteEditViewWin
virtual std::wstring GetLabelForCommandId(int command_id) const;
virtual void ExecuteCommand(int command_id);
+ // Returns true if the user is composing something in an IME.
+ bool IsImeComposing() const;
+
private:
enum MouseButton {
kLeft = 0,
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index fc76fb0..7915916 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -1157,7 +1157,8 @@ void LocationBarView::SetSuggestedText(const string16& input) {
} else if (suggested_text_view_->GetText() != UTF16ToWide(text)) {
suggested_text_view_->SetText(UTF16ToWide(text));
}
- suggested_text_view_->StartAnimation();
+ if (!location_entry_->IsImeComposing())
+ suggested_text_view_->StartAnimation();
} else if (suggested_text_view_) {
delete suggested_text_view_;
suggested_text_view_ = NULL;