|
1 package org.mozilla.gecko.tests; |
|
2 |
|
3 import org.mozilla.gecko.Actions; |
|
4 import org.mozilla.gecko.PaintedSurface; |
|
5 |
|
6 import android.net.Uri; |
|
7 |
|
8 /** |
|
9 * A test to ensure that when an input field is focused, it is not obscured by the VKB. |
|
10 * - Loads a page with an input field past the bottom of the visible area. |
|
11 * - scrolls down to make the input field visible at the bottom of the screen. |
|
12 * - taps on the input field to bring up the VKB |
|
13 * - verifies that the input field is still visible. |
|
14 */ |
|
15 public class testVkbOverlap extends PixelTest { |
|
16 private static final int CURSOR_BLINK_PERIOD = 500; |
|
17 private static final int LESS_THAN_CURSOR_BLINK_PERIOD = CURSOR_BLINK_PERIOD - 50; |
|
18 private static final int PAGE_SETTLE_TIME = 5000; |
|
19 |
|
20 public void testVkbOverlap() { |
|
21 blockForGeckoReady(); |
|
22 testSetup("initial-scale=1.0, user-scalable=no", false); |
|
23 testSetup("initial-scale=1.0", false); |
|
24 testSetup("", "phone".equals(mDevice.type)); |
|
25 } |
|
26 |
|
27 private void testSetup(String viewport, boolean shouldZoom) { |
|
28 loadAndPaint(getAbsoluteUrl("/robocop/test_viewport.sjs?metadata=" + Uri.encode(viewport))); |
|
29 |
|
30 // scroll to the bottom of the page and let it settle |
|
31 Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); |
|
32 MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); |
|
33 meh.dragSync(10, 150, 10, 50); |
|
34 |
|
35 // the input field has a green background, so let's count the number of green pixels |
|
36 int greenPixelCount = 0; |
|
37 |
|
38 PaintedSurface painted = waitForPaint(paintExpecter); |
|
39 paintExpecter.unregisterListener(); |
|
40 try { |
|
41 greenPixelCount = countGreenPixels(painted); |
|
42 } finally { |
|
43 painted.close(); |
|
44 } |
|
45 |
|
46 mAsserter.ok(greenPixelCount > 0, "testInputVisible", "Found " + greenPixelCount + " green pixels after scrolling"); |
|
47 |
|
48 paintExpecter = mActions.expectPaint(); |
|
49 // the input field should be in the bottom-left corner, so tap thereabouts |
|
50 meh.tap(5, mDriver.getGeckoHeight() - 5); |
|
51 |
|
52 // After tapping in the input field, the page needs some time to do stuff, like draw and undraw the focus highlight |
|
53 // on the input field, trigger the VKB, process any resulting events generated by the system, and scroll the page. So |
|
54 // we give it a few seconds to do all that. We are sufficiently generous with our definition of "few seconds" to |
|
55 // prevent intermittent test failures. |
|
56 try { |
|
57 Thread.sleep(PAGE_SETTLE_TIME); |
|
58 } catch (InterruptedException ie) { |
|
59 ie.printStackTrace(); |
|
60 } |
|
61 |
|
62 // now that the focus is in the text field we will repaint every 500ms as the cursor blinks, so we need to use a smaller |
|
63 // "no paints" threshold to consider the page painted |
|
64 paintExpecter.blockUntilClear(LESS_THAN_CURSOR_BLINK_PERIOD); |
|
65 paintExpecter.unregisterListener(); |
|
66 painted = mDriver.getPaintedSurface(); |
|
67 try { |
|
68 // if the vkb scrolled into view as expected, then the number of green pixels now visible should be about the |
|
69 // same as it was before, since the green pixels indicate the text input is in view. use a fudge factor of 0.9 to |
|
70 // account for borders and such of the text input which might still be out of view. |
|
71 int newCount = countGreenPixels(painted); |
|
72 |
|
73 // if zooming is allowed, the number of green pixels visible should have increased substatially |
|
74 if (shouldZoom) { |
|
75 mAsserter.ok(newCount > greenPixelCount * 1.5, "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount); |
|
76 } else { |
|
77 mAsserter.ok((Math.abs(greenPixelCount - newCount) / greenPixelCount < 0.1), "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount); |
|
78 } |
|
79 } finally { |
|
80 painted.close(); |
|
81 } |
|
82 } |
|
83 |
|
84 private int countGreenPixels(PaintedSurface painted) { |
|
85 int count = 0; |
|
86 for (int y = painted.getHeight() - 1; y >= 0; y--) { |
|
87 for (int x = painted.getWidth() - 1; x >= 0; x--) { |
|
88 int pixel = painted.getPixelAt(x, y); |
|
89 int r = (pixel >> 16) & 0xFF; |
|
90 int g = (pixel >> 8) & 0xFF; |
|
91 int b = (pixel & 0xFF); |
|
92 if (g > (r + 0x30) && g > (b + 0x30)) { |
|
93 // there's more green in this pixel than red or blue, so count it. |
|
94 // the reason this is so hacky-looking is because even though green is supposed to |
|
95 // be (r,g,b) = (0x00, 0x80, 0x00), the GL readback ends up coming back quite |
|
96 // different. |
|
97 count++; |
|
98 } |
|
99 // uncomment for debugging: |
|
100 // if (pixel != -1) mAsserter.dumpLog("Pixel at " + x + ", " + y + ": " + Integer.toString(pixel, 16)); |
|
101 } |
|
102 } |
|
103 return count; |
|
104 } |
|
105 } |