packages/apps/AndroidTerm
リビジョン | c5b4ec402fb96f1df1e83e22cef16785035aae90 (tree) |
---|---|
日時 | 2012-03-26 10:21:48 |
作者 | Steven Luo <steven+android@stev...> |
コミッター | Jack Palevich |
Revise screen resize check handling
Move the screen resize check code out of EmulatorView and into
TermViewFlipper, where it logically fits now that there are multiple
EmulatorViews per Term activity. While we're at it, instead of making
the activity tell us how much of the window doesn't belong to us, use
getGlobalVisibleRect() to figure that out ourselves, eliminating the
need for a WindowSizeCallback.
Signed-off-by: Jack Palevich <jackpal@google.com>
@@ -39,7 +39,6 @@ import android.view.KeyCharacterMap; | ||
39 | 39 | import android.view.KeyEvent; |
40 | 40 | import android.view.MotionEvent; |
41 | 41 | import android.view.View; |
42 | -import android.view.ViewGroup.LayoutParams; | |
43 | 42 | import android.view.inputmethod.CompletionInfo; |
44 | 43 | import android.view.inputmethod.CorrectionInfo; |
45 | 44 | import android.view.inputmethod.EditorInfo; |
@@ -75,7 +74,6 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
75 | 74 | |
76 | 75 | private int mVisibleWidth; |
77 | 76 | private int mVisibleHeight; |
78 | - private Rect mVisibleRect = new Rect(); | |
79 | 77 | |
80 | 78 | private TermSession mTermSession; |
81 | 79 |
@@ -163,8 +161,6 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
163 | 161 | |
164 | 162 | private static final int CURSOR_BLINK_PERIOD = 1000; |
165 | 163 | |
166 | - private static final int SCREEN_CHECK_PERIOD = 1000; | |
167 | - | |
168 | 164 | private boolean mCursorVisible = true; |
169 | 165 | |
170 | 166 | private boolean mIsSelectingText = false; |
@@ -186,22 +182,6 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
186 | 182 | |
187 | 183 | private boolean mIsActive = false; |
188 | 184 | |
189 | - /** | |
190 | - * True if we must poll to discover if the view has changed size. | |
191 | - * This is the only known way to detect the view changing size due to | |
192 | - * the IME being shown or hidden in API level <= 7. | |
193 | - */ | |
194 | - private boolean mbPollForWindowSizeChange = AndroidCompat.SDK <= 7; | |
195 | - | |
196 | - private Runnable mCheckSize = mbPollForWindowSizeChange | |
197 | - ? new Runnable() { | |
198 | - public void run() { | |
199 | - updateSize(false); | |
200 | - mHandler.postDelayed(this, SCREEN_CHECK_PERIOD); | |
201 | - } | |
202 | - } | |
203 | - : null; | |
204 | - | |
205 | 185 | private Runnable mBlinkCursor = new Runnable() { |
206 | 186 | public void run() { |
207 | 187 | if (mCursorBlink != 0) { |
@@ -215,21 +195,13 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
215 | 195 | } |
216 | 196 | }; |
217 | 197 | |
218 | - private boolean mRedoLayout = false; | |
219 | - | |
220 | 198 | private GestureDetector mGestureDetector; |
221 | 199 | private GestureDetector.OnGestureListener mExtGestureListener; |
222 | 200 | private float mScrollRemainder; |
223 | 201 | private TermKeyListener mKeyListener; |
224 | - private WindowSizeCallback mSizeCallback; | |
225 | 202 | |
226 | 203 | private String mImeBuffer = ""; |
227 | 204 | |
228 | - // Used by activity to inform us how much of the window belongs to us | |
229 | - public interface WindowSizeCallback { | |
230 | - public abstract void onGetSize(Rect rect); | |
231 | - } | |
232 | - | |
233 | 205 | /** |
234 | 206 | * Our message handler class. Implements a periodic callback. |
235 | 207 | */ |
@@ -266,18 +238,12 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
266 | 238 | public void onResume() { |
267 | 239 | mIsActive = true; |
268 | 240 | updateSize(false); |
269 | - if (mbPollForWindowSizeChange) { | |
270 | - mHandler.postDelayed(mCheckSize, SCREEN_CHECK_PERIOD); | |
271 | - } | |
272 | 241 | if (mCursorBlink != 0) { |
273 | 242 | mHandler.postDelayed(mBlinkCursor, CURSOR_BLINK_PERIOD); |
274 | 243 | } |
275 | 244 | } |
276 | 245 | |
277 | 246 | public void onPause() { |
278 | - if (mbPollForWindowSizeChange) { | |
279 | - mHandler.removeCallbacks(mCheckSize); | |
280 | - } | |
281 | 247 | if (mCursorBlink != 0) { |
282 | 248 | mHandler.removeCallbacks(mBlinkCursor); |
283 | 249 | } |
@@ -628,10 +594,6 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
628 | 594 | mKeyListener = new TermKeyListener(session); |
629 | 595 | } |
630 | 596 | |
631 | - public void setWindowSizeCallback(WindowSizeCallback callback) { | |
632 | - mSizeCallback = callback; | |
633 | - } | |
634 | - | |
635 | 597 | public void setExtGestureListener(GestureDetector.OnGestureListener listener) { |
636 | 598 | mExtGestureListener = listener; |
637 | 599 | } |
@@ -988,53 +950,20 @@ public class EmulatorView extends View implements GestureDetector.OnGestureListe | ||
988 | 950 | |
989 | 951 | public void updateSize(boolean force) { |
990 | 952 | if (mKnownSize) { |
991 | - getWindowVisibleDisplayFrame(mVisibleRect); | |
992 | - /* Work around bug in getWindowVisibleDisplayFrame, and avoid | |
993 | - distracting visual glitch otherwise */ | |
994 | - if (!mSettings.showStatusBar()) { | |
995 | - mVisibleRect.top = 0; | |
996 | - } | |
997 | - if (mSizeCallback != null) { | |
998 | - // Let activity adjust our size | |
999 | - mSizeCallback.onGetSize(mVisibleRect); | |
1000 | - } | |
1001 | - int w = mVisibleRect.width(); | |
1002 | - int h = mVisibleRect.height(); | |
953 | + int w = getWidth(); | |
954 | + int h = getHeight(); | |
1003 | 955 | // Log.w("Term", "(" + w + ", " + h + ")"); |
1004 | 956 | if (force || w != mVisibleWidth || h != mVisibleHeight) { |
1005 | 957 | mVisibleWidth = w; |
1006 | 958 | mVisibleHeight = h; |
1007 | - | |
1008 | - LayoutParams params = getLayoutParams(); | |
1009 | - params.width = w; | |
1010 | - params.height = h; | |
1011 | - setLayoutParams(params); | |
1012 | - mRedoLayout = true; | |
1013 | - | |
1014 | 959 | updateSize(mVisibleWidth, mVisibleHeight); |
1015 | 960 | } |
1016 | 961 | } |
1017 | 962 | } |
1018 | 963 | |
1019 | - /** | |
1020 | - * Called when the view changes size. | |
1021 | - * (Note: Not always called on Android 1.5 or Android 1.6) | |
1022 | - */ | |
1023 | - @Override | |
1024 | - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
1025 | - super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
1026 | - if (mIsActive) { | |
1027 | - updateSize(false); | |
1028 | - } | |
1029 | - } | |
1030 | - | |
1031 | 964 | @Override |
1032 | 965 | protected void onDraw(Canvas canvas) { |
1033 | 966 | updateSize(false); |
1034 | - if (mRedoLayout) { | |
1035 | - requestLayout(); | |
1036 | - mRedoLayout = false; | |
1037 | - } | |
1038 | 967 | |
1039 | 968 | if (mEmulator == null) { |
1040 | 969 | // Not ready yet |
@@ -203,14 +203,6 @@ public class Term extends Activity implements UpdateCallback { | ||
203 | 203 | } |
204 | 204 | } |
205 | 205 | |
206 | - private EmulatorView.WindowSizeCallback mSizeCallback = new EmulatorView.WindowSizeCallback() { | |
207 | - public void onGetSize(Rect rect) { | |
208 | - if (mActionBarMode == TermSettings.ACTION_BAR_MODE_ALWAYS_VISIBLE) { | |
209 | - // Fixed action bar takes space away from the EmulatorView | |
210 | - rect.top += mActionBar.getHeight(); | |
211 | - } | |
212 | - } | |
213 | - }; | |
214 | 206 | private View.OnKeyListener mBackKeyListener = new View.OnKeyListener() { |
215 | 207 | public boolean onKey(View v, int keyCode, KeyEvent event) { |
216 | 208 | if (keyCode == KeyEvent.KEYCODE_BACK && mActionBarMode == TermSettings.ACTION_BAR_MODE_HIDES && mActionBar.isShowing()) { |
@@ -349,15 +341,7 @@ public class Term extends Activity implements UpdateCallback { | ||
349 | 341 | getWindowManager().getDefaultDisplay().getMetrics(metrics); |
350 | 342 | EmulatorView emulatorView = new EmulatorView(this, session, metrics); |
351 | 343 | |
352 | - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( | |
353 | - FrameLayout.LayoutParams.WRAP_CONTENT, | |
354 | - FrameLayout.LayoutParams.WRAP_CONTENT, | |
355 | - Gravity.LEFT | |
356 | - ); | |
357 | - emulatorView.setLayoutParams(params); | |
358 | - | |
359 | 344 | emulatorView.setExtGestureListener(new EmulatorViewGestureListener(emulatorView)); |
360 | - emulatorView.setWindowSizeCallback(mSizeCallback); | |
361 | 345 | emulatorView.setOnKeyListener(mBackKeyListener); |
362 | 346 | registerForContextMenu(emulatorView); |
363 | 347 |
@@ -435,16 +419,15 @@ public class Term extends Activity implements UpdateCallback { | ||
435 | 419 | if (onResumeSelectWindow >= 0) { |
436 | 420 | mViewFlipper.setDisplayedChild(onResumeSelectWindow); |
437 | 421 | onResumeSelectWindow = -1; |
438 | - } else { | |
439 | - mViewFlipper.resumeCurrentView(); | |
440 | 422 | } |
423 | + mViewFlipper.onResume(); | |
441 | 424 | } |
442 | 425 | |
443 | 426 | @Override |
444 | 427 | public void onPause() { |
445 | 428 | super.onPause(); |
446 | 429 | |
447 | - mViewFlipper.pauseCurrentView(); | |
430 | + mViewFlipper.onPause(); | |
448 | 431 | if (mTermSessions != null) { |
449 | 432 | mTermSessions.removeCallback(this); |
450 | 433 | if (mWinListAdapter != null) { |
@@ -486,7 +469,7 @@ public class Term extends Activity implements UpdateCallback { | ||
486 | 469 | |
487 | 470 | EmulatorView v = (EmulatorView) mViewFlipper.getCurrentView(); |
488 | 471 | if (v != null) { |
489 | - v.updateSize(true); | |
472 | + v.updateSize(false); | |
490 | 473 | } |
491 | 474 | |
492 | 475 | if (mWinListAdapter != null) { |
@@ -20,12 +20,16 @@ import java.util.Iterator; | ||
20 | 20 | import java.util.LinkedList; |
21 | 21 | |
22 | 22 | import android.content.Context; |
23 | +import android.graphics.Canvas; | |
24 | +import android.graphics.Rect; | |
25 | +import android.os.Handler; | |
23 | 26 | import android.util.AttributeSet; |
24 | 27 | import android.view.Gravity; |
25 | 28 | import android.view.View; |
26 | 29 | import android.widget.Toast; |
27 | 30 | import android.widget.ViewFlipper; |
28 | 31 | |
32 | +import jackpal.androidterm.compat.AndroidCompat; | |
29 | 33 | import jackpal.androidterm.model.UpdateCallback; |
30 | 34 | import jackpal.androidterm.util.TermSettings; |
31 | 35 |
@@ -33,6 +37,29 @@ public class TermViewFlipper extends ViewFlipper implements Iterable<View> { | ||
33 | 37 | private Context context; |
34 | 38 | private Toast mToast; |
35 | 39 | private LinkedList<UpdateCallback> callbacks; |
40 | + private boolean mStatusBarVisible = false; | |
41 | + | |
42 | + private int mCurWidth; | |
43 | + private int mCurHeight; | |
44 | + private Rect mVisibleRect = new Rect(); | |
45 | + private Rect mWindowRect = new Rect(); | |
46 | + private LayoutParams mChildParams = null; | |
47 | + private boolean mRedoLayout = false; | |
48 | + | |
49 | + /** | |
50 | + * True if we must poll to discover if the view has changed size. | |
51 | + * This is the only known way to detect the view changing size due to | |
52 | + * the IME being shown or hidden in API level <= 7. | |
53 | + */ | |
54 | + private boolean mbPollForWindowSizeChange = false; | |
55 | + private static final int SCREEN_CHECK_PERIOD = 1000; | |
56 | + private final Handler mHandler = new Handler(); | |
57 | + private Runnable mCheckSize = new Runnable() { | |
58 | + public void run() { | |
59 | + adjustChildSize(); | |
60 | + mHandler.postDelayed(this, SCREEN_CHECK_PERIOD); | |
61 | + } | |
62 | + }; | |
36 | 63 | |
37 | 64 | class ViewFlipperIterator implements Iterator<View> { |
38 | 65 | int pos = 0; |
@@ -52,19 +79,32 @@ public class TermViewFlipper extends ViewFlipper implements Iterable<View> { | ||
52 | 79 | |
53 | 80 | public TermViewFlipper(Context context) { |
54 | 81 | super(context); |
55 | - this.context = context; | |
56 | - callbacks = new LinkedList<UpdateCallback>(); | |
82 | + commonConstructor(context); | |
57 | 83 | } |
58 | 84 | |
59 | 85 | public TermViewFlipper(Context context, AttributeSet attrs) { |
60 | 86 | super(context, attrs); |
87 | + commonConstructor(context); | |
88 | + } | |
89 | + | |
90 | + private void commonConstructor(Context context) { | |
61 | 91 | this.context = context; |
62 | 92 | callbacks = new LinkedList<UpdateCallback>(); |
93 | + | |
94 | + updateVisibleRect(); | |
95 | + Rect visible = mVisibleRect; | |
96 | + mChildParams = new LayoutParams(visible.width(), visible.height(), | |
97 | + Gravity.TOP|Gravity.LEFT); | |
63 | 98 | } |
64 | 99 | |
65 | 100 | public void updatePrefs(TermSettings settings) { |
101 | + mStatusBarVisible = settings.showStatusBar(); | |
66 | 102 | int[] colorScheme = settings.getColorScheme(); |
67 | 103 | setBackgroundColor(colorScheme[3]); |
104 | + | |
105 | + if (AndroidCompat.SDK < 8) { | |
106 | + mbPollForWindowSizeChange = !mStatusBarVisible; | |
107 | + } | |
68 | 108 | } |
69 | 109 | |
70 | 110 | public Iterator<View> iterator() { |
@@ -85,6 +125,20 @@ public class TermViewFlipper extends ViewFlipper implements Iterable<View> { | ||
85 | 125 | } |
86 | 126 | } |
87 | 127 | |
128 | + public void onPause() { | |
129 | + if (mbPollForWindowSizeChange) { | |
130 | + mHandler.removeCallbacks(mCheckSize); | |
131 | + } | |
132 | + pauseCurrentView(); | |
133 | + } | |
134 | + | |
135 | + public void onResume() { | |
136 | + if (mbPollForWindowSizeChange) { | |
137 | + mCheckSize.run(); | |
138 | + } | |
139 | + resumeCurrentView(); | |
140 | + } | |
141 | + | |
88 | 142 | public void pauseCurrentView() { |
89 | 143 | EmulatorView view = (EmulatorView) getCurrentView(); |
90 | 144 | if (view == null) { |
@@ -141,4 +195,95 @@ public class TermViewFlipper extends ViewFlipper implements Iterable<View> { | ||
141 | 195 | resumeCurrentView(); |
142 | 196 | notifyChange(); |
143 | 197 | } |
198 | + | |
199 | + @Override | |
200 | + public void addView(View v, int index) { | |
201 | + super.addView(v, index, mChildParams); | |
202 | + } | |
203 | + | |
204 | + @Override | |
205 | + public void addView(View v) { | |
206 | + super.addView(v, mChildParams); | |
207 | + } | |
208 | + | |
209 | + private void updateVisibleRect() { | |
210 | + Rect visible = mVisibleRect; | |
211 | + Rect window = mWindowRect; | |
212 | + | |
213 | + /* Get rectangle representing visible area of this view, as seen by | |
214 | + the activity (takes other views in the layout into account, but | |
215 | + not space used by the IME) */ | |
216 | + getGlobalVisibleRect(visible); | |
217 | + | |
218 | + /* Get rectangle representing visible area of this window (takes | |
219 | + IME into account, but not other views in the layout) */ | |
220 | + getWindowVisibleDisplayFrame(window); | |
221 | + /* Work around bug in getWindowVisibleDisplayFrame on API < 10, and | |
222 | + avoid a distracting height change as status bar hides otherwise */ | |
223 | + if (!mStatusBarVisible) { | |
224 | + window.top = 0; | |
225 | + } | |
226 | + | |
227 | + // Clip visible rectangle's top to the visible portion of the window | |
228 | + if (visible.width() == 0 && visible.height() == 0) { | |
229 | + visible.left = window.left; | |
230 | + visible.top = window.top; | |
231 | + } else { | |
232 | + if (visible.left < window.left) { | |
233 | + visible.left = window.left; | |
234 | + } | |
235 | + if (visible.top < window.top) { | |
236 | + visible.top = window.top; | |
237 | + } | |
238 | + } | |
239 | + // Always set the bottom of the rectangle to the window bottom | |
240 | + /* XXX This breaks with a split action bar, but if we don't do this, | |
241 | + it's possible that the view won't resize correctly on IME hide */ | |
242 | + visible.right = window.right; | |
243 | + visible.bottom = window.bottom; | |
244 | + } | |
245 | + | |
246 | + private void adjustChildSize() { | |
247 | + updateVisibleRect(); | |
248 | + Rect visible = mVisibleRect; | |
249 | + int width = visible.width(); | |
250 | + int height = visible.height(); | |
251 | + | |
252 | + if (mCurWidth != width || mCurHeight != height) { | |
253 | + mCurWidth = width; | |
254 | + mCurHeight = height; | |
255 | + | |
256 | + LayoutParams params = mChildParams; | |
257 | + params.width = width; | |
258 | + params.height = height; | |
259 | + for (View v : this) { | |
260 | + updateViewLayout(v, params); | |
261 | + } | |
262 | + mRedoLayout = true; | |
263 | + | |
264 | + EmulatorView currentView = (EmulatorView) getCurrentView(); | |
265 | + if (currentView != null) { | |
266 | + currentView.updateSize(false); | |
267 | + } | |
268 | + } | |
269 | + } | |
270 | + | |
271 | + /** | |
272 | + * Called when the view changes size. | |
273 | + * (Note: Not always called on Android < 2.2) | |
274 | + */ | |
275 | + @Override | |
276 | + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
277 | + adjustChildSize(); | |
278 | + super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
279 | + } | |
280 | + | |
281 | + @Override | |
282 | + protected void onDraw(Canvas canvas) { | |
283 | + if (mRedoLayout) { | |
284 | + requestLayout(); | |
285 | + mRedoLayout = false; | |
286 | + } | |
287 | + super.onDraw(canvas); | |
288 | + } | |
144 | 289 | } |