| 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.content.res.Configuration; | 8 import android.content.res.Configuration; |
| 9 import android.os.Build; | 9 import android.os.Build; |
| 10 import android.os.Bundle; | 10 import android.os.Bundle; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 private DesktopView mRemoteHostDesktop; | 86 private DesktopView mRemoteHostDesktop; |
| 87 | 87 |
| 88 /** | 88 /** |
| 89 * Indicates whether the device is connected to a non-hidden physical qwerty
keyboard. This is | 89 * Indicates whether the device is connected to a non-hidden physical qwerty
keyboard. This is |
| 90 * set by {@link Desktop#setKeyboardState(Configuration)}. DO NOT request a
soft keyboard when a | 90 * set by {@link Desktop#setKeyboardState(Configuration)}. DO NOT request a
soft keyboard when a |
| 91 * physical keyboard exists, otherwise the activity will enter an undefined
state where the soft | 91 * physical keyboard exists, otherwise the activity will enter an undefined
state where the soft |
| 92 * keyboard never shows up meanwhile request to hide status bar always fails
. | 92 * keyboard never shows up meanwhile request to hide status bar always fails
. |
| 93 */ | 93 */ |
| 94 private boolean mHasPhysicalKeyboard; | 94 private boolean mHasPhysicalKeyboard; |
| 95 | 95 |
| 96 /** Tracks whether the activity is in the resumed (running) state. */ |
| 97 private boolean mIsActivityRunning = false; |
| 98 |
| 96 /** Called when the activity is first created. */ | 99 /** Called when the activity is first created. */ |
| 97 @Override | 100 @Override |
| 98 public void onCreate(Bundle savedInstanceState) { | 101 public void onCreate(Bundle savedInstanceState) { |
| 99 super.onCreate(savedInstanceState); | 102 super.onCreate(savedInstanceState); |
| 100 setContentView(R.layout.desktop); | 103 setContentView(R.layout.desktop); |
| 101 | 104 |
| 102 mClient = Client.getInstance(); | 105 mClient = Client.getInstance(); |
| 103 mInjector = new InputEventSender(mClient); | 106 mInjector = new InputEventSender(mClient); |
| 104 | 107 |
| 105 Preconditions.notNull(mClient); | 108 Preconditions.notNull(mClient); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 125 View decorView = getWindow().getDecorView(); | 128 View decorView = getWindow().getDecorView(); |
| 126 decorView.setOnSystemUiVisibilityChangeListener(this); | 129 decorView.setOnSystemUiVisibilityChangeListener(this); |
| 127 | 130 |
| 128 mActivityLifecycleListener = mClient.getCapabilityManager().onActivityAc
ceptingListener( | 131 mActivityLifecycleListener = mClient.getCapabilityManager().onActivityAc
ceptingListener( |
| 129 this, Capabilities.CAST_CAPABILITY); | 132 this, Capabilities.CAST_CAPABILITY); |
| 130 mActivityLifecycleListener.onActivityCreated(this, savedInstanceState); | 133 mActivityLifecycleListener.onActivityCreated(this, savedInstanceState); |
| 131 | 134 |
| 132 mInputMode = getInitialInputModeValue(); | 135 mInputMode = getInitialInputModeValue(); |
| 133 | 136 |
| 134 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | 137 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| 135 attachKeyboardVisibilityListener(); | 138 attachSystemUiResizeListener(); |
| 136 | |
| 137 // Only create an Autohide task if the system supports immersive ful
lscreen mode. Older | |
| 138 // versions of the OS benefit less from this functionality and we do
n't want to change | |
| 139 // the experience for them. | |
| 140 mActionBarAutoHideTask = new Runnable() { | |
| 141 public void run() { | |
| 142 if (!mToolbar.isOverflowMenuShowing()) { | |
| 143 hideSystemUi(); | |
| 144 } | |
| 145 } | |
| 146 }; | |
| 147 | |
| 148 // Suspend the ActionBar timer when the user interacts with the opti
ons menu. | |
| 149 getSupportActionBar().addOnMenuVisibilityListener(new OnMenuVisibili
tyListener() { | |
| 150 public void onMenuVisibilityChanged(boolean isVisible) { | |
| 151 if (isVisible) { | |
| 152 stopActionBarAutoHideTimer(); | |
| 153 } else { | |
| 154 startActionBarAutoHideTimer(); | |
| 155 } | |
| 156 } | |
| 157 }); | |
| 158 } else { | 139 } else { |
| 159 mRemoteHostDesktop.setFitsSystemWindows(true); | 140 mRemoteHostDesktop.setFitsSystemWindows(true); |
| 160 } | 141 } |
| 161 } | 142 } |
| 162 | 143 |
| 163 @Override | 144 @Override |
| 164 protected void onStart() { | 145 protected void onStart() { |
| 165 super.onStart(); | 146 super.onStart(); |
| 166 mActivityLifecycleListener.onActivityStarted(this); | 147 mActivityLifecycleListener.onActivityStarted(this); |
| 167 mClient.enableVideoChannel(true); | 148 mClient.enableVideoChannel(true); |
| 168 mClient.getCapabilityManager().addListener(this); | 149 mClient.getCapabilityManager().addListener(this); |
| 169 } | 150 } |
| 170 | 151 |
| 171 @Override | 152 @Override |
| 153 public void onResume() { |
| 154 mIsActivityRunning = true; |
| 155 super.onResume(); |
| 156 mActivityLifecycleListener.onActivityResumed(this); |
| 157 mClient.enableVideoChannel(true); |
| 158 if (!inWindowedMode()) { |
| 159 setUpAutoHideToolbar(); |
| 160 syncActionBarToSystemUiState(); |
| 161 } |
| 162 } |
| 163 |
| 164 @Override |
| 172 protected void onPause() { | 165 protected void onPause() { |
| 173 if (isFinishing()) mActivityLifecycleListener.onActivityPaused(this); | 166 if (isFinishing()) mActivityLifecycleListener.onActivityPaused(this); |
| 174 super.onPause(); | 167 super.onPause(); |
| 175 mClient.enableVideoChannel(false); | 168 // The activity is paused in windowed mode when the user switches to ano
ther window. In |
| 169 // that case we should leave the video channel running so they continue
to see updates from |
| 170 // their remote machine. The video channel will be stopped when onStop(
) is called. |
| 171 if (!inWindowedMode()) { |
| 172 mClient.enableVideoChannel(false); |
| 173 } |
| 176 stopActionBarAutoHideTimer(); | 174 stopActionBarAutoHideTimer(); |
| 175 mIsActivityRunning = false; |
| 177 } | 176 } |
| 178 | 177 |
| 179 @Override | 178 @Override |
| 180 public void onResume() { | |
| 181 super.onResume(); | |
| 182 mActivityLifecycleListener.onActivityResumed(this); | |
| 183 mClient.enableVideoChannel(true); | |
| 184 syncActionBarToSystemUiState(); | |
| 185 } | |
| 186 | |
| 187 @Override | |
| 188 protected void onStop() { | 179 protected void onStop() { |
| 189 mClient.getCapabilityManager().removeListener(this); | 180 mClient.getCapabilityManager().removeListener(this); |
| 190 mActivityLifecycleListener.onActivityStopped(this); | 181 mActivityLifecycleListener.onActivityStopped(this); |
| 191 super.onStop(); | 182 super.onStop(); |
| 192 mClient.enableVideoChannel(false); | 183 mClient.enableVideoChannel(false); |
| 193 } | 184 } |
| 194 | 185 |
| 195 @Override | 186 @Override |
| 196 protected void onDestroy() { | 187 protected void onDestroy() { |
| 197 mRemoteHostDesktop.destroy(); | 188 mRemoteHostDesktop.destroy(); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 default: | 329 default: |
| 339 // Ignore. | 330 // Ignore. |
| 340 break; | 331 break; |
| 341 } | 332 } |
| 342 | 333 |
| 343 return false; | 334 return false; |
| 344 } | 335 } |
| 345 }); | 336 }); |
| 346 } | 337 } |
| 347 | 338 |
| 339 private Boolean inWindowedMode() { |
| 340 // NOTE: This method should only be called after OnResume() is called, o
therwise |
| 341 // isInMultiWindowMode() may not be accurate. The value returned by thi
s method is updated |
| 342 // on a background thread and there is a race-condition between when the
UX changes and this |
| 343 // value is updated. Hence, calling this method from onCreate() is not
safe and we need to |
| 344 // be careful when we query this value. |
| 345 Preconditions.isTrue(mIsActivityRunning); |
| 346 |
| 347 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInMultiWindow
Mode(); |
| 348 } |
| 349 |
| 350 private void setUpAutoHideToolbar() { |
| 351 // Configure the auto-hiding taskbar if the activity is not in multi-win
dow mode and the |
| 352 // application is run on an OS which supports fullscreen mode (KitKat or
higher). |
| 353 Preconditions.isTrue(!inWindowedMode()); |
| 354 if (mActionBarAutoHideTask != null || Build.VERSION.SDK_INT < Build.VERS
ION_CODES.KITKAT) { |
| 355 return; |
| 356 } |
| 357 |
| 358 mActionBarAutoHideTask = new Runnable() { |
| 359 public void run() { |
| 360 if (!mToolbar.isOverflowMenuShowing()) { |
| 361 hideSystemUi(); |
| 362 } |
| 363 } |
| 364 }; |
| 365 |
| 366 // Suspend the ActionBar timer when the user interacts with the options
menu. |
| 367 getSupportActionBar().addOnMenuVisibilityListener(new OnMenuVisibilityLi
stener() { |
| 368 public void onMenuVisibilityChanged(boolean isVisible) { |
| 369 if (isVisible) { |
| 370 stopActionBarAutoHideTimer(); |
| 371 } else { |
| 372 startActionBarAutoHideTimer(); |
| 373 } |
| 374 } |
| 375 }); |
| 376 } |
| 377 |
| 348 // Posts a deplayed task to hide the ActionBar. If an existing task has alr
eady been scheduled, | 378 // Posts a deplayed task to hide the ActionBar. If an existing task has alr
eady been scheduled, |
| 349 // then the previous task is removed and the new one scheduled, effectively
resetting the timer. | 379 // then the previous task is removed and the new one scheduled, effectively
resetting the timer. |
| 350 private void startActionBarAutoHideTimer() { | 380 private void startActionBarAutoHideTimer() { |
| 351 if (mActionBarAutoHideTask != null) { | 381 if (mActionBarAutoHideTask != null) { |
| 352 stopActionBarAutoHideTimer(); | 382 stopActionBarAutoHideTimer(); |
| 353 getWindow().getDecorView().postDelayed( | 383 getWindow().getDecorView().postDelayed( |
| 354 mActionBarAutoHideTask, ACTIONBAR_AUTO_HIDE_DELAY_MS); | 384 mActionBarAutoHideTask, ACTIONBAR_AUTO_HIDE_DELAY_MS); |
| 355 } | 385 } |
| 356 } | 386 } |
| 357 | 387 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 mInjector.sendCtrlAltDel(); | 551 mInjector.sendCtrlAltDel(); |
| 522 return true; | 552 return true; |
| 523 } | 553 } |
| 524 if (id == R.id.actionbar_help) { | 554 if (id == R.id.actionbar_help) { |
| 525 HelpSingleton.getInstance().launchHelp(this, HelpContext.DESKTOP); | 555 HelpSingleton.getInstance().launchHelp(this, HelpContext.DESKTOP); |
| 526 return true; | 556 return true; |
| 527 } | 557 } |
| 528 return super.onOptionsItemSelected(item); | 558 return super.onOptionsItemSelected(item); |
| 529 } | 559 } |
| 530 | 560 |
| 531 private void attachKeyboardVisibilityListener() { | 561 private void attachSystemUiResizeListener() { |
| 532 View keyboardVisibilityDetector = findViewById(R.id.resize_detector); | 562 View systemUiResizeDetector = findViewById(R.id.resize_detector); |
| 533 keyboardVisibilityDetector.addOnLayoutChangeListener(new OnLayoutChangeL
istener() { | 563 systemUiResizeDetector.addOnLayoutChangeListener(new OnLayoutChangeListe
ner() { |
| 534 // Tracks the maximum 'bottom' value seen during layout changes. Th
is value represents | 564 // Tracks the maximum 'bottom' value seen during layout changes. Th
is value represents |
| 535 // the top of the SystemUI displayed at the bottom of the screen. | 565 // the top of the SystemUI displayed at the bottom of the screen. |
| 536 // Note: This value is a screen coordinate so a larger value means l
ower on the screen. | 566 // Note: This value is a screen coordinate so a larger value means l
ower on the screen. |
| 537 private int mMaxBottomValue; | 567 private int mMaxBottomValue; |
| 538 | 568 |
| 539 @Override | 569 @Override |
| 540 public void onLayoutChange(View v, int left, int top, int right, int
bottom, | 570 public void onLayoutChange(View v, int left, int top, int right, int
bottom, |
| 541 int oldLeft, int oldTop, int oldRight, int oldBottom) { | 571 int oldLeft, int oldTop, int oldRight, int oldBottom) { |
| 542 // As the activity is started, a number of layout changes will f
low through. If | 572 // As the activity is started, a number of layout changes will f
low through. If |
| 543 // this is a fresh start, then we will see one layout change whi
ch will represent | 573 // this is a fresh start, then we will see one layout change whi
ch will represent |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 @Override | 617 @Override |
| 588 public boolean dispatchKeyEvent(KeyEvent event) { | 618 public boolean dispatchKeyEvent(KeyEvent event) { |
| 589 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { | 619 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { |
| 590 mClient.destroy(); | 620 mClient.destroy(); |
| 591 return super.dispatchKeyEvent(event); | 621 return super.dispatchKeyEvent(event); |
| 592 } | 622 } |
| 593 | 623 |
| 594 return mInjector.sendKeyEvent(event); | 624 return mInjector.sendKeyEvent(event); |
| 595 } | 625 } |
| 596 } | 626 } |
| OLD | NEW |