diff options
author | John Reck <jreck@google.com> | 2012-02-06 09:00:44 -0800 |
---|---|---|
committer | John Reck <jreck@google.com> | 2012-02-15 16:57:38 -0800 |
commit | ceeeab6161d7d8bf970ecf98affa4f4966df6f01 (patch) | |
tree | 0666a9ebf25e9d4e09ef3f8ee8ed0f6cf33fd4f1 /Source | |
parent | 628a06bda2490e4c405ce3263381412423f4c735 (diff) | |
download | external_webkit-ceeeab6161d7d8bf970ecf98affa4f4966df6f01.zip external_webkit-ceeeab6161d7d8bf970ecf98affa4f4966df6f01.tar.gz external_webkit-ceeeab6161d7d8bf970ecf98affa4f4966df6f01.tar.bz2 |
Initial support for keyboard navigation
Bug: 6019693
Change-Id: I7b4f6d83e8913e647e8ac7340afd01d609c4343b
Diffstat (limited to 'Source')
-rw-r--r-- | Source/JavaScriptCore/wtf/Platform.h | 2 | ||||
-rw-r--r-- | Source/WebCore/editing/SelectionController.cpp | 4 | ||||
-rw-r--r-- | Source/WebCore/html/HTMLAnchorElement.cpp | 4 | ||||
-rw-r--r-- | Source/WebCore/platform/android/KeyEventAndroid.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/platform/android/RenderThemeAndroid.cpp | 11 | ||||
-rw-r--r-- | Source/WebCore/platform/android/RenderThemeAndroid.h | 1 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp | 29 | ||||
-rw-r--r-- | Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp | 2 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebSettings.cpp | 3 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.cpp | 81 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.h | 5 | ||||
-rw-r--r-- | Source/WebKit/android/nav/WebView.cpp | 4 |
12 files changed, 111 insertions, 37 deletions
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index f313861..3043e56 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -754,8 +754,6 @@ // Passes the webkit-originated changes of a focused textfield to our UI // thread #define ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS -// Allow us to turn off the blinking caret as desired. -#define ANDROID_ALLOW_TURNING_OFF_CARET #define ANDROID_META_SUPPORT #define ANDROID_MULTIPLE_WINDOWS #define ANDROID_CSS_TAP_HIGHLIGHT_COLOR diff --git a/Source/WebCore/editing/SelectionController.cpp b/Source/WebCore/editing/SelectionController.cpp index e9bdd6a..acae6bf 100644 --- a/Source/WebCore/editing/SelectionController.cpp +++ b/Source/WebCore/editing/SelectionController.cpp @@ -1217,10 +1217,6 @@ void SelectionController::invalidateCaretRect() void SelectionController::paintCaret(GraphicsContext* context, int tx, int ty, const IntRect& clipRect) { -#ifdef ANDROID_ALLOW_TURNING_OFF_CARET - if (m_frame && !android::WebViewCore::getWebViewCore(m_frame->view())->shouldPaintCaret()) - return; -#endif #if ENABLE(TEXT_CARET) if (!m_caretVisible) return; diff --git a/Source/WebCore/html/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp index 60f5b4a..4636f20 100644 --- a/Source/WebCore/html/HTMLAnchorElement.cpp +++ b/Source/WebCore/html/HTMLAnchorElement.cpp @@ -531,7 +531,11 @@ bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const bool isEnterKeyKeydownEvent(Event* event) { +#if OS(ANDROID) + return event->type() == eventNames().keyupEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter"; +#else return event->type() == eventNames().keydownEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter"; +#endif } bool isMiddleMouseButtonEvent(Event* event) diff --git a/Source/WebCore/platform/android/KeyEventAndroid.cpp b/Source/WebCore/platform/android/KeyEventAndroid.cpp index eaf34a9..f309e99 100644 --- a/Source/WebCore/platform/android/KeyEventAndroid.cpp +++ b/Source/WebCore/platform/android/KeyEventAndroid.cpp @@ -191,7 +191,7 @@ static String keyIdentifierForAndroidKeyCode(int keyCode) return "U+00007F"; default: char upper[16]; - sprintf(upper, "U+%06X", windowsKeyCodeForKeyEvent(keyCode)); + sprintf(upper, "U+%04X", windowsKeyCodeForKeyEvent(keyCode)); return String(upper); } } diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp index d579003..b570d0e 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp @@ -621,8 +621,19 @@ bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& return paintCombo(obj, info, rect); } +Color RenderThemeAndroid::platformFocusRingColor() const +{ + static Color focusRingColor(0x66, 0x33, 0xB5, 0xE5); + return focusRingColor; +} + bool RenderThemeAndroid::supportsFocusRing(const RenderStyle* style) const { + // TODO: Draw this on the UI side + // For now, just return false to let WebKit draw the focus ring. We only + // draw this ring when navigating via the keyboard, this does not affect + // the touch ring + return false; return style->opacity() > 0 && style->hasAppearance() && style->appearance() != TextFieldPart diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.h b/Source/WebCore/platform/android/RenderThemeAndroid.h index 89a6d46..802d3c3 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.h +++ b/Source/WebCore/platform/android/RenderThemeAndroid.h @@ -60,6 +60,7 @@ public: virtual Color platformActiveSelectionForegroundColor() const; virtual Color platformInactiveSelectionForegroundColor() const; virtual Color platformTextSearchHighlightColor() const; + virtual Color platformFocusRingColor() const; virtual Color platformActiveListBoxSelectionBackgroundColor() const; virtual Color platformInactiveListBoxSelectionBackgroundColor() const; diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp index 848b713..9cfed60 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp @@ -36,6 +36,7 @@ #include "SkBlurMaskFilter.h" #include "SkCanvas.h" #include "SkColorPriv.h" +#include "SkCornerPathEffect.h" #include "SkDashPathEffect.h" #include "SkDevice.h" #include "SkGradientShader.h" @@ -949,9 +950,33 @@ void GraphicsContext::clearPlatformShadow() /////////////////////////////////////////////////////////////////////////////// -void GraphicsContext::drawFocusRing(const Vector<IntRect>&, int, int, const Color&) +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { - // Do nothing, since we draw the focus ring independently. + if (paintingDisabled()) + return; + + unsigned rectCount = rects.size(); + if (!rectCount) + return; + + SkRegion focusRingRegion; + const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8); + for (unsigned i = 0; i < rectCount; i++) { + SkIRect r = rects[i]; + r.inset(-focusRingOutset, -focusRingOutset); + focusRingRegion.op(r, SkRegion::kUnion_Op); + } + + SkPath path; + SkPaint paint; + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kStroke_Style); + + paint.setColor(color.rgb()); + paint.setStrokeWidth(focusRingOutset * 2); + paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref(); + focusRingRegion.getBoundaryPath(&path); + platformContext()->mCanvas->drawPath(path, paint); } void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index f907440..1328675 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -298,7 +298,7 @@ bool ChromeClientAndroid::shouldInterruptJavaScript() { KeyboardUIMode ChromeClientAndroid::keyboardUIMode() { - return KeyboardAccessDefault; + return KeyboardAccessTabsToLinks; } IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); } diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp index 450b5c7..9b6f08b 100644 --- a/Source/WebKit/android/jni/WebSettings.cpp +++ b/Source/WebKit/android/jni/WebSettings.cpp @@ -591,6 +591,9 @@ public: // This is required to enable the XMLTreeViewer when loading an XML document that // has no style attached to it. http://trac.webkit.org/changeset/79799 s->setDeveloperExtrasEnabled(true); +#if !ENABLE(ANDROID_NAVCACHE) + s->setSpatialNavigationEnabled(true); +#endif } }; diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index dab5ed5..81bf577 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -292,6 +292,7 @@ struct WebViewCore::JavaGlue { jmethodID m_getDeviceOrientationService; jmethodID m_addMessageToConsole; jmethodID m_formDidBlur; + jmethodID m_focusNodeChanged; jmethodID m_getPluginClass; jmethodID m_showFullScreenPlugin; jmethodID m_hideFullScreenPlugin; @@ -378,7 +379,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m , m_groupForVisitedLinks(0) , m_isPaused(false) , m_cacheMode(0) - , m_shouldPaintCaret(true) , m_fullscreenVideoMode(false) , m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired) , m_screenOnCounter(0) @@ -425,6 +425,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_getDeviceOrientationService = GetJMethod(env, clazz, "getDeviceOrientationService", "()Landroid/webkit/DeviceOrientationService;"); m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V"); m_javaGlue->m_formDidBlur = GetJMethod(env, clazz, "formDidBlur", "(I)V"); + m_javaGlue->m_focusNodeChanged = GetJMethod(env, clazz, "focusNodeChanged", "(Landroid/webkit/WebViewCore$WebKitHitTest;)V"); m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"); m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;II)V"); m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V"); @@ -3117,7 +3118,6 @@ void WebViewCore::deleteSelection(int start, int end, int textGeneration) key(up); client->setUiGeneratedSelectionChange(false); m_textGeneration = textGeneration; - m_shouldPaintCaret = true; } void WebViewCore::replaceTextfieldText(int oldStart, @@ -3142,7 +3142,6 @@ void WebViewCore::replaceTextfieldText(int oldStart, // setSelection calls revealSelection, so there is no need to do it here. setSelection(start, end); m_textGeneration = textGeneration; - m_shouldPaintCaret = true; } void WebViewCore::passToJs(int generation, const WTF::String& current, @@ -3174,7 +3173,6 @@ void WebViewCore::passToJs(int generation, const WTF::String& current, } // Now that the selection has settled down, send it. updateTextSelection(); - m_shouldPaintCaret = true; } void WebViewCore::scrollFocusedTextInput(float xPercent, int y) @@ -3323,8 +3321,6 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event) { WebCore::EventHandler* eventHandler; WebCore::Node* focusNode = currentFocus(); - DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p", - event.keyIdentifier().utf8().data(), event.unichar(), focusNode); if (focusNode) { WebCore::Frame* frame = focusNode->document()->frame(); WebFrame* webFrame = WebFrame::getWebFrame(frame); @@ -3344,7 +3340,7 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event) } return handled; } else { - eventHandler = m_mainFrame->eventHandler(); + eventHandler = focusedFrame()->eventHandler(); } return eventHandler->keyEvent(event); } @@ -3638,19 +3634,66 @@ void WebViewCore::formDidBlur(const WebCore::Node* node) m_blurringNodePointer = reinterpret_cast<int>(node); } -void WebViewCore::focusNodeChanged(const WebCore::Node* newFocus) +// This is a slightly modified Node::nextNodeConsideringAtomicNodes() with the +// extra constraint of limiting the search to inside a containing parent +WebCore::Node* nextNodeWithinParent(WebCore::Node* parent, WebCore::Node* start) { - if (isTextInput(newFocus)) - m_shouldPaintCaret = true; - else if (m_blurringNodePointer) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject javaObject = m_javaGlue->object(env); - if (!javaObject.get()) - return; + if (!isAtomicNode(start) && start->firstChild()) + return start->firstChild(); + if (start->nextSibling()) + return start->nextSibling(); + const Node *n = start; + while (n && !n->nextSibling()) { + n = n->parentNode(); + if (n == parent) + return 0; + } + if (n) + return n->nextSibling(); + return 0; +} + +void WebViewCore::focusNodeChanged(WebCore::Node* newFocus) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject javaObject = m_javaGlue->object(env); + if (!javaObject.get()) + return; + if (!isTextInput(newFocus) && m_blurringNodePointer) { env->CallVoidMethod(javaObject.get(), m_javaGlue->m_formDidBlur, m_blurringNodePointer); checkException(env); m_blurringNodePointer = 0; } + HitTestResult focusHitResult; + focusHitResult.setInnerNode(newFocus); + focusHitResult.setInnerNonSharedNode(newFocus); + if (newFocus && newFocus->isLink() && newFocus->isElementNode()) { + focusHitResult.setURLElement(static_cast<Element*>(newFocus)); + if (newFocus->hasChildNodes() && !newFocus->hasTagName(HTMLNames::imgTag)) { + // Check to see if any of the children are images, and if so + // set them as the innerNode and innerNonSharedNode + // This will stop when it hits the first image. I'm not sure what + // should be done in the case of multiple images inside one anchor... + Node* nextNode = newFocus->firstChild(); + bool found = false; + while (nextNode) { + if (nextNode->hasTagName(HTMLNames::imgTag)) { + found = true; + break; + } + nextNode = nextNodeWithinParent(newFocus, nextNode); + } + if (found) { + focusHitResult.setInnerNode(nextNode); + focusHitResult.setInnerNonSharedNode(nextNode); + } + } + } + AndroidHitTestResult androidHitTest(this, focusHitResult); + androidHitTest.highlightRects(); + jobject jHitTestObj = androidHitTest.createJavaObject(env); + env->CallVoidMethod(javaObject.get(), m_javaGlue->m_focusNodeChanged, jHitTestObj); + env->DeleteLocalRef(jHitTestObj); } void WebViewCore::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel) { @@ -4647,11 +4690,6 @@ static jstring RetrieveImageSource(JNIEnv* env, jobject obj, jint nativeClass, return !result.isEmpty() ? wtfStringToJstring(env, result) : 0; } -static void StopPaintingCaret(JNIEnv* env, jobject obj, jint nativeClass) -{ - reinterpret_cast<WebViewCore*>(nativeClass)->setShouldPaintCaret(false); -} - static void MoveFocus(JNIEnv* env, jobject obj, jint nativeClass, jint framePtr, jint nodePtr) { @@ -4936,7 +4974,6 @@ static jobject HitTest(JNIEnv* env, jobject obj, jint nativeClass, jint x, return 0; Node* node = 0; AndroidHitTestResult result = viewImpl->hitTestAtPoint(x, y, slop, doMoveMouse); - Vector<IntRect>& rects = result.highlightRects(); return result.createJavaObject(env); } @@ -5081,8 +5118,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) RetrieveAnchorText }, { "nativeRetrieveImageSource", "(III)Ljava/lang/String;", (void*) RetrieveImageSource }, - { "nativeStopPaintingCaret", "(I)V", - (void*) StopPaintingCaret }, { "nativeUpdateFrameCache", "(I)V", (void*) UpdateFrameCache }, { "nativeGetContentMinPrefWidth", "(I)I", diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 956ffed..4d731d5 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -142,7 +142,7 @@ namespace android { * @param Node The Node that blurred. */ void formDidBlur(const WebCore::Node*); - void focusNodeChanged(const WebCore::Node*); + void focusNodeChanged(WebCore::Node*); /** * Scroll to an absolute position. @@ -572,8 +572,6 @@ namespace android { void listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount, bool multiple, const int selected[], size_t selectedCountOrSelection); - bool shouldPaintCaret() { return m_shouldPaintCaret; } - void setShouldPaintCaret(bool should) { m_shouldPaintCaret = should; } bool isPaused() const { return m_isPaused; } void setIsPaused(bool isPaused) { m_isPaused = isPaused; } bool drawIsPaused() const; @@ -757,7 +755,6 @@ namespace android { PageGroup* m_groupForVisitedLinks; bool m_isPaused; int m_cacheMode; - bool m_shouldPaintCaret; bool m_fullscreenVideoMode; SkTDArray<PluginWidgetAndroid*> m_plugins; diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 5d01e49..61fdb4e 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -1666,6 +1666,7 @@ static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj) static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj) { +#if ENABLE(ANDROID_NAVCACHE) const CachedNode* focus = getFocusNode(env, obj); if (!focus) return false; // Plugins handle shift and arrows whether or not they have focus. @@ -1675,6 +1676,9 @@ static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj) // both the cursor and the focus. return cursor && cursor->nodePointer() == focus->nodePointer() && cursor->isContentEditable(); +#else + return true; +#endif } static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj) |