Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit 6762cf7

Browse files
MortimerGorobluemarvin
authored andcommitted
Capture tab snapshots when stacking sessions and opening the tabs dialog. (#2093)
* Capture tab snapshots when stacking sessions and opening the tabs dialog. * Address review comments
1 parent 48be65a commit 6762cf7

File tree

5 files changed

+118
-5
lines changed

5 files changed

+118
-5
lines changed

app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.content.Intent;
1111
import android.content.IntentFilter;
1212
import android.content.res.Configuration;
13+
import android.graphics.Bitmap;
1314
import android.graphics.Canvas;
1415
import android.graphics.Color;
1516
import android.graphics.Paint;
@@ -66,6 +67,7 @@
6667
import org.mozilla.vrbrowser.ui.widgets.Windows;
6768
import org.mozilla.vrbrowser.ui.widgets.dialogs.CrashDialogWidget;
6869
import org.mozilla.vrbrowser.ui.widgets.prompts.ConfirmPromptWidget;
70+
import org.mozilla.vrbrowser.utils.BitmapCache;
6971
import org.mozilla.vrbrowser.utils.ConnectivityReceiver;
7072
import org.mozilla.vrbrowser.utils.DeviceType;
7173
import org.mozilla.vrbrowser.utils.LocaleUtils;
@@ -210,6 +212,8 @@ protected void onCreate(Bundle savedInstanceState) {
210212
}
211213
mUiThread = Thread.currentThread();
212214

215+
BitmapCache.getInstance(this).onCreate();
216+
213217
Bundle extras = getIntent() != null ? getIntent().getExtras() : null;
214218
SessionStore.get().setContext(this, extras);
215219
SessionStore.get().initializeServices();
@@ -246,7 +250,10 @@ protected void onCreate(Bundle savedInstanceState) {
246250

247251
mSettings = SettingsStore.getInstance(this);
248252

249-
queueRunnable(() -> createOffscreenDisplay());
253+
queueRunnable(() -> {
254+
createOffscreenDisplay();
255+
createCaptureSurface();
256+
});
250257
final String tempPath = getCacheDir().getAbsolutePath();
251258
queueRunnable(() -> setTemporaryFilePath(tempPath));
252259
updateFoveatedLevel();
@@ -422,8 +429,11 @@ protected void onDestroy() {
422429
// Remove all widget listeners
423430
mWindows.onDestroy();
424431

432+
BitmapCache.getInstance(this).onDestroy();
433+
425434
SessionStore.get().onDestroy();
426435

436+
427437
super.onDestroy();
428438
}
429439

@@ -1031,7 +1041,7 @@ public void dismiss() {
10311041
});
10321042
}
10331043

1034-
void createOffscreenDisplay() {
1044+
private SurfaceTexture createSurfaceTexture() {
10351045
int[] ids = new int[1];
10361046
GLES20.glGenTextures(1, ids, 0);
10371047
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, ids[0]);
@@ -1042,16 +1052,29 @@ void createOffscreenDisplay() {
10421052
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
10431053
int error = GLES20.glGetError();
10441054
if (error != GLES20.GL_NO_ERROR) {
1045-
Log.e(LOGTAG, "OpenGL Error creating OffscreenDisplay: " + error);
1055+
Log.e(LOGTAG, "OpenGL Error creating SurfaceTexture: " + error);
10461056
}
10471057

1048-
final SurfaceTexture texture = new SurfaceTexture(ids[0]);
1058+
return new SurfaceTexture(ids[0]);
1059+
}
1060+
1061+
void createOffscreenDisplay() {
1062+
final SurfaceTexture texture = createSurfaceTexture();
10491063
runOnUiThread(() -> {
10501064
mOffscreenDisplay = new OffscreenDisplay(VRBrowserActivity.this, texture, 16, 16);
10511065
mOffscreenDisplay.setContentView(mWidgetContainer);
10521066
});
10531067
}
10541068

1069+
void createCaptureSurface() {
1070+
final SurfaceTexture texture = createSurfaceTexture();
1071+
runOnUiThread(() -> {
1072+
SettingsStore settings = SettingsStore.getInstance(this);
1073+
texture.setDefaultBufferSize(settings.getWindowWidth(), settings.getWindowHeight());
1074+
BitmapCache.getInstance(this).setCaptureSurface(texture);
1075+
});
1076+
}
1077+
10551078
@Override
10561079
public int newWidgetHandle() {
10571080
return mWidgetHandleIndex++;

app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import android.content.Context;
1010
import android.content.SharedPreferences;
1111
import android.graphics.Bitmap;
12+
import android.graphics.SurfaceTexture;
1213
import android.preference.PreferenceManager;
1314
import android.util.Log;
15+
import android.view.Surface;
1416
import android.view.inputmethod.CursorAnchorInfo;
1517
import android.view.inputmethod.ExtractedText;
1618
import android.view.inputmethod.ExtractedTextRequest;
@@ -421,6 +423,30 @@ public void captureBitmap(@NonNull GeckoDisplay aDisplay) {
421423
});
422424
}
423425

