diff options
Diffstat (limited to 'WebKit/android')
| -rw-r--r-- | WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp | 8 | ||||
| -rw-r--r-- | WebKit/android/WebCoreSupport/ChromeClientAndroid.h | 2 | ||||
| -rw-r--r-- | WebKit/android/WebCoreSupport/PlatformBridge.cpp | 20 | ||||
| -rw-r--r-- | WebKit/android/jni/WebSettings.cpp | 4 | ||||
| -rw-r--r-- | WebKit/android/jni/WebViewCore.cpp | 135 | ||||
| -rw-r--r-- | WebKit/android/jni/WebViewCore.h | 17 | ||||
| -rw-r--r-- | WebKit/android/nav/CacheBuilder.cpp | 4 | ||||
| -rw-r--r-- | WebKit/android/nav/WebView.cpp | 15 | ||||
| -rw-r--r-- | WebKit/android/plugins/ANPWindowInterface.cpp | 3 | ||||
| -rw-r--r-- | WebKit/android/plugins/PluginDebugAndroid.cpp | 130 | ||||
| -rw-r--r-- | WebKit/android/plugins/PluginDebugAndroid.h | 14 | ||||
| -rw-r--r-- | WebKit/android/plugins/PluginWidgetAndroid.cpp | 180 | ||||
| -rw-r--r-- | WebKit/android/plugins/PluginWidgetAndroid.h | 20 |
13 files changed, 395 insertions, 157 deletions
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index ffa96f8..17dc0d0 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -71,8 +71,10 @@ void ChromeClientAndroid::compositingLayerSync() frameView->syncCompositingStateRecursive(); GraphicsLayerAndroid* androidGraphicsLayer = static_cast<GraphicsLayerAndroid*>(m_rootGraphicsLayer); - if (androidGraphicsLayer) + if (androidGraphicsLayer) { androidGraphicsLayer->sendImmediateRepaint(); + androidGraphicsLayer->notifyClientAnimationStarted(); + } return; } } @@ -466,12 +468,12 @@ void ChromeClientAndroid::wakeUpMainThreadWithNewQuota(long newQuota) { } #if ENABLE(TOUCH_EVENTS) -void ChromeClientAndroid::needTouchEvents(bool needTouchEvents, bool force) +void ChromeClientAndroid::needTouchEvents(bool needTouchEvents) { FrameView* frameView = m_webFrame->page()->mainFrame()->view(); android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView); if (core) - core->needTouchEvents(needTouchEvents, force); + core->needTouchEvents(needTouchEvents); } #endif diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h index b61f9fd..15bf52a 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -137,7 +137,7 @@ namespace android { virtual void populateVisitedLinks(); #if ENABLE(TOUCH_EVENTS) - virtual void needTouchEvents(bool, bool); + virtual void needTouchEvents(bool); #endif // Methods used to request and provide Geolocation permissions. diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp index f36ecf7..b91a5d8 100644 --- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp +++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp @@ -29,7 +29,9 @@ #include "CookieClient.h" #include "JavaSharedClient.h" #include "KeyGeneratorClient.h" +#include "PluginView.h" #include "WebViewCore.h" +#include "npruntime.h" #include <wtf/android/AndroidThreading.h> #include <wtf/MainThread.h> @@ -98,11 +100,29 @@ bool PlatformBridge::cookiesEnabled() return client->cookiesEnabled(); } +NPObject* PlatformBridge::pluginScriptableObject(Widget* widget) +{ +#if USE(V8) + if (!widget->isPluginView()) + return 0; + + PluginView* pluginView = static_cast<PluginView*>(widget); + return pluginView->getNPObject(); +#else + return 0; +#endif +} + bool PlatformBridge::isWebViewPaused() { return WebViewCore::isPaused(); } +bool PlatformBridge::popupsAllowed(NPP) +{ + return false; +} + } // namespace WebCore diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp index 00fec85..50919b6 100644 --- a/WebKit/android/jni/WebSettings.cpp +++ b/WebKit/android/jni/WebSettings.cpp @@ -35,8 +35,8 @@ #include "Frame.h" #include "FrameLoader.h" #include "FrameView.h" -#include "Geolocation.h" #include "GeolocationPermissions.h" +#include "GeolocationPositionCache.h" #include "Page.h" #include "PageCache.h" #include "RenderTable.h" @@ -366,7 +366,7 @@ public: str = (jstring)env->GetObjectField(obj, gFieldIds->mGeolocationDatabasePath); if (str) { GeolocationPermissions::setDatabasePath(to_string(env,str)); - WebCore::Geolocation::setDatabasePath(to_string(env,str)); + WebCore::GeolocationPositionCache::setDatabasePath(to_string(env,str)); } size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity); diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 5ebc8eb..ae3e47c 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -229,6 +229,7 @@ struct WebViewCore::JavaGlue { jmethodID m_destroySurface; jmethodID m_getContext; jmethodID m_sendFindAgain; + jmethodID m_showRect; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } @@ -267,7 +268,9 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_screenWidth = 320; m_scale = 1; m_screenWidthScale = 1; - m_touchEventListenerCount = 0; +#if ENABLE(TOUCH_EVENTS) + m_forwardingTouchEvents = false; +#endif LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!"); @@ -314,6 +317,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V"); m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;"); m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V"); + m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V"); env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this); @@ -996,28 +1000,20 @@ void WebViewCore::restoreScreenWidthScale(int scale) checkException(env); } -void WebViewCore::needTouchEvents(bool need, bool force) +void WebViewCore::needTouchEvents(bool need) { DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); -#if ENABLE(TOUCH_EVENTS) // Android - bool needToUpdateJava = false; - if (need) { - if (++m_touchEventListenerCount == 1) - needToUpdateJava = true; - } else { - if (force) - m_touchEventListenerCount = 0; - else if (--m_touchEventListenerCount == 0) - needToUpdateJava = true; - } +#if ENABLE(TOUCH_EVENTS) + if (m_forwardingTouchEvents == need) + return; - if (needToUpdateJava || force) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_needTouchEvents, need); - checkException(env); - } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_needTouchEvents, need); + checkException(env); + + m_forwardingTouchEvents = need; #endif } @@ -1099,13 +1095,15 @@ void WebViewCore::setGlobalBounds(int x, int y, int h, int v) void WebViewCore::setSizeScreenWidthAndScale(int width, int height, int screenWidth, float scale, int realScreenWidth, int screenHeight, - bool ignoreHeight) + int anchorX, int anchorY, bool ignoreHeight) { WebCoreViewBridge* window = m_mainFrame->view()->platformWidget(); int ow = window->width(); int oh = window->height(); window->setSize(width, height); int osw = m_screenWidth; + int orsw = m_screenWidth * m_screenWidthScale / m_scale; + int osh = m_screenHeight; DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)", ow, oh, osw, m_scale, width, height, screenWidth, scale); m_screenWidth = screenWidth; @@ -1124,46 +1122,82 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height, DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r, realScreenWidth, screenHeight); if (r) { - // get current screen center position - WebCore::IntPoint screenCenter = WebCore::IntPoint( - m_scrollOffsetX + (realScreenWidth >> 1), - m_scrollOffsetY + (screenHeight >> 1)); + WebCore::IntPoint anchorPoint; + if ((anchorX | anchorY) == 0) + // get the current screen center position if anchor is (0, 0) + // which implies that it is not defined + anchorPoint = WebCore::IntPoint( + m_scrollOffsetX + (realScreenWidth >> 1), + m_scrollOffsetY + (screenHeight >> 1)); + else + anchorPoint = WebCore::IntPoint(anchorX, anchorY); WebCore::Node* node = 0; WebCore::IntRect bounds; WebCore::IntPoint offset; // If the screen width changed, it is probably zoom change or - // orientation change. Try to keep the node in the center of the - // screen staying at the same place. - if (osw != screenWidth) { + // orientation change. Try to keep the anchor at the same place. + if (osw && screenWidth && osw != screenWidth) { WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()-> hitTestResultAtPoint( - screenCenter, false); + anchorPoint, false); node = hitTestResult.innerNode(); } if (node) { bounds = node->getRect(); DBG_NAV_LOGD("ob:(x=%d,y=%d,w=%d,h=%d)", bounds.x(), bounds.y(), bounds.width(), bounds.height()); - offset = WebCore::IntPoint(screenCenter.x() - bounds.x(), - screenCenter.y() - bounds.y()); - if (offset.x() < 0 || offset.x() > realScreenWidth || - offset.y() < 0 || offset.y() > screenHeight) - { - DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)", - offset.x(), offset.y()); - node = 0; + // sites like nytimes.com insert a non-standard tag <nyt_text> + // in the html. If it is the HitTestResult, it may have zero + // width and height. In this case, use its parent node. + if (bounds.width() == 0) { + node = node->parent(); + if (node) { + bounds = node->getRect(); + DBG_NAV_LOGD("found a zero width node and use its parent, whose ob:(x=%d,y=%d,w=%d,h=%d)", + bounds.x(), bounds.y(), bounds.width(), bounds.height()); + } + } + if ((anchorX | anchorY) == 0) { + // if there is no explicit anchor, ignore if it is offscreen + offset = WebCore::IntPoint(anchorPoint.x() - bounds.x(), + anchorPoint.y() - bounds.y()); + if (offset.x() < 0 || offset.x() > realScreenWidth || + offset.y() < 0 || offset.y() > screenHeight) + { + DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)", + offset.x(), offset.y()); + node = 0; + } } } r->setNeedsLayoutAndPrefWidthsRecalc(); m_mainFrame->view()->forceLayout(); // scroll to restore current screen center - if (node) { - const WebCore::IntRect& newBounds = node->getRect(); - DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d," - "h=%d,ns=%d)", newBounds.x(), newBounds.y(), - newBounds.width(), newBounds.height()); - scrollBy(newBounds.x() - bounds.x(), newBounds.y() - bounds.y(), - false); + if (!node) + return; + const WebCore::IntRect& newBounds = node->getRect(); + DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d," + "h=%d)", newBounds.x(), newBounds.y(), + newBounds.width(), newBounds.height()); + if ((anchorX | anchorY) == 0) + scrollBy(newBounds.x() - bounds.x(), + newBounds.y() - bounds.y(), false); + else if ((orsw && osh && bounds.width() && bounds.height()) + && (bounds != newBounds)) { + WebCore::FrameView* view = m_mainFrame->view(); + // force left align if width is not changed while height changed. + // the anchorPoint is probably at some white space in the node + // which is affected by text wrap around the screen width. + bool leftAlign = (osw != m_screenWidth) + && (bounds.width() == newBounds.width()) + && (bounds.height() != newBounds.height()); + showRect(newBounds.x(), newBounds.y(), newBounds.width(), + newBounds.height(), view->contentsWidth(), + view->contentsHeight(), + leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width(), + leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / orsw, + (float) (anchorY - bounds.y()) / bounds.height(), + (float) (anchorY - m_scrollOffsetY) / osh); } } } @@ -2398,6 +2432,17 @@ bool WebViewCore::validNodeAndBounds(Frame* frame, Node* node, return absBounds == originalAbsoluteBounds; } +void WebViewCore::showRect(int left, int top, int width, int height, + int contentWidth, int contentHeight, float xPercentInDoc, + float xPercentInView, float yPercentInDoc, float yPercentInView) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_showRect, + left, top, width, height, contentWidth, contentHeight, + xPercentInDoc, xPercentInView, yPercentInDoc, yPercentInView); + checkException(env); +} + //---------------------------------------------------------------------- // Native JNI methods //---------------------------------------------------------------------- @@ -2425,7 +2470,7 @@ static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj) static void SetSize(JNIEnv *env, jobject obj, jint width, jint height, jint screenWidth, jfloat scale, jint realScreenWidth, jint screenHeight, - jboolean ignoreHeight) + jint anchorX, jint anchorY, jboolean ignoreHeight) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -2434,7 +2479,7 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height, LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl); LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize"); viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale, - realScreenWidth, screenHeight, ignoreHeight); + realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight); } static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y) @@ -3022,7 +3067,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SendListBoxChoices }, { "nativeSendListBoxChoice", "(I)V", (void*) SendListBoxChoice }, - { "nativeSetSize", "(IIIFIIZ)V", + { "nativeSetSize", "(IIIFIIIIZ)V", (void*) SetSize }, { "nativeSetScrollOffset", "(III)V", (void*) SetScrollOffset }, diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index c662441..2252878 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -265,8 +265,8 @@ namespace android { void setGlobalBounds(int x, int y, int h, int v); void setSizeScreenWidthAndScale(int width, int height, int screenWidth, - float scale, int realScreenWidth, int screenHeight, - bool ignoreHeight); + float scale, int realScreenWidth, int screenHeight, int anchorX, + int anchorY, bool ignoreHeight); /** * Handle key events from Java. @@ -375,7 +375,7 @@ namespace android { Node* cursorNodeIsPlugin(); // Notify the Java side whether it needs to pass down the touch events - void needTouchEvents(bool, bool); + void needTouchEvents(bool); // Notify the Java side that webkit is requesting a keyboard void requestKeyboard(bool showKeyboard, bool isTextView); @@ -405,6 +405,15 @@ namespace android { jobject getContext(); bool validNodeAndBounds(Frame* , Node* , const IntRect& ); + + // Make the rect (left, top, width, height) visible. If it can be fully + // fit, center it on the screen. Otherwise make sure the point specified + // by (left + xPercentInDoc * width, top + yPercentInDoc * height) + // pinned at the screen position (xPercentInView, yPercentInView). + void showRect(int left, int top, int width, int height, int contentWidth, + int contentHeight, float xPercentInDoc, float xPercentInView, + float yPercentInDoc, float yPercentInView); + // other public functions public: // Open a file chooser for selecting a file to upload @@ -527,7 +536,7 @@ namespace android { WebCore::HTMLAnchorElement* retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node); #if ENABLE(TOUCH_EVENTS) - int m_touchEventListenerCount; + bool m_forwardingTouchEvents; IntPoint m_lastTouchPoint; #endif diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index 784c3aa..c665887 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -1889,7 +1889,9 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars s->mProgress = ZIP_CODE; // a couple of delimiters is an indication that the state name is good // or, a non-space / non-alpha-digit is also good - s->mZipDelimiter = s->mLineCount > 2 || isUnicodeSpace(ch) == false; + s->mZipDelimiter = s->mLineCount > 2 + || isUnicodeSpace(ch) == false + || chars == s->mEnd; if (WTF::isASCIIDigit(ch)) s->mZipStart = chars; goto resetState; diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 98f308c..e2a7708 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -1533,13 +1533,10 @@ static void nativeDrawLayers(JNIEnv *env, jobject obj, #endif } -static void nativeUpdateLayers(JNIEnv *env, jobject obj, - jint layer, jint updates) +static void nativeUpdateLayers(JNIEnv *env, jobject obj, jint updates) { if (!env) return; - if (!layer) - return; if (!updates) return; @@ -1998,13 +1995,15 @@ static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj) CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); if (!root) return; - const CachedNode* current = root->currentCursor(); + const CachedFrame* containingFrame; + const CachedNode* current = root->currentCursor(&containingFrame); if (!current) - current = root->currentFocus(); + current = root->currentFocus(&containingFrame); if (!current) return; const CachedFrame* frame; - const CachedNode* next = root->nextTextField(current, &frame, true); + const CachedNode* next = containingFrame->nextTextField(current, &frame, + true); if (!next) return; const WebCore::IntRect& bounds = next->bounds(); @@ -2136,7 +2135,7 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeEvaluateLayersAnimations }, { "nativeDrawLayers", "(IIIIIFLandroid/graphics/Canvas;)V", (void*) nativeDrawLayers }, - { "nativeUpdateLayers", "(II)V", + { "nativeUpdateLayers", "(I)V", (void*) nativeUpdateLayers }, { "nativeDrawMatches", "(Landroid/graphics/Canvas;)V", (void*) nativeDrawMatches }, diff --git a/WebKit/android/plugins/ANPWindowInterface.cpp b/WebKit/android/plugins/ANPWindowInterface.cpp index 06afab1..bb7b9a3 100644 --- a/WebKit/android/plugins/ANPWindowInterface.cpp +++ b/WebKit/android/plugins/ANPWindowInterface.cpp @@ -49,7 +49,8 @@ static void anp_clearVisibleRects(NPP instance) { static void anp_showKeyboard(NPP instance, bool value) { PluginView* pluginView = pluginViewForInstance(instance); PluginWidgetAndroid* pluginWidget = pluginView->platformPluginWidget(); - pluginWidget->webViewCore()->requestKeyboard(value, false); + if(pluginWidget->hasFocus()) + pluginWidget->webViewCore()->requestKeyboard(value, false); } static void anp_requestFullScreen(NPP instance) { diff --git a/WebKit/android/plugins/PluginDebugAndroid.cpp b/WebKit/android/plugins/PluginDebugAndroid.cpp new file mode 100644 index 0000000..3f1db2d --- /dev/null +++ b/WebKit/android/plugins/PluginDebugAndroid.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginDebugAndroid.h" +#include "utils/Log.h" +#include <stdarg.h> + +#define ARRAY_COUNT(array) static_cast<int32_t>(sizeof(array) / sizeof(array[0])) + +// used for key, mouse, and touch inputs +static const char* const inputActions[] = { + "down", + "up", + "move", /* touch only */ + "cancel", /* touch only */ + "longPress", /* touch only */ + "doubleTap" /* touch only */ +}; + +static const char* const lifecycleActions[] = { + "kPause_ANPLifecycleAction", + "kResume_ANPLifecycleAction", + "kGainFocus_ANPLifecycleAction", + "kLoseFocus_ANPLifecycleAction", + "kFreeMemory_ANPLifecycleAction", + "kOnLoad_ANPLifecycleAction", + "kEnterFullScreen_ANPLifecycleAction", + "kExitFullScreen_ANPLifecycleAction", + "kOnScreen_ANPLifecycleAction", + "kOffScreen_ANPLifecycleAction" +}; + +void anp_logPlugin(const char format[], ...) { + va_list args; + va_start(args, format); + LOG_PRI_VA(ANDROID_LOG_DEBUG, "webkit_plugin", format, args); + va_end(args); +} + +void anp_logPluginEvent(void* npp, const ANPEvent* evt, int16 returnVal) { + + switch(evt->eventType) { + + case kNull_ANPEventType: + PLUGIN_LOG("%p EVENT::NULL", npp); + break; + + case kKey_ANPEventType: + if(evt->data.key.action < ARRAY_COUNT(inputActions)) { + anp_logPlugin("%p EVENT::KEY[%d] action=%s code=%d vcode=%d unichar=%d repeat=%d mods=%x", + npp, returnVal, inputActions[evt->data.key.action], + evt->data.key.nativeCode, evt->data.key.virtualCode, + evt->data.key.unichar, evt->data.key.repeatCount, + evt->data.key.modifiers); + } else { + PLUGIN_LOG("%p EVENT::KEY[%d] unknown action", npp, returnVal); + } + break; + + case kMouse_ANPEventType: + if(evt->data.mouse.action < ARRAY_COUNT(inputActions)) { + anp_logPlugin("%p EVENT::MOUSE[%d] action=%s [%d %d]", npp, + returnVal, inputActions[evt->data.mouse.action], + evt->data.touch.x, evt->data.touch.y); + } else { + anp_logPlugin("%p EVENT::MOUSE[%d] unknown action", npp, returnVal); + } + break; + + case kTouch_ANPEventType: + if(evt->data.touch.action < ARRAY_COUNT(inputActions)) { + anp_logPlugin("%p EVENT::TOUCH[%d] action=%s [%d %d]", npp, + returnVal, inputActions[evt->data.touch.action], + evt->data.touch.x, evt->data.touch.y); + } else { + anp_logPlugin("%p EVENT::TOUCH[%d] unknown action", npp, returnVal); + } + break; + + case kDraw_ANPEventType: + if (evt->data.draw.model == kBitmap_ANPDrawingModel) { + anp_logPlugin("%p EVENT::DRAW bitmap format=%d clip=[%d,%d,%d,%d]", + npp, evt->data.draw.data.bitmap.format, + evt->data.draw.clip.left, evt->data.draw.clip.top, + evt->data.draw.clip.right, evt->data.draw.clip.bottom); + } else { + anp_logPlugin("%p EVENT::DRAW unknown drawing model", npp); + } + break; + + case kLifecycle_ANPEventType: + if(evt->data.lifecycle.action < ARRAY_COUNT(lifecycleActions)) { + anp_logPlugin("%p EVENT::LIFECYCLE %s", npp, + lifecycleActions[evt->data.lifecycle.action]); + } else { + anp_logPlugin("%p EVENT::LIFECYCLE unknown action", npp); + } + break; + + case kCustom_ANPEventType: + anp_logPlugin("%p EVENT::CUSTOM", npp); + break; + + default: + anp_logPlugin("%p EVENT::UNKNOWN", npp); + break; + } +} diff --git a/WebKit/android/plugins/PluginDebugAndroid.h b/WebKit/android/plugins/PluginDebugAndroid.h index 2143b39..24944cb 100644 --- a/WebKit/android/plugins/PluginDebugAndroid.h +++ b/WebKit/android/plugins/PluginDebugAndroid.h @@ -26,21 +26,25 @@ #ifndef PLUGIN_DEBUG_ANDROID_H__ #define PLUGIN_DEBUG_ANDROID_H__ -#ifdef ANDROID_PLUGINS +#include "android_npapi.h" // Define PLUGIN_DEBUG_LOCAL in an individual C++ file to enable for // that file only. // Define PLUGIN_DEBUG_GLOBAL to 1 to turn plug-in debug for all -// Android plug-in code in this direectory. +// Android plug-in code in this directory. #define PLUGIN_DEBUG_GLOBAL 0 #if PLUGIN_DEBUG_GLOBAL || defined(PLUGIN_DEBUG_LOCAL) -# define PLUGIN_LOG(A, B...) do { LOGI( A , ## B ); } while(0) +# define PLUGIN_LOG(FORMAT, ARGS...) do { anp_logPlugin(FORMAT, ## ARGS); } while(0) +# define PLUGIN_LOG_EVENT(NPP, EVT, RET) do { anp_logPluginEvent(NPP, EVT, RET); } while(0) + +void anp_logPlugin(const char format[], ...); +void anp_logPluginEvent(void* npp, const ANPEvent* event, int16 returnVal); + #else # define PLUGIN_LOG(A, B...) do { } while(0) -#endif - +# define PLUGIN_LOG_EVENT(NPP, EVENT) do { } while(0) #endif #endif // defined(PLUGIN_DEBUG_ANDROID_H__) diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp index 553b455..7109ab4 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.cpp +++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp @@ -44,8 +44,12 @@ #include "android_graphics.h" #include <JNIUtility.h> +#define PLUGIN_DEBUG_LOCAL 0 // controls the printing of log messages #define DEBUG_VISIBLE_RECTS 1 // temporary debug printfs and fixes +// this include statement must follow the declaration of PLUGIN_DEBUG_LOCAL +#include "PluginDebugAndroid.h" + PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view) : m_pluginView(view) { m_flipPixelRef = NULL; @@ -54,7 +58,7 @@ PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view) m_eventFlags = 0; m_pluginWindow = NULL; m_requestedVisibleRectCount = 0; - m_requestedDocRect.setEmpty(); + m_requestedVisibleRect.setEmpty(); m_visibleDocRect.setEmpty(); m_pluginBounds.setEmpty(); m_hasFocus = false; @@ -113,14 +117,8 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { if (m_drawingModel == kSurface_ANPDrawingModel) { - // if the surface exists check for changes and update accordingly - if (m_embeddedView && m_pluginBounds != oldPluginBounds) { - - m_core->updateSurface(m_embeddedView, window->x, window->y, - window->width, window->height); - // if the surface does not exist then create a new surface - } else if(!m_embeddedView) { + if (!m_embeddedView) { WebCore::PluginPackage* pkg = m_pluginView->plugin(); NPP instance = m_pluginView->instance(); @@ -136,10 +134,15 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { JNIEnv* env = JSC::Bindings::getJNIEnv(); m_embeddedView = env->NewGlobalRef(tempObj); } - } - if (m_isFullScreen && m_pluginBounds != oldPluginBounds) { - m_core->updateFullScreenPlugin(window->x, window->y, - window->width, window->height); + } else if (m_pluginBounds != oldPluginBounds) { + // if the surface exists check for changes and update accordingly + if (m_isFullScreen) { + m_core->updateFullScreenPlugin(window->x, window->y, + window->width, window->height); + } else { + m_core->updateSurface(m_embeddedView, window->x, window->y, + window->width, window->height); + } } } else { m_flipPixelRef->safeUnref(); @@ -224,28 +227,38 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) { } } -bool PluginWidgetAndroid::sendEvent(const ANPEvent& evt) { +int16 PluginWidgetAndroid::sendEvent(const ANPEvent& evt) { if (!m_acceptEvents) - return false; + return 0; WebCore::PluginPackage* pkg = m_pluginView->plugin(); NPP instance = m_pluginView->instance(); // "missing" plugins won't have these if (pkg && instance) { - // keep track of whether or not the plugin currently has focus - if (evt.eventType == kLifecycle_ANPEventType) { - if (evt.data.lifecycle.action == kLoseFocus_ANPLifecycleAction) - m_hasFocus = false; - else if (evt.data.lifecycle.action == kGainFocus_ANPLifecycleAction) - m_hasFocus = true; + // if the plugin is gaining focus then update our state now to allow + // the plugin's event handler to perform actions that require focus + if (evt.eventType == kLifecycle_ANPEventType && + evt.data.lifecycle.action == kGainFocus_ANPLifecycleAction) { + m_hasFocus = true; } // make a localCopy since the actual plugin may not respect its constness, // and so we don't want our caller to have its param modified ANPEvent localCopy = evt; - return pkg->pluginFuncs()->event(instance, &localCopy); + int16 result = pkg->pluginFuncs()->event(instance, &localCopy); + PLUGIN_LOG_EVENT(instance, &evt, result); + + // if the plugin is losing focus then delay the update of our state + // until after we notify the plugin and allow them to perform actions + // that may require focus + if (evt.eventType == kLifecycle_ANPEventType && + evt.data.lifecycle.action == kLoseFocus_ANPLifecycleAction) { + m_hasFocus = false; + } + + return result; } - return false; + return 0; } void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) { @@ -258,14 +271,8 @@ void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) { Document* doc = m_pluginView->getParentFrame()->document(); #if ENABLE(TOUCH_EVENTS) if((m_eventFlags ^ flags) & kTouch_ANPEventFlag) { - if (flags & kTouch_ANPEventFlag) { - if (Page* page = doc->page()) - page->chrome()->client()->needTouchEvents(true, false); - doc->addListenerTypeIfNeeded(eventNames().touchstartEvent); - } else { - if (Page* page = doc->page()) - page->chrome()->client()->needTouchEvents(false, false); - } + if (flags & kTouch_ANPEventFlag) + doc->addListenerTypeIfNeeded(eventNames().touchstartEvent); } #endif @@ -278,22 +285,32 @@ bool PluginWidgetAndroid::isAcceptingEvent(ANPEventFlag flag) { void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) { #if DEBUG_VISIBLE_RECTS - SkDebugf("%s (%d,%d,%d,%d)", __FUNCTION__, visibleDocRect.left, - visibleDocRect.top, visibleDocRect.right, visibleDocRect.bottom); + PLUGIN_LOG("%s (%d,%d,%d,%d)[%f]", __FUNCTION__, visibleDocRect.left, + visibleDocRect.top, visibleDocRect.right, + visibleDocRect.bottom, zoom); #endif // TODO update the bitmap size based on the zoom? (for kBitmap_ANPDrawingModel) int oldScreenW = m_visibleDocRect.width(); int oldScreenH = m_visibleDocRect.height(); - m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top, - visibleDocRect.right, visibleDocRect.bottom); + // make local copies of the parameters + m_zoomLevel = zoom; + m_visibleDocRect.set(visibleDocRect.left, + visibleDocRect.top, + visibleDocRect.right, + visibleDocRect.bottom); int newScreenW = m_visibleDocRect.width(); int newScreenH = m_visibleDocRect.height(); - if (oldScreenW != newScreenW || oldScreenH != newScreenH) - computeVisibleDocRect(); + PLUGIN_LOG("%s VisibleDoc Dimensions old=[%d,%d] new=[%d,%d] ", + __FUNCTION__, oldScreenW, oldScreenH, newScreenW, newScreenH); + + // if the screen dimensions have changed by more than 5 pixels in either + // direction then recompute the plugin's visible rectangle + if (abs(oldScreenW - newScreenW) > 5 || abs(oldScreenH - newScreenH) > 5) + computeVisiblePluginRect(); bool visible = SkIRect::Intersects(m_visibleDocRect, m_pluginBounds); if(m_visible != visible) { @@ -310,7 +327,7 @@ void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) { #if DEBUG_VISIBLE_RECTS - SkDebugf("%s count=%d", __FUNCTION__, count); + PLUGIN_LOG("%s count=%d", __FUNCTION__, count); #endif // ensure the count does not exceed our allocated space if (count > MAX_REQUESTED_RECTS) @@ -318,33 +335,33 @@ void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) // store the values in member variables m_requestedVisibleRectCount = count; - memcpy(m_requestedVisibleRect, rects, count * sizeof(rects[0])); + memcpy(m_requestedVisibleRects, rects, count * sizeof(rects[0])); #if DEBUG_VISIBLE_RECTS // FIXME: this fixes bad data from the plugin // take it out once plugin supplies better data for (int index = 0; index < count; index++) { - SkDebugf("%s [%d](%d,%d,%d,%d)", __FUNCTION__, index, - m_requestedVisibleRect[index].left, - m_requestedVisibleRect[index].top, - m_requestedVisibleRect[index].right, - m_requestedVisibleRect[index].bottom); - if (m_requestedVisibleRect[index].left == - m_requestedVisibleRect[index].right) { - m_requestedVisibleRect[index].right += 1; + PLUGIN_LOG("%s [%d](%d,%d,%d,%d)", __FUNCTION__, index, + m_requestedVisibleRects[index].left, + m_requestedVisibleRects[index].top, + m_requestedVisibleRects[index].right, + m_requestedVisibleRects[index].bottom); + if (m_requestedVisibleRects[index].left == + m_requestedVisibleRects[index].right) { + m_requestedVisibleRects[index].right += 1; } - if (m_requestedVisibleRect[index].top == - m_requestedVisibleRect[index].bottom) { - m_requestedVisibleRect[index].bottom += 1; + if (m_requestedVisibleRects[index].top == + m_requestedVisibleRects[index].bottom) { + m_requestedVisibleRects[index].bottom += 1; } } #endif - computeVisibleDocRect(); + computeVisiblePluginRect(); } -void PluginWidgetAndroid::computeVisibleDocRect() { +void PluginWidgetAndroid::computeVisiblePluginRect() { // ensure the visibleDocRect has been set (i.e. not equal to zero) - if (m_visibleDocRect.isEmpty() || !m_pluginWindow) + if (m_visibleDocRect.isEmpty() || !m_pluginWindow || m_requestedVisibleRectCount < 1) return; // create a rect that will contain as many of the rects that will fit on screen @@ -353,7 +370,7 @@ void PluginWidgetAndroid::computeVisibleDocRect() { for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) { - ANPRectI* rect = &m_requestedVisibleRect[counter]; + ANPRectI* rect = &m_requestedVisibleRects[counter]; // create skia rect for easier manipulation and convert it to page coordinates SkIRect pluginRect; @@ -363,64 +380,67 @@ void PluginWidgetAndroid::computeVisibleDocRect() { // ensure the rect falls within the plugin's bounds if (!m_pluginBounds.contains(pluginRect)) { #if DEBUG_VISIBLE_RECTS - SkDebugf("%s (%d,%d,%d,%d) !contain (%d,%d,%d,%d)", __FUNCTION__, - m_pluginBounds.fLeft, m_pluginBounds.fTop, - m_pluginBounds.fRight, m_pluginBounds.fBottom, - pluginRect.fLeft, pluginRect.fTop, - pluginRect.fRight, pluginRect.fBottom); - // FIXME: assume that the desired outcome is to clamp to the container - pluginRect.intersect(m_pluginBounds); + PLUGIN_LOG("%s (%d,%d,%d,%d) !contain (%d,%d,%d,%d)", __FUNCTION__, + m_pluginBounds.fLeft, m_pluginBounds.fTop, + m_pluginBounds.fRight, m_pluginBounds.fBottom, + pluginRect.fLeft, pluginRect.fTop, + pluginRect.fRight, pluginRect.fBottom); + // assume that the desired outcome is to clamp to the container + if (pluginRect.intersect(m_pluginBounds)) { + visibleRect = pluginRect; + } #endif continue; } + // combine this new rect with the higher priority rects pluginRect.join(visibleRect); - // check to see if the new rect fits within the screen bounds. If this - // is the highest priority rect then attempt to center even if it doesn't - // fit on the screen. + // check to see if the new rect could be made to fit within the screen + // bounds. If this is the highest priority rect then attempt to center + // even if it doesn't fit on the screen. if (counter > 0 && (m_visibleDocRect.width() < pluginRect.width() || - m_visibleDocRect.height() < pluginRect.height())) + m_visibleDocRect.height() < pluginRect.height())) break; // set the new visible rect visibleRect = pluginRect; } - m_requestedDocRect = visibleRect; - scrollToVisibleDocRect(); + m_requestedVisibleRect = visibleRect; + scrollToVisiblePluginRect(); } -void PluginWidgetAndroid::scrollToVisibleDocRect() { +void PluginWidgetAndroid::scrollToVisiblePluginRect() { - if (!m_hasFocus || m_requestedDocRect.isEmpty() || m_visibleDocRect.isEmpty()) { + if (!m_hasFocus || m_requestedVisibleRect.isEmpty() || m_visibleDocRect.isEmpty()) { #if DEBUG_VISIBLE_RECTS - SkDebugf("%s call m_hasFocus=%d m_requestedDocRect.isEmpty()=%d" - " m_visibleDocRect.isEmpty()=%d", __FUNCTION__, m_hasFocus, - m_requestedDocRect.isEmpty(), m_visibleDocRect.isEmpty()); + PLUGIN_LOG("%s call m_hasFocus=%d m_requestedVisibleRect.isEmpty()=%d" + " m_visibleDocRect.isEmpty()=%d", __FUNCTION__, m_hasFocus, + m_requestedVisibleRect.isEmpty(), m_visibleDocRect.isEmpty()); #endif return; } // if the entire rect is already visible then we don't need to scroll - if (m_visibleDocRect.contains(m_requestedDocRect)) + if (m_visibleDocRect.contains(m_requestedVisibleRect)) return; // find the center of the visibleRect in document coordinates - int rectCenterX = m_requestedDocRect.fLeft + m_requestedDocRect.width()/2; - int rectCenterY = m_requestedDocRect.fTop + m_requestedDocRect.height()/2; + int rectCenterX = m_requestedVisibleRect.fLeft + m_requestedVisibleRect.width()/2; + int rectCenterY = m_requestedVisibleRect.fTop + m_requestedVisibleRect.height()/2; // find document coordinates for center of the visible screen - int screenCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2; - int screenCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2; + int visibleDocCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2; + int visibleDocCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2; - //compute the delta of the two points - int deltaX = rectCenterX - screenCenterX; - int deltaY = rectCenterY - screenCenterY; + //compute the delta of the two points and scale to screen coordinates + int deltaX = rectCenterX - visibleDocCenterX; + int deltaY = rectCenterY - visibleDocCenterY; ScrollView* scrollView = m_pluginView->parent(); android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); #if DEBUG_VISIBLE_RECTS - SkDebugf("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY); + PLUGIN_LOG("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY); #endif core->scrollBy(deltaX, deltaY, true); } diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h index 6633e1b..b47a4b3 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.h +++ b/WebKit/android/plugins/PluginWidgetAndroid.h @@ -89,10 +89,10 @@ struct PluginWidgetAndroid { */ void draw(SkCanvas* canvas = NULL); - /* Send this event to the plugin instance, and return true if the plugin - handled it. + /* Send this event to the plugin instance. A non-zero value will be + returned if the plugin handled the event. */ - bool sendEvent(const ANPEvent&); + int16 sendEvent(const ANPEvent&); /* Update the plugins event flags. If a flag is set to true then the plugin wants to be notified of events of this type. @@ -135,9 +135,15 @@ struct PluginWidgetAndroid { bool inFullScreen() { return m_isFullScreen; } + /** Called to check if a plugin currently has document focus, which is + required for certain operations (e.g. show/hide keyboard). It returns + true if the plugin currently has focus and false otherwise. + */ + bool hasFocus() const { return m_hasFocus; } + private: - void computeVisibleDocRect(); - void scrollToVisibleDocRect(); + void computeVisiblePluginRect(); + void scrollToVisiblePluginRect(); WebCore::PluginView* m_pluginView; android::WebViewCore* m_core; @@ -147,7 +153,7 @@ private: NPWindow* m_pluginWindow; SkIRect m_pluginBounds; // relative to the page SkIRect m_visibleDocRect; // relative to the page - SkIRect m_requestedDocRect; // relative to the page + SkIRect m_requestedVisibleRect; // relative to the page bool m_hasFocus; bool m_isFullScreen; bool m_visible; @@ -162,7 +168,7 @@ private: MAX_REQUESTED_RECTS = 5, }; - ANPRectI m_requestedVisibleRect[MAX_REQUESTED_RECTS]; + ANPRectI m_requestedVisibleRects[MAX_REQUESTED_RECTS]; int32_t m_requestedVisibleRectCount; }; |
