diff options
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/browser/BrowserActivity.java | 7 | ||||
-rw-r--r-- | src/com/android/browser/FakeWebView.java | 55 | ||||
-rw-r--r-- | src/com/android/browser/ImageAdapter.java | 14 | ||||
-rw-r--r-- | src/com/android/browser/TabControl.java | 165 |
4 files changed, 162 insertions, 79 deletions
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java index db4f634..46b3960 100644 --- a/src/com/android/browser/BrowserActivity.java +++ b/src/com/android/browser/BrowserActivity.java @@ -2136,6 +2136,9 @@ public class BrowserActivity extends Activity .setVisibility(View.VISIBLE); } mContentView.removeView(mTabOverview); + // Clear all the data for tab picker so next time it will be + // recreated. + mTabControl.wipeAllPickerData(); mTabOverview.clear(); mTabOverview = null; mTabListener = null; @@ -4207,10 +4210,6 @@ public class BrowserActivity extends Activity } } - // Clear all the data for tab picker so next time it will be - // recreated. - mTabControl.wipeAllPickerData(); - // NEW_TAB means that the "New Tab" cell was clicked on. if (index == ImageGrid.NEW_TAB) { openTabAndShow(mSettings.getHomePage(), null, false, null); diff --git a/src/com/android/browser/FakeWebView.java b/src/com/android/browser/FakeWebView.java index 633b799..da5ef5f 100644 --- a/src/com/android/browser/FakeWebView.java +++ b/src/com/android/browser/FakeWebView.java @@ -33,17 +33,9 @@ import android.util.Log; * overrides ImageView so it can be used for the new tab image as well. */ public class FakeWebView extends ImageView { - private TabControl.Tab mTab; - private Picture mPicture; + private TabControl.PickerData mPickerData; private boolean mUsesResource; - private class Listener implements WebView.PictureListener { - public void onNewPicture(WebView view, Picture p) { - FakeWebView.this.mPicture = p; - FakeWebView.this.invalidate(); - } - }; - public FakeWebView(Context context) { this(context, null); } @@ -68,17 +60,21 @@ public class FakeWebView extends ImageView { // would be nice to know if the picture is empty so we can avoid // drawing white. canvas.drawColor(Color.WHITE); - if (mTab != null) { - final WebView w = mTab.getTopWindow(); - if (w != null) { - if (mPicture != null) { - canvas.save(); - float scale = getWidth() * w.getScale() / w.getWidth(); - canvas.scale(scale, scale); - canvas.translate(-w.getScrollX(), -w.getScrollY()); - canvas.drawPicture(mPicture); - canvas.restore(); + if (mPickerData != null) { + final Picture p = mPickerData.mPicture; + if (p != null) { + canvas.save(); + float scale = getWidth() * mPickerData.mScale + / mPickerData.mWidth; + // Check for NaN and infinity. + if (Float.isNaN(scale) || Float.isInfinite(scale)) { + scale = 1.0f; } + canvas.scale(scale, scale); + canvas.translate(-mPickerData.mScrollX, + -mPickerData.mScrollY); + canvas.drawPicture(p); + canvas.restore(); } } } @@ -87,25 +83,24 @@ public class FakeWebView extends ImageView { @Override public void setImageResource(int resId) { mUsesResource = true; - mTab = null; + mPickerData = null; super.setImageResource(resId); } /** * Set a WebView for this FakeWebView to represent. - * @param v WebView whose picture and other data will be used in onDraw. + * @param t The tab whose picture and other data will be used in onDraw. */ public void setTab(TabControl.Tab t) { mUsesResource = false; - mTab = t; - if (t != null && t.getWebView() != null) { - Listener l = new Listener(); - if (t.getSubWebView() != null) { - t.getSubWebView().setPictureListener(l); - } else { - t.getWebView().setPictureListener(l); - } - mPicture = mTab.getTopWindow().capturePicture(); + if (mPickerData != null) { + // Clear the old tab's view first + mPickerData.mFakeWebView = null; + } + mPickerData = null; + if (t != null && t.getPickerData() != null) { + mPickerData = t.getPickerData(); + mPickerData.mFakeWebView = this; } } } diff --git a/src/com/android/browser/ImageAdapter.java b/src/com/android/browser/ImageAdapter.java index e957143..42d2224 100644 --- a/src/com/android/browser/ImageAdapter.java +++ b/src/com/android/browser/ImageAdapter.java @@ -27,7 +27,6 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater; -import android.webkit.WebView; import android.widget.ImageView; import android.widget.ListAdapter; import android.widget.TextView; @@ -73,22 +72,10 @@ public class ImageAdapter implements ListAdapter { * Clear the internal WebViews and remove their picture listeners. */ public void clear() { - for (TabControl.Tab t : mItems) { - clearPictureListeners(t); - } mItems.clear(); notifyObservers(); } - private void clearPictureListeners(TabControl.Tab t) { - if (t.getWebView() != null) { - t.getWebView().setPictureListener(null); - if (t.getSubWebView() != null) { - t.getSubWebView().setPictureListener(null); - } - } - } - /** * Add a new window web page to the grid * @@ -113,7 +100,6 @@ public class ImageAdapter implements ListAdapter { */ public void remove(int index) { if (index >= 0 && index < mItems.size()) { - clearPictureListeners(mItems.remove(index)); notifyObservers(); mMaxedOut = false; } diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java index cfe63a6..3730ce1 100644 --- a/src/com/android/browser/TabControl.java +++ b/src/com/android/browser/TabControl.java @@ -17,6 +17,7 @@ package com.android.browser; import android.content.Context; +import android.graphics.Picture; import android.net.http.SslError; import android.os.Bundle; import android.os.Message; @@ -39,6 +40,7 @@ import android.widget.FrameLayout; import android.widget.ImageButton; import java.io.File; +import java.io.FileInputStream; import java.util.ArrayList; import java.util.Vector; @@ -142,10 +144,24 @@ class TabControl { } } + // Extra saved information for displaying the tab in the picker. + public static class PickerData { + String mUrl; + String mTitle; + float mScale; + int mScrollX; + int mScrollY; + int mWidth; + Picture mPicture; + // This can be null. When a new picture comes in, this view should be + // invalidated to show the new picture. + FakeWebView mFakeWebView; + } + /** * Private class for maintaining Tabs with a main WebView and a subwindow. */ - public class Tab { + public class Tab implements WebView.PictureListener { // Main WebView private WebView mMainView; // Subwindow WebView @@ -160,10 +176,9 @@ class TabControl { // information needed to restore the WebView if the user goes back to // the tab. private Bundle mSavedState; - // Extra saved information for displaying the tab in the picker. - private String mUrl; - private String mTitle; - + // Data used when displaying the tab in the picker. + private PickerData mPickerData; + // Parent Tab. This is the Tab that created this Tab, or null // if the Tab was created by the UI private Tab mParentTab; @@ -234,7 +249,7 @@ class TabControl { * @return The WebView's url or null. */ public String getUrl() { - return mUrl; + return mPickerData.mUrl; } /** @@ -245,7 +260,14 @@ class TabControl { * @return The WebView's title (or url) or null. */ public String getTitle() { - return mTitle; + return mPickerData.mTitle; + } + + /** + * Returns the picker data. + */ + public PickerData getPickerData() { + return mPickerData; } private void setParentTab(Tab parent) { @@ -307,6 +329,18 @@ class TabControl { public boolean closeOnExit() { return mCloseOnExit; } + + public void onNewPicture(WebView view, Picture p) { + if (mPickerData == null) { + return; + } + + mPickerData.mPicture = p; + // Tell the FakeWebView to redraw. + if (mPickerData.mFakeWebView != null) { + mPickerData.mFakeWebView.invalidate(); + } + } }; // Directory to store thumbnails for each WebView. @@ -486,8 +520,8 @@ class TabControl { // This tab may have been pushed in to the background and then closed. // If the saved state contains a picture file, delete the file. if (t.mSavedState != null) { - if (t.mSavedState.containsKey("picture")) { - new File(t.mSavedState.getString("picture")).delete(); + if (t.mSavedState.containsKey(CURRPICTURE)) { + new File(t.mSavedState.getString(CURRPICTURE)).delete(); } } @@ -546,6 +580,8 @@ class TabControl { private static final String CURRTAB = "currentTab"; private static final String CURRURL = "currentUrl"; private static final String CURRTITLE = "currentTitle"; + private static final String CURRWIDTH = "currentWidth"; + private static final String CURRPICTURE = "currentPicture"; private static final String CLOSEONEXIT = "closeonexit"; private static final String PARENTTAB = "parentTab"; private static final String APPID = "appid"; @@ -598,8 +634,7 @@ class TabControl { Tab t = new Tab(null, false, null, null); t.mSavedState = inState.getBundle(WEBVIEW + i); if (t.mSavedState != null) { - t.mUrl = t.mSavedState.getString(CURRURL); - t.mTitle = t.mSavedState.getString(CURRTITLE); + populatePickerDataFromSavedState(t); // Need to maintain the app id and original url so we // can possibly reuse this tab. t.mAppId = t.mSavedState.getString(APPID); @@ -795,8 +830,7 @@ class TabControl { // Clear the saved state except for the app id and close-on-exit // values. t.mSavedState = null; - t.mUrl = null; - t.mTitle = null; + t.mPickerData = null; // Save the new url in order to avoid deleting the WebView. t.mOriginalUrl = url; return true; @@ -921,30 +955,89 @@ class TabControl { } /** - * Ensure that Tab t has a title, url, and favicon. + * Ensure that Tab t has data to display in the tab picker. * @param t Tab to populate. */ /* package */ void populatePickerData(Tab t) { - if (t == null || t.mMainView == null) { + if (t == null) { + return; + } + + // mMainView == null indicates that the tab has been freed. + if (t.mMainView == null) { + populatePickerDataFromSavedState(t); return; } + // FIXME: The only place we cared about subwindow was for // bookmarking (i.e. not when saving state). Was this deliberate? final WebBackForwardList list = t.mMainView.copyBackForwardList(); final WebHistoryItem item = list != null ? list.getCurrentItem() : null; populatePickerData(t, item); + + // This method is only called during the tab picker creation. At this + // point we need to listen for new pictures since the WebView is still + // active. + final WebView w = t.getTopWindow(); + w.setPictureListener(t); + // Capture the picture here instead of populatePickerData since it can + // be called when saving the state of a tab. + t.mPickerData.mPicture = w.capturePicture(); } - // Populate the picker data + // Create the PickerData and populate it using the saved state of the tab. + private void populatePickerDataFromSavedState(Tab t) { + if (t.mSavedState == null) { + return; + } + + final PickerData data = new PickerData(); + final Bundle state = t.mSavedState; + data.mUrl = state.getString(CURRURL); + data.mTitle = state.getString(CURRTITLE); + data.mWidth = state.getInt(CURRWIDTH, 0); + // XXX: These keys are from WebView.savePicture so if they change, this + // will break. + data.mScale = state.getFloat("scale", 1.0f); + data.mScrollX = state.getInt("scrollX", 0); + data.mScrollY = state.getInt("scrollY", 0); + + if (state.containsKey(CURRPICTURE)) { + final File f = new File(t.mSavedState.getString(CURRPICTURE)); + try { + final FileInputStream in = new FileInputStream(f); + data.mPicture = Picture.createFromStream(in); + in.close(); + } catch (Exception ex) { + // Ignore any problems with inflating the picture. We just + // won't draw anything. + } + } + + // Set the tab's picker data. + t.mPickerData = data; + } + + // Populate the picker data using the given history item and the current + // top WebView. private void populatePickerData(Tab t, WebHistoryItem item) { + final PickerData data = new PickerData(); if (item != null) { - t.mUrl = item.getUrl(); - t.mTitle = item.getTitle(); - if (t.mTitle == null) { - t.mTitle = t.mUrl; + data.mUrl = item.getUrl(); + data.mTitle = item.getTitle(); + if (data.mTitle == null) { + data.mTitle = data.mUrl; } } + // We want to display the top window in the tab picker but use the url + // and title of the main window. + final WebView w = t.getTopWindow(); + data.mWidth = w.getWidth(); + data.mScale = w.getScale(); + data.mScrollX = w.getScrollX(); + data.mScrollY = w.getScrollY(); + t.mPickerData = data; } /** @@ -955,8 +1048,14 @@ class TabControl { for (int i = 0; i < size; i++) { final Tab t = getTab(i); if (t != null && t.mSavedState == null) { - t.mUrl = null; - t.mTitle = null; + t.mPickerData = null; + } + if (t.mMainView != null) { + // Clear the picture listeners. + t.mMainView.setPictureListener(null); + if (t.mSubView != null) { + t.mSubView.setPictureListener(null); + } } } } @@ -978,7 +1077,7 @@ class TabControl { final File f = new File(mThumbnailDir, w.hashCode() + "_pic.save"); if (w.savePicture(b, f)) { - b.putString("picture", f.getPath()); + b.putString(CURRPICTURE, f.getPath()); } } @@ -986,12 +1085,17 @@ class TabControl { final WebHistoryItem item = list != null ? list.getCurrentItem() : null; populatePickerData(t, item); - if (t.mUrl != null) { - b.putString(CURRURL, t.mUrl); + + // XXX: WebView.savePicture stores the scale and scroll positions + // in the bundle so we don't have to do it here. + final PickerData data = t.mPickerData; + if (data.mUrl != null) { + b.putString(CURRURL, data.mUrl); } - if (t.mTitle != null) { - b.putString(CURRTITLE, t.mTitle); + if (data.mTitle != null) { + b.putString(CURRTITLE, data.mTitle); } + b.putInt(CURRWIDTH, data.mWidth); b.putBoolean(CLOSEONEXIT, t.mCloseOnExit); if (t.mAppId != null) { b.putString(APPID, t.mAppId); @@ -1022,8 +1126,7 @@ class TabControl { // Restore the internal state even if the WebView fails to restore. // This will maintain the app id, original url and close-on-exit values. t.mSavedState = null; - t.mUrl = null; - t.mTitle = null; + t.mPickerData = null; t.mCloseOnExit = b.getBoolean(CLOSEONEXIT); t.mAppId = b.getString(APPID); t.mOriginalUrl = b.getString(ORIGINALURL); @@ -1033,8 +1136,8 @@ class TabControl { if (list == null) { return false; } - if (b.containsKey("picture")) { - final File f = new File(b.getString("picture")); + if (b.containsKey(CURRPICTURE)) { + final File f = new File(b.getString(CURRPICTURE)); w.restorePicture(b, f); f.delete(); } |