Loading embedding/android/GeckoEvent.java +0 −3 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ import android.hardware.*; import android.location.*; import android.util.FloatMath; import android.util.DisplayMetrics; import java.nio.ByteBuffer; import android.util.Log; Loading Loading @@ -101,8 +100,6 @@ public class GeckoEvent { public int mNativeWindow; public ByteBuffer mBuffer; public GeckoEvent() { mType = NATIVE_POKE; } Loading ipc/chromium/src/base/message_loop.cc +0 −8 Original line number Diff line number Diff line Loading @@ -256,14 +256,6 @@ void MessageLoop::PostNonNestableDelayedTask( PostTask_Helper(from_here, task, delay_ms, false); } void MessageLoop::PostIdleTask( const tracked_objects::Location& from_here, Task* task) { DCHECK(current() == this); task->SetBirthPlace(from_here); PendingTask pending_task(task, false); deferred_non_nestable_work_queue_.push(pending_task); } // Possibly called on a background thread! void MessageLoop::PostTask_Helper( const tracked_objects::Location& from_here, Task* task, int delay_ms, Loading ipc/chromium/src/base/message_loop.h +0 −4 Original line number Diff line number Diff line Loading @@ -121,10 +121,6 @@ public: void PostNonNestableDelayedTask( const tracked_objects::Location& from_here, Task* task, int delay_ms); // PostIdleTask is not thread safe and should be called on this thread void PostIdleTask( const tracked_objects::Location& from_here, Task* task); // A variant on PostTask that deletes the given object. This is useful // if the object needs to live until the next run of the MessageLoop (for // example, deleting a RenderProcessHost from within an IPC callback is not Loading mobile/android/base/GeckoApp.java +1 −1 Original line number Diff line number Diff line Loading @@ -697,7 +697,7 @@ abstract public class GeckoApp int dw = tab.getThumbnailWidth(); int dh = tab.getThumbnailHeight(); GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer())); GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL)); } } Loading mobile/android/base/GeckoAppShell.java +56 −137 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ import org.mozilla.gecko.gfx.ScreenshotLayer; import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; import org.mozilla.gecko.gfx.ViewportMetrics; import org.mozilla.gecko.gfx.RectUtils; import java.io.*; import java.lang.reflect.*; Loading Loading @@ -84,7 +83,8 @@ public class GeckoAppShell public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark"; static public final int SCREENSHOT_THUMBNAIL = 0; static public final int SCREENSHOT_CHECKERBOARD = 1; static public final int SCREENSHOT_WHOLE_PAGE = 1; static public final int SCREENSHOT_UPDATE = 2; static public final int RESTORE_NONE = 0; static public final int RESTORE_OOM = 1; Loading @@ -98,6 +98,11 @@ 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<String, CopyOnWriteArrayList<GeckoEventListener>> mEventListeners = new HashMap<String, CopyOnWriteArrayList<GeckoEventListener>>(); Loading @@ -123,6 +128,8 @@ public class GeckoAppShell private static Handler sGeckoHandler; private static boolean sDisableScreenshot = false; /* The Android-side API: API methods that Android calls */ // Initialization methods Loading Loading @@ -528,7 +535,42 @@ 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) { ScreenshotHandler.notifyScreenShot(data, tabId, x, y, width, height, 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); } } }); } private static CountDownLatch sGeckoPendingAcks = null; Loading Loading @@ -2094,26 +2136,6 @@ 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 { private static Queue<PendingScreenshot> sPendingScreenshots = new LinkedList<PendingScreenshot>(); private static RectF sCheckerboardPageRect; private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); private static int sMaxTextureSize = 0; private static final String LOGTAG = "GeckoScreenshot"; private static boolean sDisableScreenshot = false; private static ByteBuffer sWholePageScreenshotBuffer; private static int sCheckerboardBufferWidth, sCheckerboardBufferHeight; static class RepaintRunnable implements Runnable { private boolean mIsRepaintRunnablePosted = false; Loading @@ -2136,40 +2158,25 @@ class ScreenshotHandler { mIsRepaintRunnablePosted = false; } Tab tab = Tabs.getInstance().getSelectedTab(); ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) { float width = right - left; float height = bottom - top; scheduleCheckerboardScreenshotEvent(tab.getId(), (int)left, (int)top, (int)width, (int)height, (int)(sLastCheckerboardWidthRatio * left), (int)(sLastCheckerboardHeightRatio * top), (int)(sLastCheckerboardWidthRatio * width), (int)(sLastCheckerboardHeightRatio * height), sCheckerboardBufferWidth, sCheckerboardBufferHeight); } else { GeckoAppShell.screenshotWholePage(tab); } } void addRectToRepaint(float top, float left, float bottom, float right) { synchronized(this) { ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); mDirtyTop = Math.max(sCheckerboardPageRect.top, Math.min(top, mDirtyTop)); mDirtyLeft = Math.max(sCheckerboardPageRect.left, Math.min(left, mDirtyLeft)); mDirtyBottom = Math.min(sCheckerboardPageRect.bottom, Math.max(bottom, mDirtyBottom)); mDirtyRight = Math.min(sCheckerboardPageRect.right, Math.max(right, mDirtyRight)); mDirtyTop = Math.min(top, mDirtyTop); mDirtyLeft = Math.min(left, mDirtyLeft); mDirtyBottom = Math.max(bottom, mDirtyBottom); mDirtyRight = Math.max(right, mDirtyRight); if (!mIsRepaintRunnablePosted) { GeckoAppShell.getHandler().postDelayed(this, 5000); 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); } Loading @@ -2196,9 +2203,7 @@ class ScreenshotHandler { sMaxTextureSize = maxTextureSize[0]; if (sMaxTextureSize == 0) return; sWholePageScreenshotBuffer = GeckoAppShell.allocateDirectBuffer(ScreenshotLayer.getMaxNumPixels() * 2 /* 16 bpp */); } ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); Log.i(LOGTAG, "Taking whole-screen screenshot, viewport: " + viewport); // source width and height to screenshot Loading @@ -2206,8 +2211,6 @@ class ScreenshotHandler { float sy = viewport.cssPageRectTop; float sw = viewport.cssPageRectRight - viewport.cssPageRectLeft; float sh = viewport.cssPageRectBottom - viewport.cssPageRectTop; if (sw == 0 || sh == 0) return; int maxPixels = Math.min(ScreenshotLayer.getMaxNumPixels(), sMaxTextureSize * sMaxTextureSize); // 2Mb of 16bit image data // may be bumped by up to 4x for power of 2 alignment Loading @@ -2221,98 +2224,14 @@ class ScreenshotHandler { int dy = 0; int dw = clamp(minTextureSize, idealDstWidth, sMaxTextureSize); int dh = maxPixels / dw; sCheckerboardBufferWidth = dw; sCheckerboardBufferHeight = dh; sLastCheckerboardWidthRatio = dw / sw; sLastCheckerboardHeightRatio = dh / sh; sCheckerboardPageRect = viewport.getCssPageRect(); scheduleCheckerboardScreenshotEvent(tab.getId(), (int)sx, (int)sy, (int)sw, (int)sh, dx, dy, dw, dh, dw, dh); } static void scheduleCheckerboardScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh) { float totalSize = sw * sh; int numSlices = (int) Math.ceil(totalSize / 100000); if (numSlices == 0) return; int srcSliceSize = (int) Math.ceil(sh / numSlices); int dstSliceSize = (int) Math.ceil(dh / numSlices); for (int i = 0; i < numSlices; i++) { GeckoEvent event = GeckoEvent.createScreenshotEvent(tabId, sx, sy + srcSliceSize * i, sw, srcSliceSize, dx, dy + dstSliceSize * i, dw, dstSliceSize, bw, bh, GeckoAppShell.SCREENSHOT_CHECKERBOARD, sWholePageScreenshotBuffer); synchronized(sPendingScreenshots) { sPendingScreenshots.add(new PendingScreenshot(tabId, event)); if (sPendingScreenshots.size() == 1) sendNextEventToGecko(); } } } static void sendNextEventToGecko() { synchronized(sPendingScreenshots) { if (sPendingScreenshots.isEmpty()) return; GeckoAppShell.sendEventToGecko(sPendingScreenshots.element().getEvent()); } } static class PendingScreenshot { private final GeckoEvent mEvent; private final int mTabId; PendingScreenshot(int tabId, GeckoEvent event) { mTabId = tabId; mEvent = event; } GeckoEvent getEvent() { return mEvent; } } 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) { GeckoAppShell.getHandler().post(new Runnable() { public void run() { final Tab tab = Tabs.getInstance().getTab(tabId); if (tab == null) { if (token == GeckoAppShell.SCREENSHOT_CHECKERBOARD) { synchronized(sPendingScreenshots) { sPendingScreenshots.remove(); sendNextEventToGecko(); } } return; } switch (token) { case GeckoAppShell.SCREENSHOT_CHECKERBOARD: { GeckoApp.mAppContext.getLayerController() .getView().getRenderer() .setCheckerboardBitmap(data, width, height, sCheckerboardPageRect); synchronized(sPendingScreenshots) { sPendingScreenshots.remove(); sendNextEventToGecko(); } break; } case GeckoAppShell.SCREENSHOT_THUMBNAIL: { if (Tabs.getInstance().isSelectedTab(tab)) { Bitmap b = tab.getThumbnailBitmap(); b.copyPixelsFromBuffer(data); GeckoApp.mAppContext.processThumbnail(tab, b, null); } break; } } } }); 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)); } } Loading
embedding/android/GeckoEvent.java +0 −3 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ import android.hardware.*; import android.location.*; import android.util.FloatMath; import android.util.DisplayMetrics; import java.nio.ByteBuffer; import android.util.Log; Loading Loading @@ -101,8 +100,6 @@ public class GeckoEvent { public int mNativeWindow; public ByteBuffer mBuffer; public GeckoEvent() { mType = NATIVE_POKE; } Loading
ipc/chromium/src/base/message_loop.cc +0 −8 Original line number Diff line number Diff line Loading @@ -256,14 +256,6 @@ void MessageLoop::PostNonNestableDelayedTask( PostTask_Helper(from_here, task, delay_ms, false); } void MessageLoop::PostIdleTask( const tracked_objects::Location& from_here, Task* task) { DCHECK(current() == this); task->SetBirthPlace(from_here); PendingTask pending_task(task, false); deferred_non_nestable_work_queue_.push(pending_task); } // Possibly called on a background thread! void MessageLoop::PostTask_Helper( const tracked_objects::Location& from_here, Task* task, int delay_ms, Loading
ipc/chromium/src/base/message_loop.h +0 −4 Original line number Diff line number Diff line Loading @@ -121,10 +121,6 @@ public: void PostNonNestableDelayedTask( const tracked_objects::Location& from_here, Task* task, int delay_ms); // PostIdleTask is not thread safe and should be called on this thread void PostIdleTask( const tracked_objects::Location& from_here, Task* task); // A variant on PostTask that deletes the given object. This is useful // if the object needs to live until the next run of the MessageLoop (for // example, deleting a RenderProcessHost from within an IPC callback is not Loading
mobile/android/base/GeckoApp.java +1 −1 Original line number Diff line number Diff line Loading @@ -697,7 +697,7 @@ abstract public class GeckoApp int dw = tab.getThumbnailWidth(); int dh = tab.getThumbnailHeight(); GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer())); GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL)); } } Loading
mobile/android/base/GeckoAppShell.java +56 −137 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ import org.mozilla.gecko.gfx.ScreenshotLayer; import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; import org.mozilla.gecko.gfx.ViewportMetrics; import org.mozilla.gecko.gfx.RectUtils; import java.io.*; import java.lang.reflect.*; Loading Loading @@ -84,7 +83,8 @@ public class GeckoAppShell public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark"; static public final int SCREENSHOT_THUMBNAIL = 0; static public final int SCREENSHOT_CHECKERBOARD = 1; static public final int SCREENSHOT_WHOLE_PAGE = 1; static public final int SCREENSHOT_UPDATE = 2; static public final int RESTORE_NONE = 0; static public final int RESTORE_OOM = 1; Loading @@ -98,6 +98,11 @@ 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<String, CopyOnWriteArrayList<GeckoEventListener>> mEventListeners = new HashMap<String, CopyOnWriteArrayList<GeckoEventListener>>(); Loading @@ -123,6 +128,8 @@ public class GeckoAppShell private static Handler sGeckoHandler; private static boolean sDisableScreenshot = false; /* The Android-side API: API methods that Android calls */ // Initialization methods Loading Loading @@ -528,7 +535,42 @@ 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) { ScreenshotHandler.notifyScreenShot(data, tabId, x, y, width, height, 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); } } }); } private static CountDownLatch sGeckoPendingAcks = null; Loading Loading @@ -2094,26 +2136,6 @@ 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 { private static Queue<PendingScreenshot> sPendingScreenshots = new LinkedList<PendingScreenshot>(); private static RectF sCheckerboardPageRect; private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio; private static RepaintRunnable sRepaintRunnable = new RepaintRunnable(); private static int sMaxTextureSize = 0; private static final String LOGTAG = "GeckoScreenshot"; private static boolean sDisableScreenshot = false; private static ByteBuffer sWholePageScreenshotBuffer; private static int sCheckerboardBufferWidth, sCheckerboardBufferHeight; static class RepaintRunnable implements Runnable { private boolean mIsRepaintRunnablePosted = false; Loading @@ -2136,40 +2158,25 @@ class ScreenshotHandler { mIsRepaintRunnablePosted = false; } Tab tab = Tabs.getInstance().getSelectedTab(); ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) { float width = right - left; float height = bottom - top; scheduleCheckerboardScreenshotEvent(tab.getId(), (int)left, (int)top, (int)width, (int)height, (int)(sLastCheckerboardWidthRatio * left), (int)(sLastCheckerboardHeightRatio * top), (int)(sLastCheckerboardWidthRatio * width), (int)(sLastCheckerboardHeightRatio * height), sCheckerboardBufferWidth, sCheckerboardBufferHeight); } else { GeckoAppShell.screenshotWholePage(tab); } } void addRectToRepaint(float top, float left, float bottom, float right) { synchronized(this) { ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); mDirtyTop = Math.max(sCheckerboardPageRect.top, Math.min(top, mDirtyTop)); mDirtyLeft = Math.max(sCheckerboardPageRect.left, Math.min(left, mDirtyLeft)); mDirtyBottom = Math.min(sCheckerboardPageRect.bottom, Math.max(bottom, mDirtyBottom)); mDirtyRight = Math.min(sCheckerboardPageRect.right, Math.max(right, mDirtyRight)); mDirtyTop = Math.min(top, mDirtyTop); mDirtyLeft = Math.min(left, mDirtyLeft); mDirtyBottom = Math.max(bottom, mDirtyBottom); mDirtyRight = Math.max(right, mDirtyRight); if (!mIsRepaintRunnablePosted) { GeckoAppShell.getHandler().postDelayed(this, 5000); 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); } Loading @@ -2196,9 +2203,7 @@ class ScreenshotHandler { sMaxTextureSize = maxTextureSize[0]; if (sMaxTextureSize == 0) return; sWholePageScreenshotBuffer = GeckoAppShell.allocateDirectBuffer(ScreenshotLayer.getMaxNumPixels() * 2 /* 16 bpp */); } ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics(); Log.i(LOGTAG, "Taking whole-screen screenshot, viewport: " + viewport); // source width and height to screenshot Loading @@ -2206,8 +2211,6 @@ class ScreenshotHandler { float sy = viewport.cssPageRectTop; float sw = viewport.cssPageRectRight - viewport.cssPageRectLeft; float sh = viewport.cssPageRectBottom - viewport.cssPageRectTop; if (sw == 0 || sh == 0) return; int maxPixels = Math.min(ScreenshotLayer.getMaxNumPixels(), sMaxTextureSize * sMaxTextureSize); // 2Mb of 16bit image data // may be bumped by up to 4x for power of 2 alignment Loading @@ -2221,98 +2224,14 @@ class ScreenshotHandler { int dy = 0; int dw = clamp(minTextureSize, idealDstWidth, sMaxTextureSize); int dh = maxPixels / dw; sCheckerboardBufferWidth = dw; sCheckerboardBufferHeight = dh; sLastCheckerboardWidthRatio = dw / sw; sLastCheckerboardHeightRatio = dh / sh; sCheckerboardPageRect = viewport.getCssPageRect(); scheduleCheckerboardScreenshotEvent(tab.getId(), (int)sx, (int)sy, (int)sw, (int)sh, dx, dy, dw, dh, dw, dh); } static void scheduleCheckerboardScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh) { float totalSize = sw * sh; int numSlices = (int) Math.ceil(totalSize / 100000); if (numSlices == 0) return; int srcSliceSize = (int) Math.ceil(sh / numSlices); int dstSliceSize = (int) Math.ceil(dh / numSlices); for (int i = 0; i < numSlices; i++) { GeckoEvent event = GeckoEvent.createScreenshotEvent(tabId, sx, sy + srcSliceSize * i, sw, srcSliceSize, dx, dy + dstSliceSize * i, dw, dstSliceSize, bw, bh, GeckoAppShell.SCREENSHOT_CHECKERBOARD, sWholePageScreenshotBuffer); synchronized(sPendingScreenshots) { sPendingScreenshots.add(new PendingScreenshot(tabId, event)); if (sPendingScreenshots.size() == 1) sendNextEventToGecko(); } } } static void sendNextEventToGecko() { synchronized(sPendingScreenshots) { if (sPendingScreenshots.isEmpty()) return; GeckoAppShell.sendEventToGecko(sPendingScreenshots.element().getEvent()); } } static class PendingScreenshot { private final GeckoEvent mEvent; private final int mTabId; PendingScreenshot(int tabId, GeckoEvent event) { mTabId = tabId; mEvent = event; } GeckoEvent getEvent() { return mEvent; } } 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) { GeckoAppShell.getHandler().post(new Runnable() { public void run() { final Tab tab = Tabs.getInstance().getTab(tabId); if (tab == null) { if (token == GeckoAppShell.SCREENSHOT_CHECKERBOARD) { synchronized(sPendingScreenshots) { sPendingScreenshots.remove(); sendNextEventToGecko(); } } return; } switch (token) { case GeckoAppShell.SCREENSHOT_CHECKERBOARD: { GeckoApp.mAppContext.getLayerController() .getView().getRenderer() .setCheckerboardBitmap(data, width, height, sCheckerboardPageRect); synchronized(sPendingScreenshots) { sPendingScreenshots.remove(); sendNextEventToGecko(); } break; } case GeckoAppShell.SCREENSHOT_THUMBNAIL: { if (Tabs.getInstance().isSelectedTab(tab)) { Bitmap b = tab.getThumbnailBitmap(); b.copyPixelsFromBuffer(data); GeckoApp.mAppContext.processThumbnail(tab, b, null); } break; } } } }); 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)); } }