summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2012-02-06 09:00:44 -0800
committerJohn Reck <jreck@google.com>2012-02-15 16:57:38 -0800
commitceeeab6161d7d8bf970ecf98affa4f4966df6f01 (patch)
tree0666a9ebf25e9d4e09ef3f8ee8ed0f6cf33fd4f1 /Source
parent628a06bda2490e4c405ce3263381412423f4c735 (diff)
downloadexternal_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.h2
-rw-r--r--Source/WebCore/editing/SelectionController.cpp4
-rw-r--r--Source/WebCore/html/HTMLAnchorElement.cpp4
-rw-r--r--Source/WebCore/platform/android/KeyEventAndroid.cpp2
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.cpp11
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.h1
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp29
-rw-r--r--Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp2
-rw-r--r--Source/WebKit/android/jni/WebSettings.cpp3
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp81
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h5
-rw-r--r--Source/WebKit/android/nav/WebView.cpp4
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)