Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some fixes before syncing macOS branch #1303

Open
wants to merge 3 commits into
base: atspi
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion pywinauto/findbestmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ def get_control_names(control, allcontrols, textcontrols):
# Todo - I don't like the hardcoded classnames here!
if cleaned and control.has_title:
names.append(cleaned)
names.append(cleaned + friendly_class_name)
names.append(cleaned + six.text_type(friendly_class_name))
elif control.has_title and friendly_class_name != 'TreeView':
try:
for text in control.texts()[1:]:
Expand Down
7 changes: 7 additions & 0 deletions pywinauto/unittests/test_keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,13 @@ def testAltModifier(self):
received = self.receive_text()
self.assertEqual('abc', received)

def test_issue_1278__utf32_surrogate_pair_of_utf16(self):
"""Make sure that typing Uniocode symbols beyond U+ffff works (issue #1278)"""
cherry_symbol = '\ud83c\udf52'.encode('utf-16', errors="surrogatepass").decode("utf-16")
send_keys(cherry_symbol)
received = self.receive_text()
self.assertEqual(cherry_symbol, received)


if sys.platform == 'win32':
class SendKeysModifiersTests(unittest.TestCase):
Expand Down
44 changes: 39 additions & 5 deletions pywinauto/windows/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,31 +736,65 @@
"""
return self._get_key_info()

def _get_utf_16_surrogate_pair(self):
"""Return 2 scan codes of utf-16 surrogate pair for utf-32 symbol beyond \uFFFF"""
scan_utf32 = ord(self.key)
code = (scan_utf32 - 0x10000)
return 0xD800 | (code >> 10), 0xDC00 | (code & 0x3FF)

def GetInput(self):
"""Build the INPUT structure for the action"""
vk, scan, flags = self._get_key_info()

actions = 1
# if both up and down
if self.up and self.down:
actions = 2

# utf-32 4 byte symbol requires utf-16 surrogate pair
if 0xffff < scan <= 0x10ffff:
actions *= 2
scan_codes = self._get_utf_16_surrogate_pair()
else:
scan_codes = (scan, scan)

inputs = (win32structures.INPUT * actions)()

vk, scan, flags = self._get_key_info()
if self.down:
if self.up:
# reference to the first half of array
down_inputs = (win32structures.INPUT * (actions // 2)).from_buffer(inputs)
else:
# reference to the whole array
down_inputs = (win32structures.INPUT * actions).from_buffer(inputs)
if self.up:
if self.down:
# reference to the second half of array
up_inputs = (win32structures.INPUT * (actions // 2)).from_buffer(inputs, sizeof(win32structures.INPUT) * (actions // 2))
else:
# reference to the whole array
up_inputs = (win32structures.INPUT * actions).from_buffer(inputs)

for inp in inputs:
def _fill_input_struct(input_instance, scan_code, input_flags):
inp.type = INPUT_KEYBOARD

inp.ki.wVk = vk
inp.ki.wScan = scan
inp.ki.wScan = scan_code
inp.ki.dwFlags |= flags

# it seems to return 0 every time but it's required by MSDN specification
# so call it just in case
inp.ki.dwExtraInfo = win32functions.GetMessageExtraInfo()

# if we are releasing - then let it up
if self.down:
for i, inp in enumerate(down_inputs):

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'down_inputs' may be used before it is initialized.
_fill_input_struct(inp, scan_codes[i], flags)

if self.up:
inputs[-1].ki.dwFlags |= KEYEVENTF_KEYUP
# if we are releasing - then let it up
flags |= KEYEVENTF_KEYUP
for i, inp in enumerate(up_inputs):

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'up_inputs' may be used before it is initialized.
_fill_input_struct(inp, scan_codes[i], flags)

return inputs

Expand Down
10 changes: 7 additions & 3 deletions pywinauto/windows/uia_element_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,8 @@ def rectangle(self):
rect.top = bound_rect.top
rect.right = bound_rect.right
rect.bottom = bound_rect.bottom
except COMError:
pass
except COMError as e:
warnings.warn("Can't get element rectangle due to error: {}".format(e), RuntimeWarning)
return rect

def dump_window(self):
Expand Down Expand Up @@ -548,7 +548,11 @@ def __eq__(self, other):
"""Check if 2 UIAElementInfo objects describe 1 actual element"""
if not isinstance(other, UIAElementInfo):
return False
return bool(IUIA().iuia.CompareElements(self.element, other.element))
try:
return bool(IUIA().iuia.CompareElements(self.element, other.element))
except COMError:
warnings.warn("Can't compare elements due to error: {}".format(e), RuntimeWarning)
return False

def __ne__(self, other):
"""Check if 2 UIAElementInfo objects describe 2 different elements"""
Expand Down