diff options
author | John Reck <jreck@google.com> | 2012-02-21 15:43:45 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-02-21 15:43:45 -0800 |
commit | 489cc2648aba682fde7acdd19a71631429c5d8f8 (patch) | |
tree | 3bce8326f6c9d51b8f77661eb8c2bce0e8434889 /Source | |
parent | cb3b415105a884d70ac845b228f6bb87807f9f34 (diff) | |
parent | f404d29266675808fffe9d71b065bc03b555b58d (diff) | |
download | external_webkit-489cc2648aba682fde7acdd19a71631429c5d8f8.zip external_webkit-489cc2648aba682fde7acdd19a71631429c5d8f8.tar.gz external_webkit-489cc2648aba682fde7acdd19a71631429c5d8f8.tar.bz2 |
Merge "Improve keyboard navigation cursor rings"
Diffstat (limited to 'Source')
-rw-r--r-- | Source/WebCore/platform/android/RenderThemeAndroid.cpp | 24 | ||||
-rw-r--r-- | Source/WebCore/platform/android/RenderThemeAndroid.h | 2 | ||||
-rw-r--r-- | Source/WebKit/android/jni/AndroidHitTestResult.cpp | 92 | ||||
-rw-r--r-- | Source/WebKit/android/jni/AndroidHitTestResult.h | 4 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.cpp | 82 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.h | 2 |
6 files changed, 79 insertions, 127 deletions
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp index 97110ee..ee406c2 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp @@ -633,30 +633,16 @@ bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& Color RenderThemeAndroid::platformFocusRingColor() const { - static Color focusRingColor(0x66, 0x33, 0xB5, 0xE5); + static Color focusRingColor(0x33, 0xB5, 0xE5, 0x66); 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 - && style->appearance() != SearchFieldPart - && style->appearance() != TextAreaPart - && style->appearance() != CheckboxPart - && style->appearance() != RadioPart - && style->appearance() != PushButtonPart - && style->appearance() != SquareButtonPart - && style->appearance() != ButtonPart - && style->appearance() != ButtonBevelPart - && style->appearance() != MenulistPart - && style->appearance() != MenulistButtonPart; + // Draw the focus ring ourselves unless it is a text area (webkit does borders better) + if (!style || !style->hasAppearance()) + return true; + return style->appearance() != TextFieldPart && style->appearance() != TextAreaPart; } } // namespace WebCore diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.h b/Source/WebCore/platform/android/RenderThemeAndroid.h index 165abf8..ed4d07f 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.h +++ b/Source/WebCore/platform/android/RenderThemeAndroid.h @@ -48,7 +48,7 @@ public: ~RenderThemeAndroid(); virtual bool stateChanged(RenderObject*, ControlState) const; - + virtual bool supportsFocusRing(const RenderStyle*) const; // A method asking if the theme's controls actually care about redrawing when hovered. virtual bool supportsHover(const RenderStyle* style) const { return style->affectedByHoverRules(); } diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.cpp b/Source/WebKit/android/jni/AndroidHitTestResult.cpp index 0a69007..6f94488 100644 --- a/Source/WebKit/android/jni/AndroidHitTestResult.cpp +++ b/Source/WebKit/android/jni/AndroidHitTestResult.cpp @@ -28,7 +28,9 @@ #include "config.h" #include "AndroidHitTestResult.h" +#include "Document.h" #include "Element.h" +#include "Frame.h" #include "HitTestResult.h" #include "KURL.h" #include "LayerAndroid.h" @@ -49,18 +51,19 @@ namespace android { using namespace WebCore; static bool gJniInitialized = false; -static struct JavaGlue { - jmethodID m_hitTestInit; - jfieldID m_hitTestLinkUrl; - jfieldID m_hitTestAnchorText; - jfieldID m_hitTestImageUrl; - jfieldID m_hitTestAltDisplayString; - jfieldID m_hitTestTitle; - jfieldID m_hitTestEditable; - jfieldID m_hitTestTouchRects; - jfieldID m_hitTestTapHighlightColor; - jfieldID m_hitTestEnclosingParentRects; -} gJavaGlue; +static struct { + jmethodID m_Init; + jfieldID m_LinkUrl; + jfieldID m_AnchorText; + jfieldID m_ImageUrl; + jfieldID m_AltDisplayString; + jfieldID m_Title; + jfieldID m_Editable; + jfieldID m_TouchRects; + jfieldID m_TapHighlightColor; + jfieldID m_EnclosingParentRects; + jfieldID m_HasFocus; +} gHitTestGlue; struct field { jclass m_class; @@ -79,19 +82,20 @@ static void InitJni(JNIEnv* env) jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest"); ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest"); - gJavaGlue.m_hitTestInit = env->GetMethodID(hitTestClass, "<init>", "()V"); - ALOG_ASSERT(gJavaGlue.m_hitTestInit, "Could not find init method on android/webkit/WebViewCore$WebKitHitTest"); + gHitTestGlue.m_Init = env->GetMethodID(hitTestClass, "<init>", "()V"); + ALOG_ASSERT(gHitTestGlue.m_Init, "Could not find init method on android/webkit/WebViewCore$WebKitHitTest"); field fields[] = { - { hitTestClass, "mTouchRects", "[Landroid/graphics/Rect;", &gJavaGlue.m_hitTestTouchRects }, - { hitTestClass, "mEditable", "Z", &gJavaGlue.m_hitTestEditable }, - { hitTestClass, "mLinkUrl", "Ljava/lang/String;", &gJavaGlue.m_hitTestLinkUrl }, - { hitTestClass, "mAnchorText", "Ljava/lang/String;", &gJavaGlue.m_hitTestAnchorText }, - { hitTestClass, "mImageUrl", "Ljava/lang/String;", &gJavaGlue.m_hitTestImageUrl }, - { hitTestClass, "mAltDisplayString", "Ljava/lang/String;", &gJavaGlue.m_hitTestAltDisplayString }, - { hitTestClass, "mTitle", "Ljava/lang/String;", &gJavaGlue.m_hitTestTitle }, - { hitTestClass, "mTapHighlightColor", "I", &gJavaGlue.m_hitTestTapHighlightColor }, - { hitTestClass, "mEnclosingParentRects", "[Landroid/graphics/Rect;", &gJavaGlue.m_hitTestEnclosingParentRects }, + { hitTestClass, "mTouchRects", "[Landroid/graphics/Rect;", &gHitTestGlue.m_TouchRects }, + { hitTestClass, "mEditable", "Z", &gHitTestGlue.m_Editable }, + { hitTestClass, "mLinkUrl", "Ljava/lang/String;", &gHitTestGlue.m_LinkUrl }, + { hitTestClass, "mAnchorText", "Ljava/lang/String;", &gHitTestGlue.m_AnchorText }, + { hitTestClass, "mImageUrl", "Ljava/lang/String;", &gHitTestGlue.m_ImageUrl }, + { hitTestClass, "mAltDisplayString", "Ljava/lang/String;", &gHitTestGlue.m_AltDisplayString }, + { hitTestClass, "mTitle", "Ljava/lang/String;", &gHitTestGlue.m_Title }, + { hitTestClass, "mTapHighlightColor", "I", &gHitTestGlue.m_TapHighlightColor }, + { hitTestClass, "mEnclosingParentRects", "[Landroid/graphics/Rect;", &gHitTestGlue.m_EnclosingParentRects }, + { hitTestClass, "mHasFocus", "Z", &gHitTestGlue.m_HasFocus }, {0, 0, 0, 0}, }; @@ -109,6 +113,33 @@ AndroidHitTestResult::AndroidHitTestResult(WebViewCore* webViewCore, WebCore::Hi : m_webViewCore(webViewCore) , m_hitTestResult(hitTestResult) { + buildHighlightRects(); +} + +void AndroidHitTestResult::setURLElement(Element* element) +{ + m_hitTestResult.setURLElement(element); + buildHighlightRects(); +} + +void AndroidHitTestResult::buildHighlightRects() +{ + m_highlightRects.clear(); + Node* node = m_hitTestResult.URLElement(); + if (!node || !node->renderer()) + node = m_hitTestResult.innerNode(); + if (!node || !node->renderer()) + return; + Frame* frame = node->document()->frame(); + IntPoint frameOffset = m_webViewCore->convertGlobalContentToFrameContent(IntPoint(), frame); + RenderObject* renderer = node->renderer(); + Vector<FloatQuad> quads; + renderer->absoluteFocusRingQuads(quads); + for (int i = 0; i < quads.size(); i++) { + IntRect boundingBox = quads[i].enclosingBoundingBox(); + boundingBox.move(-frameOffset.x(), -frameOffset.y()); + m_highlightRects.append(boundingBox); + } } void setStringField(JNIEnv* env, jobject obj, jfieldID field, const String& str) @@ -126,9 +157,9 @@ void setRectArray(JNIEnv* env, jobject obj, jfieldID field, Vector<IntRect> &rec } // Some helper macros specific to setting hitTest fields -#define _SET(jtype, jfield, value) env->Set ## jtype ## Field(hitTest, gJavaGlue.m_hitTest ## jfield, value) +#define _SET(jtype, jfield, value) env->Set ## jtype ## Field(hitTest, gHitTestGlue.m_ ## jfield, value) #define SET_BOOL(jfield, value) _SET(Boolean, jfield, value) -#define SET_STRING(jfield, value) setStringField(env, hitTest, gJavaGlue.m_hitTest ## jfield, value) +#define SET_STRING(jfield, value) setStringField(env, hitTest, gHitTestGlue.m_ ## jfield, value) #define SET_INT(jfield, value) _SET(Int, jfield, value) jobject AndroidHitTestResult::createJavaObject(JNIEnv* env) @@ -137,11 +168,11 @@ jobject AndroidHitTestResult::createJavaObject(JNIEnv* env) jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest"); ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest"); - jobject hitTest = env->NewObject(hitTestClass, gJavaGlue.m_hitTestInit); - setRectArray(env, hitTest, gJavaGlue.m_hitTestTouchRects, m_highlightRects); + jobject hitTest = env->NewObject(hitTestClass, gHitTestGlue.m_Init); + setRectArray(env, hitTest, gHitTestGlue.m_TouchRects, m_highlightRects); Vector<IntRect> rects = enclosingParentRects(m_hitTestResult.innerNode()); - setRectArray(env, hitTest, gJavaGlue.m_hitTestEnclosingParentRects, rects); + setRectArray(env, hitTest, gHitTestGlue.m_EnclosingParentRects, rects); SET_BOOL(Editable, m_hitTestResult.isContentEditable()); SET_STRING(LinkUrl, m_hitTestResult.absoluteLinkURL().string()); @@ -157,6 +188,11 @@ jobject AndroidHitTestResult::createJavaObject(JNIEnv* env) urlElement->renderer()->style()->tapHighlightColor().rgb()); } } + Node* focusedNode = m_webViewCore->focusedFrame()->document()->focusedNode(); + SET_BOOL(HasFocus, + focusedNode == m_hitTestResult.URLElement() + || focusedNode == m_hitTestResult.innerNode() + || focusedNode == m_hitTestResult.innerNonSharedNode()); env->DeleteLocalRef(hitTestClass); diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.h b/Source/WebKit/android/jni/AndroidHitTestResult.h index e4233fd..f9709ac 100644 --- a/Source/WebKit/android/jni/AndroidHitTestResult.h +++ b/Source/WebKit/android/jni/AndroidHitTestResult.h @@ -26,6 +26,7 @@ #ifndef AndroidHitTestResult_h #define AndroidHitTestResult_h +#include "Element.h" #include "HitTestResult.h" #include "IntRect.h" #include "wtf/Vector.h" @@ -45,6 +46,9 @@ public: WebCore::HitTestResult& hitTestResult() { return m_hitTestResult; } Vector<WebCore::IntRect>& highlightRects() { return m_highlightRects; } + void setURLElement(WebCore::Element* element); + void buildHighlightRects(); + jobject createJavaObject(JNIEnv*); private: diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index a8b8499..4efe0d5 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -1625,7 +1625,7 @@ static IntRect getAbsoluteBoundingBox(Node* node) { rect = toRenderText(render)->linesBoundingBox(); else ALOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName()); - FloatPoint absPos = render->localToAbsolute(); + FloatPoint absPos = render->localToAbsolute(FloatPoint(), false, true); rect.move(absPos.x(), absPos.y()); return rect; } @@ -2005,7 +2005,7 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do IntRect rect = n->mBounds; rect.intersect(testRect); int a = rect.width() * rect.height(); - if (a > area) { + if (a > area || !final.mUrlNode) { final = *n; area = a; } @@ -2014,9 +2014,9 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do if (final.mUrlNode) { if (final.mUrlNode->isElementNode()) { // We found a URL element. Update the hitTestResult - androidHitResult.hitTestResult().setURLElement(static_cast<Element*>(final.mUrlNode)); + androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode)); } else { - androidHitResult.hitTestResult().setURLElement(0); + androidHitResult.setURLElement(0); } // Update innerNode and innerNonSharedNode androidHitResult.hitTestResult().setInnerNode(final.mInnerNode); @@ -2026,81 +2026,8 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do frameAdjust = frame->view()->contentsToWindow(IntPoint()); frameAdjust.move(m_scrollOffsetX, m_scrollOffsetY); } - Vector<IntRect>& rects = androidHitResult.highlightRects(); - if (final.mUrlNode->isLink() && final.mUrlNode->renderer()) { - // most of the links are inline instead of box style. So the bounding box is not - // a good representation for the highlights. Get the list of rectangles instead. - RenderObject* render = final.mUrlNode->renderer(); - IntPoint offset = roundedIntPoint(render->localToAbsolute()); - render->absoluteRects(rects, offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y()); - if (final.mInnerNode && final.mInnerNode->renderer()) { - final.mInnerNode->renderer()->absoluteRects(rects, - offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y()); - } - bool inside = false; - int distance = INT_MAX; - int newx = x, newy = y; - int i = rects.size(); - while (i--) { - if (rects[i].isEmpty()) { - rects.remove(i); - continue; - } - // check whether the point (x, y) is inside one of the rectangles. - if (inside) - continue; - if (rects[i].contains(x, y)) { - inside = true; - continue; - } - if (x >= rects[i].x() && x < rects[i].maxX()) { - if (y < rects[i].y()) { - if (rects[i].y() - y < distance) { - newx = x; - newy = rects[i].y(); - distance = rects[i].y() - y; - } - } else if (y >= rects[i].maxY()) { - if (y - rects[i].maxY() + 1 < distance) { - newx = x; - newy = rects[i].maxY() - 1; - distance = y - rects[i].maxY() + 1; - } - } - } else if (y >= rects[i].y() && y < rects[i].maxY()) { - if (x < rects[i].x()) { - if (rects[i].x() - x < distance) { - newx = rects[i].x(); - newy = y; - distance = rects[i].x() - x; - } - } else if (x >= rects[i].maxX()) { - if (x - rects[i].maxX() + 1 < distance) { - newx = rects[i].maxX() - 1; - newy = y; - distance = x - rects[i].maxX() + 1; - } - } - } - } - if (!rects.isEmpty()) { - if (!inside && doMoveMouse) { - // if neither x nor y has overlap, just pick the top/left of the first rectangle - if (newx == x && newy == y) { - newx = rects[0].x(); - newy = rects[0].y(); - } - moveMouse(m_mainFrame, newx, newy); - DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)", - x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY, - m_scrollOffsetX, m_scrollOffsetY); - } - return androidHitResult; - } - } IntRect rect = final.mBounds; rect.move(frameAdjust.x(), frameAdjust.y()); - rects.append(rect); if (doMoveMouse) { // adjust m_mousePos if it is not inside the returned highlight rectangle testRect.move(frameAdjust.x(), frameAdjust.y()); @@ -3677,7 +3604,6 @@ void WebViewCore::focusNodeChanged(WebCore::Node* newFocus) } } AndroidHitTestResult androidHitTest(this, focusHitResult); - androidHitTest.highlightRects(); jobject jHitTestObj = androidHitTest.createJavaObject(env); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_focusNodeChanged, jHitTestObj); env->DeleteLocalRef(jHitTestObj); diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 41e681e..315b024 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -152,7 +152,7 @@ namespace android { * * This method calls Java to trigger a gradual scroll event. */ - void scrollTo(int x, int y, bool animate = false); + void scrollTo(int x, int y, bool animate = true); /** * Record the invalid rectangle |