diff options
author | suzhe@google.com <suzhe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-28 00:53:35 +0000 |
---|---|---|
committer | suzhe@google.com <suzhe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-28 00:53:35 +0000 |
commit | 2f399395e09bbe0872a1fea9f9e3de7efdfaf1ed (patch) | |
tree | 36998fac7d445b572511276286cd3eec33828ecf /views | |
parent | b4e6d2db0de191126e1542bc2db2ec292d68462c (diff) | |
download | chromium_src-2f399395e09bbe0872a1fea9f9e3de7efdfaf1ed.zip chromium_src-2f399395e09bbe0872a1fea9f9e3de7efdfaf1ed.tar.gz chromium_src-2f399395e09bbe0872a1fea9f9e3de7efdfaf1ed.tar.bz2 |
Trigger find in page when pasting even if the text is not changed.
BUG=79002
TEST=See bug report.
Review URL: http://codereview.chromium.org/6825034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83268 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/controls/textfield/native_textfield_gtk.cc | 130 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_gtk.h | 46 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_views.cc | 17 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_views.h | 4 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_win.cc | 6 |
5 files changed, 108 insertions, 95 deletions
diff --git a/views/controls/textfield/native_textfield_gtk.cc b/views/controls/textfield/native_textfield_gtk.cc index 77b3940..dd0dc8f 100644 --- a/views/controls/textfield/native_textfield_gtk.cc +++ b/views/controls/textfield/native_textfield_gtk.cc @@ -32,7 +32,8 @@ const int kTextViewBorderWidth = 4; // NativeTextfieldGtk, public: NativeTextfieldGtk::NativeTextfieldGtk(Textfield* textfield) - : textfield_(textfield) { + : textfield_(textfield), + paste_clipboard_requested_(false) { if (textfield_->IsMultiLine() && textfield_->IsPassword()) NOTIMPLEMENTED(); // We don't support multiline password yet. // Make |textfield| the focused view, so that when we get focused the focus @@ -380,34 +381,10 @@ TextInputClient* NativeTextfieldGtk::GetTextInputClient() { return NULL; } -// static -gboolean NativeTextfieldGtk::OnKeyPressEventHandler( - GtkWidget* widget, - GdkEventKey* event, - NativeTextfieldGtk* textfield) { - return textfield->OnKeyPressEvent(event); -} - -gboolean NativeTextfieldGtk::OnKeyPressEvent(GdkEventKey* event) { - TextfieldController* controller = textfield_->GetController(); - if (controller) { - KeyEvent key_event(reinterpret_cast<GdkEvent*>(event)); - return controller->HandleKeyEvent(textfield_, key_event); - } - return false; -} - -// static -gboolean NativeTextfieldGtk::OnActivateHandler( - GtkWidget* widget, - NativeTextfieldGtk* textfield) { - return textfield->OnActivate(); -} - -gboolean NativeTextfieldGtk::OnActivate() { +void NativeTextfieldGtk::OnActivate(GtkWidget* native_widget) { GdkEvent* event = gtk_get_current_event(); if (!event || event->type != GDK_KEY_PRESS) - return false; + return; KeyEvent views_key_event(event); gboolean handled = false; @@ -420,51 +397,70 @@ gboolean NativeTextfieldGtk::OnActivate() { if (!handled && widget) handled = widget->HandleKeyboardEvent(views_key_event); - return handled; -} - -// static -gboolean NativeTextfieldGtk::OnChangedHandler( - GtkWidget* widget, - NativeTextfieldGtk* textfield) { - return textfield->OnChanged(); + // Stop signal emission if the key event is handled by us. + if (handled) { + // Only GtkEntry has "activate" signal. + static guint signal_id = g_signal_lookup("activate", GTK_TYPE_ENTRY); + g_signal_stop_emission(native_widget, signal_id, 0); + } } -gboolean NativeTextfieldGtk::OnChanged() { +void NativeTextfieldGtk::OnChanged(GObject* object) { + // We need to call TextfieldController::ContentsChanged() explicitly if the + // paste action didn't change the content at all. See http://crbug.com/79002 + const bool call_contents_changed = + paste_clipboard_requested_ && GetText() == textfield_->text(); textfield_->SyncText(); textfield_->GetWidget()->NotifyAccessibilityEvent( textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); - return false; + if (call_contents_changed) { + TextfieldController* controller = textfield_->GetController(); + if (controller) + controller->ContentsChanged(textfield_, textfield_->text()); + } + paste_clipboard_requested_ = false; } -// static -gboolean NativeTextfieldGtk::OnMoveCursorHandler( - GtkWidget* widget, - GtkMovementStep step, - gint count, - gboolean extend_selection, - NativeTextfieldGtk* textfield) { - return textfield->OnMoveCursor(); +gboolean NativeTextfieldGtk::OnButtonPressEvent(GtkWidget* widget, + GdkEventButton* event) { + paste_clipboard_requested_ = false; + return false; } -gboolean NativeTextfieldGtk::OnMoveCursor() { +gboolean NativeTextfieldGtk::OnButtonReleaseEventAfter(GtkWidget* widget, + GdkEventButton* event) { textfield_->GetWidget()->NotifyAccessibilityEvent( textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); return false; } -// static -gboolean NativeTextfieldGtk::OnMouseUpHandler( - GtkWidget* widget, - GdkEvent* event, - NativeTextfieldGtk* textfield) { - return textfield->OnMouseUp(); +gboolean NativeTextfieldGtk::OnKeyPressEvent(GtkWidget* widget, + GdkEventKey* event) { + paste_clipboard_requested_ = false; + return false; +} + +gboolean NativeTextfieldGtk::OnKeyPressEventAfter(GtkWidget* widget, + GdkEventKey* event) { + TextfieldController* controller = textfield_->GetController(); + if (controller) { + KeyEvent key_event(reinterpret_cast<GdkEvent*>(event)); + return controller->HandleKeyEvent(textfield_, key_event); + } + return false; } -gboolean NativeTextfieldGtk::OnMouseUp() { +void NativeTextfieldGtk::OnMoveCursor(GtkWidget* widget, + GtkMovementStep step, + gint count, + gboolean extend_selection) { textfield_->GetWidget()->NotifyAccessibilityEvent( textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); - return false; +} + +void NativeTextfieldGtk::OnPasteClipboard(GtkWidget* widget) { + if (!textfield_->read_only()) + paste_clipboard_requested_ = true; } //////////////////////////////////////////////////////////////////////////////// @@ -493,21 +489,25 @@ void NativeTextfieldGtk::NativeControlCreated(GtkWidget* widget) { if (GTK_IS_TEXT_VIEW(widget)) { GtkTextBuffer* text_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(widget)); - g_signal_connect(text_buffer, "changed", - G_CALLBACK(OnChangedHandler), this); + g_signal_connect(text_buffer, "changed", G_CALLBACK(OnChangedThunk), this); } else { - g_signal_connect(widget, "changed", - G_CALLBACK(OnChangedHandler), this); + g_signal_connect(widget, "changed", G_CALLBACK(OnChangedThunk), this); + // In order to properly trigger Accelerators bound to VKEY_RETURN, we need + // to send an event when the widget gets the activate signal. + g_signal_connect(widget, "activate", G_CALLBACK(OnActivateThunk), this); } - g_signal_connect_after(widget, "move-cursor", - G_CALLBACK(OnMoveCursorHandler), this); + g_signal_connect(widget, "move-cursor", G_CALLBACK(OnMoveCursorThunk), this); + g_signal_connect(widget, "button-press-event", + G_CALLBACK(OnButtonPressEventThunk), this); + g_signal_connect(widget, "key-press-event", + G_CALLBACK(OnKeyPressEventThunk), this); + g_signal_connect(widget, "paste-clipboard", + G_CALLBACK(OnPasteClipboardThunk), this); + g_signal_connect_after(widget, "button-release-event", - G_CALLBACK(OnMouseUpHandler), this); + G_CALLBACK(OnButtonReleaseEventAfterThunk), this); g_signal_connect_after(widget, "key-press-event", - G_CALLBACK(OnKeyPressEventHandler), this); - // In order to properly trigger Accelerators bound to VKEY_RETURN, we need to - // send an event when the widget gets the activate signal. - g_signal_connect(widget, "activate", G_CALLBACK(OnActivateHandler), this); + G_CALLBACK(OnKeyPressEventAfterThunk), this); } bool NativeTextfieldGtk::IsPassword() { diff --git a/views/controls/textfield/native_textfield_gtk.h b/views/controls/textfield/native_textfield_gtk.h index b28dd2e..0e7eb58 100644 --- a/views/controls/textfield/native_textfield_gtk.h +++ b/views/controls/textfield/native_textfield_gtk.h @@ -9,6 +9,7 @@ #include <gtk/gtk.h> #include "base/string16.h" +#include "ui/base/gtk/gtk_signal.h" #include "views/controls/native_control_gtk.h" #include "views/controls/textfield/native_textfield_wrapper.h" @@ -65,34 +66,27 @@ class NativeTextfieldGtk : public NativeControlGtk, bool IsPassword(); private: + // Gtk signal callbacks. + CHROMEGTK_CALLBACK_0(NativeTextfieldGtk, void, OnActivate); + CHROMEGTK_CALLBACK_1(NativeTextfieldGtk, gboolean, OnButtonPressEvent, + GdkEventButton*); + CHROMEGTK_CALLBACK_1(NativeTextfieldGtk, gboolean, OnButtonReleaseEventAfter, + GdkEventButton*); + CHROMEG_CALLBACK_0(NativeTextfieldGtk, void, OnChanged, GObject*); + CHROMEGTK_CALLBACK_1(NativeTextfieldGtk, gboolean, OnKeyPressEvent, + GdkEventKey*); + CHROMEGTK_CALLBACK_1(NativeTextfieldGtk, gboolean, OnKeyPressEventAfter, + GdkEventKey*); + CHROMEGTK_CALLBACK_3(NativeTextfieldGtk, void, OnMoveCursor, + GtkMovementStep, gint, gboolean); + CHROMEGTK_CALLBACK_0(NativeTextfieldGtk, void, OnPasteClipboard); + Textfield* textfield_; - // Callback when the entry text changes. - static gboolean OnKeyPressEventHandler( - GtkWidget* entry, - GdkEventKey* event, - NativeTextfieldGtk* textfield); - gboolean OnKeyPressEvent(GdkEventKey* event); - static gboolean OnActivateHandler( - GtkWidget* entry, - NativeTextfieldGtk* textfield); - gboolean OnActivate(); - static gboolean OnChangedHandler( - GtkWidget* entry, - NativeTextfieldGtk* textfield); - gboolean OnChanged(); - static gboolean OnMoveCursorHandler( - GtkWidget* entry, - GtkMovementStep step, - gint count, - gboolean extend_selection, - NativeTextfieldGtk* textfield); - gboolean OnMoveCursor(); - static gboolean OnMouseUpHandler( - GtkWidget* entry, - GdkEvent* event, - NativeTextfieldGtk* textfield); - gboolean OnMouseUp(); + // Indicates that user requested to paste clipboard. + // The actual paste clipboard action might be performed later if the + // clipboard is not empty. + bool paste_clipboard_requested_; DISALLOW_COPY_AND_ASSIGN(NativeTextfieldGtk); }; diff --git a/views/controls/textfield/native_textfield_views.cc b/views/controls/textfield/native_textfield_views.cc index 73b95f3..1f4f0d8 100644 --- a/views/controls/textfield/native_textfield_views.cc +++ b/views/controls/textfield/native_textfield_views.cc @@ -372,7 +372,7 @@ void NativeTextfieldViews::ExecuteCommand(int command_id) { break; case IDS_APP_PASTE: if (editable) - text_changed = model_->Paste(); + text_changed = Paste(); break; case IDS_APP_DELETE: if (editable) @@ -735,7 +735,7 @@ bool NativeTextfieldViews::HandleKeyEvent(const KeyEvent& key_event) { break; case ui::VKEY_V: if (control && editable) - cursor_changed = text_changed = model_->Paste(); + cursor_changed = text_changed = Paste(); break; case ui::VKEY_RIGHT: control ? model_->MoveCursorToNextWord(selection) @@ -939,6 +939,19 @@ void NativeTextfieldViews::OnAfterUserAction() { controller->OnAfterUserAction(textfield_); } +bool NativeTextfieldViews::Paste() { + const bool success = model_->Paste(); + + // Calls TextfieldController::ContentsChanged() explicitly if the paste action + // did not change the content at all. See http://crbug.com/79002 + if (success && model_->text() == textfield_->text()) { + TextfieldController* controller = textfield_->GetController(); + if (controller) + controller->ContentsChanged(textfield_, textfield_->text()); + } + return success; +} + // static bool NativeTextfieldViews::ShouldInsertChar(char16 ch, int flags) { // Filter out all control characters, including tab and new line characters, diff --git a/views/controls/textfield/native_textfield_views.h b/views/controls/textfield/native_textfield_views.h index 532c8ec..1803e21 100644 --- a/views/controls/textfield/native_textfield_views.h +++ b/views/controls/textfield/native_textfield_views.h @@ -230,6 +230,10 @@ class NativeTextfieldViews : public views::View, // Convenience method to call TextfieldController::OnAfterUserAction(); void OnAfterUserAction(); + // Calls |model_->Paste()| and calls TextfieldController::ContentsChanged() + // explicitly if paste succeeded. + bool Paste(); + // Checks if a char is ok to be inserted into the textfield. The |ch| is a // modified character, i.e., modifiers took effect when generating this char. static bool ShouldInsertChar(char16 ch, int flags); diff --git a/views/controls/textfield/native_textfield_win.cc b/views/controls/textfield/native_textfield_win.cc index a7e7443..9c4d196 100644 --- a/views/controls/textfield/native_textfield_win.cc +++ b/views/controls/textfield/native_textfield_win.cc @@ -907,8 +907,10 @@ void NativeTextfieldWin::OnPaste() { std::wstring collapsed(CollapseWhitespace(clipboard_str, false)); if (textfield_->style() & Textfield::STYLE_LOWERCASE) collapsed = l10n_util::ToLower(collapsed); - // Force a Paste operation to trigger OnContentsChanged, even if identical - // contents are pasted into the text box. + // Force a Paste operation to trigger ContentsChanged, even if identical + // contents are pasted into the text box. See http://crbug.com/79002 + ReplaceSel(L"", false); + textfield_->SyncText(); text_before_change_.clear(); ReplaceSel(collapsed.c_str(), true); } |