Skip to content

Commit de3e494

Browse files
committed
Consider window position when calculating view coordinates
- Added windows and current focus - Added apidemos dialog example
1 parent e5eeaee commit de3e494

2 files changed

Lines changed: 151 additions & 4 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#! /usr/bin/env monkeyrunner
2+
'''
3+
Copyright (C) 2012 Diego Torres Milano
4+
Created on Sep 5, 2012
5+
6+
@author: diego
7+
'''
8+
9+
10+
import re
11+
import sys
12+
import os
13+
14+
# This must be imported before MonkeyRunner and MonkeyDevice,
15+
# otherwise the import fails.
16+
# PyDev sets PYTHONPATH, use it
17+
try:
18+
for p in os.environ['PYTHONPATH'].split(':'):
19+
if not p in sys.path:
20+
sys.path.append(p)
21+
except:
22+
pass
23+
24+
try:
25+
sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
26+
except:
27+
pass
28+
from com.dtmilano.android.viewclient import ViewClient, View
29+
30+
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
31+
32+
33+
device = MonkeyRunner.waitForConnection(60, "emulator-5554")
34+
if not device:
35+
raise Exception('Cannot connect to device')
36+
37+
FLAG_ACTIVITY_NEW_TASK = 0x10000000
38+
#09-06 01:01:34.964: I/ActivityManager(873): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.android.apis/.ApiDemos bnds=[784,346][880,442]} from pid 991
39+
componentName = 'com.example.android.apis/.ApiDemos'
40+
device.startActivity(component=componentName, flags=FLAG_ACTIVITY_NEW_TASK)
41+
42+
MonkeyRunner.sleep(3)
43+
vc = ViewClient(device)
44+
app = vc.findViewWithText('App')
45+
if app:
46+
app.touch()
47+
MonkeyRunner.sleep(3)
48+
# windows changed, request a new dump
49+
vc.dump()
50+
ad = vc.findViewWithText('Alert Dialogs')
51+
if ad:
52+
ad.touch()
53+
MonkeyRunner.sleep(3)
54+
# windows changed, request a new dump
55+
vc.dump()
56+
ld = vc.findViewWithText('List dialog')
57+
if ld:
58+
ld.touch()
59+
MonkeyRunner.sleep(3)
60+
# windows changed, request a new dump
61+
vc.dump()
62+
c3 = vc.findViewWithText('Command three')
63+
if c3:
64+
c3.touch()
65+
MonkeyRunner.sleep(10)
66+
device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)
67+
else:
68+
print >> sys.stderr, "Cannot find 'Command three'"
69+
else:
70+
print >> sys.stderr, "Cannot find 'List dialog'"
71+
else:
72+
print >> sys.stderr, "Cannot find 'Alert Dialogs'"
73+
else:
74+
print >> sys.stderr, "Cannot find 'App'"
75+

AndroidViewClient/src/com/dtmilano/android/viewclient.py

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@
4242
GET_VISIBILITY_PROPERTY = 'getVisibility()'
4343
LAYOUT_TOP_MARGIN_PROPERTY = 'layout:layout_topMargin'
4444

45+
def __nd(name):
46+
'''
47+
Returns a named decimal
48+
'''
49+
return '(?P<%s>\d+)' % name
50+
51+
def __nh(name):
52+
'''
53+
Returns a named hexa
54+
'''
55+
return '(?P<%s>[0-9a-f]+)' % name
56+
4557

