summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2012-02-21 15:43:45 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-02-21 15:43:45 -0800
commit489cc2648aba682fde7acdd19a71631429c5d8f8 (patch)
tree3bce8326f6c9d51b8f77661eb8c2bce0e8434889 /Source
parentcb3b415105a884d70ac845b228f6bb87807f9f34 (diff)
parentf404d29266675808fffe9d71b065bc03b555b58d (diff)
downloadexternal_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.cpp24
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.h2
-rw-r--r--Source/WebKit/android/jni/AndroidHitTestResult.cpp92
-rw-r--r--Source/WebKit/android/jni/AndroidHitTestResult.h4
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp82
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h2
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