OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. |
| 6 |
| 7 # DESCRIPTION : |
| 8 # |
| 9 # Intended for use during manufacturing to validate that all touchpad |
| 10 # features function properly. Run normally, this program will display a |
| 11 # touchpad image and buttons will be highlighted as they are pressed and |
| 12 # released. Once all functions have been used, a brief 'PASS' message will |
| 13 # be displayed and the test will terminate. After the first button is |
| 14 # hit, a countdown will begin. If not all buttons are used in time, the |
| 15 # test will fail with an 'ERROR' message that is displayed forever. |
| 16 |
| 17 import cairo |
| 18 import gobject |
| 19 import gtk |
| 20 import os |
| 21 import sys |
| 22 import time |
| 23 |
| 24 class Button: |
| 25 def __init__(self, coords): |
| 26 self._pressed = False |
| 27 self._released = False |
| 28 self._coords = coords |
| 29 |
| 30 class TouchpadTest: |
| 31 # Coordinates of buttons we need to highlight. |
| 32 left_button_coords = (65, 321, 255, 93) |
| 33 right_button_coords = (321, 321, 254, 93) |
| 34 |
| 35 # How long TouchpadTest allows in seconds from the first move or button |
| 36 # pressed until defaulting to the failure condition. |
| 37 timeout = 50 |
| 38 |
| 39 # How long to display the success message in seconds before exit. |
| 40 pass_msg_timeout = 2 |
| 41 |
| 42 # Background color and alpha for the final result message. |
| 43 bg_rgba_error = (0.7, 0, 0, 0.9) |
| 44 bg_rgba_pass = ( 0, 0.7, 0, 0.9) |
| 45 |
| 46 # Highlight color and alpha to indicate activated keys. |
| 47 rgba_press_and_release = ( 0, 0.5, 0, 0.6) |
| 48 rgba_press_only = (0.6, 0.6, 0, 0.6) |
| 49 |
| 50 def __init__(self, image, exit_on_error=False): |
| 51 self._image = image |
| 52 self._exit_on_error = exit_on_error |
| 53 self._deadline = None |
| 54 self._success = None |
| 55 self._buttons = {} |
| 56 self._buttons[1] = Button(TouchpadTest.left_button_coords) |
| 57 self._buttons[3] = Button(TouchpadTest.right_button_coords) |
| 58 |
| 59 def has_test_passed(self): |
| 60 for key in self._buttons.keys(): |
| 61 if (not self._buttons[key]._pressed or |
| 62 not self._buttons[key]._released): |
| 63 return False |
| 64 return True |
| 65 |
| 66 def show_result(self, widget, context, text, bg_rgba): |
| 67 widget_width, widget_height = widget.get_size_request() |
| 68 context.save() |
| 69 context.scale(widget_width / 1.0, widget_height / 1.0) |
| 70 context.rectangle(0.05, 0.05, 0.9, 0.9) |
| 71 context.set_source_rgba(*bg_rgba) |
| 72 context.fill() |
| 73 context.set_source_rgba(0.1, 0.1, 0.1, 0.95) |
| 74 context.select_font_face( |
| 75 'Verdana', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) |
| 76 context.set_font_size(0.2) |
| 77 x_bearing, y_bearing, width, height = context.text_extents(text)[:4] |
| 78 context.move_to(0.5 - (width / 2) - x_bearing, |
| 79 0.5 - (height / 2) - y_bearing) |
| 80 context.show_text(text) |
| 81 context.restore() |
| 82 |
| 83 def start_countdown(self, duration): |
| 84 self._deadline = int(time.time()) + duration |
| 85 |
| 86 def show_countdown(self, widget, context): |
| 87 countdown = self._deadline - int(time.time()) |
| 88 width, height = widget.get_size_request() |
| 89 text = '%3d' % countdown |
| 90 context.save() |
| 91 context.translate(width - 60, height) |
| 92 context.set_source_rgb(0.5, 0.5, 0.5) |
| 93 context.select_font_face( |
| 94 'Courier New', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) |
| 95 context.set_font_size(20) |
| 96 x_bearing, y_bearing = context.text_extents('000')[:2] |
| 97 context.move_to(x_bearing, y_bearing) |
| 98 context.show_text(text) |
| 99 context.restore() |
| 100 |
| 101 def timer_event(self, window): |
| 102 if not self._deadline: |
| 103 # Ignore timer events with no countdown in progress. |
| 104 return True |
| 105 if self._deadline <= time.time(): |
| 106 self._deadline = None |
| 107 if self._success is None: |
| 108 self._success = False |
| 109 if self._exit_on_error: |
| 110 sys.exit(1) |
| 111 elif self._success: |
| 112 sys.exit(0) |
| 113 window.queue_draw() |
| 114 return True |
| 115 |
| 116 def expose_event(self, widget, event): |
| 117 context = widget.window.cairo_create() |
| 118 |
| 119 # Show touchpad image as the background. |
| 120 context.set_source_surface(self._image, 0, 0) |
| 121 context.paint() |
| 122 |
| 123 # Boolean values for success correspond with test pass or |
| 124 # failure. None means normal operation. |
| 125 if self._success is None: |
| 126 for key in self._buttons.keys(): |
| 127 color = None |
| 128 if self._buttons[key]._released: |
| 129 color = TouchpadTest.rgba_press_and_release |
| 130 elif self._buttons[key]._pressed: |
| 131 color = TouchpadTest.rgba_press_only |
| 132 else: |
| 133 continue |
| 134 coords = self._buttons[key]._coords |
| 135 context.rectangle(*coords) |
| 136 context.set_source_rgba(*color) |
| 137 context.fill() |
| 138 if self._deadline: |
| 139 self.show_countdown(widget, context) |
| 140 elif self._success: |
| 141 self.show_result(widget, context, 'PASS', |
| 142 TouchpadTest.bg_rgba_pass) |
| 143 else: |
| 144 self.show_result(widget, context, 'ERROR', |
| 145 TouchpadTest.bg_rgba_error) |
| 146 return False |
| 147 |
| 148 def button_press_event(self, widget, event): |
| 149 if self._success is not None: |
| 150 return True |
| 151 if not event.button in self._buttons.keys(): |
| 152 return True |
| 153 |
| 154 if self._deadline is None: |
| 155 self.start_countdown(TouchpadTest.timeout) |
| 156 self._buttons[event.button]._pressed = True |
| 157 widget.queue_draw() |
| 158 return True |
| 159 |
| 160 def button_release_event(self, widget, event): |
| 161 if self._success is not None: |
| 162 return True |
| 163 if not event.button in self._buttons.keys(): |
| 164 return True |
| 165 |
| 166 self._buttons[event.button]._released = True |
| 167 if self.has_test_passed(): |
| 168 self._success = True |
| 169 self.start_countdown(TouchpadTest.pass_msg_timeout) |
| 170 widget.queue_draw() |
| 171 return True |
| 172 |
| 173 def main(): |
| 174 window = gtk.Window(gtk.WINDOW_TOPLEVEL) |
| 175 window.set_name('Touchpad Test') |
| 176 window.connect('destroy', lambda w: gtk.main_quit()) |
| 177 |
| 178 bg_color = gtk.gdk.color_parse('midnight blue') |
| 179 window.modify_bg(gtk.STATE_NORMAL, bg_color) |
| 180 |
| 181 touchpad_image = cairo.ImageSurface.create_from_png('touchpad.png') |
| 182 touchpad_image_size = (touchpad_image.get_width(), |
| 183 touchpad_image.get_height()) |
| 184 |
| 185 drawing_area = gtk.DrawingArea() |
| 186 drawing_area.set_size_request(*touchpad_image_size) |
| 187 |
| 188 exit_on_error = False |
| 189 if '--exit-on-error' in sys.argv: |
| 190 exit_on_error = True |
| 191 tt = TouchpadTest(touchpad_image, exit_on_error=exit_on_error) |
| 192 screen = window.get_screen() |
| 193 screen_size = (screen.get_width(), screen.get_height()) |
| 194 window.set_default_size(*screen_size) |
| 195 window.connect('button_press_event', tt.button_press_event) |
| 196 window.connect('button_release_event', tt.button_release_event) |
| 197 gobject.timeout_add(1000, tt.timer_event, window) |
| 198 |
| 199 drawing_area.connect('expose_event', tt.expose_event) |
| 200 |
| 201 drawing_area.show() |
| 202 |
| 203 align = gtk.Alignment(xalign=0.5, yalign=0.5) |
| 204 align.add(drawing_area) |
| 205 align.show() |
| 206 |
| 207 drawing_area.set_events(gtk.gdk.EXPOSURE_MASK | |
| 208 gtk.gdk.BUTTON_PRESS_MASK | |
| 209 gtk.gdk.BUTTON_RELEASE_MASK) |
| 210 |
| 211 window.add(align) |
| 212 window.show() |
| 213 |
| 214 gtk.main() |
| 215 |
| 216 return (tt._success != True) |
| 217 |
| 218 if __name__ == '__main__': |
| 219 main() |
OLD | NEW |