114 lines
4.4 KiB
Python
114 lines
4.4 KiB
Python
# Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import logging
|
|
import os
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.cros.graphics import graphics_utils
|
|
from autotest_lib.client.cros.input_playback import input_playback
|
|
|
|
_CLICK_EVENTS = '/tmp/click_events'
|
|
_CLICK_TEMPLATE = 'click_events.template'
|
|
_PREFIX_RESOLUTION = 'RESOLUTION'
|
|
_PREFIX_POSITION = 'POSITION'
|
|
_STYLUS_DEVICE = 'stylus'
|
|
_STYLUS_PROPERTY = '/tmp/stylus.prop'
|
|
_STYLUS_TEMPLATE = 'stylus.prop.template'
|
|
|
|
|
|
class Stylus(object):
|
|
"""An emulated stylus device used for UI automation."""
|
|
|
|
def __init__(self):
|
|
"""Prepare an emulated stylus device based on the internal display."""
|
|
self.dirname = os.path.dirname(__file__)
|
|
width, height = graphics_utils.get_internal_resolution()
|
|
logging.info('internal display W = %d H = %d ', width, height)
|
|
# Skip the test if there is no internal display
|
|
if width == -1:
|
|
raise error.TestNAError('No internal display')
|
|
|
|
# Enlarge resolution of the emulated stylus.
|
|
self.width = width * 10
|
|
self.height = height * 10
|
|
stylus_template = os.path.join(self.dirname, _STYLUS_TEMPLATE)
|
|
self.replace_with_prefix(stylus_template, _STYLUS_PROPERTY,
|
|
_PREFIX_RESOLUTION, self.width, self.height)
|
|
# Create an emulated stylus device.
|
|
self.stylus = input_playback.InputPlayback()
|
|
self.stylus.emulate(input_type=_STYLUS_DEVICE,
|
|
property_file=_STYLUS_PROPERTY)
|
|
self.stylus.find_connected_inputs()
|
|
|
|
def replace_with_prefix(self, in_file, out_file, prefix, x_value, y_value):
|
|
"""Substitute with the real positions and write to an output file.
|
|
|
|
Replace the keywords in template file with the real values and save
|
|
the results into a file.
|
|
|
|
@param in_file: the template file containing keywords for substitution.
|
|
@param out_file: the generated file after substitution.
|
|
@param prefix: the prefix of the keywords for substituion.
|
|
@param x_value: the target value of X.
|
|
@param y_value: the target value of Y.
|
|
|
|
"""
|
|
with open(in_file) as infile:
|
|
content = infile.readlines()
|
|
|
|
with open(out_file, 'w') as outfile:
|
|
for line in content:
|
|
if line.find(prefix + '_X') > 0:
|
|
line = line.replace(prefix + '_X', str(x_value))
|
|
x_value += 1
|
|
else:
|
|
if line.find(prefix + '_Y') > 0:
|
|
line = line.replace(prefix + '_Y', str(y_value))
|
|
y_value += 1
|
|
outfile.write(line)
|
|
|
|
def click(self, position_x, position_y):
|
|
"""Click the point(x,y) on the emulated stylus panel.
|
|
|
|
@param position_x: the X position of the click point.
|
|
@param position_y: the Y position of the click point.
|
|
|
|
"""
|
|
click_template = os.path.join(self.dirname, _CLICK_TEMPLATE)
|
|
self.replace_with_prefix(click_template,
|
|
_CLICK_EVENTS,
|
|
_PREFIX_POSITION,
|
|
position_x * 10,
|
|
position_y * 10)
|
|
self.stylus.blocking_playback(_CLICK_EVENTS, input_type=_STYLUS_DEVICE)
|
|
|
|
def click_with_percentage(self, percent_x, percent_y):
|
|
"""Click a point based on the percentage of the display.
|
|
|
|
@param percent_x: the percentage of X position over display width.
|
|
@param percent_y: the percentage of Y position over display height.
|
|
|
|
"""
|
|
position_x = int(percent_x * self.width / 10)
|
|
position_y = int(percent_y * self.height / 10)
|
|
self.click(position_x, position_y)
|
|
|
|
def close(self):
|
|
"""Clean up the files/handles created in the class."""
|
|
if self.stylus:
|
|
self.stylus.close()
|
|
if os.path.exists(_STYLUS_PROPERTY):
|
|
os.remove(_STYLUS_PROPERTY)
|
|
if os.path.exists(_CLICK_EVENTS):
|
|
os.remove(_CLICK_EVENTS)
|
|
|
|
def __enter__(self):
|
|
"""Allow usage in 'with' statements."""
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
"""Release resources on completion of a 'with' statement."""
|
|
self.close()
|