| OLD | NEW |
| 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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 // sure the caret, which should be after any insertion, hasn't moved | 493 // sure the caret, which should be after any insertion, hasn't moved |
| 494 // forward of the old selection start.) | 494 // forward of the old selection start.) |
| 495 bool just_deleted_text = | 495 bool just_deleted_text = |
| 496 (text_before_change_.length() > new_text.length()) && | 496 (text_before_change_.length() > new_text.length()) && |
| 497 (new_sel.cp_min <= std::min(sel_before_change_.cp_min, | 497 (new_sel.cp_min <= std::min(sel_before_change_.cp_min, |
| 498 sel_before_change_.cp_max)); | 498 sel_before_change_.cp_max)); |
| 499 | 499 |
| 500 bool something_changed = model_->OnAfterPossibleChange(new_text, | 500 bool something_changed = model_->OnAfterPossibleChange(new_text, |
| 501 selection_differs, text_changed_, just_deleted_text, at_end_of_edit); | 501 selection_differs, text_changed_, just_deleted_text, at_end_of_edit); |
| 502 | 502 |
| 503 // If only selection was changed, we don't need to call |controller_|'s |
| 504 // OnChanged() method, which is called in TextChanged(). |
| 505 // But we still need to call EmphasizeURLComponents() to make sure the text |
| 506 // attributes are updated correctly. |
| 503 if (something_changed && text_changed_) | 507 if (something_changed && text_changed_) |
| 504 TextChanged(); | 508 TextChanged(); |
| 509 else if (selection_differs) |
| 510 EmphasizeURLComponents(); |
| 505 | 511 |
| 506 return something_changed; | 512 return something_changed; |
| 507 } | 513 } |
| 508 | 514 |
| 509 gfx::NativeView AutocompleteEditViewGtk::GetNativeView() const { | 515 gfx::NativeView AutocompleteEditViewGtk::GetNativeView() const { |
| 510 return alignment_.get(); | 516 return alignment_.get(); |
| 511 } | 517 } |
| 512 | 518 |
| 513 void AutocompleteEditViewGtk::Observe(NotificationType type, | 519 void AutocompleteEditViewGtk::Observe(NotificationType type, |
| 514 const NotificationSource& source, | 520 const NotificationSource& source, |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 if (event->type != GDK_BUTTON_PRESS) | 729 if (event->type != GDK_BUTTON_PRESS) |
| 724 return FALSE; | 730 return FALSE; |
| 725 | 731 |
| 726 if (event->button == 1) { | 732 if (event->button == 1) { |
| 727 // When the first button is pressed, track some stuff that will help us | 733 // When the first button is pressed, track some stuff that will help us |
| 728 // determine whether we should select all of the text when the button is | 734 // determine whether we should select all of the text when the button is |
| 729 // released. | 735 // released. |
| 730 button_1_pressed_ = true; | 736 button_1_pressed_ = true; |
| 731 text_view_focused_before_button_press_ = GTK_WIDGET_HAS_FOCUS(text_view_); | 737 text_view_focused_before_button_press_ = GTK_WIDGET_HAS_FOCUS(text_view_); |
| 732 text_selected_during_click_ = false; | 738 text_selected_during_click_ = false; |
| 739 |
| 740 // Button press event may change the selection, we need to record the change |
| 741 // and report it to |model_| later when button is released. |
| 742 OnBeforePossibleChange(); |
| 733 } else if (event->button == 2) { | 743 } else if (event->button == 2) { |
| 734 // GtkTextView pastes PRIMARY selection with middle click. | 744 // GtkTextView pastes PRIMARY selection with middle click. |
| 735 // We can't call model_->on_paste_replacing_all() here, because the actual | 745 // We can't call model_->on_paste_replacing_all() here, because the actual |
| 736 // paste clipboard action may not be performed if the clipboard is empty. | 746 // paste clipboard action may not be performed if the clipboard is empty. |
| 737 paste_clipboard_requested_ = true; | 747 paste_clipboard_requested_ = true; |
| 738 } | 748 } |
| 739 return FALSE; | 749 return FALSE; |
| 740 } | 750 } |
| 741 | 751 |
| 742 gboolean AutocompleteEditViewGtk::HandleViewButtonRelease( | 752 gboolean AutocompleteEditViewGtk::HandleViewButtonRelease( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 758 | 768 |
| 759 // So we told the buffer where the cursor should be, but make sure to tell | 769 // So we told the buffer where the cursor should be, but make sure to tell |
| 760 // the view so it can scroll it to be visible if needed. | 770 // the view so it can scroll it to be visible if needed. |
| 761 // NOTE: This function doesn't seem to like a count of 0, looking at the | 771 // NOTE: This function doesn't seem to like a count of 0, looking at the |
| 762 // code it will skip an important loop. Use -1 to achieve the same. | 772 // code it will skip an important loop. Use -1 to achieve the same. |
| 763 GtkTextIter start, end; | 773 GtkTextIter start, end; |
| 764 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); | 774 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); |
| 765 gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1); | 775 gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1); |
| 766 } | 776 } |
| 767 | 777 |
| 778 // Inform |model_| about possible text selection change. |
| 779 OnAfterPossibleChange(); |
| 780 |
| 768 return TRUE; // Don't continue, we called the default handler already. | 781 return TRUE; // Don't continue, we called the default handler already. |
| 769 } | 782 } |
| 770 | 783 |
| 771 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { | 784 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { |
| 772 GdkModifierType modifiers; | 785 GdkModifierType modifiers; |
| 773 gdk_window_get_pointer(text_view_->window, NULL, NULL, &modifiers); | 786 gdk_window_get_pointer(text_view_->window, NULL, NULL, &modifiers); |
| 774 model_->OnSetFocus((modifiers & GDK_CONTROL_MASK) != 0); | 787 model_->OnSetFocus((modifiers & GDK_CONTROL_MASK) != 0); |
| 775 controller_->OnSetFocus(); | 788 controller_->OnSetFocus(); |
| 776 // TODO(deanm): Some keyword hit business, etc here. | 789 // TODO(deanm): Some keyword hit business, etc here. |
| 777 | 790 |
| 778 return FALSE; // Continue propagation. | 791 return FALSE; // Continue propagation. |
| 779 } | 792 } |
| 780 | 793 |
| 781 gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { | 794 gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { |
| 782 // Close the popup. | 795 // Close the popup. |
| 783 ClosePopup(); | 796 ClosePopup(); |
| 784 // Tell the model to reset itself. | 797 // Tell the model to reset itself. |
| 785 model_->OnKillFocus(); | 798 model_->OnKillFocus(); |
| 786 return FALSE; // Pass the event on to the GtkTextView. | 799 return FALSE; // Pass the event on to the GtkTextView. |
| 787 } | 800 } |
| 788 | 801 |
| 789 void AutocompleteEditViewGtk::HandleViewMoveCursor( | 802 void AutocompleteEditViewGtk::HandleViewMoveCursor( |
| 790 GtkMovementStep step, | 803 GtkMovementStep step, |
| 791 gint count, | 804 gint count, |
| 792 gboolean extend_selection) { | 805 gboolean extend_selection) { |
| 806 GtkTextIter sel_start, sel_end; |
| 807 gboolean has_selection = |
| 808 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); |
| 809 |
| 793 // We want the GtkEntry behavior when you move the cursor while you have a | 810 // We want the GtkEntry behavior when you move the cursor while you have a |
| 794 // selection. GtkTextView just drops the selection and moves the cursor, but | 811 // selection. GtkTextView just drops the selection and moves the cursor, but |
| 795 // instead we want to move the cursor to the appropiate end of the selection. | 812 // instead we want to move the cursor to the appropiate end of the selection. |
| 796 GtkTextIter sstart, send; | 813 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection && |
| 797 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && | 814 (count == 1 || count == -1) && has_selection) { |
| 798 !extend_selection && | |
| 799 (count == 1 || count == -1) && | |
| 800 gtk_text_buffer_get_selection_bounds(text_buffer_, &sstart, &send)) { | |
| 801 // We have a selection and start / end are in ascending order. | 815 // We have a selection and start / end are in ascending order. |
| 802 gtk_text_buffer_place_cursor(text_buffer_, count == 1 ? &send : &sstart); | 816 // Cursor placement will remove the selection, so we need inform |model_| |
| 817 // about this change by calling On{Before|After}PossibleChange() methods. |
| 818 OnBeforePossibleChange(); |
| 819 gtk_text_buffer_place_cursor(text_buffer_, |
| 820 count == 1 ? &sel_end : &sel_start); |
| 821 OnAfterPossibleChange(); |
| 803 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. | 822 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. |
| 804 // Multiply by count for the direction (if we move too much that's ok). | 823 // Multiply by count for the direction (if we move too much that's ok). |
| 805 model_->OnUpOrDownKeyPressed(model_->result().size() * count); | 824 model_->OnUpOrDownKeyPressed(model_->result().size() * count); |
| 806 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. | 825 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. |
| 807 model_->OnUpOrDownKeyPressed(count); | 826 model_->OnUpOrDownKeyPressed(count); |
| 808 } else { | 827 } else { |
| 809 return; // Propagate into GtkTextView | 828 // Cursor movement may change the selection, we need to record the change |
| 829 // and report it to |model_|. |
| 830 if (has_selection || extend_selection) |
| 831 OnBeforePossibleChange(); |
| 832 |
| 833 // Propagate into GtkTextView |
| 834 GtkTextViewClass* klass = GTK_TEXT_VIEW_GET_CLASS(text_view_); |
| 835 klass->move_cursor(GTK_TEXT_VIEW(text_view_), step, count, |
| 836 extend_selection); |
| 837 |
| 838 if (has_selection || extend_selection) |
| 839 OnAfterPossibleChange(); |
| 810 } | 840 } |
| 811 | 841 |
| 812 // move-cursor doesn't use a signal accumulator on the return value (it | 842 // move-cursor doesn't use a signal accumulator on the return value (it |
| 813 // just ignores then), so we have to stop the propagation. | 843 // just ignores then), so we have to stop the propagation. |
| 814 static guint signal_id = g_signal_lookup("move-cursor", GTK_TYPE_TEXT_VIEW); | 844 static guint signal_id = g_signal_lookup("move-cursor", GTK_TYPE_TEXT_VIEW); |
| 815 g_signal_stop_emission(text_view_, signal_id, 0); | 845 g_signal_stop_emission(text_view_, signal_id, 0); |
| 816 } | 846 } |
| 817 | 847 |
| 818 void AutocompleteEditViewGtk::HandleViewSizeRequest(GtkRequisition* req) { | 848 void AutocompleteEditViewGtk::HandleViewSizeRequest(GtkRequisition* req) { |
| 819 // Don't force a minimum width, but use the font-relative height. This is a | 849 // Don't force a minimum width, but use the font-relative height. This is a |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 std::string utf8 = WideToUTF8(text); | 1281 std::string utf8 = WideToUTF8(text); |
| 1252 gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); | 1282 gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); |
| 1253 SetSelectedRange(range); | 1283 SetSelectedRange(range); |
| 1254 } | 1284 } |
| 1255 | 1285 |
| 1256 void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) { | 1286 void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) { |
| 1257 GtkTextIter insert, bound; | 1287 GtkTextIter insert, bound; |
| 1258 ItersFromCharRange(range, &bound, &insert); | 1288 ItersFromCharRange(range, &bound, &insert); |
| 1259 gtk_text_buffer_select_range(text_buffer_, &insert, &bound); | 1289 gtk_text_buffer_select_range(text_buffer_, &insert, &bound); |
| 1260 } | 1290 } |
| OLD | NEW |