1313import android .view .View ;
1414import android .widget .FrameLayout ;
1515
16+ import org .chromium .base .CommandLine ;
17+ import org .chromium .base .Log ;
1618import org .chromium .content_public .browser .WebContents ;
1719import org .chromium .ui .base .EventForwarder ;
1820import org .chromium .ui .base .WindowAndroid ;
2830 */
2931@ JNINamespace ("cobalt" )
3032public class ContentViewRenderView extends FrameLayout {
33+ private static final String TAG = "cobalt" ;
34+
3135 // The native side of this object.
3236 private long mNativeContentViewRenderView ;
3337 private WindowAndroid mWindowAndroid ;
@@ -53,7 +57,12 @@ public ContentViewRenderView(Context context) {
5357 }
5458
5559 protected SurfaceBridge createSurfaceBridge () {
56- return new SurfaceBridge ();
60+ if (CommandLine .getInstance ().hasSwitch ("use-window-surface-for-ui" )) {
61+ Log .i (TAG , "ContentViewRenderView is created using WindowSurfaceBridge" );
62+ return new WindowSurfaceBridge ();
63+ }
64+ Log .i (TAG , "ContentViewRenderView is created with SurfaceView" );
65+ return new SurfaceViewBridge ();
5766 }
5867
5968 /**
@@ -62,7 +71,8 @@ protected SurfaceBridge createSurfaceBridge() {
6271 * @param rootWindow The {@link WindowAndroid} this render view should be linked to.
6372 */
6473 public void onNativeLibraryLoaded (WindowAndroid rootWindow ) {
65- assert !getSurfaceView ().getHolder ().getSurface ().isValid ()
74+ assert mSurfaceBridge .getSurfaceView () == null
75+ || !mSurfaceBridge .getSurfaceView ().getHolder ().getSurface ().isValid ()
6676 : "Surface created before native library loaded." ;
6777 assert rootWindow != null ;
6878 mNativeContentViewRenderView =
@@ -96,7 +106,10 @@ public void surfaceCreated(SurfaceHolder holder) {
96106 // devices, where a relayout never happens. This bug is out of Chromium's
97107 // control, but can be worked around by forcibly re-setting the visibility of
98108 // the surface view. Otherwise, the screen stays black, and some tests fail.
99- getSurfaceView ().setVisibility (getSurfaceView ().getVisibility ());
109+ SurfaceView surfaceView = mSurfaceBridge .getSurfaceView ();
110+ if (surfaceView != null ) {
111+ surfaceView .setVisibility (surfaceView .getVisibility ());
112+ }
100113
101114 onReadyToRender ();
102115 }
@@ -108,7 +121,7 @@ public void surfaceDestroyed(SurfaceHolder holder) {
108121 mNativeContentViewRenderView , ContentViewRenderView .this );
109122 }
110123 };
111- mSurfaceBridge .connect (surfaceCallback );
124+ mSurfaceBridge .connect (surfaceCallback , rootWindow );
112125 }
113126
114127 @ Override
@@ -135,22 +148,12 @@ protected void onWindowVisibilityChanged(int visibility) {
135148 }
136149
137150 /**
138- * Sets the background color of the surface view. This method is necessary because the
139- * background color of ContentViewRenderView itself is covered by the background of
140- * SurfaceView.
141- * @param color The color of the background.
151+ * Gets the View used for layout anchoring, animation placeholder, or accessibility (child
152+ * SurfaceView in SurfaceView mode, or this host View in Window Surface mode).
142153 */
143- public void setSurfaceViewBackgroundColor (int color ) {
144- if (getSurfaceView () != null ) {
145- getSurfaceView ().setBackgroundColor (color );
146- }
147- }
148-
149- /**
150- * Gets the SurfaceView for this ContentViewRenderView
151- */
152- public SurfaceView getSurfaceView () {
153- return mSurfaceBridge .getSurfaceView ();
154+ public View getAnchorView () {
155+ SurfaceView surfaceView = mSurfaceBridge .getSurfaceView ();
156+ return surfaceView != null ? surfaceView : this ;
154157 }
155158
156159 /**
@@ -195,47 +198,72 @@ protected SurfaceView createSurfaceView(Context context) {
195198 return new SurfaceView (context );
196199 }
197200
198- /**
199- * @return whether the surface view is initialized and ready to render.
200- */
201- public boolean isInitialized () {
202- return getSurfaceView ().getHolder ().getSurface () != null ;
203- }
204-
205201 /**
206202 * Enter or leave overlay video mode.
207203 * @param enabled Whether overlay mode is enabled.
208204 */
209205 public void setOverlayVideoMode (boolean enabled ) {
210206 int format = enabled ? PixelFormat .TRANSLUCENT : PixelFormat .OPAQUE ;
211- getSurfaceView (). getHolder () .setFormat (format );
207+ mSurfaceBridge .setFormat (format );
212208 ContentViewRenderViewJni .get ().setOverlayVideoMode (
213209 mNativeContentViewRenderView , ContentViewRenderView .this , enabled );
214210 }
215211
216212 @ CalledByNative
217213 private void didSwapFrame () {
218- if (getSurfaceView ().getBackground () != null ) {
214+ SurfaceView surfaceView = mSurfaceBridge .getSurfaceView ();
215+ if (surfaceView == null ) {
216+ // In Window Surface mode, no child SurfaceView background to clear.
217+ return ;
218+ }
219+
220+ if (surfaceView .getBackground () != null ) {
219221 post (new Runnable () {
220222 @ Override
221223 public void run () {
222- getSurfaceView () .setBackgroundResource (0 );
224+ surfaceView .setBackgroundResource (0 );
223225 }
224226 });
225227 }
226228 }
227229
228230 /**
229- * Connecting class to hold a SurfaceView .
231+ * Connecting class to hold a surface management strategy .
230232 */
231- protected static class SurfaceBridge {
233+ protected abstract static class SurfaceBridge {
234+ protected abstract void initialize (ContentViewRenderView renderView );
235+ protected abstract void connect (SurfaceHolder .Callback surfaceCallback , WindowAndroid windowAndroid );
236+ protected abstract void disconnect ();
237+ protected abstract SurfaceView getSurfaceView ();
238+ protected abstract void setFormat (int format );
239+ }
240+
241+ /**
242+ * SurfaceBridge implementation that uses a standard SurfaceView.
243+ * This is used for the default rendering path where a child SurfaceView is embedded
244+ * within the ContentViewRenderView.
245+ *
246+ * Lifetime: Bound to the lifetime of the outer ContentViewRenderView.
247+ * Threading: Must be called on the UI thread.
248+ */
249+ protected static class SurfaceViewBridge extends SurfaceBridge {
232250 private SurfaceView mSurfaceView ;
233251 private SurfaceHolder .Callback mSurfaceCallback ;
234252
253+ @ Override
235254 protected SurfaceView getSurfaceView () {
236255 return mSurfaceView ;
237256 }
238257
258+ @ Override
259+ protected void setFormat (int format ) {
260+ if (mSurfaceView == null ) {
261+ return ;
262+ }
263+ mSurfaceView .getHolder ().setFormat (format );
264+ }
265+
266+ @ Override
239267 protected void initialize (ContentViewRenderView renderView ) {
240268 mSurfaceView = renderView .createSurfaceView (renderView .getContext ());
241269 mSurfaceView .setZOrderMediaOverlay (true );
@@ -246,17 +274,99 @@ protected void initialize(ContentViewRenderView renderView) {
246274 mSurfaceView .setVisibility (GONE );
247275 }
248276
249- protected void connect (SurfaceHolder .Callback surfaceCallback ) {
277+ @ Override
278+ protected void connect (SurfaceHolder .Callback surfaceCallback , WindowAndroid windowAndroid ) {
250279 mSurfaceCallback = surfaceCallback ;
251280 mSurfaceView .getHolder ().addCallback (mSurfaceCallback );
252281 mSurfaceView .setVisibility (VISIBLE );
253282 }
254283
284+ @ Override
255285 protected void disconnect () {
256286 mSurfaceView .getHolder ().removeCallback (mSurfaceCallback );
257287 }
258288 }
259289
290+ /**
291+ * SurfaceBridge implementation that takes ownership of the Activity's Window surface.
292+ * This allows direct rendering to the window surface instead of a child SurfaceView.
293+ *
294+ * Lifetime: Bound to the lifetime of the outer ContentViewRenderView and the associated Activity.
295+ * Threading: Must be called on the UI thread.
296+ */
297+ protected static class WindowSurfaceBridge extends SurfaceBridge {
298+ private SurfaceHolder mWindowSurfaceHolder ;
299+ private Integer mSurfaceFormat ;
300+
301+ @ Override
302+ protected void initialize (ContentViewRenderView renderView ) {}
303+
304+ @ Override
305+ protected void connect (
306+ SurfaceHolder .Callback surfaceCallback , WindowAndroid windowAndroid ) {
307+ if (windowAndroid == null ) {
308+ return ;
309+ }
310+ android .app .Activity activity = windowAndroid .getActivity ().get ();
311+ if (activity == null || activity .getWindow () == null ) {
312+ return ;
313+ }
314+
315+ activity .getWindow ().takeSurface (new SurfaceHolder .Callback2 () {
316+ @ Override
317+ public void surfaceCreated (SurfaceHolder holder ) {
318+ mWindowSurfaceHolder = holder ;
319+ if (mSurfaceFormat != null ) {
320+ Log .i (TAG , "Applying pending format" );
321+ mWindowSurfaceHolder .setFormat (mSurfaceFormat );
322+ }
323+ surfaceCallback .surfaceCreated (holder );
324+ }
325+
326+ @ Override
327+ public void surfaceChanged (
328+ SurfaceHolder holder , int format , int width , int height ) {
329+ mWindowSurfaceHolder = holder ;
330+ surfaceCallback .surfaceChanged (holder , format , width , height );
331+ }
332+
333+ @ Override
334+ public void surfaceDestroyed (SurfaceHolder holder ) {
335+ mWindowSurfaceHolder = null ;
336+ surfaceCallback .surfaceDestroyed (holder );
337+ }
338+
339+ @ Override
340+ public void surfaceRedrawNeeded (SurfaceHolder holder ) {
341+ if (surfaceCallback instanceof SurfaceHolder .Callback2 ) {
342+ ((SurfaceHolder .Callback2 ) surfaceCallback ).surfaceRedrawNeeded (holder );
343+ }
344+ }
345+ });
346+ }
347+
348+ @ Override
349+ protected void disconnect () {
350+ mWindowSurfaceHolder = null ;
351+ mSurfaceFormat = null ;
352+ }
353+
354+ @ Override
355+ protected SurfaceView getSurfaceView () {
356+ return null ;
357+ }
358+
359+ @ Override
360+ protected void setFormat (int format ) {
361+ mSurfaceFormat = format ;
362+ if (mWindowSurfaceHolder == null ) {
363+ Log .i (TAG , "Window surface is not ready yet. Will apply format later" );
364+ return ;
365+ }
366+ mWindowSurfaceHolder .setFormat (format );
367+ }
368+ }
369+
260370 private EventForwarder getEventForwarder () {
261371 if (mWebContents == null || mWebContents .isDestroyed ()) {
262372 return null ;
0 commit comments