Index: client/bin/factory_ui |
diff --git a/client/bin/factory_ui b/client/bin/factory_ui |
index ba0767eb2af038c5597a70223f011437a8e48bb6..44051bb5f1751bc7fc438ebcc11b7814580f9127 100755 |
--- a/client/bin/factory_ui |
+++ b/client/bin/factory_ui |
@@ -28,6 +28,7 @@ import gtk |
import imp |
import os |
import pango |
+import signal |
import subprocess |
import sys |
import time |
@@ -36,6 +37,10 @@ import common |
import factory |
import factory_ui_lib as ful |
+from gtk import gdk |
+from Xlib import X |
+from Xlib.display import Display as X_Display |
+ |
# These definitions are expose these classes directly into this |
# namespace, so that the test_list that is sent from the control file |
@@ -49,8 +54,6 @@ AutomatedSubTest = factory.AutomatedSubTest |
AutomatedRebootSubTest = factory.AutomatedRebootSubTest |
-_SEP_COLOR = gtk.gdk.color_parse('grey50') |
- |
_LABEL_EN_SIZE = (170, 35) |
_LABEL_ZW_SIZE = (70, 35) |
_LABEL_EN_FONT = pango.FontDescription('courier new extra-condensed 16') |
@@ -160,7 +163,7 @@ class SubTestLabelBox(gtk.EventBox): |
class UiState(): |
- def __init__(self, window, status_map, test_widget_box): |
+ def __init__(self, status_map, test_widget_box): |
def make_empty_test_label_widget(): |
label_box = gtk.EventBox() |
@@ -180,7 +183,6 @@ class UiState(): |
False, False) |
return vbox |
- self._window = window |
self._status_map = status_map |
self._test_widget_box = test_widget_box |
self._empty_test_widget = make_empty_test_label_widget() |
@@ -212,21 +214,7 @@ class UiState(): |
or self._empty_test_widget) |
self._test_widget_box.add(active_widget) |
self._active_test_widget = active_widget |
- self._window.show_all() |
- |
- |
-def make_hsep(width=1): |
- frame = gtk.EventBox() |
- frame.set_size_request(-1, width) |
- frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) |
- return frame |
- |
- |
-def make_vsep(width=1): |
- frame = gtk.EventBox() |
- frame.set_size_request(width, -1) |
- frame.modify_bg(gtk.STATE_NORMAL, _SEP_COLOR) |
- return frame |
+ self._test_widget_box.show_all() |
def refresh_status(status_map, ui_state): |
@@ -236,25 +224,46 @@ def refresh_status(status_map, ui_state): |
return True |
-def main(): |
- '''This process is launched by the autotest suite_Factory control |
- process. Communication with this process is an exchange of well |
- formed python expressions over stdin and stdout. Basically |
- sending wraps arguments in a call to repr() and recv calls eval() |
- to re-generate the python data.''' |
+def grab_shortcut_keys(kbd_shortcut_set, control_pid): |
+ disp = X_Display() |
+ root = disp.screen().root |
+ |
+ # We want to receive KeyPress events |
+ root.change_attributes(event_mask = X.KeyPressMask) |
+ |
+ keycode_map = {} |
+ for shortcut in kbd_shortcut_set: |
+ keysym = gdk.keyval_from_name(shortcut) |
+ keycode = disp.keysym_to_keycode(keysym) |
+ keycode_map[keycode] = shortcut |
+ root.grab_key(keycode, X.ControlMask, 1, |
+ X.GrabModeAsync, X.GrabModeAsync) |
- def control_recv(): |
- return eval(sys.stdin.readline().rstrip()) |
+ # This flushes the XGrabKey calls to the server. |
+ for x in range(0, root.display.pending_events()): |
+ root.display.next_event() |
- def control_send(x): |
- print repr(x) |
- sys.stdout.flush() |
+ def handle_xevent(src, cond, xhandle=root.display, |
+ keycode_map=keycode_map, |
+ control_pid=control_pid): |
+ for i in range(0, xhandle.pending_events()): |
+ xevent = xhandle.next_event() |
+ if xevent.type == X.KeyPress: |
+ keycode = xevent.detail |
+ factory.log_shared_data('activated_kbd_shortcut', |
+ keycode_map[keycode]) |
+ os.kill(control_pid, signal.SIGUSR1) |
+ return True |
- # On startup, get the list of tests to run (in order) and the |
- # autotest status file path. |
- factory.log('pulling control info') |
- test_list = control_recv() |
- status_file_path = control_recv() |
+ gobject.io_add_watch(root.display, gobject.IO_IN, handle_xevent) |
+ |
+ |
+def main(test_list, status_file_path, control_pid): |
+ '''This process is launched by the autotest suite_Factory control |
+ process, which should be identified by the <control pid> cmdline |
+ argument. When operators press keyboard shortcuts, the shortcut |
+ value is logged with log_shared_data() and a SIGUSR1 is sent to |
+ the control program.''' |
status_map = factory.StatusMap(test_list, status_file_path) |
@@ -263,6 +272,11 @@ def main(): |
window.modify_bg(gtk.STATE_NORMAL, ful.BLACK) |
screen = window.get_screen() |
+ if (screen is None): |
+ log('ERROR: communication with the X server is not working, ' + |
+ 'could not find a working screen. UI exiting.') |
+ sys.exit(1) |
+ |
screen_size = (screen.get_width(), screen.get_height()) |
window.set_size_request(*screen_size) |
@@ -280,16 +294,16 @@ def main(): |
test_widget_box = gtk.Alignment(xalign=0.5, yalign=0.5) |
test_widget_box.set_size_request(-1, -1) |
- ui_state = UiState(window, status_map, test_widget_box) |
+ ui_state = UiState(status_map, test_widget_box) |
lhs_box = gtk.VBox() |
lhs_box.pack_end(console_box, False, False) |
lhs_box.pack_start(test_widget_box) |
- lhs_box.pack_start(make_hsep(3), False, False) |
+ lhs_box.pack_start(ful.make_hsep(3), False, False) |
base_box = gtk.HBox() |
base_box.pack_end(rhs_box, False, False) |
- base_box.pack_end(make_vsep(3), False, False) |
+ base_box.pack_end(ful.make_vsep(3), False, False) |
base_box.pack_start(lhs_box) |
window.connect('key-release-event', handle_key_release_event) |
@@ -302,18 +316,19 @@ def main(): |
label_box = TestLabelBox(test) |
status_map.set_label_box(test, label_box) |
label_trough.pack_start(label_box, False, False) |
- label_trough.pack_start(make_hsep(), False, False) |
+ label_trough.pack_start(ful.make_hsep(), False, False) |
window.add(base_box) |
window.show_all() |
+ grab_shortcut_keys(status_map.test_db.kbd_shortcut_set, control_pid) |
+ |
ful.hide_cursor(window.window) |
test_widget_allocation = test_widget_box.get_allocation() |
test_widget_size = (test_widget_allocation.width, |
test_widget_allocation.height) |
- factory.log('test_widget_size = %s' % repr(test_widget_size)) |
- control_send(test_widget_size) |
+ factory.log_shared_data('test_widget_size', test_widget_size) |
console = Console(console_box.get_allocation()) |
@@ -324,4 +339,13 @@ def main(): |
factory.log('factory_ui gtk.main() finished, exiting.') |
if __name__ == '__main__': |
- main() |
+ |
+ if len(sys.argv) != 4: |
+ print ('usage: %s <test list path> <status file path> <control pid>' % |
+ sys.argv[0]) |
+ test_list_path, status_file_path, control_pid_str = sys.argv[1:] |
+ control_pid = int(control_pid_str) |
+ |
+ execfile(test_list_path) |
+ |
+ main(TEST_LIST, status_file_path, control_pid) |