Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Unified Diff: chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc

Issue 4202005: [Linux] Improve preedit string and Instant suggestion support in omnibox. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update according to review comment. Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
index cf7103e97dd0eed0d144a6371528066c3419ad75..0048ae15b4d340a056a384054e26703244878a80 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc
@@ -150,6 +150,10 @@ AutocompleteEditViewGtk::AutocompleteEditViewGtk(
faded_text_tag_(NULL),
secure_scheme_tag_(NULL),
security_error_scheme_tag_(NULL),
+ normal_text_tag_(NULL),
+ instant_anchor_tag_(NULL),
+ instant_view_(NULL),
+ instant_mark_(NULL),
model_(new AutocompleteEditModel(this, controller, profile)),
#if defined(TOOLKIT_VIEWS)
popup_view_(new AutocompletePopupContentsView(
@@ -218,6 +222,15 @@ void AutocompleteEditViewGtk::Init() {
tag_table_ = gtk_text_tag_table_new();
text_buffer_ = gtk_text_buffer_new(tag_table_);
g_object_set_data(G_OBJECT(text_buffer_), kAutocompleteEditViewGtkKey, this);
+
+ // We need to run this two handlers before undo manager's handlers, so that
+ // text iterators modified by these handlers can be passed down to undo
+ // manager's handlers.
+ g_signal_connect(text_buffer_, "delete-range",
+ G_CALLBACK(&HandleDeleteRangeThunk), this);
+ g_signal_connect(text_buffer_, "mark-set",
+ G_CALLBACK(&HandleMarkSetAlwaysThunk), this);
+
text_view_ = gtk_undo_view_new(text_buffer_);
if (popup_window_mode_)
gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view_), false);
@@ -255,8 +268,6 @@ void AutocompleteEditViewGtk::Init() {
G_CALLBACK(&HandleBeginUserActionThunk), this);
g_signal_connect(text_buffer_, "end-user-action",
G_CALLBACK(&HandleEndUserActionThunk), this);
- g_signal_connect(text_buffer_, "insert-text",
- G_CALLBACK(&HandleInsertTextThunk), this);
// We connect to key press and release for special handling of a few keys.
g_signal_connect(text_view_, "key-press-event",
G_CALLBACK(&HandleKeyPressThunk), this);
@@ -305,23 +316,55 @@ void AutocompleteEditViewGtk::Init() {
G_CALLBACK(&HandleDeleteFromCursorThunk), this);
g_signal_connect(text_view_, "hierarchy-changed",
G_CALLBACK(&HandleHierarchyChangedThunk), this);
-#if GTK_CHECK_VERSION(2,20,0)
+#if GTK_CHECK_VERSION(2, 20, 0)
g_signal_connect(text_view_, "preedit-changed",
G_CALLBACK(&HandlePreeditChangedThunk), this);
#endif
+ g_signal_connect(text_view_, "undo", G_CALLBACK(&HandleUndoRedoThunk), this);
+ g_signal_connect(text_view_, "redo", G_CALLBACK(&HandleUndoRedoThunk), this);
+ g_signal_connect_after(text_view_, "undo",
+ G_CALLBACK(&HandleUndoRedoAfterThunk), this);
+ g_signal_connect_after(text_view_, "redo",
+ G_CALLBACK(&HandleUndoRedoAfterThunk), this);
// Setup for the Instant suggestion text view.
- instant_view_ = gtk_text_view_new();
- instant_buffer_ = gtk_text_view_get_buffer(GTK_TEXT_VIEW(instant_view_));
- gtk_text_view_add_child_in_window(GTK_TEXT_VIEW(text_view_),
+ // GtkLabel is used instead of GtkTextView to get transparent background.
+ instant_view_ = gtk_label_new(NULL);
+
+ GtkTextIter end_iter;
+ gtk_text_buffer_get_end_iter(text_buffer_, &end_iter);
+
+ // Insert a Zero Width Space character just before the instant anchor.
+ // It's a hack to workaround a bug of GtkTextView which can not align the
+ // preedit string and a child anchor correctly when there is no other content
+ // around the preedit string.
+ gtk_text_buffer_insert(text_buffer_, &end_iter, "\342\200\213", -1);
+ GtkTextChildAnchor* instant_anchor =
+ gtk_text_buffer_create_child_anchor(text_buffer_, &end_iter);
+
+ gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(text_view_),
instant_view_,
- GTK_TEXT_WINDOW_WIDGET,
- 0, 0);
- instant_text_tag_ = gtk_text_buffer_create_tag(
- instant_buffer_, NULL, "foreground", kTextBaseColor, NULL);
- GTK_WIDGET_UNSET_FLAGS(instant_view_, GTK_CAN_FOCUS);
- g_signal_connect(instant_view_, "button-press-event",
- G_CALLBACK(&HandleInstantViewButtonPressThunk), this);
+ instant_anchor);
+
+ instant_anchor_tag_ = gtk_text_buffer_create_tag(text_buffer_, NULL, NULL);
+
+ GtkTextIter anchor_iter;
+ gtk_text_buffer_get_iter_at_child_anchor(text_buffer_, &anchor_iter,
+ instant_anchor);
+ gtk_text_buffer_apply_tag(text_buffer_, instant_anchor_tag_,
+ &anchor_iter, &end_iter);
+
+ GtkTextIter start_iter;
+ gtk_text_buffer_get_start_iter(text_buffer_, &start_iter);
+ instant_mark_ =
+ gtk_text_buffer_create_mark(text_buffer_, NULL, &start_iter, FALSE);
+
+ // Hooking up this handler after setting up above hacks for Instant view, so
+ // that we won't filter out the special ZWP mark itself.
+ g_signal_connect(text_buffer_, "insert-text",
+ G_CALLBACK(&HandleInsertTextThunk), this);
+
+ AdjustVerticalAlignmentOfInstantView();
#if !defined(TOOLKIT_VIEWS)
registrar_.Add(this,
@@ -364,6 +407,9 @@ int AutocompleteEditViewGtk::TextWidth() {
GtkTextIter start, end;
GdkRectangle first_char_bounds, last_char_bounds;
gtk_text_buffer_get_start_iter(text_buffer_, &start);
+
+ // Use the real end iterator here to take the width of instant suggestion
+ // text into account, so that location bar can layout its children correctly.
gtk_text_buffer_get_end_iter(text_buffer_, &end);
gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_),
&start, &first_char_bounds);
@@ -445,12 +491,27 @@ void AutocompleteEditViewGtk::OpenURL(const GURL& url,
}
std::wstring AutocompleteEditViewGtk::GetText() const {
- return GetTextFromBuffer(text_buffer_);
+ GtkTextIter start, end;
+ GetTextBufferBounds(&start, &end);
+ gchar* utf8 = gtk_text_buffer_get_text(text_buffer_, &start, &end, false);
+ std::wstring out(UTF8ToWide(utf8));
+ g_free(utf8);
+
+#if GTK_CHECK_VERSION(2, 20, 0)
+ // We need to treat the text currently being composed by the input method as
+ // part of the text content, so that omnibox can work correctly in the middle
+ // of composition.
+ if (preedit_.size()) {
+ GtkTextMark* mark = gtk_text_buffer_get_insert(text_buffer_);
+ gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark);
+ out.insert(gtk_text_iter_get_offset(&start), preedit_);
+ }
+#endif
+ return out;
}
bool AutocompleteEditViewGtk::IsEditingOrEmpty() const {
- return model_->user_input_in_progress() ||
- (gtk_text_buffer_get_char_count(text_buffer_) == 0);
+ return model_->user_input_in_progress() || (GetTextLength() == 0);
}
int AutocompleteEditViewGtk::GetIcon() const {
@@ -497,7 +558,7 @@ bool AutocompleteEditViewGtk::IsSelectAll() {
gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end);
GtkTextIter start, end;
- gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
+ GetTextBufferBounds(&start, &end);
// Returns true if the |text_buffer_| is empty.
return gtk_text_iter_equal(&start, &sel_start) &&
@@ -530,10 +591,14 @@ void AutocompleteEditViewGtk::UpdatePopup() {
return;
// Don't inline autocomplete when the caret/selection isn't at the end of
- // the text.
+ // the text, or in the middle of composition.
CharRange sel = GetSelection();
- model_->StartAutocomplete(sel.cp_min != sel.cp_max,
- std::max(sel.cp_max, sel.cp_min) < GetTextLength());
+ bool no_inline_autocomplete =
+ std::max(sel.cp_max, sel.cp_min) < GetTextLength();
+#if GTK_CHECK_VERSION(2, 20, 0)
+ no_inline_autocomplete = no_inline_autocomplete || preedit_.size();
+#endif
+ model_->StartAutocomplete(sel.cp_min != sel.cp_max, no_inline_autocomplete);
}
void AutocompleteEditViewGtk::ClosePopup() {
@@ -674,6 +739,7 @@ void AutocompleteEditViewGtk::SetBaseColor() {
gtk_widget_modify_text(text_view_, GTK_STATE_ACTIVE, NULL);
gtk_util::UndoForceFontSize(text_view_);
+ gtk_util::UndoForceFontSize(instant_view_);
// Grab the text colors out of the style and set our tags to use them.
GtkStyle* style = gtk_rc_get_style(text_view_);
@@ -684,9 +750,11 @@ void AutocompleteEditViewGtk::SetBaseColor() {
style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
g_object_set(faded_text_tag_, "foreground-gdk", &average_color, NULL);
- g_object_set(instant_text_tag_, "foreground-gdk", &average_color, NULL);
g_object_set(normal_text_tag_, "foreground-gdk",
&style->text[GTK_STATE_NORMAL], NULL);
+
+ // GtkLabel uses fg color instead of text color.
+ gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &average_color);
} else {
const GdkColor* background_color_ptr;
#if defined(TOOLKIT_VIEWS)
@@ -701,10 +769,10 @@ void AutocompleteEditViewGtk::SetBaseColor() {
text_view_, &gtk_util::kGdkBlack, &gtk_util::kGdkGray);
gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background_color_ptr);
+ GdkColor c;
#if !defined(TOOLKIT_VIEWS)
// Override the selected colors so we don't leak colors from the current
// gtk theme into the chrome-theme.
- GdkColor c;
c = gfx::SkColorToGdkColor(
theme_provider_->get_active_selection_bg_color());
gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, &c);
@@ -722,16 +790,25 @@ void AutocompleteEditViewGtk::SetBaseColor() {
gtk_widget_modify_text(text_view_, GTK_STATE_ACTIVE, &c);
#endif
+ gdk_color_parse(kTextBaseColor, &c);
+ gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &c);
+
// Until we switch to vector graphics, force the font size.
gtk_util::ForceFontSizePixels(text_view_,
popup_window_mode_ ?
browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
browser_defaults::kAutocompleteEditFontPixelSize);
+ gtk_util::ForceFontSizePixels(instant_view_,
+ popup_window_mode_ ?
+ browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
+ browser_defaults::kAutocompleteEditFontPixelSize);
+
g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL);
- g_object_set(instant_text_tag_, "foreground", kTextBaseColor, NULL);
g_object_set(normal_text_tag_, "foreground", "#000000", NULL);
}
+
+ AdjustVerticalAlignmentOfInstantView();
}
void AutocompleteEditViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) {
@@ -946,7 +1023,7 @@ gboolean AutocompleteEditViewGtk::HandleViewButtonRelease(
// NOTE: This function doesn't seem to like a count of 0, looking at the
// code it will skip an important loop. Use -1 to achieve the same.
GtkTextIter start, end;
- gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
+ GetTextBufferBounds(&start, &end);
gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1);
}
#endif
@@ -1025,7 +1102,7 @@ void AutocompleteEditViewGtk::HandleViewMoveCursor(
gint cursor_pos;
g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos,
NULL);
- if (cursor_pos == gtk_text_buffer_get_char_count(text_buffer_))
+ if (cursor_pos == GetTextLength())
controller_->OnCommitSuggestedText(GetText());
else
handled = false;
@@ -1203,8 +1280,8 @@ void AutocompleteEditViewGtk::HandleInsertText(
filtered_text.reserve(len);
// Filter out new line and tab characters.
- // |text| is guaranteed to be a valid UTF-8 string, so it's safe here to
- // filter byte by byte.
+ // |text| is guaranteed to be a valid UTF-8 string, so we don't need to
+ // validate it here.
//
// If there was only a single character, then it might be generated by a key
// event. In this case, we save the single character to help our
@@ -1213,15 +1290,25 @@ void AutocompleteEditViewGtk::HandleInsertText(
if (len == 1 && (text[0] == '\n' || text[0] == '\r'))
enter_was_inserted_ = true;
- for (gint i = 0; i < len; ++i) {
- gchar c = text[i];
- if (c == '\n' || c == '\r' || c == '\t')
- continue;
+ const gchar* p = text;
+ while(*p) {
+ gunichar c = g_utf8_get_char(p);
+ const gchar* next = g_utf8_next_char(p);
+
+ // 0x200B is Zero Width Space, which is inserted just before the instant
+ // anchor for working around the GtkTextView's misalignment bug.
+ // This character might be captured and inserted into the content by undo
+ // manager, so we need to filter it out here.
+ if (c != L'\n' && c != L'\r' && c != L'\t' && c != 0x200B)
+ filtered_text.append(p, next);
- filtered_text.push_back(c);
+ p = next;
}
if (filtered_text.length()) {
+ // Avoid inserting the text after the instant anchor.
+ ValidateTextBufferIter(location);
+
// Call the default handler to insert filtered text.
GtkTextBufferClass* klass = GTK_TEXT_BUFFER_GET_CLASS(buffer);
klass->insert_text(buffer, location, filtered_text.data(),
@@ -1410,9 +1497,9 @@ void AutocompleteEditViewGtk::SelectAllInternal(bool reversed,
bool update_primary_selection) {
GtkTextIter start, end;
if (reversed) {
- gtk_text_buffer_get_bounds(text_buffer_, &end, &start);
+ GetTextBufferBounds(&end, &start);
} else {
- gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
+ GetTextBufferBounds(&start, &end);
}
if (!update_primary_selection)
StartUpdatingHighlightedText();
@@ -1459,6 +1546,11 @@ AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() {
mark = gtk_text_buffer_get_insert(text_buffer_);
gtk_text_buffer_get_iter_at_mark(text_buffer_, &insert, mark);
+#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));
+#endif
+
return CharRange(gtk_text_iter_get_offset(&start),
gtk_text_iter_get_offset(&insert));
}
@@ -1470,23 +1562,28 @@ void AutocompleteEditViewGtk::ItersFromCharRange(const CharRange& range,
gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max);
}
-int AutocompleteEditViewGtk::GetTextLength() {
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
+int AutocompleteEditViewGtk::GetTextLength() const {
+ GtkTextIter end;
+ gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_);
+#if GTK_CHECK_VERSION(2, 20, 0)
+ // We need to count the length of the text being composed, because we treat
+ // it as part of the content in GetText().
+ return gtk_text_iter_get_offset(&end) + preedit_.size();
+#else
return gtk_text_iter_get_offset(&end);
-}
-
-std::wstring AutocompleteEditViewGtk::GetTextFromBuffer(
- GtkTextBuffer* buffer) const {
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gchar* utf8 = gtk_text_buffer_get_text(buffer, &start, &end, false);
- std::wstring out(UTF8ToWide(utf8));
- g_free(utf8);
- return out;
+#endif
}
void AutocompleteEditViewGtk::EmphasizeURLComponents() {
+#if GTK_CHECK_VERSION(2, 20, 0)
+ // We can't change the text style easily, if the preedit string (the text
+ // being composed by the input method) is not empty, which is not treated as
+ // 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())
+ 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
// by Parse(), ask the model, which will check the desired page transition for
@@ -1501,7 +1598,7 @@ void AutocompleteEditViewGtk::EmphasizeURLComponents() {
// Set the baseline emphasis.
GtkTextIter start, end;
- gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
+ GetTextBufferBounds(&start, &end);
gtk_text_buffer_remove_all_tags(text_buffer_, &start, &end);
if (emphasize) {
gtk_text_buffer_apply_tag(text_buffer_, faded_text_tag_, &start, &end);
@@ -1545,28 +1642,22 @@ void AutocompleteEditViewGtk::EmphasizeURLComponents() {
void AutocompleteEditViewGtk::SetInstantSuggestion(
const std::string& suggestion) {
+ gtk_label_set_text(GTK_LABEL(instant_view_), suggestion.c_str());
if (suggestion.empty()) {
gtk_widget_hide(instant_view_);
} else {
- gtk_text_buffer_set_text(instant_buffer_, suggestion.data(),
- suggestion.size());
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(instant_buffer_, &start, &end);
- gtk_text_buffer_apply_tag(instant_buffer_, instant_text_tag_, &start, &end);
gtk_widget_show(instant_view_);
+ AdjustVerticalAlignmentOfInstantView();
}
}
bool AutocompleteEditViewGtk::CommitInstantSuggestion() {
- if (!GTK_WIDGET_VISIBLE(instant_view_))
- return false;
-
- std::wstring suggest_text = GetTextFromBuffer(instant_buffer_);
- if (suggest_text.empty())
+ const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_));
+ if (!suggestion || !*suggestion)
return false;
OnBeforePossibleChange();
- SetUserText(GetText() + suggest_text);
+ SetUserText(GetText() + UTF8ToWide(suggestion));
OnAfterPossibleChange();
return true;
}
@@ -1574,16 +1665,6 @@ bool AutocompleteEditViewGtk::CommitInstantSuggestion() {
void AutocompleteEditViewGtk::TextChanged() {
EmphasizeURLComponents();
controller_->OnChanged();
-
- // Move the instant suggestion to the end of the text.
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
- GdkRectangle rect;
- gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), &end, &rect);
-
- // +1 so the cursor will show.
- gtk_text_view_move_child(GTK_TEXT_VIEW(text_view_), instant_view_,
- rect.x + rect.width + 1, 0);
}
void AutocompleteEditViewGtk::SavePrimarySelection(
@@ -1672,12 +1753,40 @@ void AutocompleteEditViewGtk::HandleKeymapDirectionChanged(GdkKeymap* sender) {
AdjustTextJustification();
}
-gboolean AutocompleteEditViewGtk::HandleInstantViewButtonPress(
- GtkWidget* sender,
- GdkEventButton* event) {
- // Clicking on the view should have no effect; just stop propagation of the
- // event.
- return TRUE;
+void AutocompleteEditViewGtk::HandleDeleteRange(GtkTextBuffer* buffer,
+ GtkTextIter* start,
+ GtkTextIter* end) {
+ // Prevent the user from deleting the instant anchor. We can't simply set the
+ // instant anchor readonly by applying a tag with "editable" = FALSE, because
+ // it'll prevent the insert caret from blinking.
+ ValidateTextBufferIter(start);
+ ValidateTextBufferIter(end);
+ if (!gtk_text_iter_compare(start, end)) {
+ static guint signal_id =
+ g_signal_lookup("delete-range", GTK_TYPE_TEXT_BUFFER);
+ g_signal_stop_emission(buffer, signal_id, 0);
+ }
+}
+
+void AutocompleteEditViewGtk::HandleMarkSetAlways(GtkTextBuffer* buffer,
+ GtkTextIter* location,
+ GtkTextMark* mark) {
+ if (mark == instant_mark_)
+ return;
+
+ GtkTextIter new_iter = *location;
+ ValidateTextBufferIter(&new_iter);
+
+ // "mark-set" signal is actually emitted after the mark's location is already
+ // set, so if the location is beyond the instant anchor, we need to move the
+ // mark again, which will emit the signal again. In order to prevent other
+ // signal handlers from being called twice, we need to stop signal emission
+ // before moving the mark again.
+ if (gtk_text_iter_compare(&new_iter, location)) {
+ static guint signal_id = g_signal_lookup("mark-set", GTK_TYPE_TEXT_BUFFER);
+ g_signal_stop_emission(buffer, signal_id, 0);
+ gtk_text_buffer_move_mark(buffer, mark, &new_iter);
+ }
}
// static
@@ -1731,7 +1840,7 @@ void AutocompleteEditViewGtk::UpdatePrimarySelectionIfValidURL() {
}
}
-#if GTK_CHECK_VERSION(2,20,0)
+#if GTK_CHECK_VERSION(2, 20, 0)
void AutocompleteEditViewGtk::HandlePreeditChanged(GtkWidget* sender,
const gchar* preedit) {
// GtkTextView won't fire "begin-user-action" and "end-user-action" signals
@@ -1759,3 +1868,40 @@ void AutocompleteEditViewGtk::HandleWindowSetFocus(
// |focus|. I doubt that is likely to happen however.
going_to_focus_ = focus;
}
+
+void AutocompleteEditViewGtk::HandleUndoRedo(GtkWidget* sender) {
+ OnBeforePossibleChange();
+}
+
+void AutocompleteEditViewGtk::HandleUndoRedoAfter(GtkWidget* sender) {
+ OnAfterPossibleChange();
+}
+
+void AutocompleteEditViewGtk::GetTextBufferBounds(GtkTextIter* start,
+ GtkTextIter* end) const {
+ gtk_text_buffer_get_start_iter(text_buffer_, start);
+ gtk_text_buffer_get_iter_at_mark(text_buffer_, end, instant_mark_);
+}
+
+void AutocompleteEditViewGtk::ValidateTextBufferIter(GtkTextIter* iter) const {
+ if (!instant_mark_)
+ return;
+
+ GtkTextIter end;
+ gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_);
+ if (gtk_text_iter_compare(iter, &end) > 0)
+ *iter = end;
+}
+
+void AutocompleteEditViewGtk::AdjustVerticalAlignmentOfInstantView() {
+ // By default, GtkTextView layouts an anchored child widget just above the
+ // baseline, so we need to move the |instant_view_| down to make sure it
+ // has the same baseline as the |text_view_|.
+ PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_));
+ int height;
+ pango_layout_get_size(layout, NULL, &height);
+ PangoLayoutIter* iter = pango_layout_get_iter(layout);
+ int baseline = pango_layout_iter_get_baseline(iter);
+ pango_layout_iter_free(iter);
+ g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL);
+}
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698