Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: tools/accessibility/nvda/winapi.py

Issue 660633002: Fixed IAccessibleText::TextAtOffset with IA2_TEXT_BOUNDARY_WORD to return text that spans from the … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Broke up different boundary tests in their own test cases. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Windows API functions required by tests of Chrome with NVDA."""
7
8
9 from ctypes import wintypes
10
11 import ctypes
12
13 _user = ctypes.windll.user32
14 # Argument types for Windows API functions.
15 _user.VkKeyScanW.argtypes = [wintypes.WCHAR]
16 _user.VkKeyScanW.restype = wintypes.SHORT
17 _ENUM_WINDOWS_CALLBACK = ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintyp es.LPARAM)
18 _user.EnumWindows.argtypes = [_ENUM_WINDOWS_CALLBACK, wintypes.LPARAM]
19 _user.GetWindowThreadProcessId.argtypes = [wintypes.HWND, ctypes.POINTER(wintype s.DWORD)]
20 # Flags required by some API calls.
21 _MAP_VKCODE_TO_SCAN_CODE = 0
22 _PRESS_KEY = 0
23 _RELEASE_KEY = 2
24
25 _MODIFIER_KEYS = {
26 'shift': 0x10,
27 'control': 0x11,
28 'alt': 0x12,
29 'windows': 0x5B,
30
31 # Screen reader modifiers.
32 'insert': 0x2D,
33 'capslock': 0x14,
34 }
35
36 _SPECIAL_KEYS = {
37 'enter': 0x0D,
38 'space': 0x20,
39 'tab': 0x09,
40 'applications': 0x5D, # Context menu key.
41 'escape': 0x1B,
42 'backspace': 0x08,
43 'delete': 0x2E,
44
45 # Navigation keys.
46 'pageup': 0x21,
47 'pagedown': 0x22,
48 'end': 0x23,
49 'home': 0x24,
50 'left': 0x25,
51 'up': 0x26,
52 'right': 0x27,
53 'down': 0x28,
54
55 # Browser keys.
56 'back': 0xA6,
57 'forward': 0xA7,
58 'refresh': 0xA8,
59 'home': 0xAC,
60 }
61
62 def _getKeyAndScanCode(key):
63 if key[0] == '{' and key[-1] == '}':
64 # This is a modifier or a special key.
65 key = key[1:-1]
66 keyCode = dict(_MODIFIER_KEYS.items() + _SPECIAL_KEYS.items()).get(key)
67 if keyCode is not None:
68 return keyCode, _user.MapVirtualKeyW(keyCode, _MAP_VKCODE_TO_SCAN_CODE)
69 else:
70 raise ValueError, key
71 else:
72 # This is a character to be typed.
73 keyCodes = []
74 retVal = _user.VkKeyScanW(key)
75 modifiers = retVal >> 8 # Upper byte only.
76 keyCode = retVal & 0xFF # Lower byte only.
77 if modifiers == -1 or keyCode == -1:
78 raise ValueError, key
79 if modifiers & 0x1: # Shift key.
80 keyCodes.append(_getKeyAndScanCode('{shift}'))
81 if modifiers & 0x2: # Control key.
82 keyCodes.append(_getKeyAndScanCode('{control}'))
83 if modifiers & 0x4: # Alt key.
84 keyCodes.append(_getKeyAndScanCode('{alt}'))
85 keyCodes.append((keyCode, _user.MapVirtualKeyW(keyCode, _MAP_VKCODE_TO_SCAN_ CODE)))
86 return keyCodes
87
88 def typeKeys(keys):
89 """Enters the given keys in the active application's input queue.
90
91 The argument to this function should be a string containing a sequence of
92 keys to be pressed. Keys are separated using '+'. Special keys like control
93 should be placed in braces.
94 Examples:
95 Open the Task Manager: winapi.typeKeys('{control}+{shift}{escape}')
96 Read the current line using NVDA: winapi.typeKeys('{insert}{up}')
97 Type a combination of capital and small letters: winapi.typeKeys('TeStIng')
98 """
99 try:
100 pressedModifiers = []
101 for key in keys.split('+'):
102 if key[0] == '{' and key[-1] == '}':
103 # This is a modifier or a special key.
104 keyCode, scanCode = _getKeyAndScanCode(key)
105 _user.keybd_event(keyCode, scanCode, _PRESS_KEY)
106 if key[1:-1] in _MODIFIER_KEYS:
107 pressedModifiers.append((keyCode, scanCode))
108 else:
109 # Key is a sequence of one or more characters.
110 textCodes = [_getKeyAndScanCode(c) for c in key]
111 for charCodes in textCodes:
112 for keyCode, scanCode in charCodes:
113 _user.keybd_event(keyCode, scanCode, _PRESS_KEY)
114 for keyCode, scanCode in reversed(charCodes):
115 _user.keybd_event(keyCode, scanCode, _RELEASE_KEY)
116 except ValueError:
117 raise
118 finally:
119 # Release any modifiers in reverse order.
120 for keyCode, scanCode in reversed(pressedModifiers):
121 _user.keybd_event(keyCode, scanCode, _RELEASE_KEY)
122
123 def _getWindowHandleFromProcessId(processId):
124 hWnds = []
125 def enumWindowsCallback(hWnd, lParam):
126 if _isWindowHandleOwnedByProcess(processId, hWnd):
127 hWnds.append(hWnd)
128 return True # Continue enumerating.
129 _user.EnumWindows(_ENUM_WINDOWS_CALLBACK(enumWindowsCallback), 0)
130 return hWnds[0] if len(hWnds) > 0 else None
131
132 def _isWindowHandleOwnedByProcess(processId, hWnd):
133 windowProcessId = wintypes.DWORD()
134 if _user.GetWindowThreadProcessId(hWnd, ctypes.byref(windowProcessId)):
135 if windowProcessId.value == processId:
136 return True
137 return False
138
139 def focusWindow(processId):
140 hWnd = _getWindowHandleFromProcessId(processId)
141 if hWnd is None:
142 raise ValueError, processId
143 _user.SwitchToThisWindow(hWnd)
144
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698