diff options
Diffstat (limited to 'Source/WebKit/android')
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.cpp | 143 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.h | 25 |
2 files changed, 137 insertions, 31 deletions
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 1c8d0d0..0030621 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -80,6 +80,7 @@ #include "HitTestRequest.h" #include "HitTestResult.h" #include "InlineTextBox.h" +#include "KeyboardEvent.h" #include "MemoryUsage.h" #include "NamedNodeMap.h" #include "Navigator.h" @@ -441,7 +442,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m #endif m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V"); m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V"); - m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;II)V"); + m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;IZZLjava/lang/String;III)V"); m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)V"); env->DeleteLocalRef(clazz); @@ -534,7 +535,7 @@ CacheBuilder& WebViewCore::cacheBuilder() WebCore::Node* WebViewCore::currentFocus() { - return m_mainFrame->document()->focusedNode(); + return focusedFrame()->document()->focusedNode(); } void WebViewCore::recordPicture(SkPicture* picture) @@ -1752,7 +1753,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) { // We need to agressively check to see if this is an empty selection to prevent // accidentally entering text selection mode - if (!selection.isRange() || !comparePositions(selection.start(), selection.end())) + bool isCaret = selection.isCaret(); + if (selection.isNone() || (!selection.isContentEditable() && isCaret)) return 0; RefPtr<Range> range = selection.firstRange(); @@ -1761,7 +1763,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) if (!startContainer || !endContainer) return 0; - if (startContainer == endContainer && range->startOffset() == range->endOffset()) + if (!isCaret && startContainer == endContainer + && range->startOffset() == range->endOffset()) return 0; SelectText* selectTextContainer = new SelectText(); @@ -1769,35 +1772,56 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) IntRect startHandle; IntRect endHandle; - Node* stopNode = range->pastLastNode(); - for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) { - RenderObject* r = node->renderer(); - if (!r || !r->isText() || r->style()->visibility() != VISIBLE) - continue; - RenderText* renderText = toRenderText(r); - int startOffset = node == startContainer ? range->startOffset() : 0; - int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max(); + if (isCaret) { + // Caret selection + Position start = selection.start(); + Node* node = start.anchorNode(); LayerAndroid* layer = 0; int layerId = platformLayerIdFromNode(node, &layer); - Vector<IntRect> rects; - renderText->absoluteRectsForRange(rects, startOffset, endOffset, true); - if (rects.size()) { - IntPoint offset; - layerToAbsoluteOffset(layer, offset); - endHandle = rects[rects.size() - 1]; - endHandle.move(-offset.x(), -offset.y()); - selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId); - if (startHandle.isEmpty()) { - startHandle = rects[0]; - startHandle.move(-offset.x(), -offset.y()); - selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId); + selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId); + selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId); + IntPoint layerOffset; + layerToAbsoluteOffset(layer, layerOffset); + RenderObject* r = node->renderer(); + RenderText* renderText = toRenderText(r); + int caretOffset; + InlineBox* inlineBox; + start.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset); + startHandle = renderText->localCaretRect(inlineBox, caretOffset); + FloatPoint absoluteOffset = renderText->localToAbsolute(startHandle.location()); + startHandle.setX(absoluteOffset.x() - layerOffset.x()); + startHandle.setY(absoluteOffset.y() - layerOffset.y()); + endHandle = startHandle; + } else { + // Selected range + Node* stopNode = range->pastLastNode(); + for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) { + RenderObject* r = node->renderer(); + if (!r || !r->isText() || r->style()->visibility() != VISIBLE) + continue; + RenderText* renderText = toRenderText(r); + int startOffset = node == startContainer ? range->startOffset() : 0; + int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max(); + LayerAndroid* layer = 0; + int layerId = platformLayerIdFromNode(node, &layer); + Vector<IntRect> rects; + renderText->absoluteRectsForRange(rects, startOffset, endOffset, true); + if (rects.size()) { + IntPoint offset; + layerToAbsoluteOffset(layer, offset); + endHandle = rects[rects.size() - 1]; + endHandle.move(-offset.x(), -offset.y()); + selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId); + if (startHandle.isEmpty()) { + startHandle = rects[0]; + startHandle.move(-offset.x(), -offset.y()); + selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId); + } } + selectTextContainer->addHighlightRegion(layer, rects, frameOffset); } - selectTextContainer->addHighlightRegion(layer, rects, frameOffset); } - IntRect caretRect; - int layerId; selectTextContainer->setBaseFirst(selection.isBaseFirst()); // Squish the handle rects @@ -1830,7 +1854,7 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY) IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY)); VisiblePosition endPosition(visiblePositionForContentPoint(endPoint)); - if (startPosition.isNull() || endPosition.isNull() || startPosition == endPosition) + if (startPosition.isNull() || endPosition.isNull()) return; // Ensure startPosition is before endPosition @@ -1859,7 +1883,9 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY) } VisibleSelection selection(startPosition, endPosition); - if (selection.isRange() && sc->shouldChangeSelection(selection)) + // Only allow changes between caret positions or to text selection. + bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret()); + if (selectChangeAllowed && sc->shouldChangeSelection(selection)) sc->setSelection(selection); } @@ -3500,6 +3526,46 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node return handled; } +WebViewCore::InputType WebViewCore::getInputType(Node* node) +{ + WebCore::RenderObject* renderer = node->renderer(); + if (!renderer) + return WebViewCore::NONE; + if (renderer->isTextArea()) + return WebViewCore::TEXT_AREA; + + if (node->hasTagName(WebCore::HTMLNames::inputTag)) { + HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node); + if (htmlInput->isPasswordField()) + return WebViewCore::PASSWORD; + if (htmlInput->isSearchField()) + return WebViewCore::SEARCH; + if (htmlInput->isEmailField()) + return WebViewCore::EMAIL; + if (htmlInput->isNumberField()) + return WebViewCore::NUMBER; + if (htmlInput->isTelephoneField()) + return WebViewCore::TELEPHONE; + if (htmlInput->isTextField()) + return WebViewCore::NORMAL_TEXT_FIELD; + } + + if (node->isContentEditable()) + return WebViewCore::TEXT_AREA; + + return WebViewCore::NONE; +} + +bool WebViewCore::isSpellCheckEnabled(Node* node) +{ + bool isEnabled = true; + if (node->isElementNode()) { + WebCore::Element* element = static_cast<WebCore::Element*>(node); + isEnabled = element->isSpellCheckingEnabled(); + } + return isEnabled; +} + void WebViewCore::initEditField(Node* node) { String text = getInputText(node); @@ -3511,9 +3577,22 @@ void WebViewCore::initEditField(Node* node) if (!javaObject.get()) return; m_textGeneration = 0; + InputType inputType = getInputType(node); + Document* document = node->document(); + PlatformKeyboardEvent tab(AKEYCODE_TAB, 0, 0, false, false, false, false); + PassRefPtr<KeyboardEvent> tabEvent = + KeyboardEvent::create(tab, document->defaultView()); + Node* nextFocus = document->nextFocusableNode(node, tabEvent.get()); + bool isNextText = isTextInput(nextFocus); + bool spellCheckEnabled = isSpellCheckEnabled(node); + String label = requestLabel(document->frame(), node); jstring fieldText = wtfStringToJstring(env, text, true); + jstring labelText = wtfStringToJstring(env, text, false); + SelectText* selectText = createSelectText(focusedFrame()->selection()->selection()); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField, - reinterpret_cast<int>(node), fieldText, start, end); + reinterpret_cast<int>(node), fieldText, inputType, + spellCheckEnabled, isNextText, labelText, start, end, + reinterpret_cast<int>(selectText)); checkException(env); } @@ -3868,7 +3947,7 @@ void WebViewCore::updateTextSelection() SelectText* selectText = createSelectText(focusedFrame()->selection()->selection()); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode), - start, end, m_textGeneration, selectText); + start, end, m_textGeneration, reinterpret_cast<int>(selectText)); checkException(env); } @@ -4354,6 +4433,8 @@ void WebViewCore::findNextOnPage(bool forward) m_activeMatch = selection.firstRange(); m_mainFrame->document()->markers()->setMarkersActive( m_activeMatch.get(), true); + m_mainFrame->selection()->revealSelection( + ScrollAlignment::alignCenterIfNeeded, true); } updateMatchCount(); } diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 0532742..38bde58 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -639,6 +639,18 @@ namespace android { // internal functions private: + enum InputType { + NONE = -1, + NORMAL_TEXT_FIELD = 0, + TEXT_AREA = 1, + PASSWORD = 2, + SEARCH = 3, + EMAIL = 4, + NUMBER = 5, + TELEPHONE = 6, + URL = 7, + }; + #ifndef DISABLE_NAVCACHE CacheBuilder& cacheBuilder(); #endif @@ -684,6 +696,19 @@ namespace android { * current contents and selection. */ void initEditField(Node* node); + + /** + * Gets the input type a Node. NONE is returned if it isn't an + * input field. + */ + InputType getInputType(Node* node); + + /** + * If node is an input field, the spellcheck value for the + * field is returned. Otherwise true is returned. + */ + static bool isSpellCheckEnabled(Node* node); + /** * Returns the offsets of the selection area for both normal text * fields and content editable fields. start and end are modified |