4658
class View:
4759
'''
@@ -58,6 +70,8 @@ def __init__(self, map, device):
5870
self.device = device
5971
self.children = []
6072
self.parent = None
73+
self.windows = {}
74+
self.currentFocus = None
6175

6276
def __getitem__(self, key):
6377
return self.map[key]
@@ -189,13 +203,15 @@ def getXY(self):
189203
if DEBUG_COORDS: print >> sys.stderr, " getXY: skipping %s %s" % (parent.getClass(), parent.getId())
190204
parent = parent.parent
191205
continue
192-
if DEBUG_COORDS: print >> sys.stderr, " getXY: parent=%s y=%d hy=%d" % (parent.getId(), y, hy)
206+
if DEBUG_COORDS: print >> sys.stderr, " getXY: parent=%s x=%d hx=%d y=%d hy=%d" % (parent.getId(), x, hx, y, hy)
193207
hx += parent.getX()
194208
hy += parent.getY()
195209
parent = parent.parent
196210

197-
if DEBUG_COORDS: print >>sys.stderr, " getXY: returning (%d, %d) ***" % (x+hx, y+hy)
198-
return (x+hx, y+hy)
211+
(wvx, wvy) = self.__dumpWindowsInformation()
212+
if DEBUG_COORDS: print >>sys.stderr, " getXY: wv=(%d, %d)" % (wvx, wvy)
213+
if DEBUG_COORDS: print >>sys.stderr, " getXY: returning (%d, %d) ***" % (x+hx+wvx, y+hy+wvy)
214+
return (x+hx+wvx, y+hy+wvy)
199215

200216
def getCoords(self):
201217
'''
@@ -209,6 +225,59 @@ def getCoords(self):
209225
h = self.getHeight()
210226
return ((x, y), (x+w, y+h))
211227

228+
def __obtainVxVy(self, m):
229+
wvx = int(m.group('vx'))
230+
wvy = int(m.group('vy'))
231+
return wvx, wvy
232+
233+
def __dumpWindowsInformation(self):
234+
self.windows = {}
235+
self.currentFocus = None
236+
lines = self.device.shell('dumpsys window windows').split('\n')
237+
widRE = re.compile('^ *Window #%s Window{%s (?P<activity>\S+).*}:' %
238+
(__nd('num'), __nh('winId')))
239+
currentFocusRE = re.compile('^ mCurrentFocus=Window{%s .*' % __nh('winId'))
240+
# This is for 4.0.4 API-15
241+
contentFrameRE = re.compile('^ *mContentFrame=\[%s,%s\]\[%s,%s\] mVisibleFrame=\[%s,%s\]' %
242+
(__nd('x'), __nd('y'), __nd('w'), __nd('h'), __nd('vx'), __nd('vy')))
243+
# This is for 4.1 API-16
244+
framesRE = re.compile('^ *Frames:')
245+
contentRE = re.compile('^ *content=\[%s,%s\]\[%s,%s\] visible=\[%s,%s\]' %
246+
(__nd('x'), __nd('y'), __nd('w'), __nd('h'), __nd('vx'), __nd('vy')))
247+
248+
for l in range(len(lines)):
249+
m = widRE.search(lines[l])
250+
if m:
251+
num = int(m.group('num'))
252+
winId = m.group('winId')
253+
activity = m.group('activity')
254+
wvx = 0
255+
wvy = 0
256+
for l2 in range(l+1, len(lines)):
257+
m = widRE.search(lines[l2])
258+
if m:
259+
l += (l2-1)
260+
break
261+
m = framesRE.search(lines[l2])
262+
if m:
263+
m = contentRE.search(lines[l2+1])
264+
if m:
265+
wvx, wvy = self.__obtainVxVy(m)
266+
else:
267+
m = contentFrameRE.search(lines[l2])
268+
if m:
269+
wvx, wvy = self.__obtainVxVy(m)
270+
self.windows[winId] = (wvx, wvy)
271+
else:
272+
m = currentFocusRE.search(lines[l])
273+
if m:
274+
self.currentFocus = m.group('winId')
275+
276+
if self.currentFocus in self.windows:
277+
return self.windows[self.currentFocus]
278+
else:
279+
return (0,0)
280+
212281
def touch(self, type=MonkeyDevice.DOWN_AND_UP):
213282
'''
214283
Touches this View
@@ -218,7 +287,7 @@ def touch(self, type=MonkeyDevice.DOWN_AND_UP):
218287
if DEBUG_TOUCH:
219288
print >>sys.stderr, "should touch @ (%d, %d)" % (x+OFFSET, y+OFFSET)
220289
self.device.touch(x+OFFSET, y+OFFSET, type)
221-
290+
222291
def allPossibleNamesWithColon(self, name):
223292
l = []
224293
for i in range(name.count("_")):
@@ -597,6 +666,9 @@ def getViewIds(self):
597666
'''
598667

599668
return self.viewsById
669+
670+
def __getFocusedWindowPosition(self):
671+
focusedWindowId = self.__getFocusedWindowId()
600672

601673

602674
if __name__ == "__main__":

0 commit comments

Comments
 (0)