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/ui/gtk/omnibox/omnibox_view_gtk.h" | 5 #include "chrome/browser/ui/gtk/omnibox/omnibox_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> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "base/utf_string_conversion_utils.h" | |
15 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
16 #include "chrome/app/chrome_command_ids.h" | 15 #include "chrome/app/chrome_command_ids.h" |
17 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 16 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
18 #include "chrome/browser/autocomplete/autocomplete_match.h" | 17 #include "chrome/browser/autocomplete/autocomplete_match.h" |
19 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 18 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
20 #include "chrome/browser/bookmarks/bookmark_node_data.h" | 19 #include "chrome/browser/bookmarks/bookmark_node_data.h" |
21 #include "chrome/browser/command_updater.h" | 20 #include "chrome/browser/command_updater.h" |
22 #include "chrome/browser/defaults.h" | 21 #include "chrome/browser/defaults.h" |
23 #include "chrome/browser/instant/instant_controller.h" | 22 #include "chrome/browser/instant/instant_controller.h" |
24 #include "chrome/browser/platform_util.h" | 23 #include "chrome/browser/platform_util.h" |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 int OmniboxViewGtk::OnPerformDrop( | 873 int OmniboxViewGtk::OnPerformDrop( |
875 const views::DropTargetEvent& event) { | 874 const views::DropTargetEvent& event) { |
876 string16 text; | 875 string16 text; |
877 const ui::OSExchangeData& data = event.data(); | 876 const ui::OSExchangeData& data = event.data(); |
878 if (data.HasURL()) { | 877 if (data.HasURL()) { |
879 GURL url; | 878 GURL url; |
880 string16 title; | 879 string16 title; |
881 if (data.GetURLAndTitle(&url, &title)) | 880 if (data.GetURLAndTitle(&url, &title)) |
882 text = UTF8ToUTF16(url.spec()); | 881 text = UTF8ToUTF16(url.spec()); |
883 } else { | 882 } else { |
884 data.GetString(&text); | 883 string16 data_string; |
| 884 if (data.GetString(&data_string)) |
| 885 text = CollapseWhitespace(data_string, true); |
885 } | 886 } |
886 | 887 |
887 if (!text.empty() && OnPerformDropImpl(text)) | 888 if (!text.empty() && OnPerformDropImpl(text)) |
888 return CopyOrLinkDragOperation(event.source_operations()); | 889 return CopyOrLinkDragOperation(event.source_operations()); |
889 | 890 |
890 return ui::DragDropTypes::DRAG_NONE; | 891 return ui::DragDropTypes::DRAG_NONE; |
891 } | 892 } |
892 #endif // defined(TOOLKIT_VIEWS) | 893 #endif // defined(TOOLKIT_VIEWS) |
893 | 894 |
894 void OmniboxViewGtk::Observe(int type, | 895 void OmniboxViewGtk::Observe(int type, |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 gtk_widget_set_sensitive(search_engine_menuitem, | 1439 gtk_widget_set_sensitive(search_engine_menuitem, |
1439 command_updater_->IsCommandEnabled(IDC_EDIT_SEARCH_ENGINES)); | 1440 command_updater_->IsCommandEnabled(IDC_EDIT_SEARCH_ENGINES)); |
1440 gtk_widget_show(search_engine_menuitem); | 1441 gtk_widget_show(search_engine_menuitem); |
1441 | 1442 |
1442 // We need to update the paste and go controller before we know what text | 1443 // We need to update the paste and go controller before we know what text |
1443 // to show. We could do this all asynchronously, but it would be elaborate | 1444 // to show. We could do this all asynchronously, but it would be elaborate |
1444 // because we'd have to account for multiple menus showing, getting called | 1445 // because we'd have to account for multiple menus showing, getting called |
1445 // back after shutdown, and similar issues. | 1446 // back after shutdown, and similar issues. |
1446 GtkClipboard* x_clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | 1447 GtkClipboard* x_clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); |
1447 gchar* text = gtk_clipboard_wait_for_text(x_clipboard); | 1448 gchar* text = gtk_clipboard_wait_for_text(x_clipboard); |
1448 string16 sanitized_text(text ? | 1449 string16 text_wstr = UTF8ToUTF16(text ? text : ""); |
1449 StripJavascriptSchemas(CollapseWhitespace(UTF8ToUTF16(text), true)) : | |
1450 string16()); | |
1451 g_free(text); | 1450 g_free(text); |
1452 | 1451 |
1453 // Paste and Go menu item. Note that CanPasteAndGo() needs to be called | 1452 // Paste and Go menu item. |
1454 // before is_paste_and_search() in order to set up the paste-and-go state. | |
1455 bool can_paste_and_go = model_->CanPasteAndGo(sanitized_text); | |
1456 GtkWidget* paste_go_menuitem = gtk_menu_item_new_with_mnemonic( | 1453 GtkWidget* paste_go_menuitem = gtk_menu_item_new_with_mnemonic( |
1457 gfx::ConvertAcceleratorsFromWindowsStyle( | 1454 gfx::ConvertAcceleratorsFromWindowsStyle( |
1458 l10n_util::GetStringUTF8(model_->is_paste_and_search() ? | 1455 l10n_util::GetStringUTF8(model_->is_paste_and_search() ? |
1459 IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO)).c_str()); | 1456 IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO)).c_str()); |
1460 gtk_menu_shell_append(GTK_MENU_SHELL(menu), paste_go_menuitem); | 1457 gtk_menu_shell_append(GTK_MENU_SHELL(menu), paste_go_menuitem); |
1461 g_signal_connect(paste_go_menuitem, "activate", | 1458 g_signal_connect(paste_go_menuitem, "activate", |
1462 G_CALLBACK(HandlePasteAndGoThunk), this); | 1459 G_CALLBACK(HandlePasteAndGoThunk), this); |
1463 gtk_widget_set_sensitive(paste_go_menuitem, can_paste_and_go); | 1460 gtk_widget_set_sensitive(paste_go_menuitem, |
| 1461 model_->CanPasteAndGo(text_wstr)); |
1464 gtk_widget_show(paste_go_menuitem); | 1462 gtk_widget_show(paste_go_menuitem); |
1465 | 1463 |
1466 g_signal_connect(menu, "deactivate", | 1464 g_signal_connect(menu, "deactivate", |
1467 G_CALLBACK(HandlePopupMenuDeactivateThunk), this); | 1465 G_CALLBACK(HandlePopupMenuDeactivateThunk), this); |
1468 } | 1466 } |
1469 | 1467 |
1470 void OmniboxViewGtk::HandleEditSearchEngines(GtkWidget* sender) { | 1468 void OmniboxViewGtk::HandleEditSearchEngines(GtkWidget* sender) { |
1471 command_updater_->ExecuteCommand(IDC_EDIT_SEARCH_ENGINES); | 1469 command_updater_->ExecuteCommand(IDC_EDIT_SEARCH_ENGINES); |
1472 } | 1470 } |
1473 | 1471 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1629 GtkTargetList* copy_targets = | 1627 GtkTargetList* copy_targets = |
1630 gtk_text_buffer_get_copy_target_list(text_buffer_); | 1628 gtk_text_buffer_get_copy_target_list(text_buffer_); |
1631 gtk_target_list_remove(copy_targets, atom); | 1629 gtk_target_list_remove(copy_targets, atom); |
1632 dragged_text_.clear(); | 1630 dragged_text_.clear(); |
1633 } | 1631 } |
1634 | 1632 |
1635 void OmniboxViewGtk::HandleInsertText(GtkTextBuffer* buffer, | 1633 void OmniboxViewGtk::HandleInsertText(GtkTextBuffer* buffer, |
1636 GtkTextIter* location, | 1634 GtkTextIter* location, |
1637 const gchar* text, | 1635 const gchar* text, |
1638 gint len) { | 1636 gint len) { |
1639 string16 filtered_text; | 1637 std::string filtered_text; |
1640 filtered_text.reserve(len); | 1638 filtered_text.reserve(len); |
1641 | 1639 |
1642 // Filter out new line and tab characters. | 1640 // Filter out new line and tab characters. |
1643 // |text| is guaranteed to be a valid UTF-8 string, so we don't need to | 1641 // |text| is guaranteed to be a valid UTF-8 string, so we don't need to |
1644 // validate it here. | 1642 // validate it here. |
1645 // | 1643 // |
1646 // If there was only a single character, then it might be generated by a key | 1644 // If there was only a single character, then it might be generated by a key |
1647 // event. In this case, we save the single character to help our | 1645 // event. In this case, we save the single character to help our |
1648 // "key-press-event" signal handler distinguish if an Enter key event is | 1646 // "key-press-event" signal handler distinguish if an Enter key event is |
1649 // handled by IME or not. | 1647 // handled by IME or not. |
1650 if (len == 1 && (text[0] == '\n' || text[0] == '\r')) | 1648 if (len == 1 && (text[0] == '\n' || text[0] == '\r')) |
1651 enter_was_inserted_ = true; | 1649 enter_was_inserted_ = true; |
1652 | 1650 |
1653 for (const gchar* p = text; *p && (p - text) < len; | 1651 const gchar* p = text; |
1654 p = g_utf8_next_char(p)) { | 1652 while (*p && (p - text) < len) { |
1655 gunichar c = g_utf8_get_char(p); | 1653 gunichar c = g_utf8_get_char(p); |
| 1654 const gchar* next = g_utf8_next_char(p); |
1656 | 1655 |
1657 // 0x200B is Zero Width Space, which is inserted just before the instant | 1656 // 0x200B is Zero Width Space, which is inserted just before the instant |
1658 // anchor for working around the GtkTextView's misalignment bug. | 1657 // anchor for working around the GtkTextView's misalignment bug. |
1659 // This character might be captured and inserted into the content by undo | 1658 // This character might be captured and inserted into the content by undo |
1660 // manager, so we need to filter it out here. | 1659 // manager, so we need to filter it out here. |
1661 if (c != 0x200B) | 1660 if (c != L'\n' && c != L'\r' && c != L'\t' && c != 0x200B) |
1662 base::WriteUnicodeCharacter(c, &filtered_text); | 1661 filtered_text.append(p, next); |
| 1662 |
| 1663 p = next; |
1663 } | 1664 } |
1664 | 1665 |
1665 if (model_->is_pasting()) | 1666 if (filtered_text.length()) { |
1666 filtered_text = StripJavascriptSchemas( | |
1667 CollapseWhitespace(filtered_text, true)); | |
1668 | |
1669 if (!filtered_text.empty()) { | |
1670 // Avoid inserting the text after the instant anchor. | 1667 // Avoid inserting the text after the instant anchor. |
1671 ValidateTextBufferIter(location); | 1668 ValidateTextBufferIter(location); |
1672 | 1669 |
1673 // Call the default handler to insert filtered text. | 1670 // Call the default handler to insert filtered text. |
1674 GtkTextBufferClass* klass = GTK_TEXT_BUFFER_GET_CLASS(buffer); | 1671 GtkTextBufferClass* klass = GTK_TEXT_BUFFER_GET_CLASS(buffer); |
1675 std::string utf8_text = UTF16ToUTF8(filtered_text); | 1672 klass->insert_text(buffer, location, filtered_text.data(), |
1676 klass->insert_text(buffer, location, utf8_text.data(), | 1673 static_cast<gint>(filtered_text.length())); |
1677 static_cast<gint>(utf8_text.length())); | |
1678 } | 1674 } |
1679 | 1675 |
1680 // Stop propagating the signal emission to prevent the default handler from | 1676 // Stop propagating the signal emission to prevent the default handler from |
1681 // being called again. | 1677 // being called again. |
1682 static guint signal_id = g_signal_lookup("insert-text", GTK_TYPE_TEXT_BUFFER); | 1678 static guint signal_id = g_signal_lookup("insert-text", GTK_TYPE_TEXT_BUFFER); |
1683 g_signal_stop_emission(buffer, signal_id, 0); | 1679 g_signal_stop_emission(buffer, signal_id, 0); |
1684 } | 1680 } |
1685 | 1681 |
1686 void OmniboxViewGtk::HandleBackSpace(GtkWidget* sender) { | 1682 void OmniboxViewGtk::HandleBackSpace(GtkWidget* sender) { |
1687 // Checks if it's currently in keyword search mode. | 1683 // Checks if it's currently in keyword search mode. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 0); | 1790 0); |
1795 | 1791 |
1796 if (!copy && gtk_text_view_get_editable(GTK_TEXT_VIEW(text_view_))) | 1792 if (!copy && gtk_text_view_get_editable(GTK_TEXT_VIEW(text_view_))) |
1797 gtk_text_buffer_delete_selection(text_buffer_, true, true); | 1793 gtk_text_buffer_delete_selection(text_buffer_, true, true); |
1798 } | 1794 } |
1799 | 1795 |
1800 OwnPrimarySelection(UTF16ToUTF8(text)); | 1796 OwnPrimarySelection(UTF16ToUTF8(text)); |
1801 } | 1797 } |
1802 | 1798 |
1803 bool OmniboxViewGtk::OnPerformDropImpl(const string16& text) { | 1799 bool OmniboxViewGtk::OnPerformDropImpl(const string16& text) { |
1804 if (model_->CanPasteAndGo(StripJavascriptSchemas( | 1800 if (model_->CanPasteAndGo(CollapseWhitespace(text, true))) { |
1805 CollapseWhitespace(text, true)))) { | |
1806 model_->PasteAndGo(); | 1801 model_->PasteAndGo(); |
1807 return true; | 1802 return true; |
1808 } | 1803 } |
1809 | 1804 |
1810 return false; | 1805 return false; |
1811 } | 1806 } |
1812 | 1807 |
1813 gfx::Font OmniboxViewGtk::GetFont() { | 1808 gfx::Font OmniboxViewGtk::GetFont() { |
1814 #if defined(TOOLKIT_VIEWS) | 1809 #if defined(TOOLKIT_VIEWS) |
1815 bool use_gtk = false; | 1810 bool use_gtk = false; |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2401 | 2396 |
2402 // Make all the children of the widget visible. NOTE: this won't display | 2397 // Make all the children of the widget visible. NOTE: this won't display |
2403 // anything, it just toggles the visible flag. | 2398 // anything, it just toggles the visible flag. |
2404 gtk_widget_show_all(omnibox_view->GetNativeView()); | 2399 gtk_widget_show_all(omnibox_view->GetNativeView()); |
2405 // Hide the widget. NativeViewHostGtk will make it visible again as necessary. | 2400 // Hide the widget. NativeViewHostGtk will make it visible again as necessary. |
2406 gtk_widget_hide(omnibox_view->GetNativeView()); | 2401 gtk_widget_hide(omnibox_view->GetNativeView()); |
2407 | 2402 |
2408 return omnibox_view; | 2403 return omnibox_view; |
2409 } | 2404 } |
2410 #endif | 2405 #endif |
OLD | NEW |