OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.fullscreen; | 5 package org.chromium.chrome.browser.fullscreen; |
6 | 6 |
7 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; | 7 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; |
8 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; | 8 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
9 import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE; | 9 import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE; |
10 | 10 |
11 import android.content.res.Resources; | 11 import android.content.res.Resources; |
12 import android.os.Build; | 12 import android.os.Build; |
13 import android.os.Bundle; | 13 import android.os.Bundle; |
14 import android.os.Handler; | 14 import android.os.Handler; |
15 import android.os.Message; | 15 import android.os.Message; |
16 import android.view.Gravity; | 16 import android.view.Gravity; |
17 import android.view.View; | 17 import android.view.View; |
18 import android.view.View.OnLayoutChangeListener; | 18 import android.view.View.OnLayoutChangeListener; |
19 import android.view.Window; | 19 import android.view.Window; |
20 import android.view.WindowManager; | 20 import android.view.WindowManager; |
21 | 21 |
22 import org.chromium.chrome.R; | 22 import org.chromium.chrome.R; |
23 import org.chromium.chrome.browser.widget.TextBubble; | 23 import org.chromium.chrome.browser.widget.TextBubble; |
24 import org.chromium.content.browser.ContentViewCore; | 24 import org.chromium.content.browser.ContentViewCore; |
25 | 25 |
| 26 import java.lang.ref.WeakReference; |
| 27 |
26 /** | 28 /** |
27 * Handles updating the UI based on requests to the HTML Fullscreen API. | 29 * Handles updating the UI based on requests to the HTML Fullscreen API. |
28 */ | 30 */ |
29 public class FullscreenHtmlApiHandler { | 31 public class FullscreenHtmlApiHandler { |
30 private static final int MSG_ID_HIDE_NOTIFICATION_BUBBLE = 1; | 32 private static final int MSG_ID_HIDE_NOTIFICATION_BUBBLE = 1; |
31 private static final int MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS = 2; | 33 private static final int MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS = 2; |
32 private static final int MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG = 3; | 34 private static final int MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG = 3; |
33 | 35 |
34 private static final int MAX_NOTIFICATION_DIMENSION_DP = 600; | 36 private static final int MAX_NOTIFICATION_DIMENSION_DP = 600; |
35 | 37 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 */ | 99 */ |
98 void onFullscreenExited(ContentViewCore contentViewCore); | 100 void onFullscreenExited(ContentViewCore contentViewCore); |
99 | 101 |
100 /** | 102 /** |
101 * @return Whether the notification bubble should be shown. For fullscre
en video in | 103 * @return Whether the notification bubble should be shown. For fullscre
en video in |
102 * overlay mode, the notification bubble should be disabled. | 104 * overlay mode, the notification bubble should be disabled. |
103 */ | 105 */ |
104 boolean shouldShowNotificationBubble(); | 106 boolean shouldShowNotificationBubble(); |
105 } | 107 } |
106 | 108 |
| 109 // This static inner class holds a WeakReference to the outer object, to avo
id triggering the |
| 110 // lint HandlerLeak warning. |
| 111 private static class FullscreenHandler extends Handler { |
| 112 private final WeakReference<FullscreenHtmlApiHandler> mFullscreenHtmlApi
Handler; |
| 113 |
| 114 public FullscreenHandler(FullscreenHtmlApiHandler fullscreenHtmlApiHandl
er) { |
| 115 mFullscreenHtmlApiHandler = new WeakReference<FullscreenHtmlApiHandl
er>( |
| 116 fullscreenHtmlApiHandler); |
| 117 } |
| 118 |
| 119 @Override |
| 120 public void handleMessage(Message msg) { |
| 121 if (msg == null) return; |
| 122 FullscreenHtmlApiHandler fullscreenHtmlApiHandler = mFullscreenHtmlA
piHandler.get(); |
| 123 switch (msg.what) { |
| 124 case MSG_ID_HIDE_NOTIFICATION_BUBBLE: |
| 125 fullscreenHtmlApiHandler.hideNotificationBubble(); |
| 126 break; |
| 127 case MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS: { |
| 128 assert fullscreenHtmlApiHandler.getPersistentFullscreenMode(
) : |
| 129 "Calling after we exited fullscreen"; |
| 130 final ContentViewCore contentViewCore = |
| 131 fullscreenHtmlApiHandler.getContentViewCoreInFullscr
een(); |
| 132 if (contentViewCore == null) return; |
| 133 final View contentView = contentViewCore.getContainerView(); |
| 134 int systemUiVisibility = contentView.getSystemUiVisibility()
; |
| 135 if ((systemUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) |
| 136 == SYSTEM_UI_FLAG_FULLSCREEN) { |
| 137 return; |
| 138 } |
| 139 systemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; |
| 140 systemUiVisibility |= SYSTEM_UI_FLAG_LOW_PROFILE; |
| 141 contentView.setSystemUiVisibility(systemUiVisibility); |
| 142 |
| 143 // Trigger a update to clear the SYSTEM_UI_FLAG_LAYOUT_FULLS
CREEN flag |
| 144 // once the view has been laid out after this system UI upda
te. Without |
| 145 // clearing this flag, the keyboard appearing will not trigg
er a relayout |
| 146 // of the contents, which prevents updating the overdraw amo
unt to the |
| 147 // renderer. |
| 148 contentView.addOnLayoutChangeListener(new OnLayoutChangeList
ener() { |
| 149 @Override |
| 150 public void onLayoutChange(View v, int left, int top, in
t right, |
| 151 int bottom, int oldLeft, int oldTop, int oldRigh
t, |
| 152 int oldBottom) { |
| 153 sendEmptyMessageDelayed(MSG_ID_CLEAR_LAYOUT_FULLSCRE
EN_FLAG, |
| 154 CLEAR_LAYOUT_FULLSCREEN_DELAY_MS); |
| 155 contentView.removeOnLayoutChangeListener(this); |
| 156 } |
| 157 }); |
| 158 break; |
| 159 } |
| 160 case MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG: { |
| 161 // Change this assert to simply ignoring the message to work
around |
| 162 // http://crbug/365638 |
| 163 // TODO(aberent): Fix bug |
| 164 // assert mIsPersistentMode : "Calling after we exited fulls
creen"; |
| 165 if (!fullscreenHtmlApiHandler.getPersistentFullscreenMode())
return; |
| 166 final ContentViewCore contentViewCore = |
| 167 fullscreenHtmlApiHandler.getContentViewCoreInFullscr
een(); |
| 168 if (contentViewCore == null) return; |
| 169 final View view = contentViewCore.getContainerView(); |
| 170 int systemUiVisibility = view.getSystemUiVisibility(); |
| 171 if ((systemUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
== 0) { |
| 172 return; |
| 173 } |
| 174 systemUiVisibility &= ~SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
| 175 view.setSystemUiVisibility(systemUiVisibility); |
| 176 break; |
| 177 } |
| 178 default: |
| 179 assert false : "Unexpected message for ID: " + msg.what; |
| 180 break; |
| 181 } |
| 182 } |
| 183 } |
| 184 |
107 /** | 185 /** |
108 * Constructs the handler that will manage the UI transitions from the HTML
fullscreen API. | 186 * Constructs the handler that will manage the UI transitions from the HTML
fullscreen API. |
109 * | 187 * |
110 * @param window The window containing the view going to fullscreen. | 188 * @param window The window containing the view going to fullscreen. |
111 * @param delegate The delegate that allows embedders to handle fullscreen t
ransitions. | 189 * @param delegate The delegate that allows embedders to handle fullscreen t
ransitions. |
112 * @param persistentFullscreenSupported | 190 * @param persistentFullscreenSupported |
113 */ | 191 */ |
114 public FullscreenHtmlApiHandler(Window window, FullscreenHtmlApiDelegate del
egate, | 192 public FullscreenHtmlApiHandler(Window window, FullscreenHtmlApiDelegate del
egate, |
115 boolean persistentFullscreenSupported) { | 193 boolean persistentFullscreenSupported) { |
116 mWindow = window; | 194 mWindow = window; |
117 mDelegate = delegate; | 195 mDelegate = delegate; |
118 mPersistentFullscreenSupported = persistentFullscreenSupported; | 196 mPersistentFullscreenSupported = persistentFullscreenSupported; |
119 | 197 mHandler = new FullscreenHandler(this); |
120 mHandler = new Handler() { | |
121 @Override | |
122 public void handleMessage(Message msg) { | |
123 if (msg == null) return; | |
124 switch (msg.what) { | |
125 case MSG_ID_HIDE_NOTIFICATION_BUBBLE: | |
126 hideNotificationBubble(); | |
127 break; | |
128 case MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS: { | |
129 assert mIsPersistentMode : "Calling after we exited full
screen"; | |
130 final ContentViewCore contentViewCore = mContentViewCore
InFullscreen; | |
131 if (contentViewCore == null) return; | |
132 final View contentView = contentViewCore.getContainerVie
w(); | |
133 int systemUiVisibility = contentView.getSystemUiVisibili
ty(); | |
134 if ((systemUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) | |
135 == SYSTEM_UI_FLAG_FULLSCREEN) { | |
136 return; | |
137 } | |
138 systemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; | |
139 systemUiVisibility |= SYSTEM_UI_FLAG_LOW_PROFILE; | |
140 contentView.setSystemUiVisibility(systemUiVisibility); | |
141 | |
142 // Trigger a update to clear the SYSTEM_UI_FLAG_LAYOUT_F
ULLSCREEN flag | |
143 // once the view has been laid out after this system UI
update. Without | |
144 // clearing this flag, the keyboard appearing will not t
rigger a relayout | |
145 // of the contents, which prevents updating the overdraw
amount to the | |
146 // renderer. | |
147 contentView.addOnLayoutChangeListener(new OnLayoutChange
Listener() { | |
148 @Override | |
149 public void onLayoutChange(View v, int left, int top
, int right, | |
150 int bottom, int oldLeft, int oldTop, int old
Right, | |
151 int oldBottom) { | |
152 sendEmptyMessageDelayed(MSG_ID_CLEAR_LAYOUT_FULL
SCREEN_FLAG, | |
153 CLEAR_LAYOUT_FULLSCREEN_DELAY_MS); | |
154 contentView.removeOnLayoutChangeListener(this); | |
155 } | |
156 }); | |
157 break; | |
158 } | |
159 case MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG: { | |
160 // Change this assert to simply ignoring the message to
work around | |
161 // http://crbug/365638 | |
162 // TODO(aberent): Fix bug | |
163 // assert mIsPersistentMode : "Calling after we exited f
ullscreen"; | |
164 if (!mIsPersistentMode) return; | |
165 if (mContentViewCoreInFullscreen == null) return; | |
166 final View view = mContentViewCoreInFullscreen.getContai
nerView(); | |
167 int systemUiVisibility = view.getSystemUiVisibility(); | |
168 if ((systemUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCRE
EN) == 0) { | |
169 return; | |
170 } | |
171 systemUiVisibility &= ~SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; | |
172 view.setSystemUiVisibility(systemUiVisibility); | |
173 break; | |
174 } | |
175 default: | |
176 assert false : "Unexpected message for ID: " + msg.what; | |
177 break; | |
178 } | |
179 } | |
180 }; | |
181 | |
182 Resources resources = mWindow.getContext().getResources(); | 198 Resources resources = mWindow.getContext().getResources(); |
183 float density = resources.getDisplayMetrics().density; | 199 float density = resources.getDisplayMetrics().density; |
184 mNotificationMaxDimension = (int) (density * MAX_NOTIFICATION_DIMENSION_
DP); | 200 mNotificationMaxDimension = (int) (density * MAX_NOTIFICATION_DIMENSION_
DP); |
185 } | 201 } |
186 | 202 |
187 /** | 203 /** |
188 * Enters or exits persistent fullscreen mode. In this mode, the top contro
ls will be | 204 * Enters or exits persistent fullscreen mode. In this mode, the top contro
ls will be |
189 * permanently hidden until this mode is exited. | 205 * permanently hidden until this mode is exited. |
190 * | 206 * |
191 * @param enabled Whether to enable persistent fullscreen mode. | 207 * @param enabled Whether to enable persistent fullscreen mode. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 } | 311 } |
296 contentView.removeOnLayoutChangeListener(this); | 312 contentView.removeOnLayoutChangeListener(this); |
297 } | 313 } |
298 }; | 314 }; |
299 contentView.addOnLayoutChangeListener(mFullscreenOnLayoutChangeListener)
; | 315 contentView.addOnLayoutChangeListener(mFullscreenOnLayoutChangeListener)
; |
300 contentView.setSystemUiVisibility(systemUiVisibility); | 316 contentView.setSystemUiVisibility(systemUiVisibility); |
301 mContentViewCoreInFullscreen = contentViewCore; | 317 mContentViewCoreInFullscreen = contentViewCore; |
302 } | 318 } |
303 | 319 |
304 /** | 320 /** |
| 321 * Gets the fullscreen ContentViewCore. |
| 322 */ |
| 323 public ContentViewCore getContentViewCoreInFullscreen() { |
| 324 return mContentViewCoreInFullscreen; |
| 325 } |
| 326 |
| 327 /** |
305 * Creates (if necessary) and returns a notification bubble. | 328 * Creates (if necessary) and returns a notification bubble. |
306 */ | 329 */ |
307 private TextBubble getOrCreateNotificationBubble() { | 330 private TextBubble getOrCreateNotificationBubble() { |
308 if (mNotificationBubble == null) { | 331 if (mNotificationBubble == null) { |
309 Bundle b = new Bundle(); | 332 Bundle b = new Bundle(); |
310 b.putBoolean(TextBubble.BACKGROUND_INTRINSIC_PADDING, true); | 333 b.putBoolean(TextBubble.BACKGROUND_INTRINSIC_PADDING, true); |
311 b.putBoolean(TextBubble.CENTER, true); | 334 b.putBoolean(TextBubble.CENTER, true); |
312 b.putBoolean(TextBubble.UP_DOWN, true); | 335 b.putBoolean(TextBubble.UP_DOWN, true); |
313 b.putInt(TextBubble.TEXT_STYLE_ID, android.R.style.TextAppearance_De
viceDefault_Medium); | 336 b.putInt(TextBubble.TEXT_STYLE_ID, android.R.style.TextAppearance_De
viceDefault_Medium); |
314 b.putInt(TextBubble.ANIM_STYLE_ID, R.style.FullscreenNotificationBub
ble); | 337 b.putInt(TextBubble.ANIM_STYLE_ID, R.style.FullscreenNotificationBub
ble); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 if (!hasWindowFocus) hideNotificationBubble(); | 398 if (!hasWindowFocus) hideNotificationBubble(); |
376 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) return; | 399 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) return; |
377 | 400 |
378 mHandler.removeMessages(MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS); | 401 mHandler.removeMessages(MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS); |
379 mHandler.removeMessages(MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG); | 402 mHandler.removeMessages(MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG); |
380 if (mContentViewCoreInFullscreen == null || !mIsPersistentMode || !hasWi
ndowFocus) return; | 403 if (mContentViewCoreInFullscreen == null || !mIsPersistentMode || !hasWi
ndowFocus) return; |
381 mHandler.sendEmptyMessageDelayed( | 404 mHandler.sendEmptyMessageDelayed( |
382 MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS, ANDROID_CONTROLS_SHOW_DUR
ATION_MS); | 405 MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS, ANDROID_CONTROLS_SHOW_DUR
ATION_MS); |
383 } | 406 } |
384 } | 407 } |
OLD | NEW |