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

Side by Side Diff: chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc

Issue 173462: Fix control key and paste behavior in Linux omnibox. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" 5 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
6 6
7 #include <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 #include <gdk/gdkkeysyms.h> 8 #include <gdk/gdkkeysyms.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 popup_window_mode_(popup_window_mode), 97 popup_window_mode_(popup_window_mode),
98 scheme_security_level_(ToolbarModel::NORMAL), 98 scheme_security_level_(ToolbarModel::NORMAL),
99 selection_saved_(false), 99 selection_saved_(false),
100 mark_set_handler_id_(0), 100 mark_set_handler_id_(0),
101 button_1_pressed_(false), 101 button_1_pressed_(false),
102 text_selected_during_click_(false), 102 text_selected_during_click_(false),
103 text_view_focused_before_button_press_(false), 103 text_view_focused_before_button_press_(false),
104 #if !defined(TOOLKIT_VIEWS) 104 #if !defined(TOOLKIT_VIEWS)
105 theme_provider_(GtkThemeProvider::GetFrom(profile)), 105 theme_provider_(GtkThemeProvider::GetFrom(profile)),
106 #endif 106 #endif
107 tab_was_pressed_(false) { 107 tab_was_pressed_(false),
108 paste_clipboard_requested_(false) {
108 model_->set_popup_model(popup_view_->GetModel()); 109 model_->set_popup_model(popup_view_->GetModel());
109 } 110 }
110 111
111 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() { 112 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() {
112 NotificationService::current()->Notify( 113 NotificationService::current()->Notify(
113 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, 114 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
114 Source<AutocompleteEditViewGtk>(this), 115 Source<AutocompleteEditViewGtk>(this),
115 NotificationService::NoDetails()); 116 NotificationService::NoDetails());
116 117
117 // Explicitly teardown members which have a reference to us. Just to be safe 118 // Explicitly teardown members which have a reference to us. Just to be safe
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 g_signal_connect(text_view_, "populate-popup", 205 g_signal_connect(text_view_, "populate-popup",
205 G_CALLBACK(&HandlePopulatePopupThunk), this); 206 G_CALLBACK(&HandlePopulatePopupThunk), this);
206 mark_set_handler_id_ = g_signal_connect( 207 mark_set_handler_id_ = g_signal_connect(
207 text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this); 208 text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this);
208 g_signal_connect(text_view_, "drag-data-received", 209 g_signal_connect(text_view_, "drag-data-received",
209 G_CALLBACK(&HandleDragDataReceivedThunk), this); 210 G_CALLBACK(&HandleDragDataReceivedThunk), this);
210 g_signal_connect(text_view_, "backspace", 211 g_signal_connect(text_view_, "backspace",
211 G_CALLBACK(&HandleBackSpaceThunk), this); 212 G_CALLBACK(&HandleBackSpaceThunk), this);
212 g_signal_connect(text_view_, "copy-clipboard", 213 g_signal_connect(text_view_, "copy-clipboard",
213 G_CALLBACK(&HandleCopyClipboardThunk), this); 214 G_CALLBACK(&HandleCopyClipboardThunk), this);
215 g_signal_connect(text_view_, "paste-clipboard",
216 G_CALLBACK(&HandlePasteClipboardThunk), this);
214 217
215 #if !defined(TOOLKIT_VIEWS) 218 #if !defined(TOOLKIT_VIEWS)
216 registrar_.Add(this, 219 registrar_.Add(this,
217 NotificationType::BROWSER_THEME_CHANGED, 220 NotificationType::BROWSER_THEME_CHANGED,
218 NotificationService::AllSources()); 221 NotificationService::AllSources());
219 theme_provider_->InitThemesFor(this); 222 theme_provider_->InitThemesFor(this);
220 #else 223 #else
221 // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe 224 // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe
222 // themes. 225 // themes.
223 SetBaseColor(); 226 SetBaseColor();
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); 356 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
354 gtk_text_buffer_get_iter_at_offset(text_buffer_, &start, 1); 357 gtk_text_buffer_get_iter_at_offset(text_buffer_, &start, 1);
355 StartUpdatingHighlightedText(); 358 StartUpdatingHighlightedText();
356 gtk_text_buffer_select_range(text_buffer_, &start, &end); 359 gtk_text_buffer_select_range(text_buffer_, &start, &end);
357 FinishUpdatingHighlightedText(); 360 FinishUpdatingHighlightedText();
358 } 361 }
359 } 362 }
360 363
361 bool AutocompleteEditViewGtk::IsSelectAll() { 364 bool AutocompleteEditViewGtk::IsSelectAll() {
362 GtkTextIter sel_start, sel_end; 365 GtkTextIter sel_start, sel_end;
363 if (!gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end)) 366 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end);
364 return false;
365 367
366 GtkTextIter start, end; 368 GtkTextIter start, end;
367 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); 369 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
368 370
371 // Returns true if the |text_buffer_| is empty.
369 return gtk_text_iter_equal(&start, &sel_start) && 372 return gtk_text_iter_equal(&start, &sel_start) &&
370 gtk_text_iter_equal(&end, &sel_end); 373 gtk_text_iter_equal(&end, &sel_end);
371 } 374 }
372 375
373 void AutocompleteEditViewGtk::SelectAll(bool reversed) { 376 void AutocompleteEditViewGtk::SelectAll(bool reversed) {
374 // SelectAll() is invoked as a side effect of other actions (e.g. switching 377 // SelectAll() is invoked as a side effect of other actions (e.g. switching
375 // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the 378 // tabs or hitting Escape) in autocomplete_edit.cc, so we don't update the
376 // PRIMARY selection here. 379 // PRIMARY selection here.
377 // TODO(derat): But this is also called by LocationBarView::FocusLocation() -- 380 // TODO(derat): But this is also called by LocationBarView::FocusLocation() --
378 // should the X selection be updated when the user hits Ctrl-L? 381 // should the X selection be updated when the user hits Ctrl-L?
379 SelectAllInternal(reversed, false); 382 SelectAllInternal(reversed, false);
380 } 383 }
381 384
382 void AutocompleteEditViewGtk::RevertAll() { 385 void AutocompleteEditViewGtk::RevertAll() {
383 ClosePopup(); 386 ClosePopup();
384 model_->Revert(); 387 model_->Revert();
385 TextChanged(); 388 TextChanged();
386 } 389 }
387 390
388 void AutocompleteEditViewGtk::UpdatePopup() { 391 void AutocompleteEditViewGtk::UpdatePopup() {
389 model_->SetInputInProgress(true); 392 model_->SetInputInProgress(true);
390 if (!model_->has_focus()) 393 if (!model_->has_focus())
391 return; 394 return;
392 395
393 // Don't inline autocomplete when the caret/selection isn't at the end of 396 // Don't inline autocomplete when the caret/selection isn't at the end of
394 // the text. 397 // the text.
395 CharRange sel = GetSelection(); 398 CharRange sel = GetSelection();
396 model_->StartAutocomplete(sel.cp_max < GetTextLength()); 399 model_->StartAutocomplete(std::max(sel.cp_max, sel.cp_min) < GetTextLength());
397 } 400 }
398 401
399 void AutocompleteEditViewGtk::ClosePopup() { 402 void AutocompleteEditViewGtk::ClosePopup() {
400 popup_view_->GetModel()->StopAutocomplete(); 403 popup_view_->GetModel()->StopAutocomplete();
401 } 404 }
402 405
403 void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged( 406 void AutocompleteEditViewGtk::OnTemporaryTextMaybeChanged(
404 const std::wstring& display_text, 407 const std::wstring& display_text,
405 bool save_original_selection) { 408 bool save_original_selection) {
406 if (save_original_selection) { 409 if (save_original_selection) {
(...skipping 29 matching lines...) Expand all
436 439
437 void AutocompleteEditViewGtk::OnRevertTemporaryText() { 440 void AutocompleteEditViewGtk::OnRevertTemporaryText() {
438 StartUpdatingHighlightedText(); 441 StartUpdatingHighlightedText();
439 SetTextAndSelectedRange(saved_temporary_text_, saved_temporary_selection_); 442 SetTextAndSelectedRange(saved_temporary_text_, saved_temporary_selection_);
440 FinishUpdatingHighlightedText(); 443 FinishUpdatingHighlightedText();
441 saved_temporary_text_.clear(); 444 saved_temporary_text_.clear();
442 TextChanged(); 445 TextChanged();
443 } 446 }
444 447
445 void AutocompleteEditViewGtk::OnBeforePossibleChange() { 448 void AutocompleteEditViewGtk::OnBeforePossibleChange() {
449 // If this change is caused by a paste clipboard action and all text is
450 // selected, then call model_->on_paste_replacing_all() to prevent inline
451 // autocomplete.
452 if (paste_clipboard_requested_) {
453 paste_clipboard_requested_ = false;
454 if (IsSelectAll())
455 model_->on_paste_replacing_all();
456 }
457
446 // Record our state. 458 // Record our state.
447 text_before_change_ = GetText(); 459 text_before_change_ = GetText();
448 sel_before_change_ = GetSelection(); 460 sel_before_change_ = GetSelection();
449 } 461 }
450 462
451 // TODO(deanm): This is mostly stolen from Windows, and will need some work. 463 // TODO(deanm): This is mostly stolen from Windows, and will need some work.
452 bool AutocompleteEditViewGtk::OnAfterPossibleChange() { 464 bool AutocompleteEditViewGtk::OnAfterPossibleChange() {
453 CharRange new_sel = GetSelection(); 465 CharRange new_sel = GetSelection();
454 int length = GetTextLength(); 466 int length = GetTextLength();
455 bool selection_differs = (new_sel.cp_min != sel_before_change_.cp_min) || 467 bool selection_differs = (new_sel.cp_min != sel_before_change_.cp_min) ||
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 617 }
606 618
607 // Set |tab_was_pressed_| to true if it's a Tab key press event, so that our 619 // Set |tab_was_pressed_| to true if it's a Tab key press event, so that our
608 // handler of "move-focus" signal can trigger Tab to search behavior when 620 // handler of "move-focus" signal can trigger Tab to search behavior when
609 // necessary. 621 // necessary.
610 tab_was_pressed_ = ((event->keyval == GDK_Tab || 622 tab_was_pressed_ = ((event->keyval == GDK_Tab ||
611 event->keyval == GDK_ISO_Left_Tab || 623 event->keyval == GDK_ISO_Left_Tab ||
612 event->keyval == GDK_KP_Tab) && 624 event->keyval == GDK_KP_Tab) &&
613 !(event->state & GDK_CONTROL_MASK)); 625 !(event->state & GDK_CONTROL_MASK));
614 626
627 // Reset |paste_clipboard_requested_| to make sure we won't misinterpret this
628 // key input action as a paste action.
629 paste_clipboard_requested_ = false;
630
615 // Call the default handler, so that IME can work as normal. 631 // Call the default handler, so that IME can work as normal.
616 // New line characters will be filtered out by our "insert-text" 632 // New line characters will be filtered out by our "insert-text"
617 // signal handler attached to |text_buffer_| object. 633 // signal handler attached to |text_buffer_| object.
618 gboolean result = klass->key_press_event(widget, event); 634 gboolean result = klass->key_press_event(widget, event);
619 635
620 // Set |tab_was_pressed_| to false, to make sure Tab to search behavior can 636 // Set |tab_was_pressed_| to false, to make sure Tab to search behavior can
621 // only be triggered by pressing Tab key. 637 // only be triggered by pressing Tab key.
622 tab_was_pressed_ = false; 638 tab_was_pressed_ = false;
623 639
624 if (enter_pressed && (char_inserted_ == '\n' || char_inserted_ == '\r')) { 640 if (enter_pressed && (char_inserted_ == '\n' || char_inserted_ == '\r')) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 model_->OnControlKeyChanged(false); 693 model_->OnControlKeyChanged(false);
678 } 694 }
679 695
680 // Even though we handled the press ourselves, let GtkTextView handle the 696 // Even though we handled the press ourselves, let GtkTextView handle the
681 // release. It shouldn't do anything particularly interesting, but it will 697 // release. It shouldn't do anything particularly interesting, but it will
682 // handle the IME work for us. 698 // handle the IME work for us.
683 return FALSE; // Propagate into GtkTextView. 699 return FALSE; // Propagate into GtkTextView.
684 } 700 }
685 701
686 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) { 702 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) {
703 // We don't need to care about double and triple clicks.
704 if (event->type != GDK_BUTTON_PRESS)
705 return FALSE;
706
687 if (event->button == 1) { 707 if (event->button == 1) {
688 // When the first button is pressed, track some stuff that will help us 708 // When the first button is pressed, track some stuff that will help us
689 // determine whether we should select all of the text when the button is 709 // determine whether we should select all of the text when the button is
690 // released. 710 // released.
691 button_1_pressed_ = true; 711 button_1_pressed_ = true;
692 text_view_focused_before_button_press_ = GTK_WIDGET_HAS_FOCUS(text_view_); 712 text_view_focused_before_button_press_ = GTK_WIDGET_HAS_FOCUS(text_view_);
693 text_selected_during_click_ = false; 713 text_selected_during_click_ = false;
714 } else if (event->button == 2) {
715 // GtkTextView pastes PRIMARY selection with middle click.
716 // We can't call model_->on_paste_replacing_all() here, because the actual
717 // paste clipboard action may not be performed if the clipboard is empty.
718 paste_clipboard_requested_ = true;
694 } 719 }
695 return FALSE; 720 return FALSE;
696 } 721 }
697 722
698 gboolean AutocompleteEditViewGtk::HandleViewButtonRelease( 723 gboolean AutocompleteEditViewGtk::HandleViewButtonRelease(
699 GdkEventButton* event) { 724 GdkEventButton* event) {
700 if (event->button != 1) 725 if (event->button != 1)
701 return FALSE; 726 return FALSE;
702 727
703 button_1_pressed_ = false; 728 button_1_pressed_ = false;
(...skipping 14 matching lines...) Expand all
718 // code it will skip an important loop. Use -1 to achieve the same. 743 // code it will skip an important loop. Use -1 to achieve the same.
719 GtkTextIter start, end; 744 GtkTextIter start, end;
720 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); 745 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
721 gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1); 746 gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1);
722 } 747 }
723 748
724 return TRUE; // Don't continue, we called the default handler already. 749 return TRUE; // Don't continue, we called the default handler already.
725 } 750 }
726 751
727 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { 752 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() {
728 model_->OnSetFocus(false); 753 GdkModifierType modifiers;
754 gdk_window_get_pointer(text_view_->window, NULL, NULL, &modifiers);
755 model_->OnSetFocus((modifiers & GDK_CONTROL_MASK) != 0);
729 // TODO(deanm): Some keyword hit business, etc here. 756 // TODO(deanm): Some keyword hit business, etc here.
730 757
731 return FALSE; // Continue propagation. 758 return FALSE; // Continue propagation.
732 } 759 }
733 760
734 gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { 761 gboolean AutocompleteEditViewGtk::HandleViewFocusOut() {
735 // Close the popup. 762 // Close the popup.
736 ClosePopup(); 763 ClosePopup();
737 // Tell the model to reset itself. 764 // Tell the model to reset itself.
738 model_->OnKillFocus(); 765 model_->OnKillFocus();
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 SavePrimarySelection(selected_text_); 888 SavePrimarySelection(selected_text_);
862 selection_saved_ = true; 889 selection_saved_ = true;
863 } 890 }
864 } 891 }
865 892
866 // Just use the default behavior for DnD, except if the drop can be a PasteAndGo 893 // Just use the default behavior for DnD, except if the drop can be a PasteAndGo
867 // then override. 894 // then override.
868 void AutocompleteEditViewGtk::HandleDragDataReceived( 895 void AutocompleteEditViewGtk::HandleDragDataReceived(
869 GdkDragContext* context, gint x, gint y, 896 GdkDragContext* context, gint x, gint y,
870 GtkSelectionData* selection_data, guint target_type, guint time) { 897 GtkSelectionData* selection_data, guint target_type, guint time) {
898 // Reset |paste_clipboard_requested_| to make sure we won't misinterpret this
899 // drop action as a paste action.
900 paste_clipboard_requested_ = false;
901
871 // Don't try to PasteAndGo on drops originating from this omnibox. However, do 902 // Don't try to PasteAndGo on drops originating from this omnibox. However, do
872 // allow default behavior for such drags. 903 // allow default behavior for such drags.
873 if (context->source_window == text_view_->window) 904 if (context->source_window == text_view_->window)
874 return; 905 return;
875 906
876 guchar* text = gtk_selection_data_get_text(selection_data); 907 guchar* text = gtk_selection_data_get_text(selection_data);
877 if (!text) 908 if (!text)
878 return; 909 return;
879 910
880 std::wstring possible_url = UTF8ToWide(reinterpret_cast<char*>(text)); 911 std::wstring possible_url = UTF8ToWide(reinterpret_cast<char*>(text));
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 // don't want to do (and it also appears to at least sometimes trigger a 1015 // don't want to do (and it also appears to at least sometimes trigger a
985 // failed G_IS_OBJECT() assertion). 1016 // failed G_IS_OBJECT() assertion).
986 if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_)) 1017 if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_))
987 return; 1018 return;
988 1019
989 // We can't just call SavePrimarySelection(); that makes the text view lose 1020 // We can't just call SavePrimarySelection(); that makes the text view lose
990 // the selection and unhighlight its text. 1021 // the selection and unhighlight its text.
991 gtk_text_buffer_copy_clipboard(text_buffer_, clipboard); 1022 gtk_text_buffer_copy_clipboard(text_buffer_, clipboard);
992 } 1023 }
993 1024
1025 void AutocompleteEditViewGtk::HandlePasteClipboard() {
1026 // We can't call model_->on_paste_replacing_all() here, because the actual
1027 // paste clipboard action may not be performed if the clipboard is empty.
1028 paste_clipboard_requested_ = true;
1029 }
1030
994 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed, 1031 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed,
995 bool update_primary_selection) { 1032 bool update_primary_selection) {
996 GtkTextIter start, end; 1033 GtkTextIter start, end;
997 if (reversed) { 1034 if (reversed) {
998 gtk_text_buffer_get_bounds(text_buffer_, &end, &start); 1035 gtk_text_buffer_get_bounds(text_buffer_, &end, &start);
999 } else { 1036 } else {
1000 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); 1037 gtk_text_buffer_get_bounds(text_buffer_, &start, &end);
1001 } 1038 }
1002 if (!update_primary_selection) 1039 if (!update_primary_selection)
1003 StartUpdatingHighlightedText(); 1040 StartUpdatingHighlightedText();
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 const std::string& selected_text) { 1156 const std::string& selected_text) {
1120 GtkClipboard* clipboard = 1157 GtkClipboard* clipboard =
1121 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); 1158 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY);
1122 DCHECK(clipboard); 1159 DCHECK(clipboard);
1123 if (!clipboard) 1160 if (!clipboard)
1124 return; 1161 return;
1125 1162
1126 gtk_clipboard_set_text( 1163 gtk_clipboard_set_text(
1127 clipboard, selected_text.data(), selected_text.size()); 1164 clipboard, selected_text.data(), selected_text.size());
1128 } 1165 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698