426+
public void captureBackgroundBitmap(int displayWidth, int displayHeight) {
427+
Surface captureSurface = BitmapCache.getInstance(mContext).acquireCaptureSurface(displayWidth, displayHeight);
428+
if (captureSurface == null) {
429+
return;
430+
}
431+
GeckoSession session = mState.mSession;
432+
GeckoDisplay display = session.acquireDisplay();
433+
display.surfaceChanged(captureSurface, displayWidth, displayHeight);
434+
display.capturePixels().then(bitmap -> {
435+
if (bitmap != null) {
436+
BitmapCache.getInstance(mContext).scaleBitmap(bitmap, 500, 280).thenAccept(scaledBitmap -> {
437+
BitmapCache.getInstance(mContext).addBitmap(getId(), scaledBitmap);
438+
for (BitmapChangedListener listener: mBitmapChangedListeners) {
439+
listener.onBitmapChanged(Session.this, scaledBitmap);
440+
}
441+
});
442+
}
443+
display.surfaceDestroyed();
444+
session.releaseDisplay(display);
445+
BitmapCache.getInstance(mContext).releaseCaptureSurface();
446+
return null;
447+
});
448+
}
449+
424450
public boolean hasCapturedBitmap() {
425451
return BitmapCache.getInstance(mContext).hasBitmap(mState.mId);
426452
}

app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,14 @@ public boolean isHistoryVisible() {
391391
return (mView != null && mView == mHistoryView);
392392
}
393393

394+
public int getWindowWidth() {
395+
return mWidgetPlacement.width;
396+
}
397+
398+
public int getWindowHeight() {
399+
return mWidgetPlacement.height;
400+
}
401+
394402
public void addBookmarksViewListener(@NonNull BookmarksViewDelegate listener) {
395403
mBookmarksViewListeners.add(listener);
396404
}
@@ -1050,6 +1058,7 @@ public void onStackSession(Session aSession) {
10501058
setSession(aSession);
10511059
SessionStore.get().setActiveSession(aSession);
10521060
current.setActive(false);
1061+
current.captureBackgroundBitmap(getWindowWidth(), getWindowHeight());
10531062
mWidgetManager.getTray().showTabAddedNotification();
10541063
}
10551064

@@ -1468,7 +1477,7 @@ public void onPageStop(@NonNull GeckoSession aSession, boolean b) {
14681477
}
14691478
}
14701479

1471-
private void captureImage() {
1480+
public void captureImage() {
14721481
if (mDisplay != null) {
14731482
mSession.captureBitmap(mDisplay);
14741483
}

app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,11 @@ public void onTabsClicked() {
956956
((VRBrowserApplication)mContext.getApplicationContext()).getAccounts().refreshDevicesAsync();
957957
((VRBrowserApplication)mContext.getApplicationContext()).getAccounts().pollForEventsAsync();
958958
}
959+
960+
// Capture active session snapshots when showing the tabs menu
961+
for (WindowWidget window: getCurrentWindows()) {
962+
window.captureImage();
963+
}
959964
}
960965

961966
// TopBarWidget Delegate

app/src/common/shared/org/mozilla/vrbrowser/utils/BitmapCache.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
import android.content.Context;
44
import android.graphics.Bitmap;
55
import android.graphics.BitmapFactory;
6+
import android.graphics.SurfaceTexture;
67
import android.util.Log;
78
import android.util.LruCache;
9+
import android.view.Surface;
10+
811
import androidx.annotation.NonNull;
12+
import androidx.annotation.Nullable;
13+
914
import com.jakewharton.disklrucache.DiskLruCache;
1015

1116
import org.mozilla.vrbrowser.VRBrowserApplication;
@@ -24,6 +29,9 @@ public class BitmapCache {
2429
private final Object mLock = new Object();
2530
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 100; // 100MB
2631
private static final String LOGTAG = SystemUtils.createLogtag(BitmapCache.class);
32+
private SurfaceTexture mCaptureSurfaceTexture;
33+
private Surface mCaptureSurface;
34+
private boolean mCapturedAcquired;
2735

2836
public static BitmapCache getInstance(Context aContext) {
2937
return ((VRBrowserApplication)aContext.getApplicationContext()).getBitmapCache();
@@ -33,6 +41,9 @@ public BitmapCache(@NonNull Context aContext, @NonNull Executor aIOExecutor, @No
3341
mContext = aContext;
3442
mIOExecutor = aIOExecutor;
3543
mMainThreadExecutor = aMainThreadExecutor;
44+
}
45+
46+
public void onCreate() {
3647
initMemoryCache();
3748
initDiskCache();
3849
}
@@ -182,4 +193,43 @@ public CompletableFuture<Bitmap> scaleBitmap(Bitmap aBitmap, int aMaxWidth, int
182193

183194
return result;
184195
}
196+
197+
public void setCaptureSurface(SurfaceTexture aSurfaceTexture) {
198+
mCaptureSurfaceTexture = aSurfaceTexture;
199+
mCaptureSurface = new Surface(aSurfaceTexture);
200+
}
201+
202+
public @Nullable Surface acquireCaptureSurface(int width, int height) {
203+
if (mCapturedAcquired) {
204+
return null;
205+
}
206+
mCapturedAcquired = true;
207+
mCaptureSurfaceTexture.setDefaultBufferSize(width, height);
208+
return mCaptureSurface;
209+
}
210+
211+
public void releaseCaptureSurface() {
212+
mCapturedAcquired = false;
213+
}
214+
215+
public void onDestroy() {
216+
if (mDiskCache != null) {
217+
runIO(() -> {
218+
try {
219+
mDiskCache.close();
220+
} catch (IOException ex) {
221+
Log.e(LOGTAG, "Failed to close DiskLruCache:" + ex.getMessage());
222+
}
223+
mDiskCache = null;
224+
});
225+
}
226+
if (mCaptureSurface != null) {
227+
mCaptureSurface.release();
228+
mCaptureSurface = null;
229+
}
230+
if (mCaptureSurfaceTexture != null) {
231+
mCaptureSurfaceTexture.release();
232+
mCaptureSurfaceTexture = null;
233+
}
234+
}
185235
}

0 commit comments

Comments
 (0)