OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 |
| 6 from autotest_lib.client.bin import test |
| 7 from autotest_lib.client.common_lib import error |
| 8 from autotest_lib.client.common_lib import factory_test |
| 9 |
| 10 import cairo |
| 11 import gobject |
| 12 import gtk |
| 13 import pango |
| 14 import time |
| 15 import os |
| 16 import sys |
| 17 import subprocess |
| 18 |
| 19 |
| 20 _SYNCLIENT_SETTINGS_CMDLINE = '/usr/bin/synclient -l' |
| 21 _SYNCLIENT_CMDLINE = '/usr/bin/synclient -m 50' |
| 22 |
| 23 _RGBA_GREEN_OVERLAY = (0, 0.5, 0, 0.6) |
| 24 |
| 25 _X_SEGMENTS = 5 |
| 26 _Y_SEGMENTS = 4 |
| 27 |
| 28 _X_TP_OFFSET = 10 |
| 29 _Y_TP_OFFSET = 10 |
| 30 _TP_WIDTH = 397 |
| 31 _TP_HEIGHT = 213 |
| 32 _TP_SECTOR_WIDTH = (_TP_WIDTH / _X_SEGMENTS) - 1 |
| 33 _TP_SECTOR_HEIGHT = (_TP_HEIGHT / _Y_SEGMENTS) - 1 |
| 34 |
| 35 _X_SP_OFFSET = 432 |
| 36 _SP_WIDTH = 19 |
| 37 |
| 38 |
| 39 class TouchpadTest: |
| 40 |
| 41 def __init__(self, tp_image, drawing_area): |
| 42 self._tp_image = tp_image |
| 43 self._drawing_area = drawing_area |
| 44 self._motion_grid = {} |
| 45 for x in range(_X_SEGMENTS): |
| 46 for y in range(_Y_SEGMENTS): |
| 47 self._motion_grid['%d,%d' % (x, y)] = False |
| 48 self._scroll_array = {} |
| 49 for y in range(_Y_SEGMENTS): |
| 50 self._scroll_array[y] = False |
| 51 self._l_click = False |
| 52 self._r_click = False |
| 53 |
| 54 def timer_event(self, window): |
| 55 if not self._deadline: |
| 56 # Ignore timer events with no countdown in progress. |
| 57 return True |
| 58 if self._deadline <= time.time(): |
| 59 XXX_log('deadline reached') |
| 60 gtk.main_quit() |
| 61 window.queue_draw() |
| 62 return True |
| 63 |
| 64 def device_event(self, x, y, z, fingers, left, right): |
| 65 x_seg = int(round(x / (1.0 / float(_X_SEGMENTS - 1)))) |
| 66 y_seg = int(round(y / (1.0 / float(_Y_SEGMENTS - 1)))) |
| 67 index = '%d,%d' % (x_seg, y_seg) |
| 68 assert(index in self._motion_grid) |
| 69 assert(y_seg in self._scroll_array) |
| 70 if left and not self._l_click: |
| 71 self._l_click = True |
| 72 factory_test.XXX_log('ok left click') |
| 73 elif right and not self._r_click: |
| 74 self._r_click = True |
| 75 factory_test.XXX_log('ok right click') |
| 76 elif fingers == 1 and not self._motion_grid[index]: |
| 77 self._motion_grid[index] = True |
| 78 elif fingers == 2 and not self._scroll_array[y_seg]: |
| 79 self._scroll_array[y_seg] = True |
| 80 else: |
| 81 return |
| 82 self._drawing_area.queue_draw() |
| 83 missing_motion_sectors = set(i for i, v in self._motion_grid.items() |
| 84 if v is False) |
| 85 missing_scroll_segments = set(i for i, v in self._scroll_array.items() |
| 86 if v is False) |
| 87 if (self._l_click and self._r_click |
| 88 and not missing_motion_sectors |
| 89 and not missing_scroll_segments): |
| 90 gtk.main_quit() |
| 91 |
| 92 def expose_event(self, widget, event): |
| 93 context = widget.window.cairo_create() |
| 94 |
| 95 context.set_source_surface(self._tp_image, 0, 0) |
| 96 context.paint() |
| 97 |
| 98 for index in self._motion_grid: |
| 99 if not self._motion_grid[index]: |
| 100 continue |
| 101 ind_x, ind_y = map(int, index.split(',')) |
| 102 x = _X_TP_OFFSET + (ind_x * (_TP_SECTOR_WIDTH + 1)) |
| 103 y = _Y_TP_OFFSET + (ind_y * (_TP_SECTOR_HEIGHT + 1)) |
| 104 coords = (x, y, _TP_SECTOR_WIDTH, _TP_SECTOR_HEIGHT) |
| 105 context.rectangle(*coords) |
| 106 context.set_source_rgba(*_RGBA_GREEN_OVERLAY) |
| 107 context.fill() |
| 108 |
| 109 for y_seg in self._scroll_array: |
| 110 if not self._scroll_array[y_seg]: |
| 111 continue |
| 112 y = _Y_TP_OFFSET + (y_seg * (_TP_SECTOR_HEIGHT + 1)) |
| 113 coords = (_X_SP_OFFSET, y, _SP_WIDTH, _TP_SECTOR_HEIGHT) |
| 114 context.rectangle(*coords) |
| 115 context.set_source_rgba(*_RGBA_GREEN_OVERLAY) |
| 116 context.fill() |
| 117 |
| 118 return True |
| 119 |
| 120 def key_press_event(self, widget, event): |
| 121 factory_test.test_switch_on_trigger(event) |
| 122 return True |
| 123 |
| 124 def button_press_event(self, widget, event): |
| 125 factory_test.XXX_log('button_press_event %d,%d' % (event.x, event.y)) |
| 126 return True |
| 127 |
| 128 def button_release_event(self, widget, event): |
| 129 factory_test.XXX_log('button_release_event %d,%d' % (event.x, event.y)) |
| 130 return True |
| 131 |
| 132 def motion_event(self, widget, event): |
| 133 factory_test.XXX_log('motion_event %d,%d' % (event.x, event.y)) |
| 134 return True |
| 135 |
| 136 def register_callbacks(self, window): |
| 137 window.connect('key-press-event', self.key_press_event) |
| 138 window.add_events(gtk.gdk.KEY_PRESS_MASK) |
| 139 |
| 140 |
| 141 class SynClient: |
| 142 |
| 143 def __init__(self, test): |
| 144 self._test = test |
| 145 proc = subprocess.Popen(_SYNCLIENT_SETTINGS_CMDLINE.split(), |
| 146 stdout=subprocess.PIPE) |
| 147 settings_data = proc.stdout.readlines() |
| 148 settings = {} |
| 149 for line in settings_data: |
| 150 cols = [x for x in line.rstrip().split(' ') if x] |
| 151 if len(cols) != 3 or cols[1] != '=': |
| 152 continue |
| 153 settings[cols[0]] = cols[2] |
| 154 self._xmin = float(settings['LeftEdge']) |
| 155 self._xmax = float(settings['RightEdge']) |
| 156 self._ymin = float(settings['TopEdge']) |
| 157 self._ymax = float(settings['BottomEdge']) |
| 158 self._proc = subprocess.Popen(_SYNCLIENT_CMDLINE.split(), |
| 159 stdout=subprocess.PIPE) |
| 160 gobject.io_add_watch(self._proc.stdout, gobject.IO_IN, self.recv) |
| 161 |
| 162 def recv(self, src, cond): |
| 163 data = self._proc.stdout.readline().split() |
| 164 if len(data) != 17: |
| 165 factory_test.XXX_log('unknown data : %d, %s' % (len(data), data)) |
| 166 return True |
| 167 if data[0] == 'time': |
| 168 return True |
| 169 data_x, data_y, z, f, w, l, r = data[1:8] |
| 170 x = sorted([self._xmin, float(data_x), self._xmax])[1] |
| 171 x = (x - self._xmin) / (self._xmax - self._xmin) |
| 172 y = sorted([self._ymin, float(data_y), self._ymax])[1] |
| 173 y = (y - self._ymin) / (self._ymax - self._ymin) |
| 174 self._test.device_event(x, y, int(z), int(f), int(l), int(r)) |
| 175 return True |
| 176 |
| 177 def quit(self): |
| 178 factory_test.XXX_log('killing SynClient ...') |
| 179 self._proc.kill() |
| 180 factory_test.XXX_log('dead') |
| 181 |
| 182 |
| 183 class factory_Touchpad(test.test): |
| 184 version = 1 |
| 185 preserve_srcdir = True |
| 186 |
| 187 def run_once(self, test_widget_size=None, trigger_set=None, |
| 188 result_file_path=None): |
| 189 |
| 190 factory_test.XXX_log('factory_Touchpad') |
| 191 |
| 192 factory_test.init(trigger_set=trigger_set, |
| 193 result_file_path=result_file_path) |
| 194 |
| 195 os.chdir(self.srcdir) |
| 196 tp_image = cairo.ImageSurface.create_from_png('touchpad.png') |
| 197 image_size = (tp_image.get_width(), tp_image.get_height()) |
| 198 |
| 199 drawing_area = gtk.DrawingArea() |
| 200 |
| 201 test = TouchpadTest(tp_image, drawing_area) |
| 202 |
| 203 drawing_area.set_size_request(*image_size) |
| 204 drawing_area.connect('expose_event', test.expose_event) |
| 205 drawing_area.connect('button-press-event', test.button_press_event) |
| 206 drawing_area.connect('button-release-event', test.button_release_event) |
| 207 drawing_area.connect('motion-notify-event', test.motion_event) |
| 208 drawing_area.add_events(gtk.gdk.EXPOSURE_MASK | |
| 209 gtk.gdk.BUTTON_PRESS_MASK | |
| 210 gtk.gdk.BUTTON_RELEASE_MASK | |
| 211 gtk.gdk.POINTER_MOTION_MASK) |
| 212 |
| 213 synclient = SynClient(test) |
| 214 |
| 215 factory_test.run_test_widget( |
| 216 test_widget=drawing_area, |
| 217 test_widget_size=test_widget_size, |
| 218 window_registration_callback=test.register_callbacks, |
| 219 cleanup_callback=synclient.quit) |
| 220 |
| 221 factory_test.XXX_log('exiting factory_Touchpad') |
OLD | NEW |