diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-20 02:04:41 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-20 02:04:41 +0000 |
commit | ddbf30172076500e7b5715201ad7f528f7b3a4d6 (patch) | |
tree | f0c468f70520cbda8ed6f73143a329bf944d68f7 /webkit/glue/editor_client_impl.cc | |
parent | ac82401483eb837c35ea54402cf10ad2393817c4 (diff) | |
download | chromium_src-ddbf30172076500e7b5715201ad7f528f7b3a4d6.zip chromium_src-ddbf30172076500e7b5715201ad7f528f7b3a4d6.tar.gz chromium_src-ddbf30172076500e7b5715201ad7f528f7b3a4d6.tar.bz2 |
Review URL: http://codereview.chromium.org/11306
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5747 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/editor_client_impl.cc')
-rw-r--r-- | webkit/glue/editor_client_impl.cc | 121 |
1 files changed, 37 insertions, 84 deletions
diff --git a/webkit/glue/editor_client_impl.cc b/webkit/glue/editor_client_impl.cc index 27c2657..722d5fb 100644 --- a/webkit/glue/editor_client_impl.cc +++ b/webkit/glue/editor_client_impl.cc @@ -17,7 +17,6 @@ MSVC_PUSH_WARNING_LEVEL(0); #include "EventNames.h" #include "KeyboardCodes.h" #include "HTMLInputElement.h" -#include "HTMLNames.h" #include "Frame.h" #include "KeyboardEvent.h" #include "PlatformKeyboardEvent.h" @@ -25,7 +24,6 @@ MSVC_PUSH_WARNING_LEVEL(0); MSVC_POP_WARNING(); #undef LOG -#include "base/message_loop.h" #include "base/string_util.h" #include "webkit/glue/editor_client_impl.h" #include "webkit/glue/glue_util.h" @@ -39,10 +37,6 @@ MSVC_POP_WARNING(); // into a single action. static const size_t kMaximumUndoStackDepth = 1000; -// The size above which we stop triggering autofill for an input text field -// (so to avoid sending long strings through IPC). -static const size_t kMaximumTextSizeForAutofill = 1000; - namespace { // Record an editor command from the keyDownEntries[] below. We ignore the @@ -69,11 +63,8 @@ EditorClientImpl::EditorClientImpl(WebView* web_view) : web_view_(static_cast<WebViewImpl*>(web_view)), use_editor_delegate_(false), in_redo_(false), - backspace_pressed_(false), -// Don't complain about using "this" in initializer list. -MSVC_PUSH_DISABLE_WARNING(4355) - autofill_factory_(this) { -MSVC_POP_WARNING() + preserve_(false), + pending_inline_autocompleted_element_(NULL) { } EditorClientImpl::~EditorClientImpl() { @@ -191,6 +182,10 @@ bool EditorClientImpl::shouldDeleteRange(WebCore::Range* range) { return true; } +void EditorClientImpl::PreserveSelection() { + preserve_ = true; +} + bool EditorClientImpl::shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity affinity, @@ -205,6 +200,12 @@ bool EditorClientImpl::shouldChangeSelectedRange(WebCore::Range* fromRange, stillSelecting); } } + // Have we been told to preserve the selection? + // (See comments for PreserveSelection in header). + if (preserve_) { + preserve_ = false; + return false; + } return true; } @@ -241,6 +242,25 @@ void EditorClientImpl::respondToChangedSelection() { } void EditorClientImpl::respondToChangedContents() { + // Ugly Hack. (See also webkit bug #16976). + // Something is wrong with webcore's focusController in that when selection + // is set to a region within a text element when handling an input event, if + // you don't re-focus the node then it only _APPEARS_ to have successfully + // changed the selection (the UI "looks" right) but in reality there is no + // selection of text. And to make matters worse, you can't just re-focus it, + // you have to re-focus it in code executed after the entire event listener + // loop has finished; and hence here we are. Oh, and to make matters worse, + // this sequence of events _doesn't_ happen when you debug through the code + // -- in that case it works perfectly fine -- because swapping to the debugger + // causes the refocusing we artificially reproduce here. + // TODO (timsteele): Clean this up once root webkit problem is identified and + // the bug is patched. + if (pending_inline_autocompleted_element_) { + pending_inline_autocompleted_element_->blur(); + pending_inline_autocompleted_element_->focus(); + pending_inline_autocompleted_element_ = NULL; + } + if (use_editor_delegate_) { WebViewDelegate* d = web_view_->delegate(); if (d) @@ -601,84 +621,17 @@ void EditorClientImpl::textFieldDidBeginEditing(WebCore::Element*) { void EditorClientImpl::textFieldDidEndEditing(WebCore::Element*) { // Notification that focus was lost. Be careful with this, it's also sent // when the page is being closed. - - // Cancel any pending DoAutofill calls. - autofill_factory_.RevokeAll(); } void EditorClientImpl::textDidChangeInTextField(WebCore::Element* element) { - DCHECK(element->hasLocalName(WebCore::HTMLNames::inputTag)); - - // Cancel any pending DoAutofill calls. - autofill_factory_.RevokeAll(); - - // Let's try to trigger autofill for that field, if applicable. - WebCore::HTMLInputElement* input_element = - static_cast<WebCore::HTMLInputElement*>(element); - if (!input_element->isEnabled() || !input_element->isTextField() || - input_element->isPasswordField() || !input_element->autoComplete()) { - return; - } - - std::wstring name = webkit_glue::StringToStdWString(input_element->name()); - if (name.empty()) // If the field has no name, then we won't have values. - return; - - // Don't attempt to autofill with values that are too large. - if (input_element->value().length() > kMaximumTextSizeForAutofill) - return; - - // We post a task for doing the autofill as the caret position is not set - // properly at this point ( http://bugs.webkit.org/show_bug.cgi?id=16976) - // and we need it to determine whether or not to trigger autofill. - std::wstring value = webkit_glue::StringToStdWString(input_element->value()); - MessageLoop::current()->PostTask( - FROM_HERE, - autofill_factory_.NewRunnableMethod(&EditorClientImpl::DoAutofill, - input_element, - backspace_pressed_)); -} - -void EditorClientImpl::DoAutofill(WebCore::HTMLInputElement* input_element, - bool backspace) { - std::wstring value = webkit_glue::StringToStdWString(input_element->value()); - - // Only autofill when there is some text and the caret is at the end. - bool caret_at_end = - input_element->selectionStart() == input_element->selectionEnd() && - input_element->selectionEnd() == static_cast<int>(value.length()); - if (value.empty() || !caret_at_end) - return; - - // First let's see if there is a password listener for that element. - WebFrameImpl* webframe = - WebFrameImpl::FromFrame(input_element->form()->document()->frame()); - webkit_glue::PasswordAutocompleteListener* listener = - webframe->GetPasswordListener(input_element); - if (listener) { - if (backspace) // No autocomplete for password on backspace. - return; - - listener->OnInlineAutocompleteNeeded(input_element, value); - return; - } - - // Then trigger form autofill. - std::wstring name = webkit_glue::StringToStdWString(input_element-> - name().string()); - web_view_->delegate()->QueryFormFieldAutofill(name, value, - reinterpret_cast<int64>(input_element)); + // Track the element so we can blur/focus it in respondToChangedContents + // so that the selected range is properly set. (See respondToChangedContents). + if (static_cast<WebCore::HTMLInputElement*>(element)->autofilled()) + pending_inline_autocompleted_element_ = element; } -bool EditorClientImpl::doTextFieldCommandFromEvent( - WebCore::Element* element, - WebCore::KeyboardEvent* event) { - // Remember if backspace was pressed for the autofill. It is not clear how to - // find if backspace was pressed from textFieldDidBeginEditing and - // textDidChangeInTextField as when these methods are called the value of the - // input element already contains the type character. - backspace_pressed_ = (event->keyCode() == WebCore::VKEY_BACK); - +bool EditorClientImpl::doTextFieldCommandFromEvent(WebCore::Element*, + WebCore::KeyboardEvent*) { // The Mac code appears to use this method as a hook to implement special // keyboard commands specific to Safari's auto-fill implementation. We // just return false to allow the default action. |