OSDN Git Service

layers support
authorNicolas Roard <nicolas@android.com>
Mon, 4 Jan 2010 19:30:55 +0000 (19:30 +0000)
committerNicolas Roard <nicolas@android.com>
Mon, 4 Jan 2010 19:30:55 +0000 (19:30 +0000)
core/java/android/webkit/WebView.java
core/java/android/webkit/WebViewCore.java

index 28a3404..f58446a 100644 (file)
@@ -208,6 +208,9 @@ public class WebView extends AbsoluteLayout
     static private final boolean AUTO_REDRAW_HACK = false;
     // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
     private boolean mAutoRedraw;
+    private int mRootLayer; // C++ pointer to the root layer
+    private boolean mLayersHaveAnimations;
+    private EvaluateLayersAnimations mEvaluateThread;
 
     static final String LOGTAG = "webview";
 
@@ -494,6 +497,8 @@ public class WebView extends AbsoluteLayout
     static final int SHOW_FULLSCREEN                    = 29;
     static final int HIDE_FULLSCREEN                    = 30;
     static final int DOM_FOCUS_CHANGED                  = 31;
+    static final int IMMEDIATE_REPAINT_MSG_ID           = 32;
+    static final int SET_ROOT_LAYER_MSG_ID              = 33;
 
     static final String[] HandlerDebugString = {
         "REMEMBER_PASSWORD", //              = 1;
@@ -526,7 +531,9 @@ public class WebView extends AbsoluteLayout
         "DO_MOTION_UP", //                   = 28;
         "SHOW_FULLSCREEN", //                = 29;
         "HIDE_FULLSCREEN", //                = 30;
-        "DOM_FOCUS_CHANGED" //               = 31;
+        "DOM_FOCUS_CHANGED", //              = 31;
+        "IMMEDIATE_REPAINT_MSG_ID", //       = 32;
+        "SET_ROOT_LAYER_MSG_ID" //           = 33;
     };
 
     // If the site doesn't use the viewport meta tag to specify the viewport,
@@ -2919,6 +2926,7 @@ public class WebView extends AbsoluteLayout
         if (AUTO_REDRAW_HACK && mAutoRedraw) {
             invalidate();
         }
+        mWebViewCore.signalRepaintDone();
     }
 
     @Override
@@ -2986,11 +2994,20 @@ public class WebView extends AbsoluteLayout
         }
     }
 
