From fb4801a84168e3b3134368b976a7a26208b06f3e Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Thu, 17 May 2012 17:49:40 +0100 Subject: [PATCH] bug 755070 - Scrolling causes after paint notifications which causes screenshotting which causes checkerboarding, only take one screenshot at a time r=kats --HG-- extra : rebase_source : 8bfb8c18089282c5c496283bab10f289e314942b --- mobile/android/base/GeckoAppShell.java | 143 ++++++++++++++++--------- 1 file changed, 95 insertions(+), 48 deletions(-) diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 2a9a0d1ebdb..3867e4ab3b6 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -98,11 +98,6 @@ public class GeckoAppShell private static Boolean sNSSLibsLoaded = false; private static Boolean sLibsSetup = false; private static File sGREDir = null; - private static RectF sCheckerboardPageRect; - private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; - private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); - static private int sMaxTextureSize = 0; - private static Map> mEventListeners = new HashMap>(); @@ -128,8 +123,6 @@ public class GeckoAppShell private static Handler sGeckoHandler; - private static boolean sDisableScreenshot = false; - /* The Android-side API: API methods that Android calls */ // Initialization methods @@ -535,42 +528,7 @@ public class GeckoAppShell // Called by AndroidBridge using JNI public static void notifyScreenShot(final ByteBuffer data, final int tabId, final int x, final int y, final int width, final int height, final int token) { - getHandler().post(new Runnable() { - public void run() { - try { - final Tab tab = Tabs.getInstance().getTab(tabId); - if (tab == null) - return; - - if (!Tabs.getInstance().isSelectedTab(tab) && SCREENSHOT_THUMBNAIL != token) - return; - - Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); - b.copyPixelsFromBuffer(data); - switch (token) { - case SCREENSHOT_WHOLE_PAGE: - GeckoApp.mAppContext.getLayerController() - .getView().getRenderer() - .setCheckerboardBitmap(b, sCheckerboardPageRect); - break; - case SCREENSHOT_UPDATE: - GeckoApp.mAppContext.getLayerController().getView().getRenderer(). - updateCheckerboardBitmap( - b, sLastCheckerboardWidthRatio * x, - sLastCheckerboardHeightRatio * y, - sLastCheckerboardWidthRatio * width, - sLastCheckerboardHeightRatio * height, - sCheckerboardPageRect); - break; - case SCREENSHOT_THUMBNAIL: - GeckoApp.mAppContext.processThumbnail(tab, b, null); - break; - } - } finally { - freeDirectBuffer(data); - } - } - }); + ScreenshotHandler.notifyScreenShot(data, tabId, x, y, width, height, token); } private static CountDownLatch sGeckoPendingAcks = null; @@ -2136,6 +2094,24 @@ public class GeckoAppShell if (!GeckoApp.mAppContext.showFilePicker(aMimeType, new AsyncResultHandler(id))) GeckoAppShell.notifyFilePickerResult("", id); } + public static void screenshotWholePage(Tab tab) { + ScreenshotHandler.screenshotWholePage(tab); + } + + // Called by AndroidBridge using JNI + public static void notifyPaintedRect(float top, float left, float bottom, float right) { + ScreenshotHandler.notifyPaintedRect(top, left, bottom, right); + } +} + +class ScreenshotHandler { + static Set sPendingScreenshots = new HashSet(); + private static RectF sCheckerboardPageRect; + private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; + private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); + static private int sMaxTextureSize = 0; + static final String LOGTAG = "GeckoScreenshot"; + private static boolean sDisableScreenshot = false; static class RepaintRunnable implements Runnable { private boolean mIsRepaintRunnablePosted = false; @@ -2169,14 +2145,13 @@ public class GeckoAppShell mDirtyBottom = Math.max(bottom, mDirtyBottom); mDirtyRight = Math.max(right, mDirtyRight); if (!mIsRepaintRunnablePosted) { - getHandler().postDelayed(this, 5000); + GeckoAppShell.getHandler().postDelayed(this, 5000); mIsRepaintRunnablePosted = true; } } } } - // Called by AndroidBridge using JNI public static void notifyPaintedRect(float top, float left, float bottom, float right) { sRepaintRunnable.addRectToRepaint(top, left, bottom, right); } @@ -2204,6 +2179,7 @@ public class GeckoAppShell if (sMaxTextureSize == 0) return; } + ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); Log.i(LOGTAG, "Taking whole-screen screenshot, viewport: " + viewport); // source width and height to screenshot @@ -2229,9 +2205,80 @@ public class GeckoAppShell sLastCheckerboardHeightRatio = dh / sh; sCheckerboardPageRect = viewport.getCssPageRect(); + synchronized(sPendingScreenshots) { + PendingScreenshot ps = new PendingScreenshot(tab.getId(), GeckoAppShell.SCREENSHOT_WHOLE_PAGE); + if (sPendingScreenshots.contains(ps)) + return; + sPendingScreenshots.add(ps); + } GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), - (int)FloatMath.ceil(sx), (int)FloatMath.ceil(sy), - (int)FloatMath.floor(sw), (int)FloatMath.floor(sh), - dx, dy, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE)); + (int)FloatMath.ceil(sx), (int)FloatMath.ceil(sy), + (int)FloatMath.floor(sw), (int)FloatMath.floor(sh), + dx, dy, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE)); + } + + static class PendingScreenshot { + PendingScreenshot(int tabId, int type) { + mTabId = tabId; + mType = type; + } + + public boolean equals(Object obj) { + if (!(obj instanceof PendingScreenshot)) + return false; + PendingScreenshot ps = (PendingScreenshot) obj; + return ps.mTabId == mTabId && ps.mType == mType; + } + + public int hashCode() { + return mType + (mTabId << 2); + } + + private final int mTabId; + private final int mType; + } + + public static void notifyScreenShot(final ByteBuffer data, final int tabId, final int x, final int y, + final int width, final int height, final int token) { + synchronized(sPendingScreenshots) { + sPendingScreenshots.remove(new PendingScreenshot(tabId, token)); + } + + GeckoAppShell.getHandler().post(new Runnable() { + public void run() { + try { + final Tab tab = Tabs.getInstance().getTab(tabId); + if (tab == null) + return; + + if (!Tabs.getInstance().isSelectedTab(tab) && GeckoAppShell.SCREENSHOT_THUMBNAIL != token) + return; + + Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + b.copyPixelsFromBuffer(data); + switch (token) { + case GeckoAppShell.SCREENSHOT_WHOLE_PAGE: + GeckoApp.mAppContext.getLayerController() + .getView().getRenderer() + .setCheckerboardBitmap(b, sCheckerboardPageRect); + break; + case GeckoAppShell.SCREENSHOT_UPDATE: + GeckoApp.mAppContext.getLayerController().getView().getRenderer(). + updateCheckerboardBitmap( + b, sLastCheckerboardWidthRatio * x, + sLastCheckerboardHeightRatio * y, + sLastCheckerboardWidthRatio * width, + sLastCheckerboardHeightRatio * height, + sCheckerboardPageRect); + break; + case GeckoAppShell.SCREENSHOT_THUMBNAIL: + GeckoApp.mAppContext.processThumbnail(tab, b, null); + break; + } + } finally { + GeckoAppShell.freeDirectBuffer(data); + } + } + }); } }