Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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.chromoting; | 5 package org.chromium.chromoting; |
| 6 | 6 |
| 7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
| 8 import android.app.AlertDialog; | 8 import android.app.AlertDialog; |
| 9 import android.content.DialogInterface; | 9 import android.content.DialogInterface; |
| 10 import android.content.Intent; | 10 import android.content.Intent; |
| 11 import android.content.pm.ApplicationInfo; | 11 import android.content.pm.ApplicationInfo; |
| 12 import android.content.pm.PackageManager; | 12 import android.content.pm.PackageManager; |
| 13 import android.content.pm.PackageManager.NameNotFoundException; | 13 import android.content.pm.PackageManager.NameNotFoundException; |
| 14 import android.graphics.Rect; | |
| 14 import android.os.Build; | 15 import android.os.Build; |
| 15 import android.os.Bundle; | 16 import android.os.Bundle; |
| 16 import android.support.v7.app.AppCompatActivity; | 17 import android.support.v7.app.AppCompatActivity; |
| 17 import android.support.v7.widget.Toolbar; | 18 import android.support.v7.widget.Toolbar; |
| 18 import android.view.KeyCharacterMap; | 19 import android.view.KeyCharacterMap; |
| 19 import android.view.KeyEvent; | 20 import android.view.KeyEvent; |
| 20 import android.view.Menu; | 21 import android.view.Menu; |
| 21 import android.view.MenuItem; | 22 import android.view.MenuItem; |
| 22 import android.view.View; | 23 import android.view.View; |
| 24 import android.view.View.OnLayoutChangeListener; | |
| 23 import android.view.inputmethod.InputMethodManager; | 25 import android.view.inputmethod.InputMethodManager; |
| 24 | 26 |
| 25 import org.chromium.chromoting.cardboard.DesktopActivity; | 27 import org.chromium.chromoting.cardboard.DesktopActivity; |
| 26 import org.chromium.chromoting.jni.JniInterface; | 28 import org.chromium.chromoting.jni.JniInterface; |
| 27 | 29 |
| 28 import java.util.Set; | 30 import java.util.Set; |
| 29 import java.util.TreeSet; | 31 import java.util.TreeSet; |
| 30 | 32 |
| 31 /** | 33 /** |
| 32 * A simple screen that does nothing except display a DesktopView and notify it of rotations. | 34 * A simple screen that does nothing except display a DesktopView and notify it of rotations. |
| 33 */ | 35 */ |
| 34 public class Desktop extends AppCompatActivity implements View.OnSystemUiVisibil ityChangeListener { | 36 public class Desktop extends AppCompatActivity implements View.OnSystemUiVisibil ityChangeListener { |
| 35 /** Web page to be displayed in the Help screen when launched from this acti vity. */ | 37 /** Web page to be displayed in the Help screen when launched from this acti vity. */ |
| 36 private static final String HELP_URL = | 38 private static final String HELP_URL = |
| 37 "https://support.google.com/chrome/?p=mobile_crd_connecthost"; | 39 "https://support.google.com/chrome/?p=mobile_crd_connecthost"; |
| 38 | 40 |
| 39 /** | 41 /** |
| 40 * Preference used for displaying an interestitial dialog only when the user first accesses the | 42 * Preference used for displaying an interestitial dialog only when the user first accesses the |
| 41 * Cardboard function. | 43 * Cardboard function. |
| 42 */ | 44 */ |
| 43 private static final String PREFERENCE_CARDBOARD_DIALOG_SEEN = | 45 private static final String PREFERENCE_CARDBOARD_DIALOG_SEEN = "cardboard_di alog_seen"; |
| 44 "cardboard_dialog_seen"; | 46 |
| 47 /** The amount of time to wait to hide the Actionbar after user input is see n. */ | |
| 48 private static final int ACTIONBAR_AUTO_HIDE_DELAY_MS = 3000; | |
| 45 | 49 |
| 46 /** The surface that displays the remote host's desktop feed. */ | 50 /** The surface that displays the remote host's desktop feed. */ |
| 47 private DesktopView mRemoteHostDesktop; | 51 private DesktopView mRemoteHostDesktop; |
| 48 | 52 |
| 49 /** Set of pressed keys for which we've sent TextEvent. */ | 53 /** Set of pressed keys for which we've sent TextEvent. */ |
| 50 private Set<Integer> mPressedTextKeys = new TreeSet<Integer>(); | 54 private Set<Integer> mPressedTextKeys = new TreeSet<Integer>(); |
| 51 | 55 |
| 52 private ActivityLifecycleListener mActivityLifecycleListener; | 56 private ActivityLifecycleListener mActivityLifecycleListener; |
| 53 | 57 |
| 54 // Flag to indicate whether the current activity is going to switch to Cardb oard | 58 /** Flag to indicate whether the current activity is switching to Cardboard desktop activity. */ |
| 55 // desktop activity. | |
| 56 private boolean mSwitchToCardboardDesktopActivity; | 59 private boolean mSwitchToCardboardDesktopActivity; |
| 57 | 60 |
| 61 /** Indicates whether a Soft Input UI (such as a keyboard) is visible. */ | |
| 62 private boolean mSoftInputVisible = false; | |
| 63 | |
| 64 /** Holds the scheduled task object which will be called to hide the ActionB ar. */ | |
| 65 private Runnable mActionBarAutoHideTask; | |
| 66 | |
| 58 /** Called when the activity is first created. */ | 67 /** Called when the activity is first created. */ |
| 59 @Override | 68 @Override |
| 60 public void onCreate(Bundle savedInstanceState) { | 69 public void onCreate(Bundle savedInstanceState) { |
| 61 super.onCreate(savedInstanceState); | 70 super.onCreate(savedInstanceState); |
| 62 setContentView(R.layout.desktop); | 71 setContentView(R.layout.desktop); |
| 63 | 72 |
| 64 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); | 73 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); |
| 65 setSupportActionBar(toolbar); | 74 setSupportActionBar(toolbar); |
| 66 | 75 |
| 67 mRemoteHostDesktop = (DesktopView) findViewById(R.id.desktop_view); | 76 mRemoteHostDesktop = (DesktopView) findViewById(R.id.desktop_view); |
| 68 mRemoteHostDesktop.setDesktop(this); | 77 mRemoteHostDesktop.setDesktop(this); |
| 69 mSwitchToCardboardDesktopActivity = false; | 78 mSwitchToCardboardDesktopActivity = false; |
| 70 | 79 |
| 71 getSupportActionBar().setDisplayShowTitleEnabled(false); | 80 getSupportActionBar().setDisplayShowTitleEnabled(false); |
| 72 getSupportActionBar().setDisplayHomeAsUpEnabled(true); | 81 getSupportActionBar().setDisplayHomeAsUpEnabled(true); |
| 73 | 82 |
| 74 // For this Activity, the home button in the action bar acts as a Discon nect button, so | 83 // For this Activity, the home button in the action bar acts as a Discon nect button, so |
| 75 // set the description for accessibility/screen readers. | 84 // set the description for accessibility/screen readers. |
| 76 getSupportActionBar().setHomeActionContentDescription(R.string.disconnec t_myself_button); | 85 getSupportActionBar().setHomeActionContentDescription(R.string.disconnec t_myself_button); |
| 77 | 86 |
| 87 // The action bar is already shown when the activity is started however calling the | |
| 88 // function below will set our preferred system UI flags which will adju st the layout | |
| 89 // size of the canvas and we can avoid an initial resize event. | |
| 90 showActionBar(); | |
| 91 | |
| 78 View decorView = getWindow().getDecorView(); | 92 View decorView = getWindow().getDecorView(); |
| 79 decorView.setOnSystemUiVisibilityChangeListener(this); | 93 decorView.setOnSystemUiVisibilityChangeListener(this); |
| 80 | 94 |
| 81 mActivityLifecycleListener = CapabilityManager.getInstance() | 95 mActivityLifecycleListener = CapabilityManager.getInstance() |
| 82 .onActivityAcceptingListener(this, Capabilities.CAST_CAPABILITY); | 96 .onActivityAcceptingListener(this, Capabilities.CAST_CAPABILITY) ; |
| 83 mActivityLifecycleListener.onActivityCreated(this, savedInstanceState); | 97 mActivityLifecycleListener.onActivityCreated(this, savedInstanceState); |
| 98 | |
| 99 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | |
| 100 attachKeyboardVisibilityListener(); | |
| 101 | |
| 102 // Only create an Autohide task if the system supports immersive ful lscreen mode. Older | |
| 103 // versions of the OS benefit less from this functionality and we do n't want to change | |
| 104 // the experience for them. | |
| 105 mActionBarAutoHideTask = new Runnable() { | |
| 106 public void run() { | |
| 107 hideActionBar(); | |
| 108 } | |
| 109 }; | |
| 110 } else { | |
| 111 mRemoteHostDesktop.setFitsSystemWindows(true); | |
| 112 } | |
| 84 } | 113 } |
| 85 | 114 |
| 86 @Override | 115 @Override |
| 87 protected void onStart() { | 116 protected void onStart() { |
| 88 super.onStart(); | 117 super.onStart(); |
| 89 mActivityLifecycleListener.onActivityStarted(this); | 118 mActivityLifecycleListener.onActivityStarted(this); |
| 90 JniInterface.enableVideoChannel(true); | 119 JniInterface.enableVideoChannel(true); |
| 91 mRemoteHostDesktop.attachRedrawCallback(); | 120 mRemoteHostDesktop.attachRedrawCallback(); |
| 92 } | 121 } |
| 93 | 122 |
| 94 @Override | 123 @Override |
| 95 protected void onPause() { | 124 protected void onPause() { |
| 96 if (isFinishing()) mActivityLifecycleListener.onActivityPaused(this); | 125 if (isFinishing()) mActivityLifecycleListener.onActivityPaused(this); |
| 97 super.onPause(); | 126 super.onPause(); |
| 98 if (!mSwitchToCardboardDesktopActivity) { | 127 if (!mSwitchToCardboardDesktopActivity) { |
| 99 JniInterface.enableVideoChannel(false); | 128 JniInterface.enableVideoChannel(false); |
| 100 } | 129 } |
| 130 stopActionBarAutoHideTimer(); | |
| 101 } | 131 } |
| 102 | 132 |
| 103 @Override | 133 @Override |
| 104 public void onResume() { | 134 public void onResume() { |
| 105 super.onResume(); | 135 super.onResume(); |
| 106 mActivityLifecycleListener.onActivityResumed(this); | 136 mActivityLifecycleListener.onActivityResumed(this); |
| 107 JniInterface.enableVideoChannel(true); | 137 JniInterface.enableVideoChannel(true); |
| 138 startActionBarAutoHideTimer(); | |
| 108 } | 139 } |
| 109 | 140 |
| 110 @Override | 141 @Override |
| 111 protected void onStop() { | 142 protected void onStop() { |
| 112 mActivityLifecycleListener.onActivityStopped(this); | 143 mActivityLifecycleListener.onActivityStopped(this); |
| 113 super.onStop(); | 144 super.onStop(); |
| 114 if (mSwitchToCardboardDesktopActivity) { | 145 if (mSwitchToCardboardDesktopActivity) { |
| 115 mSwitchToCardboardDesktopActivity = false; | 146 mSwitchToCardboardDesktopActivity = false; |
| 116 } else { | 147 } else { |
| 117 JniInterface.enableVideoChannel(false); | 148 JniInterface.enableVideoChannel(false); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 131 .getApplicationInfo(getPackageName(), PackageManager.GET_MET A_DATA); | 162 .getApplicationInfo(getPackageName(), PackageManager.GET_MET A_DATA); |
| 132 Bundle bundle = ai.metaData; | 163 Bundle bundle = ai.metaData; |
| 133 enableCardboard = bundle.getInt("enable_cardboard") == 1; | 164 enableCardboard = bundle.getInt("enable_cardboard") == 1; |
| 134 } catch (NameNotFoundException e) { | 165 } catch (NameNotFoundException e) { |
| 135 // Does nothing since by default Cardboard activity is turned off. | 166 // Does nothing since by default Cardboard activity is turned off. |
| 136 } | 167 } |
| 137 | 168 |
| 138 MenuItem item = menu.findItem(R.id.actionbar_cardboard); | 169 MenuItem item = menu.findItem(R.id.actionbar_cardboard); |
| 139 item.setVisible(enableCardboard); | 170 item.setVisible(enableCardboard); |
| 140 | 171 |
| 172 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | |
| 173 // We don't need to show a hide ActionBar button if immersive fullsc reen is supported. | |
| 174 menu.findItem(R.id.actionbar_hide).setVisible(false); | |
| 175 } | |
| 176 | |
| 141 ChromotingUtil.tintMenuIcons(this, menu); | 177 ChromotingUtil.tintMenuIcons(this, menu); |
| 142 | 178 |
| 143 return super.onCreateOptionsMenu(menu); | 179 return super.onCreateOptionsMenu(menu); |
| 144 } | 180 } |
| 145 | 181 |
| 182 // Posts a deplayed task to hide the ActionBar. If an existing task has alr eady been scheduled, | |
| 183 // then the previous task is removed and the new one scheduled, effectively resetting the timer. | |
| 184 private void startActionBarAutoHideTimer() { | |
| 185 if (mActionBarAutoHideTask == null) { | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 stopActionBarAutoHideTimer(); | |
| 190 | |
| 191 View decorView = getWindow().getDecorView(); | |
| 192 decorView.postDelayed(mActionBarAutoHideTask, ACTIONBAR_AUTO_HIDE_DELAY_ MS); | |
| 193 } | |
| 194 | |
| 195 // Clear all existing delayed tasks to prevent the ActionBar from being hidd en. | |
| 196 private void stopActionBarAutoHideTimer() { | |
| 197 if (mActionBarAutoHideTask == null) { | |
| 198 return; | |
| 199 } | |
| 200 | |
| 201 View decorView = getWindow().getDecorView(); | |
|
Lambros
2015/11/02 19:48:54
optional: getWindow().getDecorView().removeCallbac
| |
| 202 decorView.removeCallbacks(mActionBarAutoHideTask); | |
| 203 } | |
| 204 | |
| 146 /** Called whenever the visibility of the system status bar or navigation ba r changes. */ | 205 /** Called whenever the visibility of the system status bar or navigation ba r changes. */ |
| 147 @Override | 206 @Override |
| 148 public void onSystemUiVisibilityChange(int visibility) { | 207 public void onSystemUiVisibilityChange(int visibility) { |
| 149 // Ensure the action-bar's visibility matches that of the system control s. This | 208 // Ensure the action-bar's visibility matches that of the system control s. This |
| 150 // minimizes the number of states the UI can be in, to keep things simpl e for the user. | 209 // minimizes the number of states the UI can be in, to keep things simpl e for the user. |
| 151 | 210 |
| 152 // Determine if the system is in fullscreen/lights-out mode. LOW_PROFILE is needed since | 211 // Determine if the system is in fullscreen/lights-out mode. LOW_PROFILE is needed since |
| 153 // it's the only flag supported in 4.0. But it is not sufficient in itse lf; when | 212 // it's the only flag supported in 4.0. But it is not sufficient in itse lf; when |
| 154 // IMMERSIVE_STICKY mode is used, the system clears this flag (leaving t he FULLSCREEN flag | 213 // IMMERSIVE_STICKY mode is used, the system clears this flag (leaving t he FULLSCREEN flag |
| 155 // set) when the user swipes the edge to reveal the bars temporarily. Wh en this happens, | 214 // set) when the user swipes the edge to reveal the bars temporarily. Wh en this happens, |
| 156 // the action-bar should remain hidden. | 215 // the action-bar should remain hidden. |
| 157 int fullscreenFlags = getSystemUiFlags(); | 216 int fullscreenFlags = getFullscreenFlags(); |
| 158 if ((visibility & fullscreenFlags) != 0) { | 217 if ((visibility & fullscreenFlags) != 0) { |
| 159 hideActionBarWithoutSystemUi(); | 218 hideActionBarWithoutSystemUi(); |
| 160 } else { | 219 } else { |
| 161 showActionBarWithoutSystemUi(); | 220 showActionBarWithoutSystemUi(); |
| 162 } | 221 } |
| 163 } | 222 } |
| 164 | 223 |
| 165 @SuppressLint("InlinedApi") | 224 @SuppressLint("InlinedApi") |
| 166 private int getSystemUiFlags() { | 225 private static int getFullscreenFlags() { |
| 167 int flags = View.SYSTEM_UI_FLAG_LOW_PROFILE; | 226 int flags = View.SYSTEM_UI_FLAG_LOW_PROFILE; |
| 168 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { | 227 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { |
| 169 flags |= View.SYSTEM_UI_FLAG_FULLSCREEN; | 228 flags |= View.SYSTEM_UI_FLAG_FULLSCREEN; |
| 170 } | 229 } |
| 171 return flags; | 230 return flags; |
| 172 } | 231 } |
| 173 | 232 |
| 233 @SuppressLint("InlinedApi") | |
| 234 private static int getImmersiveLayoutFlags() { | |
| 235 int flags = 0; | |
| 236 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | |
| 237 flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; | |
| 238 flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; | |
| 239 flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE; | |
| 240 } | |
| 241 return flags; | |
| 242 } | |
| 243 | |
| 174 public void showActionBar() { | 244 public void showActionBar() { |
| 175 // Request exit from any fullscreen mode. The action-bar controls will b e shown in response | 245 // Request exit from any fullscreen mode. The action-bar controls will b e shown in response |
| 176 // to the SystemUiVisibility notification. The visibility of the action- bar should be tied | 246 // to the SystemUiVisibility notification. The visibility of the action- bar should be tied |
| 177 // to the fullscreen state of the system, so there's no need to explicit ly show it here. | 247 // to the fullscreen state of the system, so there's no need to explicit ly show it here. |
| 178 View decorView = getWindow().getDecorView(); | 248 View decorView = getWindow().getDecorView(); |
| 179 decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); | 249 int flags = View.SYSTEM_UI_FLAG_VISIBLE; |
| 250 flags |= getImmersiveLayoutFlags(); | |
|
Lambros
2015/11/02 19:48:54
optional:
int flags = getImmersiveLayoutFlags() |
| |
| 251 decorView.setSystemUiVisibility(flags); | |
|
Lambros
2015/11/02 19:48:54
optional: remove |decorView| temporary.
| |
| 252 | |
| 253 // The OS will not call onSystemUiVisibilityChange() if the keyboard is visible which means | |
| 254 // our ActionBar will not be visible until then. This check allows us t o work around this | |
| 255 // issue and still allow the system to show the ActionBar normally with the soft keyboard. | |
| 256 if (mSoftInputVisible) { | |
| 257 showActionBarWithoutSystemUi(); | |
| 258 } | |
| 180 } | 259 } |
| 181 | 260 |
| 182 /** Shows the action bar without changing SystemUiVisibility. */ | 261 /** Shows the action bar without changing SystemUiVisibility. */ |
| 183 private void showActionBarWithoutSystemUi() { | 262 private void showActionBarWithoutSystemUi() { |
| 184 getSupportActionBar().show(); | 263 getSupportActionBar().show(); |
| 264 startActionBarAutoHideTimer(); | |
| 185 } | 265 } |
| 186 | 266 |
| 187 @SuppressLint("InlinedApi") | 267 @SuppressLint("InlinedApi") |
| 188 public void hideActionBar() { | 268 public void hideActionBar() { |
| 189 // Request the device to enter fullscreen mode. Don't hide the controls yet, because the | 269 // Request the device to enter fullscreen mode. Don't hide the controls yet, because the |
| 190 // system might not honor the fullscreen request immediately (for exampl e, if the | 270 // system might not honor the fullscreen request immediately (for exampl e, if the |
| 191 // keyboard is visible, the system might delay fullscreen until the keyb oard is hidden). | 271 // keyboard is visible, the system might delay fullscreen until the keyb oard is hidden). |
| 192 // The controls will be hidden in response to the SystemUiVisibility not ification. | 272 // The controls will be hidden in response to the SystemUiVisibility not ification. |
| 193 // This helps ensure that the visibility of the controls is synchronized with the | 273 // This helps ensure that the visibility of the controls is synchronized with the |
| 194 // fullscreen state. | 274 // fullscreen state. |
| 195 View decorView = getWindow().getDecorView(); | 275 View decorView = getWindow().getDecorView(); |
| 196 | 276 |
| 197 // LOW_PROFILE gives the status and navigation bars a "lights-out" appea rance. | 277 // LOW_PROFILE gives the status and navigation bars a "lights-out" appea rance. |
| 198 // FULLSCREEN hides the status bar on supported devices (4.1 and above). | 278 // FULLSCREEN hides the status bar on supported devices (4.1 and above). |
| 199 int flags = getSystemUiFlags(); | 279 int flags = getFullscreenFlags(); |
| 200 | 280 |
| 201 // HIDE_NAVIGATION hides the navigation bar. However, if the user touche s the screen, the | 281 // HIDE_NAVIGATION hides the navigation bar. However, if the user touche s the screen, the |
| 202 // event is not seen by the application and instead the navigation bar i s re-shown. | 282 // event is not seen by the application and instead the navigation bar i s re-shown. |
| 203 // IMMERSIVE(_STICKY) fixes this problem and allows the user to interact with the app while | 283 // IMMERSIVE(_STICKY) fixes this problem and allows the user to interact with the app while |
| 204 // keeping the navigation controls hidden. This flag was introduced in 4 .4, later than | 284 // keeping the navigation controls hidden. This flag was introduced in 4 .4, later than |
| 205 // HIDE_NAVIGATION, and so a runtime check is needed before setting eith er of these flags. | 285 // HIDE_NAVIGATION, and so a runtime check is needed before setting eith er of these flags. |
| 206 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | 286 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| 207 flags |= (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_ IMMERSIVE); | 287 flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; |
| 288 flags |= View.SYSTEM_UI_FLAG_IMMERSIVE; | |
| 289 flags |= getImmersiveLayoutFlags(); | |
| 208 } | 290 } |
| 209 | 291 |
| 210 decorView.setSystemUiVisibility(flags); | 292 decorView.setSystemUiVisibility(flags); |
| 293 | |
| 294 // The OS will not call onSystemUiVisibilityChange() until the keyboard has been dismissed | |
| 295 // which means our ActionBar will still be visible. This check allows u s to work around | |
| 296 // this issue when the keyboard is visible and the user wants additional space on the screen | |
| 297 // and still allow the system to hide the ActionBar normally when no key board is present. | |
| 298 if (mSoftInputVisible) { | |
| 299 hideActionBarWithoutSystemUi(); | |
| 300 } | |
| 211 } | 301 } |
| 212 | 302 |
| 213 /** Hides the action bar without changing SystemUiVisibility. */ | 303 /** Hides the action bar without changing SystemUiVisibility. */ |
| 214 private void hideActionBarWithoutSystemUi() { | 304 private void hideActionBarWithoutSystemUi() { |
| 215 getSupportActionBar().hide(); | 305 getSupportActionBar().hide(); |
| 306 stopActionBarAutoHideTimer(); | |
| 216 } | 307 } |
| 217 | 308 |
| 218 /** Called whenever an action bar button is pressed. */ | 309 /** Called whenever an action bar button is pressed. */ |
| 219 @Override | 310 @Override |
| 220 public boolean onOptionsItemSelected(MenuItem item) { | 311 public boolean onOptionsItemSelected(MenuItem item) { |
| 221 int id = item.getItemId(); | 312 int id = item.getItemId(); |
| 222 | 313 |
| 223 mActivityLifecycleListener.onActivityOptionsItemSelected(this, item); | 314 mActivityLifecycleListener.onActivityOptionsItemSelected(this, item); |
| 224 | 315 |
| 316 // Whenever a user selects an option from the ActionBar, reset the auto- hide timer. | |
| 317 startActionBarAutoHideTimer(); | |
| 318 | |
| 225 if (id == R.id.actionbar_cardboard) { | 319 if (id == R.id.actionbar_cardboard) { |
| 226 onCardboardItemSelected(); | 320 onCardboardItemSelected(); |
| 227 return true; | 321 return true; |
| 228 } | 322 } |
| 229 if (id == R.id.actionbar_keyboard) { | 323 if (id == R.id.actionbar_keyboard) { |
| 230 ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).toggle SoftInput(0, 0); | 324 ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).toggle SoftInput(0, 0); |
| 231 return true; | 325 return true; |
| 232 } | 326 } |
| 233 if (id == R.id.actionbar_hide) { | 327 if (id == R.id.actionbar_hide) { |
| 234 hideActionBar(); | 328 hideActionBar(); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 252 } | 346 } |
| 253 return true; | 347 return true; |
| 254 } | 348 } |
| 255 if (id == R.id.actionbar_help) { | 349 if (id == R.id.actionbar_help) { |
| 256 HelpActivity.launch(this, HELP_URL); | 350 HelpActivity.launch(this, HELP_URL); |
| 257 return true; | 351 return true; |
| 258 } | 352 } |
| 259 return super.onOptionsItemSelected(item); | 353 return super.onOptionsItemSelected(item); |
| 260 } | 354 } |
| 261 | 355 |
| 356 private void attachKeyboardVisibilityListener() { | |
| 357 View keyboardVisibilityDetector = findViewById(R.id.resize_detector); | |
| 358 keyboardVisibilityDetector.addOnLayoutChangeListener(new OnLayoutChangeL istener() { | |
| 359 // Tracks the maximum 'bottom' value seen during layout changes. Th is value represents | |
| 360 // the top of the SystemUI displayed at the bottom of the screen. | |
| 361 // Note: This value is a screen coordinate so a larger value means l ower on the screen. | |
| 362 private int mInitialBottomValue = 0; | |
|
Lambros
2015/11/02 19:48:54
Maybe rename to mMaximumBottomValue ?
Lambros
2015/11/02 19:48:54
optional: remove '= 0', int members are 0 by defau
| |
| 363 | |
| 364 @Override | |
| 365 public void onLayoutChange(View v, int left, int top, int right, int bottom, | |
| 366 int oldLeft, int oldTop, int oldRight, int oldBottom) { | |
| 367 // As the activity is started, a number of layout changes will f low through. If | |
| 368 // this is a fresh start, then we will see one layout change whi ch will represent | |
| 369 // the steady state of the UI and will include an accurate 'bott om' value. If we | |
| 370 // are transitioning from another activity/orientation, then the re may be several | |
| 371 // layout change events as the view is updated (i.e. the OSK mig ht have been | |
| 372 // displayed previously but is being dismissed). Therefore we w ant to track the | |
| 373 // largest value we have seen and use it to determine if a new s ystem UI (such as | |
| 374 // the OSK) is being displayed. | |
| 375 if (mInitialBottomValue < bottom) { | |
| 376 mInitialBottomValue = bottom; | |
| 377 return; | |
| 378 } | |
| 379 | |
| 380 // If the delta between lowest bound we have seen (should be a s ystemUI such as | |
| 381 // the navigation bar) and the current bound does not match, the n we have a form | |
| 382 // of soft input displayed. Note that the size of a soft input device can change | |
| 383 // when the input method is changed so we want to send updates t o the image canvas | |
| 384 // whenever they occur. | |
| 385 mSoftInputVisible = (bottom < mInitialBottomValue); | |
| 386 mRemoteHostDesktop.onSoftInputMethodVisibilityChanged( | |
| 387 mSoftInputVisible, new Rect(left, top, right, bottom)); | |
| 388 } | |
| 389 }); | |
| 390 } | |
| 391 | |
| 262 private void onCardboardItemSelected() { | 392 private void onCardboardItemSelected() { |
| 263 if (getPreferences(MODE_PRIVATE).getBoolean(PREFERENCE_CARDBOARD_DIALOG_ SEEN, false)) { | 393 if (getPreferences(MODE_PRIVATE).getBoolean(PREFERENCE_CARDBOARD_DIALOG_ SEEN, false)) { |
| 264 switchToCardboardMode(); | 394 switchToCardboardMode(); |
| 265 return; | 395 return; |
| 266 } | 396 } |
| 267 | 397 |
| 268 new AlertDialog.Builder(this) | 398 new AlertDialog.Builder(this) |
| 269 .setTitle(getTitle()) | 399 .setTitle(getTitle()) |
| 270 .setMessage(R.string.cardboard_warning_message) | 400 .setMessage(R.string.cardboard_warning_message) |
| 271 .setIcon(R.drawable.ic_cardboard) | 401 .setIcon(R.drawable.ic_cardboard) |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse d); | 505 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse d); |
| 376 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed); | 506 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed); |
| 377 return true; | 507 return true; |
| 378 | 508 |
| 379 default: | 509 default: |
| 380 // We try to send all other key codes to the host directly. | 510 // We try to send all other key codes to the host directly. |
| 381 return JniInterface.sendKeyEvent(0, keyCode, pressed); | 511 return JniInterface.sendKeyEvent(0, keyCode, pressed); |
| 382 } | 512 } |
| 383 } | 513 } |
| 384 } | 514 } |
| OLD | NEW |