OSDN Git Service

Merge pinch zoom from Eclair to Master. Including,
authorGrace Kloba <klobag@google.com>
Sat, 23 Jan 2010 18:09:03 +0000 (10:09 -0800)
committerGrace Kloba <klobag@google.com>
Sun, 24 Jan 2010 05:12:01 +0000 (21:12 -0800)
commit 237bd75b6ebc1298cbd1c46b43903d19d7dd18b1
commit dbb3061334333f32b6f12c294a551bd2a4a3844c
commit f48712a096831a3b85a5e18dabd44a541f6b4712
commit b99dd716b4af0afde074e28b50b7b28ae3c03da7

WebKit/android/jni/WebViewCore.cpp
WebKit/android/jni/WebViewCore.h

index 5ebc8eb..9778ea0 100644 (file)
@@ -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);
     }
@@ -314,6 +315,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);
 
@@ -1099,13 +1101,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 +1128,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 +2438,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 +2476,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 +2485,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 +3073,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
         (void*) SendListBoxChoices },
     { "nativeSendListBoxChoice", "(I)V",
         (void*) SendListBoxChoice },
-    { "nativeSetSize", "(IIIFIIZ)V",
+    { "nativeSetSize", "(IIIFIIIIZ)V",
         (void*) SetSize },
     { "nativeSetScrollOffset", "(III)V",
         (void*) SetScrollOffset },
index c662441..f528c73 100644 (file)
@@ -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.
@@ -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