Home | History | Annotate | Download | only in autocomplete
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
      6 
      7 #include <gdk/gdkkeysyms.h>
      8 #include <gtk/gtk.h>
      9 
     10 #include <algorithm>
     11 
     12 #include "base/logging.h"
     13 #include "base/string_util.h"
     14 #include "base/utf_string_conversions.h"
     15 #include "chrome/app/chrome_command_ids.h"
     16 #include "chrome/browser/autocomplete/autocomplete_edit.h"
     17 #include "chrome/browser/autocomplete/autocomplete_match.h"
     18 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
     19 #include "chrome/browser/bookmarks/bookmark_node_data.h"
     20 #include "chrome/browser/command_updater.h"
     21 #include "chrome/browser/defaults.h"
     22 #include "chrome/browser/instant/instant_controller.h"
     23 #include "chrome/browser/platform_util.h"
     24 #include "chrome/browser/ui/gtk/gtk_util.h"
     25 #include "chrome/browser/ui/gtk/view_id_util.h"
     26 #include "chrome/browser/ui/toolbar/toolbar_model.h"
     27 #include "content/browser/tab_contents/tab_contents.h"
     28 #include "content/common/notification_service.h"
     29 #include "googleurl/src/gurl.h"
     30 #include "grit/generated_resources.h"
     31 #include "net/base/escape.h"
     32 #include "third_party/undoview/undo_view.h"
     33 #include "ui/base/animation/multi_animation.h"
     34 #include "ui/base/dragdrop/drag_drop_types.h"
     35 #include "ui/base/l10n/l10n_util.h"
     36 #include "ui/base/resource/resource_bundle.h"
     37 #include "ui/gfx/color_utils.h"
     38 #include "ui/gfx/font.h"
     39 #include "ui/gfx/gtk_util.h"
     40 #include "ui/gfx/skia_utils_gtk.h"
     41 
     42 #if defined(TOOLKIT_VIEWS)
     43 #include "chrome/browser/autocomplete/autocomplete_edit_view_views.h"
     44 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
     45 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
     46 #include "views/controls/textfield/native_textfield_views.h"
     47 #include "views/events/event.h"
     48 #else
     49 #include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h"
     50 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
     51 #include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
     52 #endif
     53 
     54 namespace {
     55 
     56 const gchar* kAutocompleteEditViewGtkKey = "__ACE_VIEW_GTK__";
     57 
     58 const char kTextBaseColor[] = "#808080";
     59 const char kSecureSchemeColor[] = "#079500";
     60 const char kSecurityErrorSchemeColor[] = "#a20000";
     61 
     62 const double kStrikethroughStrokeRed = 162.0 / 256.0;
     63 const double kStrikethroughStrokeWidth = 2.0;
     64 
     65 size_t GetUTF8Offset(const string16& text, size_t text_offset) {
     66   return UTF16ToUTF8(text.substr(0, text_offset)).size();
     67 }
     68 
     69 // A helper method for determining a valid drag operation given the allowed
     70 // operation.  We prefer copy over link.
     71 int CopyOrLinkDragOperation(int drag_operation) {
     72   if (drag_operation & ui::DragDropTypes::DRAG_COPY)
     73     return ui::DragDropTypes::DRAG_COPY;
     74   if (drag_operation & ui::DragDropTypes::DRAG_LINK)
     75     return ui::DragDropTypes::DRAG_LINK;
     76   return ui::DragDropTypes::DRAG_NONE;
     77 }
     78 
     79 // Stores GTK+-specific state so it can be restored after switching tabs.
     80 struct ViewState {
     81   explicit ViewState(const AutocompleteEditViewGtk::CharRange& selection_range)
     82       : selection_range(selection_range) {
     83   }
     84 
     85   // Range of selected text.
     86   AutocompleteEditViewGtk::CharRange selection_range;
     87 };
     88 
     89 struct AutocompleteEditState {
     90   AutocompleteEditState(const AutocompleteEditModel::State& model_state,
     91                         const ViewState& view_state)
     92       : model_state(model_state),
     93         view_state(view_state) {
     94   }
     95 
     96   const AutocompleteEditModel::State model_state;
     97   const ViewState view_state;
     98 };
     99 
    100 // Returns a lazily initialized property bag accessor for saving our state in a
    101 // TabContents.
    102 PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
    103   static PropertyAccessor<AutocompleteEditState> state;
    104   return &state;
    105 }
    106 
    107 // Set up style properties to override the default GtkTextView; if a theme has
    108 // overridden some of these properties, an inner-line will be displayed inside
    109 // the fake GtkTextEntry.
    110 void SetEntryStyle() {
    111   static bool style_was_set = false;
    112 
    113   if (style_was_set)
    114     return;
    115   style_was_set = true;
    116 
    117   gtk_rc_parse_string(
    118       "style \"chrome-location-bar-entry\" {"
    119       "  xthickness = 0\n"
    120       "  ythickness = 0\n"
    121       "  GtkWidget::focus_padding = 0\n"
    122       "  GtkWidget::focus-line-width = 0\n"
    123       "  GtkWidget::interior_focus = 0\n"
    124       "  GtkWidget::internal-padding = 0\n"
    125       "  GtkContainer::border-width = 0\n"
    126       "}\n"
    127       "widget \"*chrome-location-bar-entry\" "
    128       "style \"chrome-location-bar-entry\"");
    129 }
    130 
    131 // Copied from GTK+. Called when we lose the primary selection. This will clear
    132 // the selection in the text buffer.
    133 void ClipboardSelectionCleared(GtkClipboard* clipboard,
    134                                gpointer data) {
    135   GtkTextIter insert;
    136   GtkTextIter selection_bound;
    137   GtkTextBuffer* buffer = GTK_TEXT_BUFFER(data);
    138 
    139   gtk_text_buffer_get_iter_at_mark(buffer, &insert,
    140                                    gtk_text_buffer_get_insert(buffer));
    141   gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound,
    142                                    gtk_text_buffer_get_selection_bound(buffer));
    143 
    144   if (!gtk_text_iter_equal(&insert, &selection_bound)) {
    145     gtk_text_buffer_move_mark(buffer,
    146                               gtk_text_buffer_get_selection_bound(buffer),
    147                               &insert);
    148   }
    149 }
    150 
    151 }  // namespace
    152 
    153 AutocompleteEditViewGtk::AutocompleteEditViewGtk(
    154     AutocompleteEditController* controller,
    155     ToolbarModel* toolbar_model,
    156     Profile* profile,
    157     CommandUpdater* command_updater,
    158     bool popup_window_mode,
    159 #if defined(TOOLKIT_VIEWS)
    160     views::View* location_bar)
    161 #else
    162     GtkWidget* location_bar)
    163 #endif
    164     : text_view_(NULL),
    165       tag_table_(NULL),
    166       text_buffer_(NULL),
    167       faded_text_tag_(NULL),
    168       secure_scheme_tag_(NULL),
    169       security_error_scheme_tag_(NULL),
    170       normal_text_tag_(NULL),
    171       instant_anchor_tag_(NULL),
    172       instant_view_(NULL),
    173       instant_mark_(NULL),
    174       model_(new AutocompleteEditModel(this, controller, profile)),
    175       controller_(controller),
    176       toolbar_model_(toolbar_model),
    177       command_updater_(command_updater),
    178       popup_window_mode_(popup_window_mode),
    179       security_level_(ToolbarModel::NONE),
    180       mark_set_handler_id_(0),
    181 #if defined(OS_CHROMEOS)
    182       button_1_pressed_(false),
    183       text_selected_during_click_(false),
    184       text_view_focused_before_button_press_(false),
    185 #endif
    186 #if defined(TOOLKIT_VIEWS)
    187       location_bar_view_(location_bar),
    188 #else
    189       theme_service_(GtkThemeService::GetFrom(profile)),
    190 #endif
    191       enter_was_pressed_(false),
    192       tab_was_pressed_(false),
    193       paste_clipboard_requested_(false),
    194       enter_was_inserted_(false),
    195       selection_suggested_(false),
    196       delete_was_pressed_(false),
    197       delete_at_end_pressed_(false),
    198       handling_key_press_(false),
    199       content_maybe_changed_by_key_press_(false),
    200       update_popup_without_focus_(false),
    201 #if GTK_CHECK_VERSION(2, 20, 0)
    202       preedit_size_before_change_(0),
    203 #endif
    204       going_to_focus_(NULL) {
    205   popup_view_.reset(
    206 #if defined(TOOLKIT_VIEWS)
    207       new AutocompletePopupContentsView
    208 #else
    209       new AutocompletePopupViewGtk
    210 #endif
    211           (GetFont(), this, model_.get(), profile, location_bar));
    212 }
    213 
    214 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() {
    215   NotificationService::current()->Notify(
    216       NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
    217       Source<AutocompleteEditViewGtk>(this),
    218       NotificationService::NoDetails());
    219 
    220   // Explicitly teardown members which have a reference to us.  Just to be safe
    221   // we want them to be destroyed before destroying any other internal state.
    222   popup_view_.reset();
    223   model_.reset();
    224 
    225   // We own our widget and TextView related objects.
    226   if (alignment_.get()) {  // Init() has been called.
    227     alignment_.Destroy();
    228     g_object_unref(text_buffer_);
    229     g_object_unref(tag_table_);
    230     // The tags we created are owned by the tag_table, and should be destroyed
    231     // along with it.  We don't hold our own reference to them.
    232   }
    233 }
    234 
    235 void AutocompleteEditViewGtk::Init() {
    236   SetEntryStyle();
    237 
    238   // The height of the text view is going to change based on the font used.  We
    239   // don't want to stretch the height, and we want it vertically centered.
    240   alignment_.Own(gtk_alignment_new(0., 0.5, 1.0, 0.0));
    241   gtk_widget_set_name(alignment_.get(),
    242                       "chrome-autocomplete-edit-view");
    243 
    244   // The GtkTagTable and GtkTextBuffer are not initially unowned, so we have
    245   // our own reference when we create them, and we own them.  Adding them to
    246   // the other objects adds a reference; it doesn't adopt them.
    247   tag_table_ = gtk_text_tag_table_new();
    248   text_buffer_ = gtk_text_buffer_new(tag_table_);
    249   g_object_set_data(G_OBJECT(text_buffer_), kAutocompleteEditViewGtkKey, this);
    250 
    251   // We need to run this two handlers before undo manager's handlers, so that
    252   // text iterators modified by these handlers can be passed down to undo
    253   // manager's handlers.
    254   g_signal_connect(text_buffer_, "delete-range",
    255                    G_CALLBACK(&HandleDeleteRangeThunk), this);
    256   g_signal_connect(text_buffer_, "mark-set",
    257                    G_CALLBACK(&HandleMarkSetAlwaysThunk), this);
    258 
    259   text_view_ = gtk_undo_view_new(text_buffer_);
    260   if (popup_window_mode_)
    261     gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view_), false);
    262 
    263   // One pixel left margin is necessary to make the cursor visible when UI
    264   // language direction is LTR but |text_buffer_|'s content direction is RTL.
    265   gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_view_), 1);
    266 
    267   // See SetEntryStyle() comments.
    268   gtk_widget_set_name(text_view_, "chrome-location-bar-entry");
    269 
    270   // The text view was floating.  It will now be owned by the alignment.
    271   gtk_container_add(GTK_CONTAINER(alignment_.get()), text_view_);
    272 
    273   // Do not allow inserting tab characters when pressing Tab key, so that when
    274   // Tab key is pressed, |text_view_| will emit "move-focus" signal, which will
    275   // be intercepted by our own handler to trigger Tab to search feature when
    276   // necessary.
    277   gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(text_view_), FALSE);
    278 
    279   faded_text_tag_ = gtk_text_buffer_create_tag(text_buffer_,
    280       NULL, "foreground", kTextBaseColor, NULL);
    281   secure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
    282       NULL, "foreground", kSecureSchemeColor, NULL);
    283   security_error_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_,
    284       NULL, "foreground", kSecurityErrorSchemeColor, NULL);
    285   normal_text_tag_ = gtk_text_buffer_create_tag(text_buffer_,
    286       NULL, "foreground", "#000000", NULL);
    287 
    288   // NOTE: This code used to connect to "changed", however this was fired too
    289   // often and during bad times (our own buffer changes?).  It works out much
    290   // better to listen to end-user-action, which should be fired whenever the
    291   // user makes some sort of change to the buffer.
    292   g_signal_connect(text_buffer_, "begin-user-action",
    293                    G_CALLBACK(&HandleBeginUserActionThunk), this);
    294   g_signal_connect(text_buffer_, "end-user-action",
    295                    G_CALLBACK(&HandleEndUserActionThunk), this);
    296   // We connect to key press and release for special handling of a few keys.
    297   g_signal_connect(text_view_, "key-press-event",
    298                    G_CALLBACK(&HandleKeyPressThunk), this);
    299   g_signal_connect(text_view_, "key-release-event",
    300                    G_CALLBACK(&HandleKeyReleaseThunk), this);
    301   g_signal_connect(text_view_, "button-press-event",
    302                    G_CALLBACK(&HandleViewButtonPressThunk), this);
    303   g_signal_connect(text_view_, "button-release-event",
    304                    G_CALLBACK(&HandleViewButtonReleaseThunk), this);
    305   g_signal_connect(text_view_, "focus-in-event",
    306                    G_CALLBACK(&HandleViewFocusInThunk), this);
    307   g_signal_connect(text_view_, "focus-out-event",
    308                    G_CALLBACK(&HandleViewFocusOutThunk), this);
    309   // NOTE: The GtkTextView documentation asks you not to connect to this
    310   // signal, but it is very convenient and clean for catching up/down.
    311   g_signal_connect(text_view_, "move-cursor",
    312                    G_CALLBACK(&HandleViewMoveCursorThunk), this);
    313   g_signal_connect(text_view_, "move-focus",
    314                    G_CALLBACK(&HandleViewMoveFocusThunk), this);
    315   // Override the size request.  We want to keep the original height request
    316   // from the widget, since that's font dependent.  We want to ignore the width
    317   // so we don't force a minimum width based on the text length.
    318   g_signal_connect(text_view_, "size-request",
    319                    G_CALLBACK(&HandleViewSizeRequestThunk), this);
    320   g_signal_connect(text_view_, "populate-popup",
    321                    G_CALLBACK(&HandlePopulatePopupThunk), this);
    322   mark_set_handler_id_ = g_signal_connect(
    323       text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this);
    324   mark_set_handler_id2_ = g_signal_connect_after(
    325       text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetAfterThunk), this);
    326   g_signal_connect(text_view_, "drag-data-received",
    327                    G_CALLBACK(&HandleDragDataReceivedThunk), this);
    328   // Override the text_view_'s default drag-data-get handler by calling our own
    329   // version after the normal call has happened.
    330   g_signal_connect_after(text_view_, "drag-data-get",
    331                    G_CALLBACK(&HandleDragDataGetThunk), this);
    332   g_signal_connect(text_view_, "backspace",
    333                    G_CALLBACK(&HandleBackSpaceThunk), this);
    334   g_signal_connect(text_view_, "copy-clipboard",
    335                    G_CALLBACK(&HandleCopyClipboardThunk), this);
    336   g_signal_connect(text_view_, "cut-clipboard",
    337                    G_CALLBACK(&HandleCutClipboardThunk), this);
    338   g_signal_connect(text_view_, "paste-clipboard",
    339                    G_CALLBACK(&HandlePasteClipboardThunk), this);
    340   g_signal_connect_after(text_view_, "expose-event",
    341                          G_CALLBACK(&HandleExposeEventThunk), this);
    342   g_signal_connect(text_view_, "direction-changed",
    343                    G_CALLBACK(&HandleWidgetDirectionChangedThunk), this);
    344   g_signal_connect(text_view_, "delete-from-cursor",
    345                    G_CALLBACK(&HandleDeleteFromCursorThunk), this);
    346   g_signal_connect(text_view_, "hierarchy-changed",
    347                    G_CALLBACK(&HandleHierarchyChangedThunk), this);
    348 #if GTK_CHECK_VERSION(2, 20, 0)
    349   g_signal_connect(text_view_, "preedit-changed",
    350                    G_CALLBACK(&HandlePreeditChangedThunk), this);
    351 #endif
    352   g_signal_connect(text_view_, "undo", G_CALLBACK(&HandleUndoRedoThunk), this);
    353   g_signal_connect(text_view_, "redo", G_CALLBACK(&HandleUndoRedoThunk), this);
    354   g_signal_connect_after(text_view_, "undo",
    355                          G_CALLBACK(&HandleUndoRedoAfterThunk), this);
    356   g_signal_connect_after(text_view_, "redo",
    357                          G_CALLBACK(&HandleUndoRedoAfterThunk), this);
    358   g_signal_connect(text_view_, "destroy",
    359                    G_CALLBACK(&gtk_widget_destroyed), &text_view_);
    360 
    361   // Setup for the Instant suggestion text view.
    362   // GtkLabel is used instead of GtkTextView to get transparent background.
    363   instant_view_ = gtk_label_new(NULL);
    364   gtk_widget_set_no_show_all(instant_view_, TRUE);
    365   gtk_label_set_selectable(GTK_LABEL(instant_view_), TRUE);
    366 
    367   GtkTextIter end_iter;
    368   gtk_text_buffer_get_end_iter(text_buffer_, &end_iter);
    369 
    370   // Insert a Zero Width Space character just before the instant anchor.
    371   // It's a hack to workaround a bug of GtkTextView which can not align the
    372   // preedit string and a child anchor correctly when there is no other content
    373   // around the preedit string.
    374   gtk_text_buffer_insert(text_buffer_, &end_iter, "\342\200\213", -1);
    375   GtkTextChildAnchor* instant_anchor =
    376       gtk_text_buffer_create_child_anchor(text_buffer_, &end_iter);
    377 
    378   gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(text_view_),
    379                                     instant_view_,
    380                                     instant_anchor);
    381 
    382   instant_anchor_tag_ = gtk_text_buffer_create_tag(text_buffer_, NULL, NULL);
    383 
    384   GtkTextIter anchor_iter;
    385   gtk_text_buffer_get_iter_at_child_anchor(text_buffer_, &anchor_iter,
    386                                            instant_anchor);
    387   gtk_text_buffer_apply_tag(text_buffer_, instant_anchor_tag_,
    388                             &anchor_iter, &end_iter);
    389 
    390   GtkTextIter start_iter;
    391   gtk_text_buffer_get_start_iter(text_buffer_, &start_iter);
    392   instant_mark_ =
    393       gtk_text_buffer_create_mark(text_buffer_, NULL, &start_iter, FALSE);
    394 
    395   // Hooking up this handler after setting up above hacks for Instant view, so
    396   // that we won't filter out the special ZWP mark itself.
    397   g_signal_connect(text_buffer_, "insert-text",
    398                    G_CALLBACK(&HandleInsertTextThunk), this);
    399 
    400   AdjustVerticalAlignmentOfInstantView();
    401 
    402   ui::MultiAnimation::Parts parts;
    403   parts.push_back(ui::MultiAnimation::Part(
    404       InstantController::kAutoCommitPauseTimeMS, ui::Tween::ZERO));
    405   parts.push_back(ui::MultiAnimation::Part(
    406       InstantController::kAutoCommitFadeInTimeMS, ui::Tween::EASE_IN));
    407   instant_animation_.reset(new ui::MultiAnimation(parts));
    408   instant_animation_->set_continuous(false);
    409 
    410 #if !defined(TOOLKIT_VIEWS)
    411   registrar_.Add(this,
    412                  NotificationType::BROWSER_THEME_CHANGED,
    413                  NotificationService::AllSources());
    414   theme_service_->InitThemesFor(this);
    415 #else
    416   // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe
    417   // themes.
    418   SetBaseColor();
    419 #endif
    420 
    421   ViewIDUtil::SetID(GetNativeView(), VIEW_ID_AUTOCOMPLETE);
    422 }
    423 
    424 void AutocompleteEditViewGtk::HandleHierarchyChanged(
    425     GtkWidget* sender, GtkWidget* old_toplevel) {
    426   GtkWindow* new_toplevel = platform_util::GetTopLevel(sender);
    427   if (!new_toplevel)
    428     return;
    429 
    430   // Use |signals_| to make sure we don't get called back after destruction.
    431   signals_.Connect(new_toplevel, "set-focus",
    432                    G_CALLBACK(&HandleWindowSetFocusThunk), this);
    433 }
    434 
    435 void AutocompleteEditViewGtk::SetFocus() {
    436   DCHECK(text_view_);
    437   gtk_widget_grab_focus(text_view_);
    438 }
    439 
    440 int AutocompleteEditViewGtk::WidthOfTextAfterCursor() {
    441   // Not used.
    442   return -1;
    443 }
    444 
    445 AutocompleteEditModel* AutocompleteEditViewGtk::model() {
    446   return model_.get();
    447 }
    448 
    449 const AutocompleteEditModel* AutocompleteEditViewGtk::model() const {
    450   return model_.get();
    451 }
    452 
    453 void AutocompleteEditViewGtk::SaveStateToTab(TabContents* tab) {
    454   DCHECK(tab);
    455   // If any text has been selected, register it as the PRIMARY selection so it
    456   // can still be pasted via middle-click after the text view is cleared.
    457   if (!selected_text_.empty())
    458     SavePrimarySelection(selected_text_);
    459   // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important.
    460   AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch();
    461   GetStateAccessor()->SetProperty(
    462       tab->property_bag(),
    463       AutocompleteEditState(model_state, ViewState(GetSelection())));
    464 }
    465 
    466 void AutocompleteEditViewGtk::Update(const TabContents* contents) {
    467   // NOTE: We're getting the URL text here from the ToolbarModel.
    468   bool visibly_changed_permanent_text =
    469       model_->UpdatePermanentText(WideToUTF16Hack(toolbar_model_->GetText()));
    470 
    471   ToolbarModel::SecurityLevel security_level =
    472         toolbar_model_->GetSecurityLevel();
    473   bool changed_security_level = (security_level != security_level_);
    474   security_level_ = security_level;
    475 
    476   if (contents) {
    477     selected_text_.clear();
    478     RevertAll();
    479     const AutocompleteEditState* state =
    480         GetStateAccessor()->GetProperty(contents->property_bag());
    481     if (state) {
    482       model_->RestoreState(state->model_state);
    483 
    484       // Move the marks for the cursor and the other end of the selection to
    485       // the previously-saved offsets (but preserve PRIMARY).
    486       StartUpdatingHighlightedText();
    487       SetSelectedRange(state->view_state.selection_range);
    488       FinishUpdatingHighlightedText();
    489     }
    490   } else if (visibly_changed_permanent_text) {
    491     RevertAll();
    492     // TODO(deanm): There should be code to restore select all here.
    493   } else if (changed_security_level) {
    494     EmphasizeURLComponents();
    495   }
    496 }
    497 
    498 void AutocompleteEditViewGtk::OpenURL(const GURL& url,
    499                                       WindowOpenDisposition disposition,
    500                                       PageTransition::Type transition,
    501                                       const GURL& alternate_nav_url,
    502                                       size_t selected_line,
    503                                       const string16& keyword) {
    504   if (!url.is_valid())
    505     return;
    506 
    507   model_->OpenURL(url, disposition, transition, alternate_nav_url,
    508                   selected_line, keyword);
    509 }
    510 
    511 string16 AutocompleteEditViewGtk::GetText() const {
    512   GtkTextIter start, end;
    513   GetTextBufferBounds(&start, &end);
    514   gchar* utf8 = gtk_text_buffer_get_text(text_buffer_, &start, &end, false);
    515   string16 out(UTF8ToUTF16(utf8));
    516   g_free(utf8);
    517 
    518 #if GTK_CHECK_VERSION(2, 20, 0)
    519   // We need to treat the text currently being composed by the input method as
    520   // part of the text content, so that omnibox can work correctly in the middle
    521   // of composition.
    522   if (preedit_.size()) {
    523     GtkTextMark* mark = gtk_text_buffer_get_insert(text_buffer_);
    524     gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark);
    525     out.insert(gtk_text_iter_get_offset(&start), preedit_);
    526   }
    527 #endif
    528   return out;
    529 }
    530 
    531 bool AutocompleteEditViewGtk::IsEditingOrEmpty() const {
    532   return model_->user_input_in_progress() || (GetTextLength() == 0);
    533 }
    534 
    535 int AutocompleteEditViewGtk::GetIcon() const {
    536   return IsEditingOrEmpty() ?
    537       AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
    538       toolbar_model_->GetIcon();
    539 }
    540 
    541 void AutocompleteEditViewGtk::SetUserText(const string16& text) {
    542   SetUserText(text, text, true);
    543 }
    544 
    545 void AutocompleteEditViewGtk::SetUserText(const string16& text,
    546                                           const string16& display_text,
    547                                           bool update_popup) {
    548   model_->SetUserText(text);
    549   // TODO(deanm): something about selection / focus change here.
    550   SetWindowTextAndCaretPos(display_text, display_text.length());
    551   if (update_popup)
    552     UpdatePopup();
    553   TextChanged();
    554 }
    555 
    556 void AutocompleteEditViewGtk::SetWindowTextAndCaretPos(const string16& text,
    557                                                        size_t caret_pos) {
    558   CharRange range(static_cast<int>(caret_pos), static_cast<int>(caret_pos));
    559   SetTextAndSelectedRange(text, range);
    560 }
    561 
    562 void AutocompleteEditViewGtk::SetForcedQuery() {
    563   const string16 current_text(GetText());
    564   const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
    565   if (start == string16::npos || (current_text[start] != '?')) {
    566     SetUserText(ASCIIToUTF16("?"));
    567   } else {
    568     StartUpdatingHighlightedText();
    569     SetSelectedRange(CharRange(current_text.size(), start + 1));
    570     FinishUpdatingHighlightedText();
    571   }
    572 }
    573 
    574 bool AutocompleteEditViewGtk::IsSelectAll() {
    575   GtkTextIter sel_start, sel_end;
    576   gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end);
    577 
    578   GtkTextIter start, end;
    579   GetTextBufferBounds(&start, &end);
    580 
    581   // Returns true if the |text_buffer_| is empty.
    582   return gtk_text_iter_equal(&start, &sel_start) &&
    583       gtk_text_iter_equal(&end, &sel_end);
    584 }
    585 
    586 bool AutocompleteEditViewGtk::DeleteAtEndPressed() {
    587   return delete_at_end_pressed_;
    588 }
    589 
    590 void AutocompleteEditViewGtk::GetSelectionBounds(string16::size_type* start,
    591                                                  string16::size_type* end) {
    592   CharRange selection = GetSelection();
    593   *start = static_cast<size_t>(selection.cp_min);
    594   *end = static_cast<size_t>(selection.cp_max);
    595 }
    596 
    597 void AutocompleteEditViewGtk::SelectAll(bool reversed) {
    598   // SelectAll() is invoked as a side effect of other actions (e.g.  switching
    599   // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the
    600   // PRIMARY selection here.
    601   SelectAllInternal(reversed, false);
    602 }
    603 
    604 void AutocompleteEditViewGtk::RevertAll() {
    605   ClosePopup();
    606   model_->Revert();
    607   TextChanged();
    608 }
    609 
    610 void AutocompleteEditViewGtk::UpdatePopup() {
    611   model_->SetInputInProgress(true);
    612   if (!update_popup_without_focus_ && !model_->has_focus())
    613     return;
    614 
    615   // Don't inline autocomplete when the caret/selection isn't at the end of
    616   // the text, or in the middle of composition.
    617   CharRange sel = GetSelection();
    618   bool no_inline_autocomplete =
    619       std::max(sel.cp_max, sel.cp_min) < GetTextLength() || IsImeComposing();
    620   model_->StartAutocomplete(sel.cp_min != sel.cp_max, no_inline_autocomplete);
    621 }
    622 
    623 void AutocompleteEditViewGtk::ClosePopup() {
    624   model_->StopAutocomplete();
    625 }
    626 
    627 void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged(
    628     const string16& display_text,
    629     bool save_original_selection) {
    630   if (save_original_selection)
    631     saved_temporary_selection_ = GetSelection();
    632 
    633   StartUpdatingHighlightedText();
    634   SetWindowTextAndCaretPos(display_text, display_text.length());
    635   FinishUpdatingHighlightedText();
    636   TextChanged();
    637 }
    638 
    639 bool AutocompleteEditViewGtk::OnInlineAutocompleteTextMaybeChanged(
    640     const string16& display_text,
    641     size_t user_text_length) {
    642   if (display_text == GetText())
    643     return false;
    644 
    645   StartUpdatingHighlightedText();
    646   CharRange range(display_text.size(), user_text_length);
    647   SetTextAndSelectedRange(display_text, range);
    648   FinishUpdatingHighlightedText();
    649   TextChanged();
    650   return true;
    651 }
    652 
    653 void AutocompleteEditViewGtk::OnRevertTemporaryText() {
    654   StartUpdatingHighlightedText();
    655   SetSelectedRange(saved_temporary_selection_);
    656   FinishUpdatingHighlightedText();
    657   TextChanged();
    658 }
    659 
    660 void AutocompleteEditViewGtk::OnBeforePossibleChange() {
    661   // Record this paste, so we can do different behavior.
    662   if (paste_clipboard_requested_) {
    663     paste_clipboard_requested_ = false;
    664     model_->on_paste();
    665   }
    666 
    667   // This method will be called in HandleKeyPress() method just before
    668   // handling a key press event. So we should prevent it from being called
    669   // when handling the key press event.
    670   if (handling_key_press_)
    671     return;
    672 
    673   // Record our state.
    674   text_before_change_ = GetText();
    675   sel_before_change_ = GetSelection();
    676 #if GTK_CHECK_VERSION(2, 20, 0)
    677   preedit_size_before_change_ = preedit_.size();
    678 #endif
    679 }
    680 
    681 // TODO(deanm): This is mostly stolen from Windows, and will need some work.
    682 bool AutocompleteEditViewGtk::OnAfterPossibleChange() {
    683   // This method will be called in HandleKeyPress() method just after
    684   // handling a key press event. So we should prevent it from being called
    685   // when handling the key press event.
    686   if (handling_key_press_) {
    687     content_maybe_changed_by_key_press_ = true;
    688     return false;
    689   }
    690 
    691   // If the change is caused by an Enter key press event, and the event was not
    692   // handled by IME, then it's an unexpected change and shall be reverted here.
    693   // {Start|Finish}UpdatingHighlightedText() are called here to prevent the
    694   // PRIMARY selection from being changed.
    695   if (enter_was_pressed_ && enter_was_inserted_) {
    696     StartUpdatingHighlightedText();
    697     SetTextAndSelectedRange(text_before_change_, sel_before_change_);
    698     FinishUpdatingHighlightedText();
    699     return false;
    700   }
    701 
    702   const CharRange new_sel = GetSelection();
    703   const int length = GetTextLength();
    704   const bool selection_differs =
    705       ((new_sel.cp_min != new_sel.cp_max) ||
    706        (sel_before_change_.cp_min != sel_before_change_.cp_max)) &&
    707       ((new_sel.cp_min != sel_before_change_.cp_min) ||
    708        (new_sel.cp_max != sel_before_change_.cp_max));
    709   const bool at_end_of_edit =
    710       (new_sel.cp_min == length && new_sel.cp_max == length);
    711 
    712   // See if the text or selection have changed since OnBeforePossibleChange().
    713   const string16 new_text(GetText());
    714   text_changed_ = (new_text != text_before_change_);
    715 #if GTK_CHECK_VERSION(2, 20, 0)
    716   text_changed_ =
    717       text_changed_ || (preedit_.size() != preedit_size_before_change_);
    718 #endif
    719 
    720   if (text_changed_)
    721     AdjustTextJustification();
    722 
    723   // When the user has deleted text, we don't allow inline autocomplete.  Make
    724   // sure to not flag cases like selecting part of the text and then pasting
    725   // (or typing) the prefix of that selection.  (We detect these by making
    726   // sure the caret, which should be after any insertion, hasn't moved
    727   // forward of the old selection start.)
    728   const bool just_deleted_text =
    729       (text_before_change_.length() > new_text.length()) &&
    730       (new_sel.cp_min <= std::min(sel_before_change_.cp_min,
    731                                  sel_before_change_.cp_max));
    732 
    733   delete_at_end_pressed_ = false;
    734 
    735   const bool something_changed = model_->OnAfterPossibleChange(
    736       new_text, new_sel.selection_min(), new_sel.selection_max(),
    737       selection_differs, text_changed_, just_deleted_text,
    738       !IsImeComposing());
    739 
    740   // If only selection was changed, we don't need to call |controller_|'s
    741   // OnChanged() method, which is called in TextChanged().
    742   // But we still need to call EmphasizeURLComponents() to make sure the text
    743   // attributes are updated correctly.
    744   if (something_changed && text_changed_) {
    745     TextChanged();
    746   } else if (selection_differs) {
    747     EmphasizeURLComponents();
    748   } else if (delete_was_pressed_ && at_end_of_edit) {
    749     delete_at_end_pressed_ = true;
    750     model_->OnChanged();
    751   }
    752   delete_was_pressed_ = false;
    753 
    754   return something_changed;
    755 }
    756 
    757 gfx::NativeView AutocompleteEditViewGtk::GetNativeView() const {
    758   return alignment_.get();
    759 }
    760 
    761 CommandUpdater* AutocompleteEditViewGtk::GetCommandUpdater() {
    762   return command_updater_;
    763 }
    764 
    765 void AutocompleteEditViewGtk::SetInstantSuggestion(const string16& suggestion,
    766                                                    bool animate_to_complete) {
    767   std::string suggestion_utf8 = UTF16ToUTF8(suggestion);
    768 
    769   gtk_label_set_text(GTK_LABEL(instant_view_), suggestion_utf8.c_str());
    770 
    771   StopAnimation();
    772 
    773   if (suggestion.empty()) {
    774     gtk_widget_hide(instant_view_);
    775     return;
    776   }
    777   if (animate_to_complete
    778 #if GTK_CHECK_VERSION(2, 20, 0)
    779       && preedit_.empty()
    780 #endif
    781       ) {
    782     instant_animation_->set_delegate(this);
    783     instant_animation_->Start();
    784   }
    785 
    786   gtk_widget_show(instant_view_);
    787   AdjustVerticalAlignmentOfInstantView();
    788   UpdateInstantViewColors();
    789 }
    790 
    791 string16 AutocompleteEditViewGtk::GetInstantSuggestion() const {
    792   const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_));
    793   return suggestion ? UTF8ToUTF16(suggestion) : string16();
    794 }
    795 
    796 int AutocompleteEditViewGtk::TextWidth() const {
    797   // TextWidth may be called after gtk widget tree is destroyed but
    798   // before AutocompleteEditViewGtk gets deleted.  This is a safe guard
    799   // to avoid accessing |text_view_| that has already been destroyed.
    800   // See crbug.com/70192.
    801   if (!text_view_)
    802     return 0;
    803 
    804   int horizontal_border_size =
    805       gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_),
    806                                            GTK_TEXT_WINDOW_LEFT) +
    807       gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_),
    808                                            GTK_TEXT_WINDOW_RIGHT) +
    809       gtk_text_view_get_left_margin(GTK_TEXT_VIEW(text_view_)) +
    810       gtk_text_view_get_right_margin(GTK_TEXT_VIEW(text_view_));
    811 
    812   GtkTextIter start, end;
    813   GdkRectangle first_char_bounds, last_char_bounds;
    814   gtk_text_buffer_get_start_iter(text_buffer_, &start);
    815 
    816   // Use the real end iterator here to take the width of instant suggestion
    817   // text into account, so that location bar can layout its children correctly.
    818   gtk_text_buffer_get_end_iter(text_buffer_, &end);
    819   gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_),
    820                                   &start, &first_char_bounds);
    821   gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_),
    822                                   &end, &last_char_bounds);
    823 
    824   gint first_char_start = first_char_bounds.x;
    825   gint first_char_end = first_char_start + first_char_bounds.width;
    826   gint last_char_start = last_char_bounds.x;
    827   gint last_char_end = last_char_start + last_char_bounds.width;
    828 
    829   // bounds width could be negative for RTL text.
    830   if (first_char_start > first_char_end)
    831     std::swap(first_char_start, first_char_end);
    832   if (last_char_start > last_char_end)
    833     std::swap(last_char_start, last_char_end);
    834 
    835   gint text_width = first_char_start < last_char_start ?
    836       last_char_end - first_char_start : first_char_end - last_char_start;
    837 
    838   return text_width + horizontal_border_size;
    839 }
    840 
    841 bool AutocompleteEditViewGtk::IsImeComposing() const {
    842 #if GTK_CHECK_VERSION(2, 20, 0)
    843   return !preedit_.empty();
    844 #else
    845   return false;
    846 #endif
    847 }
    848 
    849 #if defined(TOOLKIT_VIEWS)
    850 views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) {
    851   views::NativeViewHost* host = new views::NativeViewHost;
    852   parent->AddChildView(host);
    853   host->set_focus_view(parent);
    854   host->Attach(GetNativeView());
    855   return host;
    856 }
    857 
    858 int AutocompleteEditViewGtk::OnPerformDrop(
    859     const views::DropTargetEvent& event) {
    860   string16 text;
    861   const ui::OSExchangeData& data = event.data();
    862   if (data.HasURL()) {
    863     GURL url;
    864     string16 title;
    865     if (data.GetURLAndTitle(&url, &title))
    866       text = UTF8ToUTF16(url.spec());
    867   } else {
    868     string16 data_string;
    869     if (data.GetString(&data_string))
    870       text = CollapseWhitespace(data_string, true);
    871   }
    872 
    873   if (!text.empty() && OnPerformDropImpl(text))
    874     return CopyOrLinkDragOperation(event.source_operations());
    875 
    876   return ui::DragDropTypes::DRAG_NONE;
    877 }
    878 
    879 // static
    880 AutocompleteEditView* AutocompleteEditViewGtk::Create(
    881     AutocompleteEditController* controller,
    882     ToolbarModel* toolbar_model,
    883     Profile* profile,
    884     CommandUpdater* command_updater,
    885     bool popup_window_mode,
    886     views::View* location_bar) {
    887   if (views::NativeTextfieldViews::IsTextfieldViewsEnabled()) {
    888     AutocompleteEditViewViews* autocomplete =
    889         new AutocompleteEditViewViews(controller,
    890                                       toolbar_model,
    891                                       profile,
    892                                       command_updater,
    893                                       popup_window_mode,
    894                                       location_bar);
    895     autocomplete->Init();
    896     return autocomplete;
    897   }
    898 
    899   AutocompleteEditViewGtk* autocomplete =
    900       new AutocompleteEditViewGtk(controller,
    901                                   toolbar_model,
    902                                   profile,
    903                                   command_updater,
    904                                   popup_window_mode,
    905                                   location_bar);
    906   autocomplete->Init();
    907 
    908   // Make all the children of the widget visible. NOTE: this won't display
    909   // anything, it just toggles the visible flag.
    910   gtk_widget_show_all(autocomplete->GetNativeView());
    911   // Hide the widget. NativeViewHostGtk will make it visible again as
    912   // necessary.
    913   gtk_widget_hide(autocomplete->GetNativeView());
    914 
    915   return autocomplete;
    916 }
    917 #endif
    918 
    919 void AutocompleteEditViewGtk::Observe(NotificationType type,
    920                                       const NotificationSource& source,
    921                                       const NotificationDetails& details) {
    922   DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
    923 
    924   SetBaseColor();
    925 }
    926 
    927 void AutocompleteEditViewGtk::AnimationEnded(const ui::Animation* animation) {
    928   model_->CommitSuggestedText(false);
    929 }
    930 
    931 void AutocompleteEditViewGtk::AnimationProgressed(
    932     const ui::Animation* animation) {
    933   UpdateInstantViewColors();
    934 }
    935 
    936 void AutocompleteEditViewGtk::AnimationCanceled(
    937     const ui::Animation* animation) {
    938   UpdateInstantViewColors();
    939 }
    940 
    941 void AutocompleteEditViewGtk::SetBaseColor() {
    942   DCHECK(text_view_);
    943 
    944 #if defined(TOOLKIT_VIEWS)
    945   bool use_gtk = false;
    946 #else
    947   bool use_gtk = theme_service_->UseGtkTheme();
    948 #endif
    949   if (use_gtk) {
    950     gtk_widget_modify_cursor(text_view_, NULL, NULL);
    951     gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, NULL);
    952     gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, NULL);
    953     gtk_widget_modify_text(text_view_, GTK_STATE_SELECTED, NULL);
    954     gtk_widget_modify_base(text_view_, GTK_STATE_ACTIVE, NULL);
    955     gtk_widget_modify_text(text_view_, GTK_STATE_ACTIVE, NULL);
    956 
    957     gtk_util::UndoForceFontSize(text_view_);
    958     gtk_util::UndoForceFontSize(instant_view_);
    959 
    960     // Grab the text colors out of the style and set our tags to use them.
    961     GtkStyle* style = gtk_rc_get_style(text_view_);
    962 
    963     // style may be unrealized at this point, so calculate the halfway point
    964     // between text[] and base[] manually instead of just using text_aa[].
    965     GdkColor average_color = gtk_util::AverageColors(
    966         style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
    967 
    968     g_object_set(faded_text_tag_, "foreground-gdk", &average_color, NULL);
    969     g_object_set(normal_text_tag_, "foreground-gdk",
    970                  &style->text[GTK_STATE_NORMAL], NULL);
    971   } else {
    972     const GdkColor* background_color_ptr;
    973 #if defined(TOOLKIT_VIEWS)
    974     const GdkColor background_color = gfx::SkColorToGdkColor(
    975         LocationBarView::GetColor(ToolbarModel::NONE,
    976                                   LocationBarView::BACKGROUND));
    977     background_color_ptr = &background_color;
    978 #else
    979     background_color_ptr = &LocationBarViewGtk::kBackgroundColor;
    980 #endif
    981     gtk_widget_modify_cursor(
    982         text_view_, &gtk_util::kGdkBlack, &gtk_util::kGdkGray);
    983     gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background_color_ptr);
    984 
    985 #if !defined(TOOLKIT_VIEWS)
    986     GdkColor c;
    987     // Override the selected colors so we don't leak colors from the current
    988     // gtk theme into the chrome-theme.
    989     c = gfx::SkColorToGdkColor(
    990         theme_service_->get_active_selection_bg_color());
    991     gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, &c);
    992 
    993     c = gfx::SkColorToGdkColor(
    994         theme_service_->get_active_selection_fg_color());
    995     gtk_widget_modify_text(text_view_, GTK_STATE_SELECTED, &c);
    996 
    997     c = gfx::SkColorToGdkColor(
    998         theme_service_->get_inactive_selection_bg_color());
    999     gtk_widget_modify_base(text_view_, GTK_STATE_ACTIVE, &c);
   1000 
   1001     c = gfx::SkColorToGdkColor(
   1002         theme_service_->get_inactive_selection_fg_color());
   1003     gtk_widget_modify_text(text_view_, GTK_STATE_ACTIVE, &c);
   1004 #endif
   1005 
   1006     // Until we switch to vector graphics, force the font size.
   1007     gtk_util::ForceFontSizePixels(text_view_, GetFont().GetFontSize());
   1008     gtk_util::ForceFontSizePixels(instant_view_, GetFont().GetFontSize());
   1009 
   1010     g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL);
   1011     g_object_set(normal_text_tag_, "foreground", "#000000", NULL);
   1012   }
   1013 
   1014   AdjustVerticalAlignmentOfInstantView();
   1015   UpdateInstantViewColors();
   1016 }
   1017 
   1018 void AutocompleteEditViewGtk::UpdateInstantViewColors() {
   1019   SkColor selection_text, selection_bg;
   1020   GdkColor faded_text, normal_bg;
   1021 
   1022 #if defined(TOOLKIT_VIEWS)
   1023   bool use_gtk = false;
   1024 #else
   1025   bool use_gtk = theme_service_->UseGtkTheme();
   1026 #endif
   1027 
   1028   if (use_gtk) {
   1029     GtkStyle* style = gtk_rc_get_style(instant_view_);
   1030 
   1031     faded_text = gtk_util::AverageColors(
   1032         style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
   1033     normal_bg = style->base[GTK_STATE_NORMAL];
   1034 
   1035     selection_text = gfx::GdkColorToSkColor(style->text[GTK_STATE_SELECTED]);
   1036     selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]);
   1037   } else {
   1038     gdk_color_parse(kTextBaseColor, &faded_text);
   1039 
   1040 #if defined(TOOLKIT_VIEWS)
   1041     normal_bg = gfx::SkColorToGdkColor(
   1042         LocationBarView::GetColor(ToolbarModel::NONE,
   1043                                   LocationBarView::BACKGROUND));
   1044     selection_text = LocationBarView::GetColor(
   1045         ToolbarModel::NONE, LocationBarView::SELECTED_TEXT);
   1046 
   1047     GtkStyle* style = gtk_rc_get_style(instant_view_);
   1048     selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]);
   1049 #else
   1050     normal_bg = LocationBarViewGtk::kBackgroundColor;
   1051     selection_text =
   1052         theme_service_->get_active_selection_fg_color();
   1053     selection_bg =
   1054         theme_service_->get_active_selection_bg_color();
   1055 #endif
   1056   }
   1057 
   1058   double alpha = instant_animation_->is_animating() ?
   1059       instant_animation_->GetCurrentValue() : 0.0;
   1060   GdkColor text = gfx::SkColorToGdkColor(color_utils::AlphaBlend(
   1061       selection_text,
   1062       gfx::GdkColorToSkColor(faded_text),
   1063       alpha * 0xff));
   1064   GdkColor bg = gfx::SkColorToGdkColor(color_utils::AlphaBlend(
   1065       selection_bg,
   1066       gfx::GdkColorToSkColor(normal_bg),
   1067       alpha * 0xff));
   1068 
   1069   if (alpha > 0.0) {
   1070     gtk_label_select_region(GTK_LABEL(instant_view_), 0, -1);
   1071     // ACTIVE is the state for text that is selected, but not focused.
   1072     gtk_widget_modify_text(instant_view_, GTK_STATE_ACTIVE, &text);
   1073     gtk_widget_modify_base(instant_view_, GTK_STATE_ACTIVE, &bg);
   1074   } else {
   1075     // When the text is unselected, fg is used for text color, the state
   1076     // is NORMAL, and the background is transparent.
   1077     gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &text);
   1078   }
   1079 }
   1080 
   1081 void AutocompleteEditViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) {
   1082   OnBeforePossibleChange();
   1083 }
   1084 
   1085 void AutocompleteEditViewGtk::HandleEndUserAction(GtkTextBuffer* sender) {
   1086   OnAfterPossibleChange();
   1087 }
   1088 
   1089 gboolean AutocompleteEditViewGtk::HandleKeyPress(GtkWidget* widget,
   1090                                                  GdkEventKey* event) {
   1091   // Background of this piece of complicated code:
   1092   // The omnibox supports several special behaviors which may be triggered by
   1093   // certain key events:
   1094   // Tab to search - triggered by Tab key
   1095   // Accept input - triggered by Enter key
   1096   // Revert input - triggered by Escape key
   1097   //
   1098   // Because we use a GtkTextView object |text_view_| for text input, we need
   1099   // send all key events to |text_view_| before handling them, to make sure
   1100   // IME works without any problem. So here, we intercept "key-press-event"
   1101   // signal of |text_view_| object and call its default handler to handle the
   1102   // key event first.
   1103   //
   1104   // Then if the key event is one of Tab, Enter and Escape, we need to trigger
   1105   // the corresponding special behavior if IME did not handle it.
   1106   // For Escape key, if the default signal handler returns FALSE, then we know
   1107   // it's not handled by IME.
   1108   //
   1109   // For Tab key, as "accepts-tab" property of |text_view_| is set to FALSE,
   1110   // if IME did not handle it then "move-focus" signal will be emitted by the
   1111   // default signal handler of |text_view_|. So we can intercept "move-focus"
   1112   // signal of |text_view_| to know if a Tab key press event was handled by IME,
   1113   // and trigger Tab to search behavior when necessary in the signal handler.
   1114   //
   1115   // But for Enter key, if IME did not handle the key event, the default signal
   1116   // handler will delete current selection range and insert '\n' and always
   1117   // return TRUE. We need to prevent |text_view_| from performing this default
   1118   // action if IME did not handle the key event, because we don't want the
   1119   // content of omnibox to be changed before triggering our special behavior.
   1120   // Otherwise our special behavior would not be performed correctly.
   1121   //
   1122   // But there is no way for us to prevent GtkTextView from handling the key
   1123   // event and performing built-in operation. So in order to achieve our goal,
   1124   // "insert-text" signal of |text_buffer_| object is intercepted, and
   1125   // following actions are done in the signal handler:
   1126   // - If there is only one character in inserted text, and it's '\n' or '\r',
   1127   //   then set |enter_was_inserted_| to true.
   1128   // - Filter out all new line and tab characters.
   1129   //
   1130   // So if |enter_was_inserted_| is true after calling |text_view_|'s default
   1131   // signal handler against an Enter key press event, then we know that the
   1132   // Enter key press event was handled by GtkTextView rather than IME, and can
   1133   // perform the special behavior for Enter key safely.
   1134   //
   1135   // Now the last thing is to prevent the content of omnibox from being changed
   1136   // by GtkTextView when Enter key is pressed. As OnBeforePossibleChange() and
   1137   // OnAfterPossibleChange() will be called by GtkTextView before and after
   1138   // changing the content, and the content is already saved in
   1139   // OnBeforePossibleChange(), so if the Enter key press event was not handled
   1140   // by IME, it's easy to restore the content in OnAfterPossibleChange(), as if
   1141   // it's not changed at all.
   1142 
   1143   GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(widget);
   1144 
   1145   enter_was_pressed_ = event->keyval == GDK_Return ||
   1146                        event->keyval == GDK_ISO_Enter ||
   1147                        event->keyval == GDK_KP_Enter;
   1148 
   1149   // Set |tab_was_pressed_| to true if it's a Tab key press event, so that our
   1150   // handler of "move-focus" signal can trigger Tab to search behavior when
   1151   // necessary.
   1152   tab_was_pressed_ = (event->keyval == GDK_Tab ||
   1153                       event->keyval == GDK_ISO_Left_Tab ||
   1154                       event->keyval == GDK_KP_Tab) &&
   1155                      !(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
   1156 
   1157   delete_was_pressed_ = event->keyval == GDK_Delete ||
   1158                         event->keyval == GDK_KP_Delete;
   1159 
   1160   // Reset |enter_was_inserted_|, which may be set in the "insert-text" signal
   1161   // handler, so that we'll know if an Enter key event was handled by IME.
   1162   enter_was_inserted_ = false;
   1163 
   1164   // Reset |paste_clipboard_requested_| to make sure we won't misinterpret this
   1165   // key input action as a paste action.
   1166   paste_clipboard_requested_ = false;
   1167 
   1168   // Reset |text_changed_| before passing the key event on to the text view.
   1169   text_changed_ = false;
   1170 
   1171   OnBeforePossibleChange();
   1172   handling_key_press_ = true;
   1173   content_maybe_changed_by_key_press_ = false;
   1174 
   1175   // Call the default handler, so that IME can work as normal.
   1176   // New line characters will be filtered out by our "insert-text"
   1177   // signal handler attached to |text_buffer_| object.
   1178   gboolean result = klass->key_press_event(widget, event);
   1179 
   1180   handling_key_press_ = false;
   1181   if (content_maybe_changed_by_key_press_)
   1182     OnAfterPossibleChange();
   1183 
   1184   // Set |tab_was_pressed_| to false, to make sure Tab to search behavior can
   1185   // only be triggered by pressing Tab key.
   1186   tab_was_pressed_ = false;
   1187 
   1188   if (enter_was_pressed_ && enter_was_inserted_) {
   1189     bool alt_held = (event->state & GDK_MOD1_MASK);
   1190     model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false);
   1191     result = TRUE;
   1192   } else if (!result && event->keyval == GDK_Escape &&
   1193              (event->state & gtk_accelerator_get_default_mod_mask()) == 0) {
   1194     // We can handle the Escape key if |text_view_| did not handle it.
   1195     // If it's not handled by us, then we need to propagate it up to the parent
   1196     // widgets, so that Escape accelerator can still work.
   1197     result = model_->OnEscapeKeyPressed();
   1198   } else if (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R) {
   1199     // Omnibox2 can switch its contents while pressing a control key. To switch
   1200     // the contents of omnibox2, we notify the AutocompleteEditModel class when
   1201     // the control-key state is changed.
   1202     model_->OnControlKeyChanged(true);
   1203   } else if (!text_changed_ && event->keyval == GDK_Delete &&
   1204              event->state & GDK_SHIFT_MASK) {
   1205     // If shift+del didn't change the text, we let this delete an entry from
   1206     // the popup.  We can't check to see if the IME handled it because even if
   1207     // nothing is selected, the IME or the TextView still report handling it.
   1208     if (model_->popup_model()->IsOpen())
   1209       model_->popup_model()->TryDeletingCurrentItem();
   1210   }
   1211 
   1212   // Set |enter_was_pressed_| to false, to make sure OnAfterPossibleChange() can
   1213   // act as normal for changes made by other events.
   1214   enter_was_pressed_ = false;
   1215 
   1216   // If the key event is not handled by |text_view_| or us, then we need to
   1217   // propagate the key event up to parent widgets by returning FALSE.
   1218   // In this case we need to stop the signal emission explicitly to prevent the
   1219   // default "key-press-event" handler of |text_view_| from being called again.
   1220   if (!result) {
   1221     static guint signal_id =
   1222         g_signal_lookup("key-press-event", GTK_TYPE_WIDGET);
   1223     g_signal_stop_emission(widget, signal_id, 0);
   1224   }
   1225 
   1226 #if defined(TOOLKIT_VIEWS)
   1227   location_bar_view_->GetWidget()->NotifyAccessibilityEvent(
   1228       location_bar_view_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
   1229 #endif
   1230 
   1231   return result;
   1232 }
   1233 
   1234 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget,
   1235                                                    GdkEventKey* event) {
   1236   // Omnibox2 can switch its contents while pressing a control key. To switch
   1237   // the contents of omnibox2, we notify the AutocompleteEditModel class when
   1238   // the control-key state is changed.
   1239   if (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R) {
   1240     // Round trip to query the control state after the release.  This allows
   1241     // you to release one control key while still holding another control key.
   1242     GdkDisplay* display = gdk_drawable_get_display(event->window);
   1243     GdkModifierType mod;
   1244     gdk_display_get_pointer(display, NULL, NULL, NULL, &mod);
   1245     if (!(mod & GDK_CONTROL_MASK))
   1246       model_->OnControlKeyChanged(false);
   1247   }
   1248 
   1249   // Even though we handled the press ourselves, let GtkTextView handle the
   1250   // release.  It shouldn't do anything particularly interesting, but it will
   1251   // handle the IME work for us.
   1252   return FALSE;  // Propagate into GtkTextView.
   1253 }
   1254 
   1255 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GtkWidget* sender,
   1256                                                         GdkEventButton* event) {
   1257   // We don't need to care about double and triple clicks.
   1258   if (event->type != GDK_BUTTON_PRESS)
   1259     return FALSE;
   1260 
   1261   DCHECK(text_view_);
   1262 
   1263   if (event->button == 1) {
   1264 #if defined(OS_CHROMEOS)
   1265     // When the first button is pressed, track some stuff that will help us
   1266     // determine whether we should select all of the text when the button is
   1267     // released.
   1268     button_1_pressed_ = true;
   1269     text_view_focused_before_button_press_ = GTK_WIDGET_HAS_FOCUS(text_view_);
   1270     text_selected_during_click_ = false;
   1271 #endif
   1272 
   1273     // Button press event may change the selection, we need to record the change
   1274     // and report it to |model_| later when button is released.
   1275     OnBeforePossibleChange();
   1276   } else if (event->button == 2) {
   1277     // GtkTextView pastes PRIMARY selection with middle click.
   1278     // We can't call model_->on_paste_replacing_all() here, because the actual
   1279     // paste clipboard action may not be performed if the clipboard is empty.
   1280     paste_clipboard_requested_ = true;
   1281   }
   1282   return FALSE;
   1283 }
   1284 
   1285 gboolean AutocompleteEditViewGtk::HandleViewButtonRelease(
   1286     GtkWidget* sender, GdkEventButton* event) {
   1287   if (event->button != 1)
   1288     return FALSE;
   1289 
   1290   DCHECK(text_view_);
   1291 
   1292 #if defined(OS_CHROMEOS)
   1293   button_1_pressed_ = false;
   1294 #endif
   1295 
   1296   // Call the GtkTextView default handler, ignoring the fact that it will
   1297   // likely have told us to stop propagating.  We want to handle selection.
   1298   GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(text_view_);
   1299   klass->button_release_event(text_view_, event);
   1300 
   1301 #if defined(OS_CHROMEOS)
   1302   if (!text_view_focused_before_button_press_ && !text_selected_during_click_) {
   1303     // If this was a focusing click and the user didn't drag to highlight any
   1304     // text, select the full input and update the PRIMARY selection.
   1305     SelectAllInternal(false, true);
   1306 
   1307     // So we told the buffer where the cursor should be, but make sure to tell
   1308     // the view so it can scroll it to be visible if needed.
   1309     // NOTE: This function doesn't seem to like a count of 0, looking at the
   1310     // code it will skip an important loop.  Use -1 to achieve the same.
   1311     GtkTextIter start, end;
   1312     GetTextBufferBounds(&start, &end);
   1313     gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1);
   1314   }
   1315 #endif
   1316 
   1317   // Inform |model_| about possible text selection change.
   1318   OnAfterPossibleChange();
   1319 
   1320   return TRUE;  // Don't continue, we called the default handler already.
   1321 }
   1322 
   1323 gboolean AutocompleteEditViewGtk::HandleViewFocusIn(GtkWidget* sender,
   1324                                                     GdkEventFocus* event) {
   1325   DCHECK(text_view_);
   1326   update_popup_without_focus_ = false;
   1327 
   1328   GdkModifierType modifiers;
   1329   gdk_window_get_pointer(text_view_->window, NULL, NULL, &modifiers);
   1330   model_->OnSetFocus((modifiers & GDK_CONTROL_MASK) != 0);
   1331   controller_->OnSetFocus();
   1332   // TODO(deanm): Some keyword hit business, etc here.
   1333 
   1334   g_signal_connect(
   1335       gdk_keymap_get_for_display(gtk_widget_get_display(text_view_)),
   1336       "direction-changed",
   1337       G_CALLBACK(&HandleKeymapDirectionChangedThunk), this);
   1338 
   1339   AdjustTextJustification();
   1340 
   1341   return FALSE;  // Continue propagation.
   1342 }
   1343 
   1344 gboolean AutocompleteEditViewGtk::HandleViewFocusOut(GtkWidget* sender,
   1345                                                      GdkEventFocus* event) {
   1346   DCHECK(text_view_);
   1347   GtkWidget* view_getting_focus = NULL;
   1348   GtkWindow* toplevel = platform_util::GetTopLevel(sender);
   1349   if (gtk_window_is_active(toplevel))
   1350     view_getting_focus = going_to_focus_;
   1351 
   1352   // This must be invoked before ClosePopup.
   1353   model_->OnWillKillFocus(view_getting_focus);
   1354 
   1355   // Close the popup.
   1356   ClosePopup();
   1357   // Tell the model to reset itself.
   1358   model_->OnKillFocus();
   1359   controller_->OnKillFocus();
   1360 
   1361   g_signal_handlers_disconnect_by_func(
   1362       gdk_keymap_get_for_display(gtk_widget_get_display(text_view_)),
   1363       reinterpret_cast<gpointer>(&HandleKeymapDirectionChangedThunk), this);
   1364 
   1365   return FALSE;  // Pass the event on to the GtkTextView.
   1366 }
   1367 
   1368 void AutocompleteEditViewGtk::HandleViewMoveCursor(
   1369     GtkWidget* sender,
   1370     GtkMovementStep step,
   1371     gint count,
   1372     gboolean extend_selection) {
   1373   DCHECK(text_view_);
   1374   GtkTextIter sel_start, sel_end;
   1375   gboolean has_selection =
   1376       gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end);
   1377   bool handled = false;
   1378 
   1379   if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection &&
   1380       (count == 1 || count == -1)) {
   1381     // We need to take the content direction into account when handling cursor
   1382     // movement, because the behavior of Left and Right key will be inverted if
   1383     // the direction is RTL. Although we should check the direction around the
   1384     // input caret, it's much simpler and good enough to check whole content's
   1385     // direction.
   1386     PangoDirection content_dir = GetContentDirection();
   1387     gint count_towards_end = content_dir == PANGO_DIRECTION_RTL ? -1 : 1;
   1388 
   1389     // We want the GtkEntry behavior when you move the cursor while you have a
   1390     // selection.  GtkTextView just drops the selection and moves the cursor,
   1391     // but instead we want to move the cursor to the appropiate end of the
   1392     // selection.
   1393     if (has_selection) {
   1394       // We have a selection and start / end are in ascending order.
   1395       // Cursor placement will remove the selection, so we need inform
   1396       // |model_| about this change by
   1397       // calling On{Before|After}PossibleChange() methods.
   1398       OnBeforePossibleChange();
   1399       gtk_text_buffer_place_cursor(
   1400           text_buffer_, count == count_towards_end ? &sel_end : &sel_start);
   1401       OnAfterPossibleChange();
   1402       handled = true;
   1403     } else if (count == count_towards_end && !IsCaretAtEnd()) {
   1404       handled = model_->CommitSuggestedText(true);
   1405     }
   1406   } else if (step == GTK_MOVEMENT_PAGES) {  // Page up and down.
   1407     // Multiply by count for the direction (if we move too much that's ok).
   1408     model_->OnUpOrDownKeyPressed(model_->result().size() * count);
   1409     handled = true;
   1410   } else if (step == GTK_MOVEMENT_DISPLAY_LINES) {  // Arrow up and down.
   1411     model_->OnUpOrDownKeyPressed(count);
   1412     handled = true;
   1413   }
   1414 
   1415   if (!handled) {
   1416     // Cursor movement may change the selection, we need to record the change
   1417     // and report it to |model_|.
   1418     if (has_selection || extend_selection)
   1419       OnBeforePossibleChange();
   1420 
   1421     // Propagate into GtkTextView
   1422     GtkTextViewClass* klass = GTK_TEXT_VIEW_GET_CLASS(text_view_);
   1423     klass->move_cursor(GTK_TEXT_VIEW(text_view_), step, count,
   1424                        extend_selection);
   1425 
   1426     if (has_selection || extend_selection)
   1427       OnAfterPossibleChange();
   1428   }
   1429 
   1430   // move-cursor doesn't use a signal accumulator on the return value (it
   1431   // just ignores then), so we have to stop the propagation.
   1432   static guint signal_id = g_signal_lookup("move-cursor", GTK_TYPE_TEXT_VIEW);
   1433   g_signal_stop_emission(text_view_, signal_id, 0);
   1434 }
   1435 
   1436 void AutocompleteEditViewGtk::HandleViewSizeRequest(GtkWidget* sender,
   1437                                                     GtkRequisition* req) {
   1438   // Don't force a minimum width, but use the font-relative height.  This is a
   1439   // run-first handler, so the default handler was already called.
   1440   req->width = 1;
   1441 }
   1442 
   1443 void AutocompleteEditViewGtk::HandlePopupMenuDeactivate(GtkWidget* sender) {
   1444   // When the context menu appears, |text_view_|'s focus is lost. After an item
   1445   // is activated, the focus comes back to |text_view_|, but only after the
   1446   // check in UpdatePopup(). We set this flag to make UpdatePopup() aware that
   1447   // it will be receiving focus again.
   1448   if (!model_->has_focus())
   1449     update_popup_without_focus_ = true;
   1450 }
   1451 
   1452 void AutocompleteEditViewGtk::HandlePopulatePopup(GtkWidget* sender,
   1453                                                   GtkMenu* menu) {
   1454   GtkWidget* separator = gtk_separator_menu_item_new();
   1455   gtk_menu_shell_append(GTK_MENU_SHELL(menu), separator);
   1456   gtk_widget_show(separator);
   1457 
   1458   // Search Engine menu item.
   1459   GtkWidget* search_engine_menuitem = gtk_menu_item_new_with_mnemonic(
   1460       gfx::ConvertAcceleratorsFromWindowsStyle(
   1461           l10n_util::GetStringUTF8(IDS_EDIT_SEARCH_ENGINES)).c_str());
   1462   gtk_menu_shell_append(GTK_MENU_SHELL(menu), search_engine_menuitem);
   1463   g_signal_connect(search_engine_menuitem, "activate",
   1464                    G_CALLBACK(HandleEditSearchEnginesThunk), this);
   1465   gtk_widget_set_sensitive(search_engine_menuitem,
   1466       command_updater_->IsCommandEnabled(IDC_EDIT_SEARCH_ENGINES));
   1467   gtk_widget_show(search_engine_menuitem);
   1468 
   1469   // We need to update the paste and go controller before we know what text
   1470   // to show. We could do this all asynchronously, but it would be elaborate
   1471   // because we'd have to account for multiple menus showing, getting called
   1472   // back after shutdown, and similar issues.
   1473   GtkClipboard* x_clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
   1474   gchar* text = gtk_clipboard_wait_for_text(x_clipboard);
   1475   string16 text_wstr = UTF8ToUTF16(text ? text : "");
   1476   g_free(text);
   1477 
   1478   // Paste and Go menu item.
   1479   GtkWidget* paste_go_menuitem = gtk_menu_item_new_with_mnemonic(
   1480       gfx::ConvertAcceleratorsFromWindowsStyle(
   1481           l10n_util::GetStringUTF8(model_->is_paste_and_search() ?
   1482               IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO)).c_str());
   1483   gtk_menu_shell_append(GTK_MENU_SHELL(menu), paste_go_menuitem);
   1484   g_signal_connect(paste_go_menuitem, "activate",
   1485                    G_CALLBACK(HandlePasteAndGoThunk), this);
   1486   gtk_widget_set_sensitive(paste_go_menuitem,
   1487                            model_->CanPasteAndGo(text_wstr));
   1488   gtk_widget_show(paste_go_menuitem);
   1489 
   1490   g_signal_connect(menu, "deactivate",
   1491                    G_CALLBACK(HandlePopupMenuDeactivateThunk), this);
   1492 }
   1493 
   1494 void AutocompleteEditViewGtk::HandleEditSearchEngines(GtkWidget* sender) {
   1495   command_updater_->ExecuteCommand(IDC_EDIT_SEARCH_ENGINES);
   1496 }
   1497 
   1498 void AutocompleteEditViewGtk::HandlePasteAndGo(GtkWidget* sender) {
   1499   model_->PasteAndGo();
   1500 }
   1501 
   1502 void AutocompleteEditViewGtk::HandleMarkSet(GtkTextBuffer* buffer,
   1503                                             GtkTextIter* location,
   1504                                             GtkTextMark* mark) {
   1505   if (!text_buffer_ || buffer != text_buffer_)
   1506     return;
   1507 
   1508   if (mark != gtk_text_buffer_get_insert(text_buffer_) &&
   1509       mark != gtk_text_buffer_get_selection_bound(text_buffer_)) {
   1510     return;
   1511   }
   1512 
   1513   StopAnimation();
   1514 
   1515   // If we are here, that means the user may be changing the selection
   1516   selection_suggested_ = false;
   1517 
   1518   // Get the currently-selected text, if there is any.
   1519   std::string new_selected_text = GetSelectedText();
   1520 
   1521 #if defined(OS_CHROMEOS)
   1522   // If the user just selected some text with the mouse (or at least while the
   1523   // mouse button was down), make sure that we won't blow their selection away
   1524   // later by selecting all of the text when the button is released.
   1525   if (button_1_pressed_ && !new_selected_text.empty())
   1526     text_selected_during_click_ = true;
   1527 #endif
   1528 
   1529   // If we had some text selected earlier but it's no longer highlighted, we
   1530   // might need to save it now...
   1531   if (!selected_text_.empty() && new_selected_text.empty()) {
   1532     // ... but only if we currently own the selection.  We want to manually
   1533     // update the selection when the text is unhighlighted because the user
   1534     // clicked in a blank area of the text view, but not when it's unhighlighted
   1535     // because another client or widget took the selection.  (This handler gets
   1536     // called before the default handler, so as long as nobody else took the
   1537     // selection, the text buffer still owns it even if GTK is about to take it
   1538     // away in the default handler.)
   1539     GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
   1540     if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_))
   1541       SavePrimarySelection(selected_text_);
   1542   }
   1543 
   1544   selected_text_ = new_selected_text;
   1545 }
   1546 
   1547 // Override the primary selection the text buffer has set. This has to happen
   1548 // after the default handler for the "mark-set" signal.
   1549 void AutocompleteEditViewGtk::HandleMarkSetAfter(GtkTextBuffer* buffer,
   1550                                                  GtkTextIter* location,
   1551                                                  GtkTextMark* mark) {
   1552   if (!text_buffer_ || buffer != text_buffer_)
   1553     return;
   1554 
   1555   // We should only update primary selection when the user changes the selection
   1556   // range.
   1557   if (mark != gtk_text_buffer_get_insert(text_buffer_) &&
   1558       mark != gtk_text_buffer_get_selection_bound(text_buffer_)) {
   1559     return;
   1560   }
   1561 
   1562   UpdatePrimarySelectionIfValidURL();
   1563 }
   1564 
   1565 // Just use the default behavior for DnD, except if the drop can be a PasteAndGo
   1566 // then override.
   1567 void AutocompleteEditViewGtk::HandleDragDataReceived(
   1568     GtkWidget* sender, GdkDragContext* context, gint x, gint y,
   1569     GtkSelectionData* selection_data, guint target_type, guint time) {
   1570   DCHECK(text_view_);
   1571 
   1572   // Reset |paste_clipboard_requested_| to make sure we won't misinterpret this
   1573   // drop action as a paste action.
   1574   paste_clipboard_requested_ = false;
   1575 
   1576   // Don't try to PasteAndGo on drops originating from this omnibox. However, do
   1577   // allow default behavior for such drags.
   1578   if (context->source_window == text_view_->window)
   1579     return;
   1580 
   1581   guchar* text = gtk_selection_data_get_text(selection_data);
   1582   if (!text)
   1583     return;
   1584 
   1585   string16 possible_url = UTF8ToUTF16(reinterpret_cast<char*>(text));
   1586   g_free(text);
   1587   if (OnPerformDropImpl(possible_url)) {
   1588     gtk_drag_finish(context, TRUE, TRUE, time);
   1589 
   1590     static guint signal_id =
   1591         g_signal_lookup("drag-data-received", GTK_TYPE_WIDGET);
   1592     g_signal_stop_emission(text_view_, signal_id, 0);
   1593   }
   1594 }
   1595 
   1596 void AutocompleteEditViewGtk::HandleDragDataGet(
   1597     GtkWidget* widget,
   1598     GdkDragContext* context,
   1599     GtkSelectionData* selection_data,
   1600     guint target_type,
   1601     guint time) {
   1602   DCHECK(text_view_);
   1603   // If GTK put the normal textual version of the selection in our drag data,
   1604   // put our doctored selection that might have the 'http://' prefix. Also, GTK
   1605   // is confused about signedness of its datatypes, leading to the weird switch
   1606   // statement (no set of casts fixes this).
   1607   switch (target_type) {
   1608     case GTK_TEXT_BUFFER_TARGET_INFO_TEXT: {
   1609       gtk_selection_data_set_text(selection_data, selected_text_.c_str(), -1);
   1610     }
   1611   }
   1612 }
   1613 
   1614 void AutocompleteEditViewGtk::HandleInsertText(
   1615     GtkTextBuffer* buffer, GtkTextIter* location, const gchar* text, gint len) {
   1616   std::string filtered_text;
   1617   filtered_text.reserve(len);
   1618 
   1619   // Filter out new line and tab characters.
   1620   // |text| is guaranteed to be a valid UTF-8 string, so we don't need to
   1621   // validate it here.
   1622   //
   1623   // If there was only a single character, then it might be generated by a key
   1624   // event. In this case, we save the single character to help our
   1625   // "key-press-event" signal handler distinguish if an Enter key event is
   1626   // handled by IME or not.
   1627   if (len == 1 && (text[0] == '\n' || text[0] == '\r'))
   1628     enter_was_inserted_ = true;
   1629 
   1630   const gchar* p = text;
   1631   while (*p && (p - text) < len) {
   1632     gunichar c = g_utf8_get_char(p);
   1633     const gchar* next = g_utf8_next_char(p);
   1634 
   1635     // 0x200B is Zero Width Space, which is inserted just before the instant
   1636     // anchor for working around the GtkTextView's misalignment bug.
   1637     // This character might be captured and inserted into the content by undo
   1638     // manager, so we need to filter it out here.
   1639     if (c != L'\n' && c != L'\r' && c != L'\t' && c != 0x200B)
   1640       filtered_text.append(p, next);
   1641 
   1642     p = next;
   1643   }
   1644 
   1645   if (filtered_text.length()) {
   1646     // Avoid inserting the text after the instant anchor.
   1647     ValidateTextBufferIter(location);
   1648 
   1649     // Call the default handler to insert filtered text.
   1650     GtkTextBufferClass* klass = GTK_TEXT_BUFFER_GET_CLASS(buffer);
   1651     klass->insert_text(buffer, location, filtered_text.data(),
   1652                        static_cast<gint>(filtered_text.length()));
   1653   }
   1654 
   1655   // Stop propagating the signal emission to prevent the default handler from
   1656   // being called again.
   1657   static guint signal_id = g_signal_lookup("insert-text", GTK_TYPE_TEXT_BUFFER);
   1658   g_signal_stop_emission(buffer, signal_id, 0);
   1659 }
   1660 
   1661 void AutocompleteEditViewGtk::HandleBackSpace(GtkWidget* sender) {
   1662   // Checks if it's currently in keyword search mode.
   1663   if (model_->is_keyword_hint() || model_->keyword().empty())
   1664     return;  // Propgate into GtkTextView.
   1665 
   1666   DCHECK(text_view_);
   1667 
   1668   GtkTextIter sel_start, sel_end;
   1669   // Checks if there is some text selected.
   1670   if (gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end))
   1671     return;  // Propgate into GtkTextView.
   1672 
   1673   GtkTextIter start;
   1674   gtk_text_buffer_get_start_iter(text_buffer_, &start);
   1675 
   1676   if (!gtk_text_iter_equal(&start, &sel_start))
   1677     return;  // Propgate into GtkTextView.
   1678 
   1679   // We're showing a keyword and the user pressed backspace at the beginning
   1680   // of the text. Delete the selected keyword.
   1681   model_->ClearKeyword(GetText());
   1682 
   1683   // Stop propagating the signal emission into GtkTextView.
   1684   static guint signal_id = g_signal_lookup("backspace", GTK_TYPE_TEXT_VIEW);
   1685   g_signal_stop_emission(text_view_, signal_id, 0);
   1686 }
   1687 
   1688 void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget,
   1689                                                   GtkDirectionType direction) {
   1690   if (!tab_was_pressed_)
   1691     return;
   1692 
   1693   // If special behavior is triggered, then stop the signal emission to
   1694   // prevent the focus from being moved.
   1695   bool handled = false;
   1696 
   1697   // Trigger Tab to search behavior only when Tab key is pressed.
   1698   if (model_->is_keyword_hint())
   1699     handled = model_->AcceptKeyword();
   1700 
   1701 #if GTK_CHECK_VERSION(2, 20, 0)
   1702   if (!handled && !preedit_.empty())
   1703     handled = true;
   1704 #endif
   1705 
   1706   if (!handled && GTK_WIDGET_VISIBLE(instant_view_))
   1707     handled = model_->CommitSuggestedText(true);
   1708 
   1709   if (!handled) {
   1710     if (!IsCaretAtEnd()) {
   1711       OnBeforePossibleChange();
   1712       PlaceCaretAt(GetTextLength());
   1713       OnAfterPossibleChange();
   1714       handled = true;
   1715     }
   1716   }
   1717 
   1718   if (!handled)
   1719     handled = model_->AcceptCurrentInstantPreview();
   1720 
   1721   if (handled) {
   1722     static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET);
   1723     g_signal_stop_emission(widget, signal_id, 0);
   1724   }
   1725 }
   1726 
   1727 void AutocompleteEditViewGtk::HandleCopyClipboard(GtkWidget* sender) {
   1728   HandleCopyOrCutClipboard(true);
   1729 }
   1730 
   1731 void AutocompleteEditViewGtk::HandleCutClipboard(GtkWidget* sender) {
   1732   HandleCopyOrCutClipboard(false);
   1733 }
   1734 
   1735 void AutocompleteEditViewGtk::HandleCopyOrCutClipboard(bool copy) {
   1736   DCHECK(text_view_);
   1737 
   1738   // On copy or cut, we manually update the PRIMARY selection to contain the
   1739   // highlighted text.  This matches Firefox -- we highlight the URL but don't
   1740   // update PRIMARY on Ctrl-L, so Ctrl-L, Ctrl-C and then middle-click is a
   1741   // convenient way to paste the current URL somewhere.
   1742   if (!gtk_text_buffer_get_has_selection(text_buffer_))
   1743     return;
   1744 
   1745   GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
   1746   DCHECK(clipboard);
   1747   if (!clipboard)
   1748     return;
   1749 
   1750   CharRange selection = GetSelection();
   1751   GURL url;
   1752   string16 text(UTF8ToUTF16(GetSelectedText()));
   1753   bool write_url;
   1754   model_->AdjustTextForCopy(selection.selection_min(), IsSelectAll(), &text,
   1755                             &url, &write_url);
   1756 
   1757   if (write_url) {
   1758     BookmarkNodeData data;
   1759     data.ReadFromTuple(url, text);
   1760     data.WriteToClipboard(NULL);
   1761 
   1762     // Stop propagating the signal.
   1763     static guint copy_signal_id =
   1764         g_signal_lookup("copy-clipboard", GTK_TYPE_TEXT_VIEW);
   1765     static guint cut_signal_id =
   1766         g_signal_lookup("cut-clipboard", GTK_TYPE_TEXT_VIEW);
   1767     g_signal_stop_emission(text_view_,
   1768                            copy ? copy_signal_id : cut_signal_id,
   1769                            0);
   1770 
   1771     if (!copy && gtk_text_view_get_editable(GTK_TEXT_VIEW(text_view_)))
   1772       gtk_text_buffer_delete_selection(text_buffer_, true, true);
   1773   }
   1774 
   1775   OwnPrimarySelection(UTF16ToUTF8(text));
   1776 }
   1777 
   1778 bool AutocompleteEditViewGtk::OnPerformDropImpl(const string16& text) {
   1779   if (model_->CanPasteAndGo(CollapseWhitespace(text, true))) {
   1780     model_->PasteAndGo();
   1781     return true;
   1782   }
   1783 
   1784   return false;
   1785 }
   1786 
   1787 gfx::Font AutocompleteEditViewGtk::GetFont() {
   1788 #if defined(TOOLKIT_VIEWS)
   1789   bool use_gtk = false;
   1790 #else
   1791   bool use_gtk = theme_service_->UseGtkTheme();
   1792 #endif
   1793 
   1794   if (use_gtk) {
   1795     // If we haven't initialized the text view yet, just create a temporary one
   1796     // whose style we can grab.
   1797     GtkWidget* widget = text_view_ ? text_view_ : gtk_text_view_new();
   1798     GtkRcStyle* rc_style = gtk_widget_get_modifier_style(widget);
   1799     gfx::Font font((rc_style && rc_style->font_desc) ?
   1800                    rc_style->font_desc :
   1801                    widget->style->font_desc);
   1802     if (!text_view_)
   1803       g_object_unref(g_object_ref_sink(widget));
   1804 
   1805     // Scaling the font down for popup windows doesn't help here, since we just
   1806     // use the normal unforced font size when using the GTK theme.
   1807     return font;
   1808   } else {
   1809     return gfx::Font(
   1810         ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont).
   1811             GetFontName(),
   1812         popup_window_mode_ ?
   1813             browser_defaults::kAutocompleteEditFontPixelSizeInPopup :
   1814             browser_defaults::kAutocompleteEditFontPixelSize);
   1815   }
   1816 }
   1817 
   1818 void AutocompleteEditViewGtk::OwnPrimarySelection(const std::string& text) {
   1819   primary_selection_text_ = text;
   1820 
   1821   GtkTargetList* list = gtk_target_list_new(NULL, 0);
   1822   gtk_target_list_add_text_targets(list, 0);
   1823   gint len;
   1824   GtkTargetEntry* entries = gtk_target_table_new_from_list(list, &len);
   1825 
   1826   // When |text_buffer_| is destroyed, it will clear the clipboard, hence
   1827   // we needn't worry about calling gtk_clipboard_clear().
   1828   gtk_clipboard_set_with_owner(gtk_clipboard_get(GDK_SELECTION_PRIMARY),
   1829                                entries, len,
   1830                                ClipboardGetSelectionThunk,
   1831                                ClipboardSelectionCleared,
   1832                                G_OBJECT(text_buffer_));
   1833 
   1834   gtk_target_list_unref(list);
   1835   gtk_target_table_free(entries, len);
   1836 }
   1837 
   1838 void AutocompleteEditViewGtk::HandlePasteClipboard(GtkWidget* sender) {
   1839   // We can't call model_->on_paste_replacing_all() here, because the actual
   1840   // paste clipboard action may not be performed if the clipboard is empty.
   1841   paste_clipboard_requested_ = true;
   1842 }
   1843 
   1844 gfx::Rect AutocompleteEditViewGtk::WindowBoundsFromIters(
   1845     GtkTextIter* iter1, GtkTextIter* iter2) {
   1846   GdkRectangle start_location, end_location;
   1847   GtkTextView* text_view = GTK_TEXT_VIEW(text_view_);
   1848   gtk_text_view_get_iter_location(text_view, iter1, &start_location);
   1849   gtk_text_view_get_iter_location(text_view, iter2, &end_location);
   1850 
   1851   gint x1, x2, y1, y2;
   1852   gtk_text_view_buffer_to_window_coords(text_view, GTK_TEXT_WINDOW_WIDGET,
   1853                                         start_location.x, start_location.y,
   1854                                         &x1, &y1);
   1855   gtk_text_view_buffer_to_window_coords(text_view, GTK_TEXT_WINDOW_WIDGET,
   1856                                         end_location.x + end_location.width,
   1857                                         end_location.y + end_location.height,
   1858                                         &x2, &y2);
   1859 
   1860   return gfx::Rect(x1, y1, x2 - x1, y2 - y1);
   1861 }
   1862 
   1863 gboolean AutocompleteEditViewGtk::HandleExposeEvent(GtkWidget* sender,
   1864                                                     GdkEventExpose* expose) {
   1865   if (strikethrough_.cp_min >= strikethrough_.cp_max)
   1866     return FALSE;
   1867   DCHECK(text_view_);
   1868 
   1869   gfx::Rect expose_rect(expose->area);
   1870 
   1871   GtkTextIter iter_min, iter_max;
   1872   ItersFromCharRange(strikethrough_, &iter_min, &iter_max);
   1873   gfx::Rect strikethrough_rect = WindowBoundsFromIters(&iter_min, &iter_max);
   1874 
   1875   if (!expose_rect.Intersects(strikethrough_rect))
   1876     return FALSE;
   1877 
   1878   // Finally, draw.
   1879   cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(expose->window));
   1880   cairo_rectangle(cr, expose_rect.x(), expose_rect.y(),
   1881                       expose_rect.width(), expose_rect.height());
   1882   cairo_clip(cr);
   1883 
   1884   // TODO(estade): we probably shouldn't draw the strikethrough on selected
   1885   // text. I started to do this, but it was way more effort than it seemed
   1886   // worth.
   1887   strikethrough_rect.Inset(kStrikethroughStrokeWidth,
   1888                            kStrikethroughStrokeWidth);
   1889   cairo_set_source_rgb(cr, kStrikethroughStrokeRed, 0.0, 0.0);
   1890   cairo_set_line_width(cr, kStrikethroughStrokeWidth);
   1891   cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
   1892   cairo_move_to(cr, strikethrough_rect.x(), strikethrough_rect.bottom());
   1893   cairo_line_to(cr, strikethrough_rect.right(), strikethrough_rect.y());
   1894   cairo_stroke(cr);
   1895   cairo_destroy(cr);
   1896 
   1897   return FALSE;
   1898 }
   1899 
   1900 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed,
   1901                                                 bool update_primary_selection) {
   1902   GtkTextIter start, end;
   1903   if (reversed) {
   1904     GetTextBufferBounds(&end, &start);
   1905   } else {
   1906     GetTextBufferBounds(&start, &end);
   1907   }
   1908   if (!update_primary_selection)
   1909     StartUpdatingHighlightedText();
   1910   gtk_text_buffer_select_range(text_buffer_, &start, &end);
   1911   if (!update_primary_selection)
   1912     FinishUpdatingHighlightedText();
   1913 }
   1914 
   1915 void AutocompleteEditViewGtk::StartUpdatingHighlightedText() {
   1916   if (GTK_WIDGET_REALIZED(text_view_)) {
   1917     GtkClipboard* clipboard =
   1918         gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
   1919     DCHECK(clipboard);
   1920     if (clipboard)
   1921       gtk_text_buffer_remove_selection_clipboard(text_buffer_, clipboard);
   1922   }
   1923   g_signal_handler_block(text_buffer_, mark_set_handler_id_);
   1924   g_signal_handler_block(text_buffer_, mark_set_handler_id2_);
   1925 }
   1926 
   1927 void AutocompleteEditViewGtk::FinishUpdatingHighlightedText() {
   1928   if (GTK_WIDGET_REALIZED(text_view_)) {
   1929     GtkClipboard* clipboard =
   1930         gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
   1931     DCHECK(clipboard);
   1932     if (clipboard)
   1933       gtk_text_buffer_add_selection_clipboard(text_buffer_, clipboard);
   1934   }
   1935   g_signal_handler_unblock(text_buffer_, mark_set_handler_id_);
   1936   g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_);
   1937 }
   1938 
   1939 AutocompleteEditViewGtk::CharRange
   1940   AutocompleteEditViewGtk::GetSelection() const {
   1941   // You can not just use get_selection_bounds here, since the order will be
   1942   // ascending, and you don't know where the user's start and end of the
   1943   // selection was (if the selection was forwards or backwards).  Get the
   1944   // actual marks so that we can preserve the selection direction.
   1945   GtkTextIter start, insert;
   1946   GtkTextMark* mark;
   1947 
   1948   mark = gtk_text_buffer_get_selection_bound(text_buffer_);
   1949   gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark);
   1950 
   1951   mark = gtk_text_buffer_get_insert(text_buffer_);
   1952   gtk_text_buffer_get_iter_at_mark(text_buffer_, &insert, mark);
   1953 
   1954   gint start_offset = gtk_text_iter_get_offset(&start);
   1955   gint end_offset = gtk_text_iter_get_offset(&insert);
   1956 
   1957 #if GTK_CHECK_VERSION(2, 20, 0)
   1958   // Nothing should be selected when we are in the middle of composition.
   1959   DCHECK(preedit_.empty() || start_offset == end_offset);
   1960   if (!preedit_.empty()) {
   1961     start_offset += preedit_.size();
   1962     end_offset += preedit_.size();
   1963   }
   1964 #endif
   1965 
   1966   return CharRange(start_offset, end_offset);
   1967 }
   1968 
   1969 void AutocompleteEditViewGtk::ItersFromCharRange(const CharRange& range,
   1970                                                  GtkTextIter* iter_min,
   1971                                                  GtkTextIter* iter_max) {
   1972   DCHECK(!IsImeComposing());
   1973   gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min);
   1974   gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max);
   1975 }
   1976 
   1977 int AutocompleteEditViewGtk::GetTextLength() const {
   1978   GtkTextIter end;
   1979   gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_);
   1980 #if GTK_CHECK_VERSION(2, 20, 0)
   1981   // We need to count the length of the text being composed, because we treat
   1982   // it as part of the content in GetText().
   1983   return gtk_text_iter_get_offset(&end) + preedit_.size();
   1984 #else
   1985   return gtk_text_iter_get_offset(&end);
   1986 #endif
   1987 }
   1988 
   1989 void AutocompleteEditViewGtk::PlaceCaretAt(int pos) {
   1990   GtkTextIter cursor;
   1991   gtk_text_buffer_get_iter_at_offset(text_buffer_, &cursor, pos);
   1992   gtk_text_buffer_place_cursor(text_buffer_, &cursor);
   1993 }
   1994 
   1995 bool AutocompleteEditViewGtk::IsCaretAtEnd() const {
   1996   const CharRange selection = GetSelection();
   1997   return selection.cp_min == selection.cp_max &&
   1998       selection.cp_min == GetTextLength();
   1999 }
   2000 
   2001 void AutocompleteEditViewGtk::EmphasizeURLComponents() {
   2002 #if GTK_CHECK_VERSION(2, 20, 0)
   2003   // We can't change the text style easily, if the preedit string (the text
   2004   // being composed by the input method) is not empty, which is not treated as
   2005   // a part of the text content inside GtkTextView. And it's ok to simply return
   2006   // in this case, as this method will be called again when the preedit string
   2007   // gets committed.
   2008   if (preedit_.size()) {
   2009     strikethrough_ = CharRange();
   2010     return;
   2011   }
   2012 #endif
   2013   // See whether the contents are a URL with a non-empty host portion, which we
   2014   // should emphasize.  To check for a URL, rather than using the type returned
   2015   // by Parse(), ask the model, which will check the desired page transition for
   2016   // this input.  This can tell us whether an UNKNOWN input string is going to
   2017   // be treated as a search or a navigation, and is the same method the Paste
   2018   // And Go system uses.
   2019   url_parse::Component scheme, host;
   2020   string16 text(GetText());
   2021   AutocompleteInput::ParseForEmphasizeComponents(
   2022       text, model_->GetDesiredTLD(), &scheme, &host);
   2023   const bool emphasize = model_->CurrentTextIsURL() && (host.len > 0);
   2024 
   2025   // Set the baseline emphasis.
   2026   GtkTextIter start, end;
   2027   GetTextBufferBounds(&start, &end);
   2028   gtk_text_buffer_remove_all_tags(text_buffer_, &start, &end);
   2029   if (emphasize) {
   2030     gtk_text_buffer_apply_tag(text_buffer_, faded_text_tag_, &start, &end);
   2031 
   2032     // We've found a host name, give it more emphasis.
   2033     gtk_text_buffer_get_iter_at_line_index(text_buffer_, &start, 0,
   2034                                            GetUTF8Offset(text,
   2035                                                          host.begin));
   2036     gtk_text_buffer_get_iter_at_line_index(text_buffer_, &end, 0,
   2037                                            GetUTF8Offset(text,
   2038                                                          host.end()));
   2039 
   2040     gtk_text_buffer_apply_tag(text_buffer_, normal_text_tag_, &start, &end);
   2041   } else {
   2042     gtk_text_buffer_apply_tag(text_buffer_, normal_text_tag_, &start, &end);
   2043   }
   2044 
   2045   strikethrough_ = CharRange();
   2046   // Emphasize the scheme for security UI display purposes (if necessary).
   2047   if (!model_->user_input_in_progress() && scheme.is_nonempty() &&
   2048       (security_level_ != ToolbarModel::NONE)) {
   2049     CharRange scheme_range = CharRange(GetUTF8Offset(text, scheme.begin),
   2050                                        GetUTF8Offset(text, scheme.end()));
   2051     ItersFromCharRange(scheme_range, &start, &end);
   2052 
   2053     if (security_level_ == ToolbarModel::SECURITY_ERROR) {
   2054       strikethrough_ = scheme_range;
   2055       // When we draw the strikethrough, we don't want to include the ':' at the
   2056       // end of the scheme.
   2057       strikethrough_.cp_max--;
   2058 
   2059       gtk_text_buffer_apply_tag(text_buffer_, security_error_scheme_tag_,
   2060                                 &start, &end);
   2061     } else if (security_level_ == ToolbarModel::SECURITY_WARNING) {
   2062       gtk_text_buffer_apply_tag(text_buffer_, faded_text_tag_, &start, &end);
   2063     } else {
   2064       gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, &start, &end);
   2065     }
   2066   }
   2067 }
   2068 
   2069 void AutocompleteEditViewGtk::StopAnimation() {
   2070   // Clear the animation delegate so we don't get an AnimationEnded() callback.
   2071   instant_animation_->set_delegate(NULL);
   2072   instant_animation_->Stop();
   2073   UpdateInstantViewColors();
   2074 }
   2075 
   2076 void AutocompleteEditViewGtk::TextChanged() {
   2077   EmphasizeURLComponents();
   2078   model_->OnChanged();
   2079 }
   2080 
   2081 void AutocompleteEditViewGtk::SavePrimarySelection(
   2082     const std::string& selected_text) {
   2083   DCHECK(text_view_);
   2084 
   2085   GtkClipboard* clipboard =
   2086       gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
   2087   DCHECK(clipboard);
   2088   if (!clipboard)
   2089     return;
   2090 
   2091   gtk_clipboard_set_text(
   2092       clipboard, selected_text.data(), selected_text.size());
   2093 }
   2094 
   2095 void AutocompleteEditViewGtk::SetTextAndSelectedRange(const string16& text,
   2096                                                       const CharRange& range) {
   2097   if (text != GetText()) {
   2098     std::string utf8 = UTF16ToUTF8(text);
   2099     gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length());
   2100   }
   2101   SetSelectedRange(range);
   2102   AdjustTextJustification();
   2103 }
   2104 
   2105 void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) {
   2106   GtkTextIter insert, bound;
   2107   ItersFromCharRange(range, &bound, &insert);
   2108   gtk_text_buffer_select_range(text_buffer_, &insert, &bound);
   2109 
   2110   // This should be set *after* setting the selection range, in case setting the
   2111   // selection triggers HandleMarkSet which sets |selection_suggested_| to
   2112   // false.
   2113   selection_suggested_ = true;
   2114 }
   2115 
   2116 void AutocompleteEditViewGtk::AdjustTextJustification() {
   2117   DCHECK(text_view_);
   2118 
   2119   PangoDirection content_dir = GetContentDirection();
   2120 
   2121   // Use keymap direction if content does not have strong direction.
   2122   // It matches the behavior of GtkTextView.
   2123   if (content_dir == PANGO_DIRECTION_NEUTRAL) {
   2124     content_dir = gdk_keymap_get_direction(
   2125       gdk_keymap_get_for_display(gtk_widget_get_display(text_view_)));
   2126   }
   2127 
   2128   GtkTextDirection widget_dir = gtk_widget_get_direction(text_view_);
   2129 
   2130   if ((widget_dir == GTK_TEXT_DIR_RTL && content_dir == PANGO_DIRECTION_LTR) ||
   2131       (widget_dir == GTK_TEXT_DIR_LTR && content_dir == PANGO_DIRECTION_RTL)) {
   2132     gtk_text_view_set_justification(GTK_TEXT_VIEW(text_view_),
   2133                                     GTK_JUSTIFY_RIGHT);
   2134   } else {
   2135     gtk_text_view_set_justification(GTK_TEXT_VIEW(text_view_),
   2136                                     GTK_JUSTIFY_LEFT);
   2137   }
   2138 }
   2139 
   2140 PangoDirection AutocompleteEditViewGtk::GetContentDirection() {
   2141   GtkTextIter iter;
   2142   gtk_text_buffer_get_start_iter(text_buffer_, &iter);
   2143 
   2144   PangoDirection dir = PANGO_DIRECTION_NEUTRAL;
   2145   do {
   2146     dir = pango_unichar_direction(gtk_text_iter_get_char(&iter));
   2147     if (dir != PANGO_DIRECTION_NEUTRAL)
   2148       break;
   2149   } while (gtk_text_iter_forward_char(&iter));
   2150 
   2151   return dir;
   2152 }
   2153 
   2154 void AutocompleteEditViewGtk::HandleWidgetDirectionChanged(
   2155     GtkWidget* sender, GtkTextDirection previous_direction) {
   2156   AdjustTextJustification();
   2157 }
   2158 
   2159 void AutocompleteEditViewGtk::HandleDeleteFromCursor(GtkWidget *sender,
   2160     GtkDeleteType type, gint count) {
   2161   // If the selected text was suggested for autocompletion, then erase those
   2162   // first and then let the default handler take over.
   2163   if (selection_suggested_) {
   2164     gtk_text_buffer_delete_selection(text_buffer_, true, true);
   2165     selection_suggested_ = false;
   2166   }
   2167 }
   2168 
   2169 void AutocompleteEditViewGtk::HandleKeymapDirectionChanged(GdkKeymap* sender) {
   2170   AdjustTextJustification();
   2171 }
   2172 
   2173 void AutocompleteEditViewGtk::HandleDeleteRange(GtkTextBuffer* buffer,
   2174                                                 GtkTextIter* start,
   2175                                                 GtkTextIter* end) {
   2176   // Prevent the user from deleting the instant anchor. We can't simply set the
   2177   // instant anchor readonly by applying a tag with "editable" = FALSE, because
   2178   // it'll prevent the insert caret from blinking.
   2179   ValidateTextBufferIter(start);
   2180   ValidateTextBufferIter(end);
   2181   if (!gtk_text_iter_compare(start, end)) {
   2182     static guint signal_id =
   2183         g_signal_lookup("delete-range", GTK_TYPE_TEXT_BUFFER);
   2184     g_signal_stop_emission(buffer, signal_id, 0);
   2185   }
   2186 }
   2187 
   2188 void AutocompleteEditViewGtk::HandleMarkSetAlways(GtkTextBuffer* buffer,
   2189                                                   GtkTextIter* location,
   2190                                                   GtkTextMark* mark) {
   2191   if (mark == instant_mark_ || !instant_mark_)
   2192     return;
   2193 
   2194   GtkTextIter new_iter = *location;
   2195   ValidateTextBufferIter(&new_iter);
   2196 
   2197   static guint signal_id = g_signal_lookup("mark-set", GTK_TYPE_TEXT_BUFFER);
   2198 
   2199   // "mark-set" signal is actually emitted after the mark's location is already
   2200   // set, so if the location is beyond the instant anchor, we need to move the
   2201   // mark again, which will emit the signal again. In order to prevent other
   2202   // signal handlers from being called twice, we need to stop signal emission
   2203   // before moving the mark again.
   2204   if (gtk_text_iter_compare(&new_iter, location)) {
   2205     g_signal_stop_emission(buffer, signal_id, 0);
   2206     gtk_text_buffer_move_mark(buffer, mark, &new_iter);
   2207     return;
   2208   }
   2209 
   2210   if (mark != gtk_text_buffer_get_insert(text_buffer_) &&
   2211       mark != gtk_text_buffer_get_selection_bound(text_buffer_)) {
   2212     return;
   2213   }
   2214 
   2215   // See issue http://crbug.com/63860
   2216   GtkTextIter insert;
   2217   GtkTextIter selection_bound;
   2218   gtk_text_buffer_get_iter_at_mark(buffer, &insert,
   2219                                    gtk_text_buffer_get_insert(buffer));
   2220   gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound,
   2221                                    gtk_text_buffer_get_selection_bound(buffer));
   2222 
   2223   GtkTextIter end;
   2224   gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_);
   2225 
   2226   if (gtk_text_iter_compare(&insert, &end) > 0 ||
   2227       gtk_text_iter_compare(&selection_bound, &end) > 0) {
   2228     g_signal_stop_emission(buffer, signal_id, 0);
   2229   }
   2230 }
   2231 
   2232 // static
   2233 void AutocompleteEditViewGtk::ClipboardGetSelectionThunk(
   2234     GtkClipboard* clipboard,
   2235     GtkSelectionData* selection_data,
   2236     guint info,
   2237     gpointer object) {
   2238   AutocompleteEditViewGtk* edit_view =
   2239       reinterpret_cast<AutocompleteEditViewGtk*>(
   2240           g_object_get_data(G_OBJECT(object), kAutocompleteEditViewGtkKey));
   2241   edit_view->ClipboardGetSelection(clipboard, selection_data, info);
   2242 }
   2243 
   2244 void AutocompleteEditViewGtk::ClipboardGetSelection(
   2245     GtkClipboard* clipboard,
   2246     GtkSelectionData* selection_data,
   2247     guint info) {
   2248   gtk_selection_data_set_text(selection_data, primary_selection_text_.c_str(),
   2249                               primary_selection_text_.size());
   2250 }
   2251 
   2252 std::string AutocompleteEditViewGtk::GetSelectedText() const {
   2253   GtkTextIter start, end;
   2254   std::string result;
   2255   if (gtk_text_buffer_get_selection_bounds(text_buffer_, &start, &end)) {
   2256     gchar* text = gtk_text_iter_get_text(&start, &end);
   2257     size_t text_len = strlen(text);
   2258     if (text_len)
   2259       result = std::string(text, text_len);
   2260     g_free(text);
   2261   }
   2262   return result;
   2263 }
   2264 
   2265 void AutocompleteEditViewGtk::UpdatePrimarySelectionIfValidURL() {
   2266   string16 text = UTF8ToUTF16(GetSelectedText());
   2267 
   2268   if (text.empty())
   2269     return;
   2270 
   2271   // Use AdjustTextForCopy to make sure we prefix the text with 'http://'.
   2272   CharRange selection = GetSelection();
   2273   GURL url;
   2274   bool write_url;
   2275   model_->AdjustTextForCopy(selection.selection_min(), IsSelectAll(), &text,
   2276                             &url, &write_url);
   2277   if (write_url) {
   2278     selected_text_ = UTF16ToUTF8(text);
   2279     OwnPrimarySelection(selected_text_);
   2280   }
   2281 }
   2282 
   2283 #if GTK_CHECK_VERSION(2, 20, 0)
   2284 void AutocompleteEditViewGtk::HandlePreeditChanged(GtkWidget* sender,
   2285                                                    const gchar* preedit) {
   2286   // GtkTextView won't fire "begin-user-action" and "end-user-action" signals
   2287   // when changing the preedit string, so we need to call
   2288   // OnBeforePossibleChange() and OnAfterPossibleChange() by ourselves.
   2289   OnBeforePossibleChange();
   2290   if (preedit && *preedit) {
   2291     // GtkTextView will only delete the selection range when committing the
   2292     // preedit string, which will cause very strange behavior, so we need to
   2293     // delete the selection range here explicitly. See http://crbug.com/18808.
   2294     if (preedit_.empty())
   2295       gtk_text_buffer_delete_selection(text_buffer_, false, true);
   2296     preedit_ = UTF8ToUTF16(preedit);
   2297   } else {
   2298     preedit_.clear();
   2299   }
   2300   OnAfterPossibleChange();
   2301 }
   2302 #endif
   2303 
   2304 void AutocompleteEditViewGtk::HandleWindowSetFocus(
   2305     GtkWindow* sender, GtkWidget* focus) {
   2306   // This is actually a guess. If the focused widget changes in "focus-out"
   2307   // event handler, then the window will respect that and won't focus
   2308   // |focus|. I doubt that is likely to happen however.
   2309   going_to_focus_ = focus;
   2310 }
   2311 
   2312 void AutocompleteEditViewGtk::HandleUndoRedo(GtkWidget* sender) {
   2313   OnBeforePossibleChange();
   2314 }
   2315 
   2316 void AutocompleteEditViewGtk::HandleUndoRedoAfter(GtkWidget* sender) {
   2317   OnAfterPossibleChange();
   2318 }
   2319 
   2320 void AutocompleteEditViewGtk::GetTextBufferBounds(GtkTextIter* start,
   2321                                                   GtkTextIter* end) const {
   2322   gtk_text_buffer_get_start_iter(text_buffer_, start);
   2323   gtk_text_buffer_get_iter_at_mark(text_buffer_, end, instant_mark_);
   2324 }
   2325 
   2326 void AutocompleteEditViewGtk::ValidateTextBufferIter(GtkTextIter* iter) const {
   2327   if (!instant_mark_)
   2328     return;
   2329 
   2330   GtkTextIter end;
   2331   gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_);
   2332   if (gtk_text_iter_compare(iter, &end) > 0)
   2333     *iter = end;
   2334 }
   2335 
   2336 void AutocompleteEditViewGtk::AdjustVerticalAlignmentOfInstantView() {
   2337   // By default, GtkTextView layouts an anchored child widget just above the
   2338   // baseline, so we need to move the |instant_view_| down to make sure it
   2339   // has the same baseline as the |text_view_|.
   2340   PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_));
   2341   int height;
   2342   pango_layout_get_size(layout, NULL, &height);
   2343   PangoLayoutIter* iter = pango_layout_get_iter(layout);
   2344   int baseline = pango_layout_iter_get_baseline(iter);
   2345   pango_layout_iter_free(iter);
   2346   g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL);
   2347 }
   2348