diff options
| author | Cary Clark <cary@android.com> | 2009-06-26 14:29:51 -0400 |
|---|---|---|
| committer | Cary Clark <cary@android.com> | 2009-06-29 08:20:09 -0400 |
| commit | b6631b666120e63a9ceee4a77613cf962fa37b1f (patch) | |
| tree | f6d2e38213df23f732bb5c6c27b6e124438eeeb2 /WebKit | |
| parent | af20123d135af00dd2762754671d88e4d52122c8 (diff) | |
| download | external_webkit-b6631b666120e63a9ceee4a77613cf962fa37b1f.zip external_webkit-b6631b666120e63a9ceee4a77613cf962fa37b1f.tar.gz external_webkit-b6631b666120e63a9ceee4a77613cf962fa37b1f.tar.bz2 | |
work in progress to enable plugins to receive arrow keys
Consolidate key handling. Simplify interface between android
and webkit so multiple clients can use common code to pass keys.
Add helper to return if cached node is plugin.
Use WebView::m_clickedOnPlugin to remember active plugins.
Add WebView.MOVE_CURSOR to replay key events the plugin
doesn't want.
Diffstat (limited to 'WebKit')
| -rw-r--r-- | WebKit/android/jni/WebViewCore.cpp | 76 | ||||
| -rw-r--r-- | WebKit/android/jni/WebViewCore.h | 7 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedNode.h | 3 | ||||
| -rw-r--r-- | WebKit/android/nav/WebView.cpp | 88 |
4 files changed, 102 insertions, 72 deletions
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 11576be..00cd64f 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -1382,9 +1382,6 @@ void WebViewCore::setSelection(int start, int end) focus->document()->frame()->revealSelection(); } -// Shortcut for no modifier keys -#define NO_MODIFIER_KEYS (static_cast<WebCore::PlatformKeyboardEvent::ModifierKey>(0)) - void WebViewCore::deleteSelection(int start, int end) { setSelection(start, end); @@ -1394,11 +1391,11 @@ void WebViewCore::deleteSelection(int start, int end) if (!focus) return; WebCore::Frame* frame = focus->document()->frame(); - WebCore::PlatformKeyboardEvent downEvent(kKeyCodeDel, WebCore::VK_BACK, - WebCore::PlatformKeyboardEvent::KeyDown, 0, NO_MODIFIER_KEYS); + WebCore::PlatformKeyboardEvent downEvent(kKeyCodeDel, 0, + true, 0, false, false, false); frame->eventHandler()->keyEvent(downEvent); - WebCore::PlatformKeyboardEvent upEvent(kKeyCodeDel, WebCore::VK_BACK, - WebCore::PlatformKeyboardEvent::KeyUp, 0, NO_MODIFIER_KEYS); + WebCore::PlatformKeyboardEvent upEvent(kKeyCodeDel, 0, + false, 0, false, false, false); frame->eventHandler()->keyEvent(upEvent); } @@ -1415,36 +1412,24 @@ void WebViewCore::replaceTextfieldText(int oldStart, setFocusControllerActive(true); } -void WebViewCore::passToJs( - int generation, const WebCore::String& current, int keyCode, - int keyValue, bool down, bool cap, bool fn, bool sym) +void WebViewCore::passToJs(int generation, const WebCore::String& current, + const PlatformKeyboardEvent& event) { WebCore::Node* focus = currentFocus(); if (!focus) { DBG_NAV_LOG("!focus"); return; } - WebCore::Frame* frame = focus->document()->frame(); - // Construct the ModifierKey value - WebCore::PlatformKeyboardEvent::ModifierKey mods = - static_cast<WebCore::PlatformKeyboardEvent::ModifierKey> - ((cap ? WebCore::PlatformKeyboardEvent::ShiftKey : 0) - | (fn ? WebCore::PlatformKeyboardEvent::AltKey : 0) - | (sym ? WebCore::PlatformKeyboardEvent::CtrlKey : 0)); - WebCore::PlatformKeyboardEvent event(keyCode, keyValue, - down ? WebCore::PlatformKeyboardEvent::KeyDown : - WebCore::PlatformKeyboardEvent::KeyUp, 0, mods); - // Block text field updates during a key press. - m_blockTextfieldUpdates = true; - frame->eventHandler()->keyEvent(event); - m_blockTextfieldUpdates = false; - m_textGeneration = generation; - DBG_NAV_LOGD("focus=%p keyCode=%d keyValue=%d", focus, keyCode, keyValue); WebCore::RenderObject* renderer = focus->renderer(); if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) { DBG_NAV_LOGD("renderer==%p || not text", renderer); return; } + // Block text field updates during a key press. + m_blockTextfieldUpdates = true; + key(event); + m_blockTextfieldUpdates = false; + m_textGeneration = generation; setFocusControllerActive(true); WebCore::RenderTextControl* renderText = static_cast<WebCore::RenderTextControl*>(renderer); @@ -1634,26 +1619,15 @@ void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, s m_popupReply = reply; } -bool WebViewCore::key(int keyCode, UChar32 unichar, int repeatCount, bool isShift, bool isAlt, bool isDown) +bool WebViewCore::key(const PlatformKeyboardEvent& event) { WebCore::EventHandler* eventHandler = m_mainFrame->eventHandler(); WebCore::Node* focusNode = currentFocus(); - if (focusNode) { + if (focusNode) eventHandler = focusNode->document()->frame()->eventHandler(); - } - - int mods = 0; // PlatformKeyboardEvent::ModifierKey - if (isShift) { - mods |= WebCore::PlatformKeyboardEvent::ShiftKey; - } - if (isAlt) { - mods |= WebCore::PlatformKeyboardEvent::AltKey; - } - DBG_NAV_LOGD("keyCode=%d focusNode=%p", keyCode, focusNode); - WebCore::PlatformKeyboardEvent evt(keyCode, unichar, - isDown ? WebCore::PlatformKeyboardEvent::KeyDown : WebCore::PlatformKeyboardEvent::KeyUp, - repeatCount, static_cast<WebCore::PlatformKeyboardEvent::ModifierKey> (mods)); - return eventHandler->keyEvent(evt); + DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p", + event.keyIdentifier().utf8().data(), event.unichar(), focusNode); + return eventHandler->keyEvent(event); } // For when the user clicks the trackball @@ -2031,15 +2005,14 @@ static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h, } static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar, - jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isDown) + jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isSym, + jboolean isDown) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in Key"); - - return viewImpl->key(keyCode, unichar, repeatCount, isShift, isAlt, isDown); + return GET_NATIVE_VIEW(env, obj)->key(PlatformKeyboardEvent(keyCode, + unichar, repeatCount, isDown, isShift, isAlt, isSym)); } static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr) @@ -2092,12 +2065,9 @@ static void PassToJs(JNIEnv *env, jobject obj, #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - LOGV("webviewcore::nativePassToJs()\n"); - WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in nativePassToJs"); WebCore::String current = to_string(env, currentText); - viewImpl->passToJs( - generation, current, keyCode, keyValue, down, cap, fn, sym); + GET_NATIVE_VIEW(env, obj)->passToJs(generation, current, + PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym)); } static void SetFocusControllerInactive(JNIEnv *env, jobject obj) @@ -2480,7 +2450,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) CopyContentToPicture }, { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z", (void*) DrawContent } , - { "nativeKey", "(IIIZZZ)Z", + { "nativeKey", "(IIIZZZZ)Z", (void*) Key }, { "nativeClick", "(II)V", (void*) Click }, diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index b9fff87..06e9100 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -48,6 +48,7 @@ namespace WebCore { class RenderPart; class RenderText; class Node; + class PlatformKeyboardEvent; class RenderTextControl; class ScrollView; class TimerBase; @@ -211,7 +212,7 @@ namespace android { * Handle key events from Java. * @return Whether keyCode was handled by this class. */ - bool key(int keyCode, UChar32 unichar, int repeatCount, bool isShift, bool isAlt, bool isDown); + bool key(const WebCore::PlatformKeyboardEvent& event); /** * Handle (trackball) click event from Java @@ -257,8 +258,7 @@ namespace android { void replaceTextfieldText(int oldStart, int oldEnd, const WebCore::String& replace, int start, int end); void passToJs(int generation, - const WebCore::String& currentText, int jKeyCode, int keyVal, - bool down, bool cap, bool fn, bool sym); + const WebCore::String& , const WebCore::PlatformKeyboardEvent& ); void setFocusControllerActive(bool active); void saveDocumentState(WebCore::Frame* frame); @@ -302,7 +302,6 @@ namespace android { // other public functions public: - // reset the picture set to empty void clearContent(); diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h index 9361309..2efbaf7 100644 --- a/WebKit/android/nav/CachedNode.h +++ b/WebKit/android/nav/CachedNode.h @@ -117,6 +117,9 @@ public: return clip.intersects(mBounds); } bool isPassword() const { return mIsPassword; } + bool isPlugin() const { + return mWantsKeyEvents && !mIsTextArea && !mIsTextField; + } bool isRtlText() const { return mIsRtlText; } bool isTextArea() const { return mIsTextArea; } bool isTextField() const { return mIsTextField; } diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index ec33948..022ca6f 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -161,6 +161,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_matches = 0; m_hasCurrentLocation = false; m_isFindPaintSetUp = false; + m_pluginReceivesEvents = false; } ~WebView() @@ -404,21 +405,25 @@ void drawMatches(SkCanvas* canvas) } } +void resetCursorRing() +{ + m_followedLink = m_pluginReceivesEvents = false; + m_viewImpl->m_hasCursorBounds = false; +} + void drawCursorRing(SkCanvas* canvas) { const CachedRoot* root = getFrameCache(AllowNewer); if (!root) { DBG_NAV_LOG("!root"); - m_followedLink = false; - m_viewImpl->m_hasCursorBounds = false; + resetCursorRing(); return; } const CachedFrame* frame; const CachedNode* node = root->currentCursor(&frame); if (!node) { DBG_NAV_LOG("!node"); - m_followedLink = false; - m_viewImpl->m_hasCursorBounds = false; + resetCursorRing(); return; } if (!node->hasCursorRing()) { @@ -466,29 +471,31 @@ void drawCursorRing(SkCanvas* canvas) DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" " bounds=(%d,%d,w=%d,h=%d)", node->index(), node->nodePointer(), bounds.x(), bounds.y(), bounds.width(), bounds.height()); - m_followedLink = false; + m_followedLink = m_pluginReceivesEvents = false; return; } CursorRing::Flavor flavor = CursorRing::NORMAL_FLAVOR; if (!isButton) { flavor = node->type() != NORMAL_CACHEDNODETYPE ? CursorRing::FAKE_FLAVOR : CursorRing::NORMAL_FLAVOR; + if (m_pluginReceivesEvents && node->isPlugin()) { + return; + } if (m_followedLink) { - if (node->wantsKeyEvents() && !node->isTextArea() - && !node->isTextField()) { - return; // don't draw after click on plugin - } flavor = static_cast<CursorRing::Flavor> (flavor + CursorRing::NORMAL_ANIMATING); } #if DEBUG_NAV_UI const WebCore::IntRect& ring = (*rings)[0]; DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) flavor=%s rings=%d" - " (%d, %d, %d, %d)", node->index(), node->nodePointer(), + " (%d, %d, %d, %d) pluginReceivesEvents=%s isPlugin=%s", + node->index(), node->nodePointer(), flavor == CursorRing::FAKE_FLAVOR ? "FAKE_FLAVOR" : flavor == CursorRing::NORMAL_ANIMATING ? "NORMAL_ANIMATING" : flavor == CursorRing::FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR", - rings->size(), ring.x(), ring.y(), ring.width(), ring.height()); + rings->size(), ring.x(), ring.y(), ring.width(), ring.height(), + m_pluginReceivesEvents ? "true" : "false", + node->isPlugin() ? "true" : "false"); #endif } if (isButton || flavor >= CursorRing::NORMAL_ANIMATING) { @@ -668,7 +675,7 @@ static CachedFrame::Direction KeyToDirection(KeyCode keyCode) DBG_NAV_LOGD("keyCode=%s", "up"); return CachedFrame::UP; default: - LOGD("------- bad key sent to WebView::moveCursor"); + DBG_NAV_LOGD("bad key %d sent", keyCode); return CachedFrame::UNINITIALIZED; } } @@ -720,6 +727,7 @@ void updateCursorBounds(const CachedRoot* root, const CachedFrame* cachedFrame, /* returns true if the key had no effect (neither scrolled nor changed cursor) */ bool moveCursor(int keyCode, int count, bool ignoreScroll) { + m_pluginReceivesEvents = false; CachedRoot* root = getFrameCache(AllowNewer); if (!root) { DBG_NAV_LOG("!root"); @@ -804,6 +812,21 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll) return result; } +bool pluginEatsNavKey() +{ + CachedRoot* root = getFrameCache(DontAllowNewer); + if (!root) { + DBG_NAV_LOG("!root"); + return false; + } + const CachedNode* cursor = root->currentCursor(); + DBG_NAV_LOGD("cursor=%p isPlugin=%s pluginReceivesEvents=%s", + cursor, cursor && cursor->isPlugin() ? "true" : "false", + m_pluginReceivesEvents ? "true" : "false"); + // FIXME: check to see if plugin wants keys + return cursor && cursor->isPlugin() && m_pluginReceivesEvents; +} + void notifyProgressFinished() { DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer)); @@ -876,7 +899,7 @@ void setNavBounds(const WebCore::IntRect& rect) bool motionUp(int x, int y, int slop) { bool pageScrolled = false; - m_followedLink = false; + m_followedLink = m_pluginReceivesEvents = false; const CachedFrame* frame; WebCore::IntRect rect = WebCore::IntRect(x - slop, y - slop, slop * 2, slop * 2); int rx, ry; @@ -906,6 +929,7 @@ bool motionUp(int x, int y, int slop) updateCursorBounds(root, frame, result); root->setCursor(const_cast<CachedFrame*>(frame), const_cast<CachedNode*>(result)); + updatePluginReceivesEvents(); CachedNodeType type = result->type(); if (type == NORMAL_CACHEDNODETYPE) { sendMotionUp( @@ -941,6 +965,17 @@ void setFindIsUp(bool up) m_hasCurrentLocation = false; } +void updatePluginReceivesEvents() +{ + CachedRoot* root = getFrameCache(DontAllowNewer); + if (!root) + return; + const CachedNode* cursor = root->currentCursor(); + m_pluginReceivesEvents = cursor && cursor->isPlugin(); + DBG_NAV_LOGD("m_pluginReceivesEvents=%s cursor=%p", m_pluginReceivesEvents + ? "true" : "false", cursor); +} + void setFollowedLink(bool followed) { if ((m_followedLink = followed) != false) { @@ -1263,6 +1298,7 @@ private: // local state for WebView int m_generation; // associate unique ID with sent kit focus to match with ui SkPicture* m_navPictureUI; bool m_followedLink; + bool m_pluginReceivesEvents; SkMSec m_ringAnimationEnd; // Corresponds to the same-named boolean on the java side. bool m_heightCanMeasure; @@ -1404,6 +1440,12 @@ static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj) return node ? node->isAnchor() : false; } +static bool nativeCursorIsPlugin(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + return node ? node->isPlugin() : false; +} + static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj) { const CachedNode* node = getCursorNode(env, obj); @@ -1654,6 +1696,11 @@ static void nativeSetFindIsDown(JNIEnv *env, jobject obj) view->setFindIsUp(false); } +static void nativeUpdatePluginReceivesEvents(JNIEnv *env, jobject obj) +{ + GET_NATIVE_VIEW(env, obj)->updatePluginReceivesEvents(); +} + static void nativeSetFollowedLink(JNIEnv *env, jobject obj, bool followed) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -1777,7 +1824,7 @@ static int nativeMoveGeneration(JNIEnv *env, jobject obj) WebView* view = GET_NATIVE_VIEW(env, obj); if (!view) return 0; - return GET_NATIVE_VIEW(env, obj)->moveGeneration(); + return view->moveGeneration(); } static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y, bool ex) @@ -1787,6 +1834,11 @@ static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y, bool ex) view->moveSelection(x, y, ex); } +static bool nativePluginEatsNavKey(JNIEnv *env, jobject obj) +{ + return GET_NATIVE_VIEW(env, obj)->pluginEatsNavKey(); +} + static jobject nativeGetSelection(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -1851,6 +1903,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeCursorIntersects }, { "nativeCursorIsAnchor", "()Z", (void*) nativeCursorIsAnchor }, + { "nativeCursorIsPlugin", "()Z", + (void*) nativeCursorIsPlugin }, { "nativeCursorIsTextInput", "()Z", (void*) nativeCursorIsTextInput }, { "nativeCursorPosition", "()Landroid/graphics/Point;", @@ -1919,6 +1973,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeMoveGeneration }, { "nativeMoveSelection", "(IIZ)V", (void*) nativeMoveSelection }, + { "nativePluginEatsNavKey", "()Z", + (void*) nativePluginEatsNavKey }, { "nativeRecordButtons", "(ZZZ)V", (void*) nativeRecordButtons }, { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V", @@ -1932,7 +1988,9 @@ static JNINativeMethod gJavaWebViewMethods[] = { { "nativeTextGeneration", "()I", (void*) nativeTextGeneration }, { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V", - (void*) nativeUpdateCachedTextfield } + (void*) nativeUpdateCachedTextfield }, + { "nativeUpdatePluginReceivesEvents", "()V", + (void*) nativeUpdatePluginReceivesEvents } }; int register_webview(JNIEnv* env) |
