| 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |