Chromium Code Reviews| 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 && |
| 1373 handled = controller_->OnCommitSuggestedText(GetText()); | 1369 GetCursorPosition() == GetTextLength()) { |
| 1370 handled = controller_->OnCommitSuggestedText(true); | |
| 1374 } | 1371 } |
| 1375 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. | 1372 } 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). | 1373 // Multiply by count for the direction (if we move too much that's ok). |
| 1377 model_->OnUpOrDownKeyPressed(model_->result().size() * count); | 1374 model_->OnUpOrDownKeyPressed(model_->result().size() * count); |
| 1378 handled = true; | 1375 handled = true; |
| 1379 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. | 1376 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. |
| 1380 model_->OnUpOrDownKeyPressed(count); | 1377 model_->OnUpOrDownKeyPressed(count); |
| 1381 handled = true; | 1378 handled = true; |
| 1382 } | 1379 } |
| 1383 | 1380 |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1631 void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget, | 1628 void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget, |
| 1632 GtkDirectionType direction) { | 1629 GtkDirectionType direction) { |
| 1633 if (!tab_was_pressed_) | 1630 if (!tab_was_pressed_) |
| 1634 return; | 1631 return; |
| 1635 | 1632 |
| 1636 // If special behavior is triggered, then stop the signal emission to | 1633 // If special behavior is triggered, then stop the signal emission to |
| 1637 // prevent the focus from being moved. | 1634 // prevent the focus from being moved. |
| 1638 bool handled = false; | 1635 bool handled = false; |
| 1639 | 1636 |
| 1640 // Trigger Tab to search behavior only when Tab key is pressed. | 1637 // Trigger Tab to search behavior only when Tab key is pressed. |
| 1641 if (model_->is_keyword_hint()) { | 1638 if (model_->is_keyword_hint()) |
| 1642 handled = model_->AcceptKeyword(); | 1639 handled = model_->AcceptKeyword(); |
| 1643 } else if (GTK_WIDGET_VISIBLE(instant_view_)) { | 1640 |
| 1644 controller_->OnCommitSuggestedText(GetText()); | 1641 #if GTK_CHECK_VERSION(2, 20, 0) |
| 1642 if (!handled && !preedit_.empty()) | |
| 1645 handled = true; | 1643 handled = true; |
| 1646 } else { | 1644 #endif |
| 1645 | |
| 1646 if (!handled && GTK_WIDGET_VISIBLE(instant_view_)) | |
| 1647 handled = controller_->OnCommitSuggestedText(true); | |
| 1648 | |
| 1649 if (!handled) { | |
| 1650 CharRange selection = GetSelection(); | |
| 1651 int length = GetTextLength(); | |
| 1652 if (selection.cp_min != selection.cp_max || selection.cp_min < length) { | |
| 1653 OnBeforePossibleChange(); | |
|
sky
2011/01/27 19:55:31
Do we need the OnBefore/after here?
James Su
2011/01/27 20:07:16
Yes we need it to inform the model possible select
| |
| 1654 SetCursorPosition(length); | |
| 1655 OnAfterPossibleChange(); | |
| 1656 handled = true; | |
| 1657 } | |
| 1658 } | |
| 1659 | |
| 1660 if (!handled) | |
| 1647 handled = controller_->AcceptCurrentInstantPreview(); | 1661 handled = controller_->AcceptCurrentInstantPreview(); |
| 1648 } | |
| 1649 | 1662 |
| 1650 if (handled) { | 1663 if (handled) { |
| 1651 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); | 1664 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); |
| 1652 g_signal_stop_emission(widget, signal_id, 0); | 1665 g_signal_stop_emission(widget, signal_id, 0); |
| 1653 } | 1666 } |
| 1654 } | 1667 } |
| 1655 | 1668 |
| 1656 void AutocompleteEditViewGtk::HandleCopyClipboard(GtkWidget* sender) { | 1669 void AutocompleteEditViewGtk::HandleCopyClipboard(GtkWidget* sender) { |
| 1657 HandleCopyOrCutClipboard(true); | 1670 HandleCopyOrCutClipboard(true); |
| 1658 } | 1671 } |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1864 gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_); | 1877 gtk_text_buffer_get_iter_at_mark(text_buffer_, &end, instant_mark_); |
| 1865 #if GTK_CHECK_VERSION(2, 20, 0) | 1878 #if GTK_CHECK_VERSION(2, 20, 0) |
| 1866 // We need to count the length of the text being composed, because we treat | 1879 // We need to count the length of the text being composed, because we treat |
| 1867 // it as part of the content in GetText(). | 1880 // it as part of the content in GetText(). |
| 1868 return gtk_text_iter_get_offset(&end) + preedit_.size(); | 1881 return gtk_text_iter_get_offset(&end) + preedit_.size(); |
| 1869 #else | 1882 #else |
| 1870 return gtk_text_iter_get_offset(&end); | 1883 return gtk_text_iter_get_offset(&end); |
| 1871 #endif | 1884 #endif |
| 1872 } | 1885 } |
| 1873 | 1886 |
| 1887 int AutocompleteEditViewGtk::GetCursorPosition() const { | |
| 1888 gint cursor_pos; | |
|
sky
2011/01/27 19:55:31
Can this be implemented in terms of GetSelection?
James Su
2011/01/27 20:07:16
I'll recheck this part to see how we can do it bet
| |
| 1889 g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, NULL); | |
| 1890 return cursor_pos; | |
| 1891 } | |
| 1892 | |
| 1893 void AutocompleteEditViewGtk::SetCursorPosition(int cursor_position) { | |
| 1894 GtkTextIter cursor; | |
| 1895 gtk_text_buffer_get_iter_at_offset(text_buffer_, &cursor, cursor_position); | |
| 1896 gtk_text_buffer_place_cursor(text_buffer_, &cursor); | |
| 1897 } | |
| 1898 | |
| 1874 void AutocompleteEditViewGtk::EmphasizeURLComponents() { | 1899 void AutocompleteEditViewGtk::EmphasizeURLComponents() { |
| 1875 #if GTK_CHECK_VERSION(2, 20, 0) | 1900 #if GTK_CHECK_VERSION(2, 20, 0) |
| 1876 // We can't change the text style easily, if the preedit string (the text | 1901 // 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 | 1902 // 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 | 1903 // 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 | 1904 // in this case, as this method will be called again when the preedit string |
| 1880 // gets committed. | 1905 // gets committed. |
| 1881 if (preedit_.size()) { | 1906 if (preedit_.size()) { |
| 1882 strikethrough_ = CharRange(); | 1907 strikethrough_ = CharRange(); |
| 1883 return; | 1908 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1939 } | 1964 } |
| 1940 } | 1965 } |
| 1941 | 1966 |
| 1942 void AutocompleteEditViewGtk::StopAnimation() { | 1967 void AutocompleteEditViewGtk::StopAnimation() { |
| 1943 // Clear the animation delegate so we don't get an AnimationEnded() callback. | 1968 // Clear the animation delegate so we don't get an AnimationEnded() callback. |
| 1944 instant_animation_->set_delegate(NULL); | 1969 instant_animation_->set_delegate(NULL); |
| 1945 instant_animation_->Stop(); | 1970 instant_animation_->Stop(); |
| 1946 UpdateInstantViewColors(); | 1971 UpdateInstantViewColors(); |
| 1947 } | 1972 } |
| 1948 | 1973 |
| 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() { | 1974 void AutocompleteEditViewGtk::TextChanged() { |
| 1960 EmphasizeURLComponents(); | 1975 EmphasizeURLComponents(); |
| 1961 controller_->OnChanged(); | 1976 controller_->OnChanged(); |
| 1962 } | 1977 } |
| 1963 | 1978 |
| 1964 void AutocompleteEditViewGtk::SavePrimarySelection( | 1979 void AutocompleteEditViewGtk::SavePrimarySelection( |
| 1965 const std::string& selected_text) { | 1980 const std::string& selected_text) { |
| 1966 GtkClipboard* clipboard = | 1981 GtkClipboard* clipboard = |
| 1967 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); | 1982 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); |
| 1968 DCHECK(clipboard); | 1983 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 | 2232 // baseline, so we need to move the |instant_view_| down to make sure it |
| 2218 // has the same baseline as the |text_view_|. | 2233 // has the same baseline as the |text_view_|. |
| 2219 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); | 2234 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); |
| 2220 int height; | 2235 int height; |
| 2221 pango_layout_get_size(layout, NULL, &height); | 2236 pango_layout_get_size(layout, NULL, &height); |
| 2222 PangoLayoutIter* iter = pango_layout_get_iter(layout); | 2237 PangoLayoutIter* iter = pango_layout_get_iter(layout); |
| 2223 int baseline = pango_layout_iter_get_baseline(iter); | 2238 int baseline = pango_layout_iter_get_baseline(iter); |
| 2224 pango_layout_iter_free(iter); | 2239 pango_layout_iter_free(iter); |
| 2225 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); | 2240 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); |
| 2226 } | 2241 } |
| OLD | NEW |