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().onActivityA
cceptingListener( |
82 .onActivityAcceptingListener(this, Capabilities.CAST_CAPABILITY); | 96 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 stopActionBarAutoHideTimer(); |
| 187 getWindow().getDecorView().postDelayed( |
| 188 mActionBarAutoHideTask, ACTIONBAR_AUTO_HIDE_DELAY_MS); |
| 189 } |
| 190 } |
| 191 |
| 192 // Clear all existing delayed tasks to prevent the ActionBar from being hidd
en. |
| 193 private void stopActionBarAutoHideTimer() { |
| 194 if (mActionBarAutoHideTask != null) { |
| 195 getWindow().getDecorView().removeCallbacks(mActionBarAutoHideTask); |
| 196 } |
| 197 } |
| 198 |
146 /** Called whenever the visibility of the system status bar or navigation ba
r changes. */ | 199 /** Called whenever the visibility of the system status bar or navigation ba
r changes. */ |
147 @Override | 200 @Override |
148 public void onSystemUiVisibilityChange(int visibility) { | 201 public void onSystemUiVisibilityChange(int visibility) { |
149 // Ensure the action-bar's visibility matches that of the system control
s. This | 202 // 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. | 203 // minimizes the number of states the UI can be in, to keep things simpl
e for the user. |
151 | 204 |
152 // Determine if the system is in fullscreen/lights-out mode. LOW_PROFILE
is needed since | 205 // 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 | 206 // 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 | 207 // 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, | 208 // set) when the user swipes the edge to reveal the bars temporarily. Wh
en this happens, |
156 // the action-bar should remain hidden. | 209 // the action-bar should remain hidden. |
157 int fullscreenFlags = getSystemUiFlags(); | 210 int fullscreenFlags = getFullscreenFlags(); |
158 if ((visibility & fullscreenFlags) != 0) { | 211 if ((visibility & fullscreenFlags) != 0) { |
159 hideActionBarWithoutSystemUi(); | 212 hideActionBarWithoutSystemUi(); |
160 } else { | 213 } else { |
161 showActionBarWithoutSystemUi(); | 214 showActionBarWithoutSystemUi(); |
162 } | 215 } |
163 } | 216 } |
164 | 217 |
165 @SuppressLint("InlinedApi") | 218 @SuppressLint("InlinedApi") |
166 private int getSystemUiFlags() { | 219 private static int getFullscreenFlags() { |
167 int flags = View.SYSTEM_UI_FLAG_LOW_PROFILE; | 220 int flags = View.SYSTEM_UI_FLAG_LOW_PROFILE; |
168 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { | 221 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { |
169 flags |= View.SYSTEM_UI_FLAG_FULLSCREEN; | 222 flags |= View.SYSTEM_UI_FLAG_FULLSCREEN; |
170 } | 223 } |
171 return flags; | 224 return flags; |
172 } | 225 } |
173 | 226 |
| 227 @SuppressLint("InlinedApi") |
| 228 private static int getImmersiveLayoutFlags() { |
| 229 int flags = 0; |
| 230 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
| 231 flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; |
| 232 flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; |
| 233 flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE; |
| 234 } |
| 235 return flags; |
| 236 } |
| 237 |
174 public void showActionBar() { | 238 public void showActionBar() { |
175 // Request exit from any fullscreen mode. The action-bar controls will b
e shown in response | 239 // 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 | 240 // 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. | 241 // to the fullscreen state of the system, so there's no need to explicit
ly show it here. |
178 View decorView = getWindow().getDecorView(); | 242 int flags = View.SYSTEM_UI_FLAG_VISIBLE | getImmersiveLayoutFlags(); |
179 decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); | 243 getWindow().getDecorView().setSystemUiVisibility(flags); |
| 244 |
| 245 // The OS will not call onSystemUiVisibilityChange() if the keyboard is
visible which means |
| 246 // our ActionBar will not be visible until then. This check allows us t
o work around this |
| 247 // issue and still allow the system to show the ActionBar normally with
the soft keyboard. |
| 248 if (mSoftInputVisible) { |
| 249 showActionBarWithoutSystemUi(); |
| 250 } |
180 } | 251 } |
181 | 252 |
182 /** Shows the action bar without changing SystemUiVisibility. */ | 253 /** Shows the action bar without changing SystemUiVisibility. */ |
183 private void showActionBarWithoutSystemUi() { | 254 private void showActionBarWithoutSystemUi() { |
184 getSupportActionBar().show(); | 255 getSupportActionBar().show(); |
| 256 startActionBarAutoHideTimer(); |
185 } | 257 } |
186 | 258 |
187 @SuppressLint("InlinedApi") | 259 @SuppressLint("InlinedApi") |
188 public void hideActionBar() { | 260 public void hideActionBar() { |
189 // Request the device to enter fullscreen mode. Don't hide the controls
yet, because the | 261 // 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 | 262 // 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). | 263 // 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. | 264 // 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 | 265 // This helps ensure that the visibility of the controls is synchronized
with the |
194 // fullscreen state. | 266 // fullscreen state. |
195 View decorView = getWindow().getDecorView(); | |
196 | 267 |
197 // LOW_PROFILE gives the status and navigation bars a "lights-out" appea
rance. | 268 // 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). | 269 // FULLSCREEN hides the status bar on supported devices (4.1 and above). |
199 int flags = getSystemUiFlags(); | 270 int flags = getFullscreenFlags(); |
200 | 271 |
201 // HIDE_NAVIGATION hides the navigation bar. However, if the user touche
s the screen, the | 272 // 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. | 273 // 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 | 274 // 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 | 275 // 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. | 276 // 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) { | 277 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
207 flags |= (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_
IMMERSIVE); | 278 flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; |
| 279 flags |= View.SYSTEM_UI_FLAG_IMMERSIVE; |
| 280 flags |= getImmersiveLayoutFlags(); |
208 } | 281 } |
209 | 282 |
210 decorView.setSystemUiVisibility(flags); | 283 getWindow().getDecorView().setSystemUiVisibility(flags); |
| 284 |
| 285 // The OS will not call onSystemUiVisibilityChange() until the keyboard
has been dismissed |
| 286 // which means our ActionBar will still be visible. This check allows u
s to work around |
| 287 // this issue when the keyboard is visible and the user wants additional
space on the screen |
| 288 // and still allow the system to hide the ActionBar normally when no key
board is present. |
| 289 if (mSoftInputVisible) { |
| 290 hideActionBarWithoutSystemUi(); |
| 291 } |
211 } | 292 } |
212 | 293 |
213 /** Hides the action bar without changing SystemUiVisibility. */ | 294 /** Hides the action bar without changing SystemUiVisibility. */ |
214 private void hideActionBarWithoutSystemUi() { | 295 private void hideActionBarWithoutSystemUi() { |
215 getSupportActionBar().hide(); | 296 getSupportActionBar().hide(); |
| 297 stopActionBarAutoHideTimer(); |
216 } | 298 } |
217 | 299 |
218 /** Called whenever an action bar button is pressed. */ | 300 /** Called whenever an action bar button is pressed. */ |
219 @Override | 301 @Override |
220 public boolean onOptionsItemSelected(MenuItem item) { | 302 public boolean onOptionsItemSelected(MenuItem item) { |
221 int id = item.getItemId(); | 303 int id = item.getItemId(); |
222 | 304 |
223 mActivityLifecycleListener.onActivityOptionsItemSelected(this, item); | 305 mActivityLifecycleListener.onActivityOptionsItemSelected(this, item); |
224 | 306 |
| 307 // Whenever a user selects an option from the ActionBar, reset the auto-
hide timer. |
| 308 startActionBarAutoHideTimer(); |
| 309 |
225 if (id == R.id.actionbar_cardboard) { | 310 if (id == R.id.actionbar_cardboard) { |
226 onCardboardItemSelected(); | 311 onCardboardItemSelected(); |
227 return true; | 312 return true; |
228 } | 313 } |
229 if (id == R.id.actionbar_keyboard) { | 314 if (id == R.id.actionbar_keyboard) { |
230 ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).toggle
SoftInput(0, 0); | 315 ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).toggle
SoftInput(0, 0); |
231 return true; | 316 return true; |
232 } | 317 } |
233 if (id == R.id.actionbar_hide) { | 318 if (id == R.id.actionbar_hide) { |
234 hideActionBar(); | 319 hideActionBar(); |
(...skipping 17 matching lines...) Expand all Loading... |
252 } | 337 } |
253 return true; | 338 return true; |
254 } | 339 } |
255 if (id == R.id.actionbar_help) { | 340 if (id == R.id.actionbar_help) { |
256 HelpActivity.launch(this, HELP_URL); | 341 HelpActivity.launch(this, HELP_URL); |
257 return true; | 342 return true; |
258 } | 343 } |
259 return super.onOptionsItemSelected(item); | 344 return super.onOptionsItemSelected(item); |
260 } | 345 } |
261 | 346 |
| 347 private void attachKeyboardVisibilityListener() { |
| 348 View keyboardVisibilityDetector = findViewById(R.id.resize_detector); |
| 349 keyboardVisibilityDetector.addOnLayoutChangeListener(new OnLayoutChangeL
istener() { |
| 350 // Tracks the maximum 'bottom' value seen during layout changes. Th
is value represents |
| 351 // the top of the SystemUI displayed at the bottom of the screen. |
| 352 // Note: This value is a screen coordinate so a larger value means l
ower on the screen. |
| 353 private int mMaxBottomValue; |
| 354 |
| 355 @Override |
| 356 public void onLayoutChange(View v, int left, int top, int right, int
bottom, |
| 357 int oldLeft, int oldTop, int oldRight, int oldBottom) { |
| 358 // As the activity is started, a number of layout changes will f
low through. If |
| 359 // this is a fresh start, then we will see one layout change whi
ch will represent |
| 360 // the steady state of the UI and will include an accurate 'bott
om' value. If we |
| 361 // are transitioning from another activity/orientation, then the
re may be several |
| 362 // layout change events as the view is updated (i.e. the OSK mig
ht have been |
| 363 // displayed previously but is being dismissed). Therefore we w
ant to track the |
| 364 // largest value we have seen and use it to determine if a new s
ystem UI (such as |
| 365 // the OSK) is being displayed. |
| 366 if (mMaxBottomValue < bottom) { |
| 367 mMaxBottomValue = bottom; |
| 368 return; |
| 369 } |
| 370 |
| 371 // If the delta between lowest bound we have seen (should be a s
ystemUI such as |
| 372 // the navigation bar) and the current bound does not match, the
n we have a form |
| 373 // of soft input displayed. Note that the size of a soft input
device can change |
| 374 // when the input method is changed so we want to send updates t
o the image canvas |
| 375 // whenever they occur. |
| 376 mSoftInputVisible = (bottom < mMaxBottomValue); |
| 377 mRemoteHostDesktop.onSoftInputMethodVisibilityChanged( |
| 378 mSoftInputVisible, new Rect(left, top, right, bottom)); |
| 379 } |
| 380 }); |
| 381 } |
| 382 |
262 private void onCardboardItemSelected() { | 383 private void onCardboardItemSelected() { |
263 if (getPreferences(MODE_PRIVATE).getBoolean(PREFERENCE_CARDBOARD_DIALOG_
SEEN, false)) { | 384 if (getPreferences(MODE_PRIVATE).getBoolean(PREFERENCE_CARDBOARD_DIALOG_
SEEN, false)) { |
264 switchToCardboardMode(); | 385 switchToCardboardMode(); |
265 return; | 386 return; |
266 } | 387 } |
267 | 388 |
268 new AlertDialog.Builder(this) | 389 new AlertDialog.Builder(this) |
269 .setTitle(getTitle()) | 390 .setTitle(getTitle()) |
270 .setMessage(R.string.cardboard_warning_message) | 391 .setMessage(R.string.cardboard_warning_message) |
271 .setIcon(R.drawable.ic_cardboard) | 392 .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); | 496 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, presse
d); |
376 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed); | 497 JniInterface.sendKeyEvent(0, KeyEvent.KEYCODE_EQUALS, pressed); |
377 return true; | 498 return true; |
378 | 499 |
379 default: | 500 default: |
380 // We try to send all other key codes to the host directly. | 501 // We try to send all other key codes to the host directly. |
381 return JniInterface.sendKeyEvent(0, keyCode, pressed); | 502 return JniInterface.sendKeyEvent(0, keyCode, pressed); |
382 } | 503 } |
383 } | 504 } |
384 } | 505 } |
OLD | NEW |