| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
| 8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 ) { | 772 ) { |
| 773 instant_animation_->set_delegate(this); | 773 instant_animation_->set_delegate(this); |
| 774 instant_animation_->Start(); | 774 instant_animation_->Start(); |
| 775 } | 775 } |
| 776 | 776 |
| 777 gtk_widget_show(instant_view_); | 777 gtk_widget_show(instant_view_); |
| 778 AdjustVerticalAlignmentOfInstantView(); | 778 AdjustVerticalAlignmentOfInstantView(); |
| 779 UpdateInstantViewColors(); | 779 UpdateInstantViewColors(); |
| 780 } | 780 } |
| 781 | 781 |
| 782 string16 AutocompleteEditViewGtk::GetInstantSuggestion() const { |
| 783 const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_)); |
| 784 return suggestion ? UTF8ToUTF16(suggestion) : string16(); |
| 785 } |
| 786 |
| 782 int AutocompleteEditViewGtk::TextWidth() const { | 787 int AutocompleteEditViewGtk::TextWidth() const { |
| 783 int horizontal_border_size = | 788 int horizontal_border_size = |
| 784 gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), | 789 gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), |
| 785 GTK_TEXT_WINDOW_LEFT) + | 790 GTK_TEXT_WINDOW_LEFT) + |
| 786 gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), | 791 gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), |
| 787 GTK_TEXT_WINDOW_RIGHT) + | 792 GTK_TEXT_WINDOW_RIGHT) + |
| 788 gtk_text_view_get_left_margin(GTK_TEXT_VIEW(text_view_)) + | 793 gtk_text_view_get_left_margin(GTK_TEXT_VIEW(text_view_)) + |
| 789 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(text_view_)); | 794 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(text_view_)); |
| 790 | 795 |
| 791 GtkTextIter start, end; | 796 GtkTextIter start, end; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 | 832 |
| 828 #if defined(TOOLKIT_VIEWS) | 833 #if defined(TOOLKIT_VIEWS) |
| 829 views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) { | 834 views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) { |
| 830 views::NativeViewHost* host = new views::NativeViewHost; | 835 views::NativeViewHost* host = new views::NativeViewHost; |
| 831 parent->AddChildView(host); | 836 parent->AddChildView(host); |
| 832 host->set_focus_view(parent); | 837 host->set_focus_view(parent); |
| 833 host->Attach(GetNativeView()); | 838 host->Attach(GetNativeView()); |
| 834 return host; | 839 return host; |
| 835 } | 840 } |
| 836 | 841 |
| 837 bool AutocompleteEditViewGtk::CommitInstantSuggestion( | |
| 838 const string16& typed_text, | |
| 839 const string16& suggestion) { | |
| 840 return CommitInstantSuggestion(); | |
| 841 } | |
| 842 | |
| 843 void AutocompleteEditViewGtk::EnableAccessibility() { | 842 void AutocompleteEditViewGtk::EnableAccessibility() { |
| 844 accessible_widget_helper_.reset( | 843 accessible_widget_helper_.reset( |
| 845 new AccessibleWidgetHelper(text_view(), model_->profile())); | 844 new AccessibleWidgetHelper(text_view(), model_->profile())); |
| 846 accessible_widget_helper_->SetWidgetName( | 845 accessible_widget_helper_->SetWidgetName( |
| 847 text_view(), l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION)); | 846 text_view(), l10n_util::GetStringUTF8(IDS_ACCNAME_LOCATION)); |
| 848 } | 847 } |
| 849 | 848 |
| 850 // static | 849 // static |
| 851 AutocompleteEditView* AutocompleteEditViewGtk::Create( | 850 AutocompleteEditView* AutocompleteEditViewGtk::Create( |
| 852 AutocompleteEditController* controller, | 851 AutocompleteEditController* controller, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 | 890 |
| 892 void AutocompleteEditViewGtk::Observe(NotificationType type, | 891 void AutocompleteEditViewGtk::Observe(NotificationType type, |
| 893 const NotificationSource& source, | 892 const NotificationSource& source, |
| 894 const NotificationDetails& details) { | 893 const NotificationDetails& details) { |
| 895 DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); | 894 DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); |
| 896 | 895 |
| 897 SetBaseColor(); | 896 SetBaseColor(); |
| 898 } | 897 } |
| 899 | 898 |
| 900 void AutocompleteEditViewGtk::AnimationEnded(const ui::Animation* animation) { | 899 void AutocompleteEditViewGtk::AnimationEnded(const ui::Animation* animation) { |
| 901 controller_->OnCommitSuggestedText(GetText()); | 900 controller_->OnCommitSuggestedText(false); |
| 902 } | 901 } |
| 903 | 902 |
| 904 void AutocompleteEditViewGtk::AnimationProgressed( | 903 void AutocompleteEditViewGtk::AnimationProgressed( |
| 905 const ui::Animation* animation) { | 904 const ui::Animation* animation) { |
| 906 UpdateInstantViewColors(); | 905 UpdateInstantViewColors(); |
| 907 } | 906 } |
| 908 | 907 |
| 909 void AutocompleteEditViewGtk::AnimationCanceled( | 908 void AutocompleteEditViewGtk::AnimationCanceled( |
| 910 const ui::Animation* animation) { | 909 const ui::Animation* animation) { |
| 911 UpdateInstantViewColors(); | 910 UpdateInstantViewColors(); |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 GtkMovementStep step, | 1336 GtkMovementStep step, |
| 1338 gint count, | 1337 gint count, |
| 1339 gboolean extend_selection) { | 1338 gboolean extend_selection) { |
| 1340 GtkTextIter sel_start, sel_end; | 1339 GtkTextIter sel_start, sel_end; |
| 1341 gboolean has_selection = | 1340 gboolean has_selection = |
| 1342 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); | 1341 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); |
| 1343 bool handled = false; | 1342 bool handled = false; |
| 1344 | 1343 |
| 1345 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection && | 1344 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection && |
| 1346 (count == 1 || count == -1)) { | 1345 (count == 1 || count == -1)) { |
| 1347 gint cursor_pos; | |
| 1348 g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, NULL); | |
| 1349 | |
| 1350 // We need to take the content direction into account when handling cursor | 1346 // We need to take the content direction into account when handling cursor |
| 1351 // movement, because the behavior of Left and Right key will be inverted if | 1347 // movement, because the behavior of Left and Right key will be inverted if |
| 1352 // the direction is RTL. Although we should check the direction around the | 1348 // the direction is RTL. Although we should check the direction around the |
| 1353 // input caret, it's much simpler and good enough to check whole content's | 1349 // input caret, it's much simpler and good enough to check whole content's |
| 1354 // direction. | 1350 // direction. |
| 1355 PangoDirection content_dir = GetContentDirection(); | 1351 PangoDirection content_dir = GetContentDirection(); |
| 1356 gint count_towards_end = content_dir == PANGO_DIRECTION_RTL ? -1 : 1; | 1352 gint count_towards_end = content_dir == PANGO_DIRECTION_RTL ? -1 : 1; |
| 1357 | 1353 |
| 1358 // We want the GtkEntry behavior when you move the cursor while you have a | 1354 // We want the GtkEntry behavior when you move the cursor while you have a |
| 1359 // selection. GtkTextView just drops the selection and moves the cursor, | 1355 // selection. GtkTextView just drops the selection and moves the cursor, |
| 1360 // but instead we want to move the cursor to the appropiate end of the | 1356 // but instead we want to move the cursor to the appropiate end of the |
| 1361 // selection. | 1357 // selection. |
| 1362 if (has_selection) { | 1358 if (has_selection) { |
| 1363 // We have a selection and start / end are in ascending order. | 1359 // We have a selection and start / end are in ascending order. |
| 1364 // Cursor placement will remove the selection, so we need inform | 1360 // Cursor placement will remove the selection, so we need inform |
| 1365 // |model_| about this change by | 1361 // |model_| about this change by |
| 1366 // calling On{Before|After}PossibleChange() methods. | 1362 // calling On{Before|After}PossibleChange() methods. |
| 1367 OnBeforePossibleChange(); | 1363 OnBeforePossibleChange(); |
| 1368 gtk_text_buffer_place_cursor( | 1364 gtk_text_buffer_place_cursor( |
| 1369 text_buffer_, count == count_towards_end ? &sel_end : &sel_start); | 1365 text_buffer_, count == count_towards_end ? &sel_end : &sel_start); |
| 1370 OnAfterPossibleChange(); | 1366 OnAfterPossibleChange(); |
| 1371 handled = true; | 1367 handled = true; |
| 1372 } else if (count == count_towards_end && cursor_pos == GetTextLength()) { | 1368 } else if (count == count_towards_end && !IsCaretAtEnd()) { |
| 1373 handled = controller_->OnCommitSuggestedText(GetText()); | 1369 handled = controller_->OnCommitSuggestedText(true); |
| 1374 } | 1370 } |
| 1375 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. | 1371 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. |
| 1376 // Multiply by count for the direction (if we move too much that's ok). | 1372 // Multiply by count for the direction (if we move too much that's ok). |
| 1377 model_->OnUpOrDownKeyPressed(model_->result().size() * count); | 1373 model_->OnUpOrDownKeyPressed(model_->result().size() * count); |
| 1378 handled = true; | 1374 handled = true; |
| 1379 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. | 1375 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. |
| 1380 model_->OnUpOrDownKeyPressed(count); | 1376 model_->OnUpOrDownKeyPressed(count); |
| 1381 handled = true; | 1377 handled = true; |
| 1382 } | 1378 } |
| 1383 | 1379 |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget, | 1627 void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget, |
| 1632 GtkDirectionType direction) { | 1628 GtkDirectionType direction) { |
| 1633 if (!tab_was_pressed_) | 1629 if (!tab_was_pressed_) |
| 1634 return; | 1630 return; |
| 1635 | 1631 |
| 1636 // If special behavior is triggered, then stop the signal emission to | 1632 // If special behavior is triggered, then stop the signal emission to |
| 1637 // prevent the focus from being moved. | 1633 // prevent the focus from being moved. |
| 1638 bool handled = false; | 1634 bool handled = false; |
| 1639 | 1635 |
| 1640 // Trigger Tab to search behavior only when Tab key is pressed. | 1636 // Trigger Tab to search behavior only when Tab key is pressed. |
| 1641 if (model_->is_keyword_hint()) { | 1637 if (model_->is_keyword_hint()) |
| 1642 handled = model_->AcceptKeyword(); | 1638 handled = model_->AcceptKeyword(); |
| 1643 } else if (GTK_WIDGET_VISIBLE(instant_view_)) { | 1639 |
| 1644 controller_->OnCommitSuggestedText(GetText()); | 1640 #if GTK_CHECK_VERSION(2, 20, 0) |
| 1641 if (!handled && !preedit_.empty()) |
| 1645 handled = true; | 1642 handled = true; |
| 1646 } else { | 1643 #endif |
| 1644 |
| 1645 if (!handled && GTK_WIDGET_VISIBLE(instant_view_)) |
| 1646 handled = controller_->OnCommitSuggestedText(true); |
| 1647 |
| 1648 if (!handled) { |
| 1649 if (!IsCaretAtEnd()) { |
| 1650 OnBeforePossibleChange(); |
| 1651 PlaceCaretAt(GetTextLength()); |
| 1652 OnAfterPossibleChange(); |
| 1653 handled = true; |
| 1654 } |
| 1655 } |
| 1656 |
| 1657 if (!handled) |
| 1647 handled = controller_->AcceptCurrentInstantPreview(); | 1658 handled = controller_->AcceptCurrentInstantPreview(); |
| 1648 } | |
| 1649 | 1659 |
| 1650 if (handled) { | 1660 if (handled) { |
| 1651 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); | 1661 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); |
| 1652 g_signal_stop_emission(widget, signal_id, 0); | 1662 g_signal_stop_emission(widget, signal_id, 0); |
| 1653 } | 1663 } |
| 1654 } | 1664 } |
| 1655 | 1665 |
| 1656 void AutocompleteEditViewGtk::HandleCopyClipboard(GtkWidget* sender) { | 1666 void AutocompleteEditViewGtk::HandleCopyClipboard(GtkWidget* sender) { |
| 1657 HandleCopyOrCutClipboard(true); | 1667 HandleCopyOrCutClipboard(true); |
| 1658 } | 1668 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1815 GtkClipboard* clipboard = | 1825 GtkClipboard* clipboard = |
| 1816 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); | 1826 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); |
| 1817 DCHECK(clipboard); | 1827 DCHECK(clipboard); |
| 1818 if (clipboard) | 1828 if (clipboard) |
| 1819 gtk_text_buffer_add_selection_clipboard(text_buffer_, clipboard); | 1829 gtk_text_buffer_add_selection_clipboard(text_buffer_, clipboard); |
| 1820 } | 1830 } |
| 1821 g_signal_handler_unblock(text_buffer_, mark_set_handler_id_); | 1831 g_signal_handler_unblock(text_buffer_, mark_set_handler_id_); |
| 1822 g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_); | 1832 g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_); |
| 1823 } | 1833 } |
| 1824 | 1834 |
| 1825 AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() { | 1835 AutocompleteEditViewGtk::CharRange |
| 1836 AutocompleteEditViewGtk::GetSelection() const { |
| 1826 // You can not just use get_selection_bounds here, since the order will be | 1837 // You can not just use get_selection_bounds here, since the order will be |
| 1827 // ascending, and you don't know where the user's start and end of the | 1838 // ascending, and you don't know where the user's start and end of the |
| 1828 // selection was (if the selection was forwards or backwards). Get the | 1839 // selection was (if the selection was forwards or backwards). Get the |
| 1829 // actual marks so that we can preserve the selection direction. | 1840 // actual marks so that we can preserve the selection direction. |
| 1830 GtkTextIter start, insert; | 1841 GtkTextIter start, insert; |
| 1831 GtkTextMark* mark; | 1842 GtkTextMark* mark; |
| 1832 | 1843 |
| 1833 mark = gtk_text_buffer_get_selection_bound(text_buffer_); | 1844 mark = gtk_text_buffer_get_selection_bound(text_buffer_); |
| 1834 gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark); | 1845 gtk_text_buffer_get_iter_at_mark(text_buffer_, &start, mark); |
| 1835 | 1846 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1864 gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_); | 1875 gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_); |
| 1865 #if GTK_CHECK_VERSION(2, 20, 0) | 1876 #if GTK_CHECK_VERSION(2, 20, 0) |
| 1866 // We need to count the length of the text being composed, because we treat | 1877 // We need to count the length of the text being composed, because we treat |
| 1867 // it as part of the content in GetText(). | 1878 // it as part of the content in GetText(). |
| 1868 return gtk_text_iter_get_offset(&end) + preedit_.size(); | 1879 return gtk_text_iter_get_offset(&end) + preedit_.size(); |
| 1869 #else | 1880 #else |
| 1870 return gtk_text_iter_get_offset(&end); | 1881 return gtk_text_iter_get_offset(&end); |
| 1871 #endif | 1882 #endif |
| 1872 } | 1883 } |
| 1873 | 1884 |
| 1885 void AutocompleteEditViewGtk::PlaceCaretAt(int pos) { |
| 1886 GtkTextIter cursor; |
| 1887 gtk_text_buffer_get_iter_at_offset(text_buffer_, &cursor, pos); |
| 1888 gtk_text_buffer_place_cursor(text_buffer_, &cursor); |
| 1889 } |
| 1890 |
| 1891 bool AutocompleteEditViewGtk::IsCaretAtEnd() const { |
| 1892 const CharRange selection = GetSelection(); |
| 1893 return selection.cp_min == selection.cp_max && |
| 1894 selection.cp_min == GetTextLength(); |
| 1895 } |
| 1896 |
| 1874 void AutocompleteEditViewGtk::EmphasizeURLComponents() { | 1897 void AutocompleteEditViewGtk::EmphasizeURLComponents() { |
| 1875 #if GTK_CHECK_VERSION(2, 20, 0) | 1898 #if GTK_CHECK_VERSION(2, 20, 0) |
| 1876 // We can't change the text style easily, if the preedit string (the text | 1899 // We can't change the text style easily, if the preedit string (the text |
| 1877 // being composed by the input method) is not empty, which is not treated as | 1900 // being composed by the input method) is not empty, which is not treated as |
| 1878 // a part of the text content inside GtkTextView. And it's ok to simply return | 1901 // a part of the text content inside GtkTextView. And it's ok to simply return |
| 1879 // in this case, as this method will be called again when the preedit string | 1902 // in this case, as this method will be called again when the preedit string |
| 1880 // gets committed. | 1903 // gets committed. |
| 1881 if (preedit_.size()) { | 1904 if (preedit_.size()) { |
| 1882 strikethrough_ = CharRange(); | 1905 strikethrough_ = CharRange(); |
| 1883 return; | 1906 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 } | 1962 } |
| 1940 } | 1963 } |
| 1941 | 1964 |
| 1942 void AutocompleteEditViewGtk::StopAnimation() { | 1965 void AutocompleteEditViewGtk::StopAnimation() { |
| 1943 // Clear the animation delegate so we don't get an AnimationEnded() callback. | 1966 // Clear the animation delegate so we don't get an AnimationEnded() callback. |
| 1944 instant_animation_->set_delegate(NULL); | 1967 instant_animation_->set_delegate(NULL); |
| 1945 instant_animation_->Stop(); | 1968 instant_animation_->Stop(); |
| 1946 UpdateInstantViewColors(); | 1969 UpdateInstantViewColors(); |
| 1947 } | 1970 } |
| 1948 | 1971 |
| 1949 bool AutocompleteEditViewGtk::CommitInstantSuggestion() { | |
| 1950 const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_)); | |
| 1951 if (!suggestion || !*suggestion) | |
| 1952 return false; | |
| 1953 | |
| 1954 model()->FinalizeInstantQuery(GetText(), | |
| 1955 UTF8ToUTF16(suggestion)); | |
| 1956 return true; | |
| 1957 } | |
| 1958 | |
| 1959 void AutocompleteEditViewGtk::TextChanged() { | 1972 void AutocompleteEditViewGtk::TextChanged() { |
| 1960 EmphasizeURLComponents(); | 1973 EmphasizeURLComponents(); |
| 1961 controller_->OnChanged(); | 1974 controller_->OnChanged(); |
| 1962 } | 1975 } |
| 1963 | 1976 |
| 1964 void AutocompleteEditViewGtk::SavePrimarySelection( | 1977 void AutocompleteEditViewGtk::SavePrimarySelection( |
| 1965 const std::string& selected_text) { | 1978 const std::string& selected_text) { |
| 1966 GtkClipboard* clipboard = | 1979 GtkClipboard* clipboard = |
| 1967 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); | 1980 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); |
| 1968 DCHECK(clipboard); | 1981 DCHECK(clipboard); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2217 // baseline, so we need to move the |instant_view_| down to make sure it | 2230 // baseline, so we need to move the |instant_view_| down to make sure it |
| 2218 // has the same baseline as the |text_view_|. | 2231 // has the same baseline as the |text_view_|. |
| 2219 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); | 2232 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); |
| 2220 int height; | 2233 int height; |
| 2221 pango_layout_get_size(layout, NULL, &height); | 2234 pango_layout_get_size(layout, NULL, &height); |
| 2222 PangoLayoutIter* iter = pango_layout_get_iter(layout); | 2235 PangoLayoutIter* iter = pango_layout_get_iter(layout); |
| 2223 int baseline = pango_layout_iter_get_baseline(iter); | 2236 int baseline = pango_layout_iter_get_baseline(iter); |
| 2224 pango_layout_iter_free(iter); | 2237 pango_layout_iter_free(iter); |
| 2225 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); | 2238 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); |
| 2226 } | 2239 } |
| OLD | NEW |