+    private void drawLayers(Canvas canvas) {
+        if (mRootLayer != 0) {
+            float scrollY = Math.max(mScrollY - getTitleHeight(), 0);
+            nativeDrawLayers(mRootLayer, mScrollX, scrollY,
+                             mActualScale, canvas);
+        }
+    }
+
     private void drawCoreAndCursorRing(Canvas canvas, int color,
         boolean drawCursorRing) {
         if (mDrawHistory) {
             canvas.scale(mActualScale, mActualScale);
             canvas.drawPicture(mHistoryPicture);
+            drawLayers(canvas);
             return;
         }
 
@@ -3069,6 +3086,8 @@ public class WebView extends AbsoluteLayout
         mWebViewCore.drawContentPicture(canvas, color, animateZoom,
                 animateScroll);
 
+        drawLayers(canvas);
+
         if (mNativeClass == 0) return;
         if (mShiftIsPressed && !animateZoom) {
             if (mTouchSelection || mExtendSelection) {
@@ -3290,6 +3309,40 @@ public class WebView extends AbsoluteLayout
     }
 
     /*
+     * This class runs the layers animations in their own thread,
+     * so that we do not slow down the UI.
+     */
+    private class EvaluateLayersAnimations extends Thread {
+        boolean mRunning = true;
+        // delay corresponds to 40fps, no need to go faster.
+        int mDelay = 25; // in ms
+        public void run() {
+            while (mRunning) {
+                if (mLayersHaveAnimations && mRootLayer != 0) {
+                    // updates is a C++ pointer to a Vector of AnimationValues
+                    int updates = nativeEvaluateLayersAnimations(mRootLayer);
+                    if (updates == 0) {
+                        mRunning = false;
+                    }
+                    Message.obtain(mPrivateHandler,
+                          WebView.IMMEDIATE_REPAINT_MSG_ID,
+                          updates, 0).sendToTarget();
+                } else {
+                    mRunning = false;
+                }
+                try {
+                    Thread.currentThread().sleep(mDelay);
+                } catch (InterruptedException e) {
+                    mRunning = false;
+                }
+            }
+        }
+        public void cancel() {
+            mRunning = false;
+        }
+    }
+
+    /*
      * This class requests an Adapter for the WebTextView which shows past
      * entries stored in the database.  It is a Runnable so that it can be done
      * in its own thread, without slowing down the UI.
@@ -5308,7 +5361,7 @@ public class WebView extends AbsoluteLayout
             // exclude INVAL_RECT_MSG_ID since it is frequently output
             if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
                 Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
-                        > DOM_FOCUS_CHANGED ? Integer.toString(msg.what)
+                        > SET_ROOT_LAYER_MSG_ID ? Integer.toString(msg.what)
                         : HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
             }
             if (mWebViewCore == null) {
@@ -5564,6 +5617,38 @@ public class WebView extends AbsoluteLayout
                     }
                     break;
                 }
+                case IMMEDIATE_REPAINT_MSG_ID: {
+                    int updates = msg.arg1;
+                    if (updates != 0) {
+                        // updates is a C++ pointer to a Vector of
+                        // AnimationValues that we apply to the layers.
+                        // The Vector is deallocated in nativeUpdateLayers().
+                        nativeUpdateLayers(mRootLayer, updates);
+                    }
+                    invalidate();
+                    break;
+                }
+                case SET_ROOT_LAYER_MSG_ID: {
+                    int oldLayer = mRootLayer;
+                    mRootLayer = msg.arg1;
+                    if (oldLayer > 0) {
+                        nativeDestroyLayer(oldLayer);
+                    }
+                    if (mRootLayer == 0) {
+                        mLayersHaveAnimations = false;
+                    }
+                    if (mEvaluateThread != null) {
+                        mEvaluateThread.cancel();
+                        mEvaluateThread = null;
+                    }
+                    if (nativeLayersHaveAnimations(mRootLayer)) {
+                        mLayersHaveAnimations = true;
+                        mEvaluateThread = new EvaluateLayersAnimations();
+                        mEvaluateThread.start();
+                    }
+                    invalidate();
+                    break;
+                }
                 case REQUEST_FORM_DATA:
                     AutoCompleteAdapter adapter = (AutoCompleteAdapter) msg.obj;
                     if (mWebTextView.isSameTextField(msg.arg1)) {
@@ -6251,6 +6336,13 @@ public class WebView extends AbsoluteLayout
     private native void     nativeDebugDump();
     private native void     nativeDestroy();
     private native void     nativeDrawCursorRing(Canvas content);
+    private native void     nativeDestroyLayer(int layer);
+    private native int      nativeEvaluateLayersAnimations(int layer);
+    private native boolean  nativeLayersHaveAnimations(int layer);
+    private native void     nativeUpdateLayers(int layer, int updates);
+    private native void     nativeDrawLayers(int layer,
+                                             float scrollX, float scrollY,
+                                             float scale, Canvas canvas);
     private native void     nativeDrawMatches(Canvas canvas);
     private native void     nativeDrawSelectionPointer(Canvas content,
             float scale, int x, int y, boolean extendSelection);
index fc22f37..2de25e8 100644 (file)
@@ -1908,6 +1908,33 @@ final class WebViewCore {
         }
     }
 
+    private static boolean mRepaintScheduled = false;
+
+    /*
+     * Called by the WebView thread
+     */
+    /* package */ void signalRepaintDone() {
+        mRepaintScheduled = false;
+    }
+
+    // called by JNI
+    private void sendImmediateRepaint() {
+        if (mWebView != null && !mRepaintScheduled) {
+            mRepaintScheduled = true;
+            Message.obtain(mWebView.mPrivateHandler,
+                           WebView.IMMEDIATE_REPAINT_MSG_ID).sendToTarget();
+        }
+    }
+
+    // called by JNI
+    private void setRootLayer(int layer) {
+        if (mWebView != null) {
+            Message.obtain(mWebView.mPrivateHandler,
+                           WebView.SET_ROOT_LAYER_MSG_ID,
+                           layer, 0).sendToTarget();
+        }
+    }
+
     /* package */ WebView getWebView() {
         return mWebView;
     }