bug 755070 - Scrolling causes after paint notifications which causes screenshotting which causes checkerboarding, only update dirty rects, reuse a single bytebuffer and stop using java bitmaps r=kats

--HG--
extra : rebase_source : 2a7c299c7133da06638d9ef1d27d4b4653072dce
This commit is contained in:
Brad Lassey 2012-06-01 18:54:48 -04:00
parent fb4801a841
commit 356eca4294
13 changed files with 185 additions and 79 deletions

View File

@ -688,7 +688,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, GeckoAppShell.SCREENSHOT_THUMBNAIL));
GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer()));
}
}

View File

@ -15,6 +15,7 @@ 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.*;
@ -2109,9 +2110,11 @@ class ScreenshotHandler {
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 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;
@ -2134,16 +2137,36 @@ class ScreenshotHandler {
mIsRepaintRunnablePosted = false;
}
Tab tab = Tabs.getInstance().getSelectedTab();
GeckoAppShell.screenshotWholePage(tab);
ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics();
if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) {
float width = right - left;
float height = bottom - top;
GeckoEvent event = GeckoEvent.
createScreenshotEvent(tab.getId(),
(int)left, (int)top, (int)width, (int)height,
(int)(sLastCheckerboardWidthRatio * left),
(int)(sLastCheckerboardHeightRatio * top),
(int)(sLastCheckerboardWidthRatio * width),
(int)(sLastCheckerboardHeightRatio * height),
sCheckerboardBufferWidth, sCheckerboardBufferHeight,
GeckoAppShell.SCREENSHOT_UPDATE,
sWholePageScreenshotBuffer);
GeckoAppShell.sendEventToGecko(event);
} else {
GeckoAppShell.screenshotWholePage(tab);
}
}
void addRectToRepaint(float top, float left, float bottom, float right) {
synchronized(this) {
mDirtyTop = Math.min(top, mDirtyTop);
mDirtyLeft = Math.min(left, mDirtyLeft);
mDirtyBottom = Math.max(bottom, mDirtyBottom);
mDirtyRight = Math.max(right, mDirtyRight);
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));
if (!mIsRepaintRunnablePosted) {
GeckoAppShell.getHandler().postDelayed(this, 5000);
mIsRepaintRunnablePosted = true;
@ -2178,6 +2201,7 @@ class ScreenshotHandler {
sMaxTextureSize = maxTextureSize[0];
if (sMaxTextureSize == 0)
return;
sWholePageScreenshotBuffer = GeckoAppShell.allocateDirectBuffer(ScreenshotLayer.getMaxNumPixels() * 2 /* 16 bpp */);
}
ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics();
@ -2200,6 +2224,8 @@ 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;
@ -2214,7 +2240,7 @@ class ScreenshotHandler {
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));
dx, dy, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE, sWholePageScreenshotBuffer));
}
static class PendingScreenshot {
@ -2246,37 +2272,29 @@ class ScreenshotHandler {
GeckoAppShell.getHandler().post(new Runnable() {
public void run() {
try {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
if (!Tabs.getInstance().isSelectedTab(tab) && GeckoAppShell.SCREENSHOT_THUMBNAIL != token)
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) {
switch (token) {
case GeckoAppShell.SCREENSHOT_UPDATE:
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);
.setCheckerboardBitmap(data, width, height, sCheckerboardPageRect);
break;
}
case GeckoAppShell.SCREENSHOT_THUMBNAIL:
{
Bitmap b = tab.getThumbnailBitmap();
b.copyPixelsFromBuffer(data);
GeckoApp.mAppContext.processThumbnail(tab, b, null);
break;
}
} finally {
GeckoAppShell.freeDirectBuffer(data);
}
}
});

View File

@ -23,6 +23,7 @@ import android.text.format.Time;
import android.os.SystemClock;
import java.lang.Math;
import java.lang.System;
import java.nio.ByteBuffer;
import android.util.Log;
@ -116,6 +117,8 @@ public class GeckoEvent {
public short mScreenOrientation;
public ByteBuffer mBuffer;
private GeckoEvent(int evType) {
mType = evType;
}
@ -456,15 +459,17 @@ public class GeckoEvent {
return event;
}
public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int token) {
public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh, int token, ByteBuffer buffer) {
GeckoEvent event = new GeckoEvent(SCREENSHOT);
event.mPoints = new Point[4];
event.mPoints = new Point[5];
event.mPoints[0] = new Point(sx, sy);
event.mPoints[1] = new Point(sw, sh);
event.mPoints[2] = new Point(dx, dy);
event.mPoints[3] = new Point(dw, dh);
event.mPoints[4] = new Point(bw, bh);
event.mMetaState = tabId;
event.mFlags = token;
event.mBuffer = buffer;
return event;
}

View File

@ -21,6 +21,7 @@ import org.json.JSONObject;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.gfx.Layer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@ -64,6 +65,8 @@ public final class Tab {
private ContentObserver mContentObserver;
private int mCheckerboardColor = Color.WHITE;
private int mState;
private ByteBuffer mThumbnailBuffer;
private Bitmap mThumbnailBitmap;
public static final int STATE_DELAYED = 0;
public static final int STATE_LOADING = 1;
@ -138,6 +141,31 @@ public final class Tab {
return mThumbnail;
}
synchronized public ByteBuffer getThumbnailBuffer() {
int capacity = getThumbnailWidth() * getThumbnailHeight() * 2 /* 16 bpp */;
if (mThumbnailBuffer != null && mThumbnailBuffer.capacity() == capacity)
return mThumbnailBuffer;
if (mThumbnailBuffer != null)
GeckoAppShell.freeDirectBuffer(mThumbnailBuffer); // not calling freeBuffer() because it would deadlock
return mThumbnailBuffer = GeckoAppShell.allocateDirectBuffer(capacity);
}
public Bitmap getThumbnailBitmap() {
if (mThumbnailBitmap != null)
return mThumbnailBitmap;
return mThumbnailBitmap = Bitmap.createBitmap(getThumbnailWidth(), getThumbnailHeight(), Bitmap.Config.RGB_565);
}
public void finalize() {
freeBuffer();
}
synchronized void freeBuffer() {
if (mThumbnailBuffer != null)
GeckoAppShell.freeDirectBuffer(mThumbnailBuffer);
mThumbnailBuffer = null;
}
float getDensity() {
if (sDensity == 0.0f) {
sDensity = GeckoApp.mAppContext.getDisplayMetrics().density;
@ -159,13 +187,10 @@ public final class Tab {
public void run() {
if (b != null) {
try {
Bitmap bitmap = Bitmap.createScaledBitmap(b, getThumbnailWidth(), getThumbnailHeight(), false);
if (mState == Tab.STATE_SUCCESS)
saveThumbnailToDB(new BitmapDrawable(bitmap));
saveThumbnailToDB(new BitmapDrawable(b));
mThumbnail = new BitmapDrawable(bitmap);
b.recycle();
mThumbnail = new BitmapDrawable(b);
} catch (OutOfMemoryError oom) {
Log.e(LOGTAG, "Unable to create/scale bitmap", oom);
mThumbnail = null;

View File

@ -76,8 +76,10 @@ public class Tabs implements GeckoEventListener {
public void removeTab(int id) {
if (tabs.containsKey(id)) {
order.remove(getTab(id));
Tab tab = getTab(id);
order.remove(tab);
tabs.remove(id);
tab.freeBuffer();
Log.i(LOGTAG, "Removed a tab with id: " + id);
}
}

View File

@ -71,5 +71,11 @@ public class IntSize {
public IntSize nextPowerOfTwo() {
return new IntSize(nextPowerOfTwo(width), nextPowerOfTwo(height));
}
public static boolean isPowerOfTwo(int value) {
if (value == 0)
return false;
return (value & (value - 1)) == 0;
}
}

View File

@ -134,8 +134,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
" gl_FragColor = texture2D(sTexture, vTexCoord);\n" +
"}\n";
public void setCheckerboardBitmap(Bitmap bitmap, RectF pageRect) {
mCheckerboardLayer.setBitmap(bitmap);
public void setCheckerboardBitmap(ByteBuffer data, int width, int height, RectF pageRect) {
mCheckerboardLayer.setBitmap(data, width, height);
mCheckerboardLayer.beginTransaction();
try {
mCheckerboardLayer.setPosition(RectUtils.round(pageRect));

View File

@ -35,6 +35,7 @@ public class ScreenshotLayer extends SingleTileLayer {
private IntSize mImageSize;
// Whether we have an up-to-date image to draw
private boolean mHasImage;
private static String LOGTAG = "GeckoScreenshot";
public static int getMaxNumPixels() {
return SCREENSHOT_SIZE_LIMIT;
@ -44,6 +45,19 @@ public class ScreenshotLayer extends SingleTileLayer {
mHasImage = false;
}
void setBitmap(ByteBuffer data, int width, int height) {
mImageSize = new IntSize(width, height);
if (IntSize.isPowerOfTwo(width) && IntSize.isPowerOfTwo(height)) {
mBufferSize = mImageSize;
mHasImage = true;
mImage.setBitmap(data, width, height, CairoImage.FORMAT_RGB16_565);
} else {
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
b.copyPixelsFromBuffer(data);
setBitmap(b);
}
}
void setBitmap(Bitmap bitmap) {
mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
int width = IntSize.nextPowerOfTwo(bitmap.getWidth());
@ -116,7 +130,17 @@ public class ScreenshotLayer extends SingleTileLayer {
}
}
void setBitmap(Bitmap bitmap, int width, int height, int format) {
void copyBuffer(ByteBuffer src, ByteBuffer dst, int size) {
dst.asIntBuffer().put(src.asIntBuffer());
}
synchronized void setBitmap(ByteBuffer data, int width, int height, int format) {
mSize = new IntSize(width, height);
mFormat = format;
copyBuffer(data, mBuffer, width * height * 2);
}
synchronized void setBitmap(Bitmap bitmap, int width, int height, int format) {
Bitmap tmp;
mSize = new IntSize(width, height);
mFormat = format;
@ -138,10 +162,10 @@ public class ScreenshotLayer extends SingleTileLayer {
}
@Override
public ByteBuffer getBuffer() { return mBuffer; }
synchronized public ByteBuffer getBuffer() { return mBuffer; }
@Override
public IntSize getSize() { return mSize; }
synchronized public IntSize getSize() { return mSize; }
@Override
public int getFormat() { return mFormat; }
synchronized public int getFormat() { return mFormat; }
}
}

View File

@ -2348,9 +2348,13 @@ jobject JNICALL
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token)
nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstX, PRInt32 dstY, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer)
{
nsresult rv;
float scale = 1.0;
if (!buffer)
return NS_OK;
// take a screenshot, as wide as possible, proportional to the destination size
if (!srcW && !srcH) {
@ -2415,21 +2419,17 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt
nsPresContext::CSSPixelsToAppUnits(srcW / scale),
nsPresContext::CSSPixelsToAppUnits(srcH / scale));
PRUint32 stride = dstW * 2;
PRUint32 bufferSize = dstH * stride;
jobject buffer = Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(env, NULL, bufferSize);
if (!buffer)
return NS_OK;
PRUint32 stride = bufW * 2 /* 16 bpp */;
void* data = env->GetDirectBufferAddress(buffer);
memset(data, 0, bufferSize);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(bufW, bufH), stride, gfxASurface::ImageFormatRGB16_565);
nsRefPtr<gfxContext> context = new gfxContext(surf);
gfxPoint pt(dstX, dstY);
context->Translate(pt);
context->Scale(scale * dstW / srcW, scale * dstH / srcH);
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS(rv, rv);
env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token);
env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, bufW, bufH, token);
return NS_OK;
}

View File

@ -155,7 +155,7 @@ public:
SCREENSHOT_UPDATE = 2
};
nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token);
nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstY, PRInt32 dstX, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer);
static void NotifyPaintedRect(float top, float left, float bottom, float right);

View File

@ -42,6 +42,7 @@ jfieldID AndroidGeckoEvent::jLocationField = 0;
jfieldID AndroidGeckoEvent::jBandwidthField = 0;
jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0;
jfieldID AndroidGeckoEvent::jScreenOrientationField = 0;
jfieldID AndroidGeckoEvent::jByteBufferField = 0;
jclass AndroidPoint::jPointClass = 0;
jfieldID AndroidPoint::jXField = 0;
@ -103,6 +104,12 @@ jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0;
#define getMethod(fname, ftype) \
((jmethodID) jEnv->GetMethodID(jClass, fname, ftype))
RefCountedJavaObject::~RefCountedJavaObject() {
if (mObject)
GetJNIForThread()->DeleteGlobalRef(mObject);
mObject = NULL;
}
void
mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
{
@ -154,6 +161,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
jBandwidthField = getField("mBandwidth", "D");
jCanBeMeteredField = getField("mCanBeMetered", "Z");
jScreenOrientationField = getField("mScreenOrientation", "S");
jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;");
}
void
@ -498,7 +506,8 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
case SCREENSHOT: {
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
mFlags = jenv->GetIntField(jobj, jFlagsField);
ReadPointArray(mPoints, jenv, jPoints, 4);
ReadPointArray(mPoints, jenv, jPoints, 5);
mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField));
break;
}

View File

@ -41,6 +41,27 @@ void InitAndroidJavaWrappers(JNIEnv *jEnv);
* handle it.
*/
class RefCountedJavaObject {
public:
RefCountedJavaObject(JNIEnv* env, jobject obj) : mObject(env->NewGlobalRef(obj)) {}
~RefCountedJavaObject();
PRInt32 AddRef() { return ++mRefCnt; }
PRInt32 Release() {
PRInt32 refcnt = --mRefCnt;
if (refcnt == 0)
delete this;
return refcnt;
}
jobject GetObject() { return mObject; }
private:
PRInt32 mRefCnt;
jobject mObject;
};
class WrappedJavaObject {
public:
WrappedJavaObject() :
@ -576,6 +597,7 @@ public:
double Bandwidth() { return mBandwidth; }
bool CanBeMetered() { return mCanBeMetered; }
short ScreenOrientation() { return mScreenOrientation; }
RefCountedJavaObject* ByteBuffer() { return mByteBuffer; }
protected:
int mAction;
@ -600,6 +622,7 @@ protected:
double mBandwidth;
bool mCanBeMetered;
short mScreenOrientation;
nsRefPtr<RefCountedJavaObject> mByteBuffer;
void ReadIntArray(nsTArray<int> &aVals,
JNIEnv *jenv,
@ -653,6 +676,7 @@ protected:
static jfieldID jCanBeMeteredField;
static jfieldID jScreenOrientationField;
static jfieldID jByteBufferField;
public:
enum {

View File

@ -67,8 +67,8 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver)
class ScreenshotRunnable : public nsRunnable {
public:
ScreenshotRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, nsTArray<nsIntPoint>& aPoints, int aToken):
mBrowserApp(aBrowserApp), mTabId(aTabId), mPoints(aPoints), mToken(aToken) {}
ScreenshotRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, nsTArray<nsIntPoint>& aPoints, int aToken, RefCountedJavaObject* aBuffer):
mBrowserApp(aBrowserApp), mTabId(aTabId), mPoints(aPoints), mToken(aToken), mBuffer(aBuffer) {}
virtual nsresult Run() {
nsCOMPtr<nsIDOMWindow> domWindow;
@ -81,16 +81,16 @@ public:
if (!domWindow)
return NS_OK;
float scale = 1.0;
NS_ASSERTION(mPoints.Length() == 4, "Screenshot event does not have enough coordinates");
NS_ASSERTION(mPoints.Length() == 5, "Screenshot event does not have enough coordinates");
AndroidBridge::Bridge()->TakeScreenshot(domWindow, mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, mPoints[3].x, mPoints[3].y, mTabId, scale, mToken);
AndroidBridge::Bridge()->TakeScreenshot(domWindow, mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, mPoints[2].x, mPoints[2].y, mPoints[3].x, mPoints[3].y, mPoints[4].x, mPoints[4].y, mTabId, mToken, mBuffer->GetObject());
return NS_OK;
}
private:
nsCOMPtr<nsIAndroidBrowserApp> mBrowserApp;
nsTArray<nsIntPoint> mPoints;
int mTabId, mToken;
nsRefPtr<RefCountedJavaObject> mBuffer;
};
class AfterPaintListener : public nsIDOMEventListener {
@ -119,23 +119,15 @@ class AfterPaintListener : public nsIDOMEventListener {
if (!paintEvent)
return NS_OK;
nsCOMPtr<nsIDOMClientRectList> rects;
paintEvent->GetClientRects(getter_AddRefs(rects));
if (!rects)
return NS_OK;
PRUint32 length;
rects->GetLength(&length);
for (PRUint32 i = 0; i < length; ++i) {
float top, left, bottom, right;
nsCOMPtr<nsIDOMClientRect> rect = rects->GetItemAt(i);
if (!rect)
continue;
rect->GetTop(&top);
rect->GetLeft(&left);
rect->GetRight(&right);
rect->GetBottom(&bottom);
AndroidBridge::NotifyPaintedRect(top, left, bottom, right);
}
nsCOMPtr<nsIDOMClientRect> rect;
paintEvent->GetBoundingClientRect(getter_AddRefs(rect));
float top, left, bottom, right;
rect->GetTop(&top);
rect->GetLeft(&left);
rect->GetRight(&right);
rect->GetBottom(&bottom);
__android_log_print(ANDROID_LOG_INFO, "GeckoScreenshot", "rect: %f, %f, %f, %f", top, left, right, bottom);
AndroidBridge::NotifyPaintedRect(top, left, bottom, right);
return NS_OK;
}
@ -457,8 +449,9 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
PRInt32 token = curEvent->Flags();
PRInt32 tabId = curEvent->MetaState();
nsTArray<nsIntPoint> points = curEvent->Points();
RefCountedJavaObject* buffer = curEvent->ByteBuffer();
nsCOMPtr<ScreenshotRunnable> sr =
new ScreenshotRunnable(mBrowserApp, tabId, points, token);
new ScreenshotRunnable(mBrowserApp, tabId, points, token, buffer);
MessageLoop::current()->PostIdleTask(
FROM_HERE, NewRunnableMethod(sr.get(), &ScreenshotRunnable::Run));
break;