• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.widget.cts;
18 
19 import com.android.cts.widget.R;
20 
21 
22 import android.app.Activity;
23 import android.app.Instrumentation;
24 import android.content.Context;
25 import android.graphics.Color;
26 import android.graphics.drawable.ColorDrawable;
27 import android.graphics.drawable.Drawable;
28 import android.os.Debug;
29 import android.os.SystemClock;
30 import android.test.ActivityInstrumentationTestCase2;
31 import android.test.UiThreadTest;
32 import android.view.Display;
33 import android.view.Gravity;
34 import android.view.MotionEvent;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.view.WindowManager;
38 import android.view.View.OnTouchListener;
39 import android.view.ViewGroup.LayoutParams;
40 import android.widget.ImageView;
41 import android.widget.PopupWindow;
42 import android.widget.TextView;
43 import android.widget.PopupWindow.OnDismissListener;
44 
45 public class PopupWindowTest extends
46         ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
47     private Instrumentation mInstrumentation;
48     private Activity mActivity;
49     /** The popup window. */
50     private PopupWindow mPopupWindow;
51 
52     /**
53      * Instantiates a new popup window test.
54      */
PopupWindowTest()55     public PopupWindowTest() {
56         super("com.android.cts.widget", MockPopupWindowCtsActivity.class);
57     }
58 
59     /*
60      * (non-Javadoc)
61      *
62      * @see android.test.ActivityInstrumentationTestCase#setUp()
63      */
64     @Override
setUp()65     protected void setUp() throws Exception {
66         super.setUp();
67         mInstrumentation = getInstrumentation();
68         mActivity = getActivity();
69     }
70 
testConstructor()71     public void testConstructor() {
72         new PopupWindow(mActivity);
73 
74         new PopupWindow(mActivity, null);
75 
76         new PopupWindow(mActivity, null, com.android.internal.R.attr.popupWindowStyle);
77 
78         mPopupWindow = new PopupWindow();
79         assertEquals(0, mPopupWindow.getWidth());
80         assertEquals(0, mPopupWindow.getHeight());
81 
82         mPopupWindow = new PopupWindow(50, 50);
83         assertEquals(50, mPopupWindow.getWidth());
84         assertEquals(50, mPopupWindow.getHeight());
85 
86         mPopupWindow = new PopupWindow(-1, -1);
87         assertEquals(-1, mPopupWindow.getWidth());
88         assertEquals(-1, mPopupWindow.getHeight());
89 
90         TextView contentView = new TextView(mActivity);
91         mPopupWindow = new PopupWindow(contentView);
92         assertSame(contentView, mPopupWindow.getContentView());
93 
94         mPopupWindow = new PopupWindow(contentView, 0, 0);
95         assertEquals(0, mPopupWindow.getWidth());
96         assertEquals(0, mPopupWindow.getHeight());
97         assertSame(contentView, mPopupWindow.getContentView());
98 
99         mPopupWindow = new PopupWindow(contentView, 50, 50);
100         assertEquals(50, mPopupWindow.getWidth());
101         assertEquals(50, mPopupWindow.getHeight());
102         assertSame(contentView, mPopupWindow.getContentView());
103 
104         mPopupWindow = new PopupWindow(contentView, -1, -1);
105         assertEquals(-1, mPopupWindow.getWidth());
106         assertEquals(-1, mPopupWindow.getHeight());
107         assertSame(contentView, mPopupWindow.getContentView());
108 
109         mPopupWindow = new PopupWindow(contentView, 0, 0, true);
110         assertEquals(0, mPopupWindow.getWidth());
111         assertEquals(0, mPopupWindow.getHeight());
112         assertSame(contentView, mPopupWindow.getContentView());
113         assertTrue(mPopupWindow.isFocusable());
114 
115         mPopupWindow = new PopupWindow(contentView, 50, 50, false);
116         assertEquals(50, mPopupWindow.getWidth());
117         assertEquals(50, mPopupWindow.getHeight());
118         assertSame(contentView, mPopupWindow.getContentView());
119         assertFalse(mPopupWindow.isFocusable());
120 
121         mPopupWindow = new PopupWindow(contentView, -1, -1, true);
122         assertEquals(-1, mPopupWindow.getWidth());
123         assertEquals(-1, mPopupWindow.getHeight());
124         assertSame(contentView, mPopupWindow.getContentView());
125         assertTrue(mPopupWindow.isFocusable());
126     }
127 
testAccessBackground()128     public void testAccessBackground() {
129         mPopupWindow = new PopupWindow(mActivity);
130 
131         Drawable drawable = new ColorDrawable();
132         mPopupWindow.setBackgroundDrawable(drawable);
133         assertSame(drawable, mPopupWindow.getBackground());
134 
135         mPopupWindow.setBackgroundDrawable(null);
136         assertNull(mPopupWindow.getBackground());
137     }
138 
testAccessAnimationStyle()139     public void testAccessAnimationStyle() {
140         mPopupWindow = new PopupWindow(mActivity);
141         // default is -1
142         assertEquals(-1, mPopupWindow.getAnimationStyle());
143 
144         mPopupWindow.setAnimationStyle(com.android.internal.R.style.Animation_Toast);
145         assertEquals(com.android.internal.R.style.Animation_Toast,
146                 mPopupWindow.getAnimationStyle());
147 
148         mPopupWindow.setAnimationStyle(com.android.internal.R.style.Animation_DropDownDown);
149         assertEquals(com.android.internal.R.style.Animation_DropDownDown,
150                 mPopupWindow.getAnimationStyle());
151 
152         // abnormal values
153         mPopupWindow.setAnimationStyle(-100);
154         assertEquals(-100, mPopupWindow.getAnimationStyle());
155     }
156 
testAccessContentView()157     public void testAccessContentView() {
158         mPopupWindow = new PopupWindow(mActivity);
159         assertNull(mPopupWindow.getContentView());
160 
161         View view = new TextView(mActivity);
162         mPopupWindow.setContentView(view);
163         assertSame(view, mPopupWindow.getContentView());
164 
165         mPopupWindow.setContentView(null);
166         assertNull(mPopupWindow.getContentView());
167 
168         // can not set the content if the old content is shown
169         mPopupWindow.setContentView(view);
170         assertFalse(mPopupWindow.isShowing());
171         showPopup();
172         ImageView img = new ImageView(mActivity);
173         assertTrue(mPopupWindow.isShowing());
174         mPopupWindow.setContentView(img);
175         assertSame(view, mPopupWindow.getContentView());
176         dismissPopup();
177     }
178 
testAccessFocusable()179     public void testAccessFocusable() {
180         mPopupWindow = new PopupWindow(mActivity);
181         assertFalse(mPopupWindow.isFocusable());
182 
183         mPopupWindow.setFocusable(true);
184         assertTrue(mPopupWindow.isFocusable());
185 
186         mPopupWindow.setFocusable(false);
187         assertFalse(mPopupWindow.isFocusable());
188     }
189 
testAccessHeight()190     public void testAccessHeight() {
191         mPopupWindow = new PopupWindow(mActivity);
192         // default is 0
193         assertEquals(0, mPopupWindow.getHeight());
194 
195         int height = getDisplay().getHeight() / 2;
196         mPopupWindow.setHeight(height);
197         assertEquals(height, mPopupWindow.getHeight());
198 
199         height = getDisplay().getHeight();
200         mPopupWindow.setHeight(height);
201         assertEquals(height, mPopupWindow.getHeight());
202 
203         mPopupWindow.setHeight(0);
204         assertEquals(0, mPopupWindow.getHeight());
205 
206         height = getDisplay().getHeight() * 2;
207         mPopupWindow.setHeight(height);
208         assertEquals(height, mPopupWindow.getHeight());
209 
210         height = -getDisplay().getHeight() / 2;
211         mPopupWindow.setHeight(height);
212         assertEquals(height, mPopupWindow.getHeight());
213     }
214 
215     /**
216      * Gets the display.
217      *
218      * @return the display
219      */
getDisplay()220     private Display getDisplay() {
221         WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
222         return wm.getDefaultDisplay();
223     }
224 
testAccessWidth()225     public void testAccessWidth() {
226         mPopupWindow = new PopupWindow(mActivity);
227         assertEquals(0, mPopupWindow.getWidth());
228 
229         int width = getDisplay().getWidth() / 2;
230         mPopupWindow.setWidth(width);
231         assertEquals(width, mPopupWindow.getWidth());
232 
233         width = getDisplay().getWidth();
234         mPopupWindow.setWidth(width);
235         assertEquals(width, mPopupWindow.getWidth());
236 
237         mPopupWindow.setWidth(0);
238         assertEquals(0, mPopupWindow.getWidth());
239 
240         width = getDisplay().getWidth() * 2;
241         mPopupWindow.setWidth(width);
242         assertEquals(width, mPopupWindow.getWidth());
243 
244         width = - getDisplay().getWidth() / 2;
245         mPopupWindow.setWidth(width);
246         assertEquals(width, mPopupWindow.getWidth());
247     }
248 
testShowAsDropDown()249     public void testShowAsDropDown() {
250         int[] anchorXY = new int[2];
251         int[] viewOnScreenXY = new int[2];
252         int[] viewInWindowXY = new int[2];
253 
254         mPopupWindow = createPopupWindow(createPopupContent());
255         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
256 
257         mInstrumentation.runOnMainSync(new Runnable() {
258             public void run() {
259                 mPopupWindow.showAsDropDown(upperAnchor);
260             }
261         });
262         mInstrumentation.waitForIdleSync();
263 
264         assertTrue(mPopupWindow.isShowing());
265 
266         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
267         upperAnchor.getLocationOnScreen(anchorXY);
268         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
269         assertEquals(anchorXY[0] + viewInWindowXY[0], viewOnScreenXY[0]);
270         assertEquals(anchorXY[1] + viewInWindowXY[1] + upperAnchor.getHeight(), viewOnScreenXY[1]);
271 
272         dismissPopup();
273     }
274 
testShowAtLocation()275     public void testShowAtLocation() {
276         int[] viewInWindowXY = new int[2];
277         int[] viewOnScreenXY = new int[2];
278 
279         mPopupWindow = createPopupWindow(createPopupContent());
280         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
281 
282         final int xOff = 10;
283         final int yOff = 21;
284         assertFalse(mPopupWindow.isShowing());
285         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
286         assertEquals(0, viewInWindowXY[0]);
287         assertEquals(0, viewInWindowXY[1]);
288 
289         mInstrumentation.runOnMainSync(new Runnable() {
290             public void run() {
291                 mPopupWindow.showAtLocation(upperAnchor, Gravity.NO_GRAVITY, xOff, yOff);
292             }
293         });
294         mInstrumentation.waitForIdleSync();
295 
296         assertTrue(mPopupWindow.isShowing());
297         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
298         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
299         assertTrue(viewInWindowXY[0] >= 0);
300         assertTrue(viewInWindowXY[1] >= 0);
301         assertEquals(viewInWindowXY[0] + xOff, viewOnScreenXY[0]);
302         assertEquals(viewInWindowXY[1] + yOff, viewOnScreenXY[1]);
303 
304         dismissPopup();
305     }
306 
testShowAsDropDownWithOffsets()307     public void testShowAsDropDownWithOffsets() {
308         int[] anchorXY = new int[2];
309         int[] viewOnScreenXY = new int[2];
310         int[] viewInWindowXY = new int[2];
311 
312         mPopupWindow = createPopupWindow(createPopupContent());
313         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
314         upperAnchor.getLocationOnScreen(anchorXY);
315         int height = upperAnchor.getHeight();
316 
317         final int xOff = 11;
318         final int yOff = 12;
319 
320         mInstrumentation.runOnMainSync(new Runnable() {
321             public void run() {
322                 mPopupWindow.showAsDropDown(upperAnchor, xOff, yOff);
323             }
324         });
325         mInstrumentation.waitForIdleSync();
326 
327         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
328         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
329         assertEquals(anchorXY[0] + xOff + viewInWindowXY[0], viewOnScreenXY[0]);
330         assertEquals(anchorXY[1] + height + yOff + viewInWindowXY[1], viewOnScreenXY[1]);
331 
332         dismissPopup();
333     }
334 
testGetMaxAvailableHeight()335     public void testGetMaxAvailableHeight() {
336         mPopupWindow = createPopupWindow(createPopupContent());
337 
338         View anchorView = mActivity.findViewById(R.id.anchor_upper);
339         int avaliable = getDisplay().getHeight() - anchorView.getHeight();
340         int maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
341         assertTrue(maxAvailableHeight > 0);
342         assertTrue(maxAvailableHeight <= avaliable);
343         int maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, 2);
344         assertEquals(maxAvailableHeight - 2, maxAvailableHeightWithOffset);
345         maxAvailableHeightWithOffset =
346                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight);
347         assertTrue(maxAvailableHeightWithOffset > 0);
348         assertTrue(maxAvailableHeightWithOffset <= avaliable);
349         maxAvailableHeightWithOffset =
350                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1);
351         assertTrue(maxAvailableHeightWithOffset > 0);
352         assertTrue(maxAvailableHeightWithOffset <= avaliable);
353         maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, -1);
354         assertTrue(maxAvailableHeightWithOffset > 0);
355         assertTrue(maxAvailableHeightWithOffset <= avaliable);
356 
357         anchorView = mActivity.findViewById(R.id.anchor_lower);
358         avaliable = getDisplay().getHeight() - anchorView.getHeight();
359         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
360         assertTrue(maxAvailableHeight > 0);
361         assertTrue(maxAvailableHeight <= avaliable);
362 
363         anchorView = mActivity.findViewById(R.id.anchor_middle_left);
364         avaliable = getDisplay().getHeight() - anchorView.getHeight()
365                 - mActivity.findViewById(R.id.anchor_upper).getHeight();
366         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
367         assertTrue(maxAvailableHeight > 0);
368         assertTrue(maxAvailableHeight <= avaliable);
369     }
370 
371     @UiThreadTest
testDismiss()372     public void testDismiss() {
373         mPopupWindow = createPopupWindow(createPopupContent());
374         assertFalse(mPopupWindow.isShowing());
375         View anchorView = mActivity.findViewById(R.id.anchor_upper);
376         mPopupWindow.showAsDropDown(anchorView);
377 
378         mPopupWindow.dismiss();
379         assertFalse(mPopupWindow.isShowing());
380 
381         mPopupWindow.dismiss();
382         assertFalse(mPopupWindow.isShowing());
383     }
384 
testSetOnDismissListener()385     public void testSetOnDismissListener() {
386         mPopupWindow = new PopupWindow(new TextView(mActivity));
387         mPopupWindow.setOnDismissListener(null);
388 
389         MockOnDismissListener onDismissListener = new MockOnDismissListener();
390         mPopupWindow.setOnDismissListener(onDismissListener);
391         showPopup();
392         dismissPopup();
393         assertEquals(1, onDismissListener.getOnDismissCalledCount());
394 
395         showPopup();
396         dismissPopup();
397         assertEquals(2, onDismissListener.getOnDismissCalledCount());
398 
399         mPopupWindow.setOnDismissListener(null);
400         showPopup();
401         dismissPopup();
402         assertEquals(2, onDismissListener.getOnDismissCalledCount());
403     }
404 
testUpdate()405     public void testUpdate() {
406         mPopupWindow = createPopupWindow(createPopupContent());
407         mPopupWindow.setBackgroundDrawable(null);
408         showPopup();
409 
410         mPopupWindow.setIgnoreCheekPress();
411         mPopupWindow.setFocusable(true);
412         mPopupWindow.setTouchable(false);
413         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
414         mPopupWindow.setClippingEnabled(false);
415         mPopupWindow.setOutsideTouchable(true);
416 
417         WindowManager.LayoutParams p = (WindowManager.LayoutParams)
418                 mPopupWindow.getContentView().getLayoutParams();
419 
420         assertEquals(0, WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES & p.flags);
421         assertEquals(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
422                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE & p.flags);
423         assertEquals(0, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & p.flags);
424         assertEquals(0, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH & p.flags);
425         assertEquals(0, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
426         assertEquals(0, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
427 
428         mInstrumentation.runOnMainSync(new Runnable() {
429             public void run() {
430                 mPopupWindow.update();
431             }
432         });
433         mInstrumentation.waitForIdleSync();
434 
435         assertEquals(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES,
436                 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES & p.flags);
437         assertEquals(0, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE & p.flags);
438         assertEquals(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
439                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & p.flags);
440         assertEquals(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
441                 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH & p.flags);
442         assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
443                 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
444         assertEquals(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
445                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
446     }
447 
testUpdatePositionAndDimension()448     public void testUpdatePositionAndDimension() {
449         int[] fstXY = new int[2];
450         int[] sndXY = new int[2];
451         int[] viewInWindowXY = new int[2];
452 
453         mInstrumentation.runOnMainSync(new Runnable() {
454             public void run() {
455                 mPopupWindow = createPopupWindow(createPopupContent());
456             }
457         });
458 
459         mInstrumentation.waitForIdleSync();
460         // Do not update if it is not shown
461         assertFalse(mPopupWindow.isShowing());
462         assertEquals(100, mPopupWindow.getWidth());
463         assertEquals(100, mPopupWindow.getHeight());
464 
465         showPopup();
466         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
467 
468         // update if it is not shown
469         mInstrumentation.runOnMainSync(new Runnable() {
470             public void run() {
471                 mPopupWindow.update(20, 50, 50, 50);
472             }
473         });
474 
475         mInstrumentation.waitForIdleSync();
476         assertTrue(mPopupWindow.isShowing());
477         assertEquals(50, mPopupWindow.getWidth());
478         assertEquals(50, mPopupWindow.getHeight());
479 
480         mPopupWindow.getContentView().getLocationOnScreen(fstXY);
481         assertEquals(viewInWindowXY[0] + 20, fstXY[0]);
482         assertEquals(viewInWindowXY[1] + 50, fstXY[1]);
483 
484         // ignore if width or height is -1
485         mInstrumentation.runOnMainSync(new Runnable() {
486             public void run() {
487                 mPopupWindow.update(4, 0, -1, -1, true);
488             }
489         });
490         mInstrumentation.waitForIdleSync();
491 
492         assertTrue(mPopupWindow.isShowing());
493         assertEquals(50, mPopupWindow.getWidth());
494         assertEquals(50, mPopupWindow.getHeight());
495 
496         mPopupWindow.getContentView().getLocationOnScreen(sndXY);
497         assertEquals(viewInWindowXY[0] + 4, sndXY[0]);
498         assertEquals(viewInWindowXY[1], sndXY[1]);
499 
500         dismissPopup();
501     }
502 
testUpdateDimensionAndAlignAnchorView()503     public void testUpdateDimensionAndAlignAnchorView() {
504         mInstrumentation.runOnMainSync(new Runnable() {
505             public void run() {
506                 mPopupWindow = createPopupWindow(createPopupContent());
507             }
508         });
509         mInstrumentation.waitForIdleSync();
510 
511         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
512         mPopupWindow.update(anchorView, 50, 50);
513         // Do not update if it is not shown
514         assertFalse(mPopupWindow.isShowing());
515         assertEquals(100, mPopupWindow.getWidth());
516         assertEquals(100, mPopupWindow.getHeight());
517 
518         mInstrumentation.runOnMainSync(new Runnable() {
519             public void run() {
520                 mPopupWindow.showAsDropDown(anchorView);
521             }
522         });
523         mInstrumentation.waitForIdleSync();
524         // update if it is shown
525         mInstrumentation.runOnMainSync(new Runnable() {
526             public void run() {
527                 mPopupWindow.update(anchorView, 50, 50);
528             }
529         });
530         mInstrumentation.waitForIdleSync();
531         assertTrue(mPopupWindow.isShowing());
532         assertEquals(50, mPopupWindow.getWidth());
533         assertEquals(50, mPopupWindow.getHeight());
534 
535         // ignore if width or height is -1
536         mInstrumentation.runOnMainSync(new Runnable() {
537             public void run() {
538                 mPopupWindow.update(anchorView, -1, -1);
539             }
540         });
541         mInstrumentation.waitForIdleSync();
542         assertTrue(mPopupWindow.isShowing());
543         assertEquals(50, mPopupWindow.getWidth());
544         assertEquals(50, mPopupWindow.getHeight());
545 
546         mInstrumentation.runOnMainSync(new Runnable() {
547             public void run() {
548                 mPopupWindow.dismiss();
549             }
550         });
551         mInstrumentation.waitForIdleSync();
552     }
553 
testUpdateDimensionAndAlignAnchorViewWithOffsets()554     public void testUpdateDimensionAndAlignAnchorViewWithOffsets() {
555         int[] anchorXY = new int[2];
556         int[] viewInWindowOff = new int[2];
557         int[] viewXY = new int[2];
558 
559         mPopupWindow = createPopupWindow(createPopupContent());
560         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
561         // Do not update if it is not shown
562         assertFalse(mPopupWindow.isShowing());
563         assertEquals(100, mPopupWindow.getWidth());
564         assertEquals(100, mPopupWindow.getHeight());
565 
566         showPopup();
567         anchorView.getLocationOnScreen(anchorXY);
568         mPopupWindow.getContentView().getLocationInWindow(viewInWindowOff);
569 
570         // update if it is not shown
571         mInstrumentation.runOnMainSync(new Runnable() {
572             public void run() {
573                 mPopupWindow.update(anchorView, 20, 50, 50, 50);
574             }
575         });
576 
577         mInstrumentation.waitForIdleSync();
578 
579         assertTrue(mPopupWindow.isShowing());
580         assertEquals(50, mPopupWindow.getWidth());
581         assertEquals(50, mPopupWindow.getHeight());
582 
583         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
584 
585         // The popup should appear below and to right with an offset.
586         assertEquals(anchorXY[0] + 20 + viewInWindowOff[0], viewXY[0]);
587         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
588 
589         // ignore width and height but change location
590         mInstrumentation.runOnMainSync(new Runnable() {
591             public void run() {
592                 mPopupWindow.update(anchorView, 10, 50, -1, -1);
593             }
594         });
595         mInstrumentation.waitForIdleSync();
596 
597         assertTrue(mPopupWindow.isShowing());
598         assertEquals(50, mPopupWindow.getWidth());
599         assertEquals(50, mPopupWindow.getHeight());
600 
601         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
602 
603         // The popup should appear below and to right with an offset.
604         assertEquals(anchorXY[0] + 10 + viewInWindowOff[0], viewXY[0]);
605         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
606 
607         final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
608         mInstrumentation.runOnMainSync(new Runnable() {
609             public void run() {
610                 mPopupWindow.update(anotherView, 0, 0, 60, 60);
611             }
612         });
613         mInstrumentation.waitForIdleSync();
614 
615         assertTrue(mPopupWindow.isShowing());
616         assertEquals(60, mPopupWindow.getWidth());
617         assertEquals(60, mPopupWindow.getHeight());
618 
619         int[] newXY = new int[2];
620         anotherView.getLocationOnScreen(newXY);
621         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
622 
623         // The popup should appear below and to the right.
624         assertEquals(newXY[0] + viewInWindowOff[0], viewXY[0]);
625         assertEquals(newXY[1] + anotherView.getHeight() + viewInWindowOff[1], viewXY[1]);
626 
627         dismissPopup();
628     }
629 
testAccessInputMethodMode()630     public void testAccessInputMethodMode() {
631         mPopupWindow = new PopupWindow(mActivity);
632         assertEquals(0, mPopupWindow.getInputMethodMode());
633 
634         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE);
635         assertEquals(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE, mPopupWindow.getInputMethodMode());
636 
637         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
638         assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
639 
640         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
641         assertEquals(PopupWindow.INPUT_METHOD_NOT_NEEDED, mPopupWindow.getInputMethodMode());
642 
643         mPopupWindow.setInputMethodMode(-1);
644         assertEquals(-1, mPopupWindow.getInputMethodMode());
645     }
646 
testAccessClippingEnabled()647     public void testAccessClippingEnabled() {
648         mPopupWindow = new PopupWindow(mActivity);
649         assertTrue(mPopupWindow.isClippingEnabled());
650 
651         mPopupWindow.setClippingEnabled(false);
652         assertFalse(mPopupWindow.isClippingEnabled());
653     }
654 
testAccessOutsideTouchable()655     public void testAccessOutsideTouchable() {
656         mPopupWindow = new PopupWindow(mActivity);
657         assertFalse(mPopupWindow.isOutsideTouchable());
658 
659         mPopupWindow.setOutsideTouchable(true);
660         assertTrue(mPopupWindow.isOutsideTouchable());
661     }
662 
testAccessTouchable()663     public void testAccessTouchable() {
664         mPopupWindow = new PopupWindow(mActivity);
665         assertTrue(mPopupWindow.isTouchable());
666 
667         mPopupWindow.setTouchable(false);
668         assertFalse(mPopupWindow.isTouchable());
669     }
670 
testIsAboveAnchor()671     public void testIsAboveAnchor() {
672         mInstrumentation.runOnMainSync(new Runnable() {
673             public void run() {
674                 mPopupWindow = createPopupWindow(createPopupContent());
675             }
676         });
677         mInstrumentation.waitForIdleSync();
678         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
679 
680         mInstrumentation.runOnMainSync(new Runnable() {
681             public void run() {
682                 mPopupWindow.showAsDropDown(upperAnchor);
683             }
684         });
685         mInstrumentation.waitForIdleSync();
686         assertFalse(mPopupWindow.isAboveAnchor());
687         dismissPopup();
688 
689         mPopupWindow = createPopupWindow(createPopupContent());
690         final View lowerAnchor = mActivity.findViewById(R.id.anchor_lower);
691 
692         mInstrumentation.runOnMainSync(new Runnable() {
693             public void run() {
694                 mPopupWindow.showAsDropDown(lowerAnchor, 0, 0);
695             }
696         });
697         mInstrumentation.waitForIdleSync();
698         assertTrue(mPopupWindow.isAboveAnchor());
699         dismissPopup();
700     }
701 
testSetTouchInterceptor()702     public void testSetTouchInterceptor() {
703         mPopupWindow = new PopupWindow(new TextView(mActivity));
704 
705         MockOnTouchListener onTouchListener = new MockOnTouchListener();
706         mPopupWindow.setTouchInterceptor(onTouchListener);
707         mPopupWindow.setFocusable(true);
708         mPopupWindow.setOutsideTouchable(true);
709         Drawable drawable = new ColorDrawable();
710         mPopupWindow.setBackgroundDrawable(drawable);
711         showPopup();
712 
713         int[] xy = new int[2];
714         mPopupWindow.getContentView().getLocationOnScreen(xy);
715         final int viewWidth = mPopupWindow.getContentView().getWidth();
716         final int viewHeight = mPopupWindow.getContentView().getHeight();
717         final float x = xy[0] + (viewWidth / 2.0f);
718         float y = xy[1] + (viewHeight / 2.0f);
719 
720         long downTime = SystemClock.uptimeMillis();
721         long eventTime = SystemClock.uptimeMillis();
722         MotionEvent event = MotionEvent.obtain(downTime, eventTime,
723                 MotionEvent.ACTION_DOWN, x, y, 0);
724         getInstrumentation().sendPointerSync(event);
725         assertEquals(1, onTouchListener.getOnTouchCalledCount());
726 
727         downTime = SystemClock.uptimeMillis();
728         eventTime = SystemClock.uptimeMillis();
729         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
730         getInstrumentation().sendPointerSync(event);
731         assertEquals(2, onTouchListener.getOnTouchCalledCount());
732 
733         mPopupWindow.setTouchInterceptor(null);
734         downTime = SystemClock.uptimeMillis();
735         eventTime = SystemClock.uptimeMillis();
736         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
737         getInstrumentation().sendPointerSync(event);
738         assertEquals(2, onTouchListener.getOnTouchCalledCount());
739     }
740 
testSetWindowLayoutMode()741     public void testSetWindowLayoutMode() {
742         mPopupWindow = new PopupWindow(new TextView(mActivity));
743         showPopup();
744 
745         ViewGroup.LayoutParams p = mPopupWindow.getContentView().getLayoutParams();
746         assertEquals(0, p.width);
747         assertEquals(0, p.height);
748 
749         mPopupWindow.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
750         mInstrumentation.runOnMainSync(new Runnable() {
751             public void run() {
752                 mPopupWindow.update(20, 50, 50, 50);
753             }
754         });
755 
756         assertEquals(LayoutParams.WRAP_CONTENT, p.width);
757         assertEquals(LayoutParams.MATCH_PARENT, p.height);
758     }
759 
760     /**
761      * The listener interface for receiving OnDismiss events. The class that is
762      * interested in processing a OnDismiss event implements this interface, and
763      * the object created with that class is registered with a component using
764      * the component's <code>setOnDismissListener<code> method. When
765      * the OnDismiss event occurs, that object's appropriate
766      * method is invoked.
767      */
768     private static class MockOnDismissListener implements OnDismissListener {
769 
770         /** The Ondismiss called count. */
771         private int mOnDismissCalledCount;
772 
773         /**
774          * Gets the onDismiss() called count.
775          *
776          * @return the on dismiss called count
777          */
getOnDismissCalledCount()778         public int getOnDismissCalledCount() {
779             return mOnDismissCalledCount;
780         }
781 
782         /*
783          * (non-Javadoc)
784          *
785          * @see android.widget.PopupWindow.OnDismissListener#onDismiss()
786          */
onDismiss()787         public void onDismiss() {
788             mOnDismissCalledCount++;
789         }
790 
791     }
792 
793     /**
794      * The listener interface for receiving touch events.
795      */
796     private static class MockOnTouchListener implements OnTouchListener {
797 
798         /** The onTouch called count. */
799         private int mOnTouchCalledCount;
800 
801         /**
802          * Gets the onTouch() called count.
803          *
804          * @return the onTouch() called count
805          */
getOnTouchCalledCount()806         public int getOnTouchCalledCount() {
807             return mOnTouchCalledCount;
808         }
809 
810         /*
811          * (non-Javadoc)
812          *
813          * @see android.widget.PopupWindow.OnTouchListener#onDismiss()
814          */
onTouch(View v, MotionEvent event)815         public boolean onTouch(View v, MotionEvent event) {
816             mOnTouchCalledCount++;
817             return true;
818         }
819     }
820 
createPopupContent()821     private View createPopupContent() {
822         View popupView = new View(mActivity);
823         popupView.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
824         popupView.setBackgroundColor(Color.WHITE);
825 
826         return popupView;
827     }
828 
createPopupWindow()829     private PopupWindow createPopupWindow() {
830         PopupWindow window = new PopupWindow(mActivity);
831         window.setWidth(100);
832         window.setHeight(100);
833         return window;
834     }
835 
createPopupWindow(View content)836     private PopupWindow createPopupWindow(View content) {
837         PopupWindow window = createPopupWindow();
838         window.setContentView(content);
839         return window;
840     }
841 
842     /**
843      * Show PopupWindow.
844      */
845     // FIXME: logcat info complains that there is window leakage due to that mPopupWindow is not
846     // clean up. Need to fix it.
showPopup()847     private void showPopup() {
848         mInstrumentation.runOnMainSync(new Runnable() {
849             public void run() {
850                 if (mPopupWindow == null || mPopupWindow.isShowing()) {
851                     return;
852                 }
853                 View anchor = mActivity.findViewById(R.id.anchor_upper);
854                 mPopupWindow.showAsDropDown(anchor);
855                 assertTrue(mPopupWindow.isShowing());
856             }
857         });
858         mInstrumentation.waitForIdleSync();
859     }
860 
861     /**
862      * Dismiss PopupWindow.
863      */
dismissPopup()864     private void dismissPopup() {
865         mInstrumentation.runOnMainSync(new Runnable() {
866             public void run() {
867                 if (mPopupWindow == null || !mPopupWindow.isShowing())
868                     return;
869                 mPopupWindow.dismiss();
870             }
871         });
872         mInstrumentation.waitForIdleSync();
873     }
874 }
875