| 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 "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 insecure_scheme_tag_(NULL), | 79 insecure_scheme_tag_(NULL), |
| 80 model_(new AutocompleteEditModel(this, controller, profile)), | 80 model_(new AutocompleteEditModel(this, controller, profile)), |
| 81 popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile, | 81 popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile, |
| 82 popup_positioner)), | 82 popup_positioner)), |
| 83 controller_(controller), | 83 controller_(controller), |
| 84 toolbar_model_(toolbar_model), | 84 toolbar_model_(toolbar_model), |
| 85 command_updater_(command_updater), | 85 command_updater_(command_updater), |
| 86 popup_window_mode_(false), // TODO(deanm) | 86 popup_window_mode_(false), // TODO(deanm) |
| 87 scheme_security_level_(ToolbarModel::NORMAL), | 87 scheme_security_level_(ToolbarModel::NORMAL), |
| 88 selection_saved_(false), | 88 selection_saved_(false), |
| 89 mark_set_handler_id_(0) { | 89 mark_set_handler_id_(0), |
| 90 button_1_pressed_(false), |
| 91 text_selected_during_click_(false), |
| 92 text_view_focused_before_button_press_(false) { |
| 90 model_->set_popup_model(popup_view_->GetModel()); | 93 model_->set_popup_model(popup_view_->GetModel()); |
| 91 } | 94 } |
| 92 | 95 |
| 93 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() { | 96 AutocompleteEditViewGtk::~AutocompleteEditViewGtk() { |
| 94 NotificationService::current()->Notify( | 97 NotificationService::current()->Notify( |
| 95 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, | 98 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, |
| 96 Source<AutocompleteEditViewGtk>(this), | 99 Source<AutocompleteEditViewGtk>(this), |
| 97 NotificationService::NoDetails()); | 100 NotificationService::NoDetails()); |
| 98 | 101 |
| 99 // Explicitly teardown members which have a reference to us. Just to be safe | 102 // Explicitly teardown members which have a reference to us. Just to be safe |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 G_CALLBACK(&HandleBeginUserActionThunk), this); | 159 G_CALLBACK(&HandleBeginUserActionThunk), this); |
| 157 g_signal_connect(text_buffer_, "end-user-action", | 160 g_signal_connect(text_buffer_, "end-user-action", |
| 158 G_CALLBACK(&HandleEndUserActionThunk), this); | 161 G_CALLBACK(&HandleEndUserActionThunk), this); |
| 159 // We connect to key press and release for special handling of a few keys. | 162 // We connect to key press and release for special handling of a few keys. |
| 160 g_signal_connect(text_view_, "key-press-event", | 163 g_signal_connect(text_view_, "key-press-event", |
| 161 G_CALLBACK(&HandleKeyPressThunk), this); | 164 G_CALLBACK(&HandleKeyPressThunk), this); |
| 162 g_signal_connect(text_view_, "key-release-event", | 165 g_signal_connect(text_view_, "key-release-event", |
| 163 G_CALLBACK(&HandleKeyReleaseThunk), this); | 166 G_CALLBACK(&HandleKeyReleaseThunk), this); |
| 164 g_signal_connect(text_view_, "button-press-event", | 167 g_signal_connect(text_view_, "button-press-event", |
| 165 G_CALLBACK(&HandleViewButtonPressThunk), this); | 168 G_CALLBACK(&HandleViewButtonPressThunk), this); |
| 169 g_signal_connect(text_view_, "button-release-event", |
| 170 G_CALLBACK(&HandleViewButtonReleaseThunk), this); |
| 166 g_signal_connect(text_view_, "focus-in-event", | 171 g_signal_connect(text_view_, "focus-in-event", |
| 167 G_CALLBACK(&HandleViewFocusInThunk), this); | 172 G_CALLBACK(&HandleViewFocusInThunk), this); |
| 168 g_signal_connect(text_view_, "focus-out-event", | 173 g_signal_connect(text_view_, "focus-out-event", |
| 169 G_CALLBACK(&HandleViewFocusOutThunk), this); | 174 G_CALLBACK(&HandleViewFocusOutThunk), this); |
| 170 // NOTE: The GtkTextView documentation asks you not to connect to this | 175 // NOTE: The GtkTextView documentation asks you not to connect to this |
| 171 // signal, but it is very convenient and clean for catching up/down. | 176 // signal, but it is very convenient and clean for catching up/down. |
| 172 g_signal_connect(text_view_, "move-cursor", | 177 g_signal_connect(text_view_, "move-cursor", |
| 173 G_CALLBACK(&HandleViewMoveCursorThunk), this); | 178 G_CALLBACK(&HandleViewMoveCursorThunk), this); |
| 174 // Override the size request. We want to keep the original height request | 179 // Override the size request. We want to keep the original height request |
| 175 // from the widget, since that's font dependent. We want to ignore the width | 180 // from the widget, since that's font dependent. We want to ignore the width |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 494 |
| 490 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget, | 495 gboolean AutocompleteEditViewGtk::HandleKeyRelease(GtkWidget* widget, |
| 491 GdkEventKey* event) { | 496 GdkEventKey* event) { |
| 492 // Even though we handled the press ourselves, let GtkTextView handle the | 497 // Even though we handled the press ourselves, let GtkTextView handle the |
| 493 // release. It shouldn't do anything particularly interesting, but it will | 498 // release. It shouldn't do anything particularly interesting, but it will |
| 494 // handle the IME work for us. | 499 // handle the IME work for us. |
| 495 return FALSE; // Propagate into GtkTextView. | 500 return FALSE; // Propagate into GtkTextView. |
| 496 } | 501 } |
| 497 | 502 |
| 498 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) { | 503 gboolean AutocompleteEditViewGtk::HandleViewButtonPress(GdkEventButton* event) { |
| 499 // When the GtkTextView is clicked, it will call gtk_widget_grab_focus. | 504 if (event->button == 1) { |
| 500 // I believe this causes the focus-in event to be fired before the main | 505 // When the first button is pressed, track some stuff that will help us |
| 501 // clicked handling code. If we were to try to set the selection from | 506 // determine whether we should select all of the text when the button is |
| 502 // the focus-in event, it's just going to be undone by the click handler. | 507 // released. |
| 503 // This is a bit ugly. We shim in to get the click before the GtkTextView, | 508 button_1_pressed_ = true; |
| 504 // then if we don't have focus, we (hopefully safely) assume that the click | 509 text_view_focused_before_button_press_ = GTK_WIDGET_HAS_FOCUS(text_view_); |
| 505 // will cause us to become focused. We call GtkTextView's default handler | 510 text_selected_during_click_ = false; |
| 506 // and then stop propagation. This allows us to run our code after the | 511 } |
| 507 // default handler, even if that handler stopped propagation. | 512 return FALSE; |
| 508 if (GTK_WIDGET_HAS_FOCUS(text_view_)) | 513 } |
| 509 return FALSE; // Continue to propagate into the GtkTextView handler. | |
| 510 | 514 |
| 511 // We only want to select everything on left-click; otherwise we'll end up | 515 gboolean AutocompleteEditViewGtk::HandleViewButtonRelease( |
| 512 // stealing the PRIMARY selection when the user middle-clicks to paste it | 516 GdkEventButton* event) { |
| 513 // here. | |
| 514 if (event->button != 1) | 517 if (event->button != 1) |
| 515 return FALSE; | 518 return FALSE; |
| 516 | 519 |
| 520 button_1_pressed_ = false; |
| 521 |
| 517 // Call the GtkTextView default handler, ignoring the fact that it will | 522 // Call the GtkTextView default handler, ignoring the fact that it will |
| 518 // likely have told us to stop propagating. We want to handle selection. | 523 // likely have told us to stop propagating. We want to handle selection. |
| 519 GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(text_view_); | 524 GtkWidgetClass* klass = GTK_WIDGET_GET_CLASS(text_view_); |
| 520 klass->button_press_event(text_view_, event); | 525 klass->button_release_event(text_view_, event); |
| 521 | 526 |
| 522 // Select the full input and update the PRIMARY selection when we get focus. | 527 if (!text_view_focused_before_button_press_ && !text_selected_during_click_) { |
| 523 SelectAllInternal(false, true); | 528 // If this was a focusing click and the user didn't drag to highlight any |
| 529 // text, select the full input and update the PRIMARY selection. |
| 530 SelectAllInternal(false, true); |
| 524 | 531 |
| 525 // So we told the buffer where the cursor should be, but make sure to tell | 532 // So we told the buffer where the cursor should be, but make sure to tell |
| 526 // the view so it can scroll it to be visible if needed. | 533 // the view so it can scroll it to be visible if needed. |
| 527 // NOTE: This function doesn't seem to like a count of 0, looking at the | 534 // NOTE: This function doesn't seem to like a count of 0, looking at the |
| 528 // code it will skip an important loop. Use -1 to achieve the same. | 535 // code it will skip an important loop. Use -1 to achieve the same. |
| 529 GtkTextIter start, end; | 536 GtkTextIter start, end; |
| 530 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); | 537 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); |
| 531 gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1); | 538 gtk_text_view_move_visually(GTK_TEXT_VIEW(text_view_), &start, -1); |
| 539 } |
| 532 | 540 |
| 533 return TRUE; // Don't continue, we called the default handler already. | 541 return TRUE; // Don't continue, we called the default handler already. |
| 534 } | 542 } |
| 535 | 543 |
| 536 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { | 544 gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { |
| 537 model_->OnSetFocus(false); | 545 model_->OnSetFocus(false); |
| 538 // TODO(deanm): Some keyword hit business, etc here. | 546 // TODO(deanm): Some keyword hit business, etc here. |
| 539 | 547 |
| 540 return FALSE; // Continue propagation. | 548 return FALSE; // Continue propagation. |
| 541 } | 549 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 size_t text_len = strlen(text); | 642 size_t text_len = strlen(text); |
| 635 if (!text_len) { | 643 if (!text_len) { |
| 636 no_text_selected = true; | 644 no_text_selected = true; |
| 637 } else { | 645 } else { |
| 638 selected_text_ = std::string(text, text_len); | 646 selected_text_ = std::string(text, text_len); |
| 639 selection_saved_ = false; | 647 selection_saved_ = false; |
| 640 } | 648 } |
| 641 g_free(text); | 649 g_free(text); |
| 642 } | 650 } |
| 643 | 651 |
| 652 // If the user just selected some text with the mouse (or at least while the |
| 653 // mouse button was down), make sure that we won't blow their selection away |
| 654 // later by selecting all of the text when the button is released. |
| 655 if (button_1_pressed_ && !no_text_selected) { |
| 656 text_selected_during_click_ = true; |
| 657 } |
| 658 |
| 644 // If we have some previously-selected text but it's no longer highlighted | 659 // If we have some previously-selected text but it's no longer highlighted |
| 645 // and we haven't saved it as the selection yet, we save it now. | 660 // and we haven't saved it as the selection yet, we save it now. |
| 646 if (!selected_text_.empty() && no_text_selected && !selection_saved_) { | 661 if (!selected_text_.empty() && no_text_selected && !selection_saved_) { |
| 647 SavePrimarySelection(selected_text_); | 662 SavePrimarySelection(selected_text_); |
| 648 selection_saved_ = true; | 663 selection_saved_ = true; |
| 649 } | 664 } |
| 650 } | 665 } |
| 651 | 666 |
| 652 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed, | 667 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed, |
| 653 bool update_primary_selection) { | 668 bool update_primary_selection) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 const std::string& selected_text) { | 796 const std::string& selected_text) { |
| 782 GtkClipboard* clipboard = | 797 GtkClipboard* clipboard = |
| 783 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); | 798 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); |
| 784 DCHECK(clipboard); | 799 DCHECK(clipboard); |
| 785 if (!clipboard) | 800 if (!clipboard) |
| 786 return; | 801 return; |
| 787 | 802 |
| 788 gtk_clipboard_set_text( | 803 gtk_clipboard_set_text( |
| 789 clipboard, selected_text.data(), selected_text.size()); | 804 clipboard, selected_text.data(), selected_text.size()); |
| 790 } | 805 } |
| OLD | NEW |