/* test.c * * Copyright 2001 - 2005 Sun Microsystems, Inc., * Copyright 2001 - 2005 BAUM Retec, A.G. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include "sru-debug.h" #include "sru-test.h" #include "libke.h" #define XK_MISCELLANY #define XK_LATIN1 #include /*#define KET_NUMLOCK_LED_MASK 2 */ /*#define KET_CAPSLOCK_LED_MASK 1 */ #define KET_START_TEST_WAIT 5 #define KET_NO_OF_TRIES 3 #define KET_LINE_LENGTH 55 #define KET_DELAY_MIN 100 #define KET_DELAY_MAX 3000 #define KET_LAYER_BACK_TIMEOUT 5000 #define KET_TIME_MAX (KET_DELAY_MAX + \ KET_LAYER_BACK_TIMEOUT + \ 5000) typedef void (*KETProcessArray) (GPtrArray *array); typedef struct { gchar *message; gchar *key; gint delay; KeySym keysym; }KETKeyMessage; static GPtrArray *ket_keys_array = NULL; static gboolean ket_keyboard_grabbing = FALSE; static gboolean ket_wait = TRUE; static gint ket_index = 0; static KETKeyMessage ket_numpad_keys[] = { {"Press key \"1\" from numpad", "LxxK01", 1000, XK_KP_1 }, {"Press key \"2\" from numpad", "LxxK02", 1000, XK_KP_2 }, {"Press key \"3\" from numpad", "LxxK03", 1000, XK_KP_3 }, {"Press key \"4\" from numpad", "LxxK04", 1000, XK_KP_4 }, {"Press key \"5\" from numpad", "LxxK05", 1000, XK_KP_5 }, {"Press key \"6\" from numpad", "LxxK06", 1000, XK_KP_6 }, {"Press key \"7\" from numpad", "LxxK07", 1000, XK_KP_7 }, {"Press key \"8\" from numpad", "LxxK08", 1000, XK_KP_8 }, {"Press key \"9\" from numpad", "LxxK09", 1000, XK_KP_9 }, {"Press key \"Decimal/Separator\" from numpad", "LxxK10", 1000, XK_KP_Decimal }, {"Press key \"Enter\" from numpad", "LxxK11", 1000, XK_KP_Enter }, {"Press key \"Add\" from numpad", "LxxK12", 1000, XK_KP_Add }, {"Press key \"Substract\" from numpad", "LxxK13", 1000, XK_KP_Subtract }, {"Press key \"Multiply\" from numpad", "LxxK14", 1000, XK_KP_Multiply }, {"Press key \"Divide\" from numpad", "LxxK15", 1000, XK_KP_Divide }, {"Press key \"0\" (and wait more than 5 sec)", "Lxx", 1000 + KET_LAYER_BACK_TIMEOUT, XK_KP_0}, {"Press key \"0\" then key \"1\" (don't wait more than 5 sec)", "L01", 1000, XK_KP_1 } }; static KETKeyMessage ket_modifiers_keys[] = { {"Press key \"Window Left\"", "Window Left", 1000, XK_Super_L }, {"Press key \"Window Right\"", "Window Right", 1000, XK_Super_R }, {"Press key \"Alt Left\"", "Alt Left", 1000, XK_Alt_L }, {"Press key \"Alt Right\"", "Alt Right", 1000, XK_Alt_R }, {"Press key \"Control Left\"", "Control Left", 1000, XK_Control_L }, {"Press key \"Control Right\"", "Control Right", 1000, XK_Control_R }, {"Press key \"Shift Left\"", "Shift Left", 1000, XK_Shift_L }, {"Press key \"Shift Right\"", "Shift Right", 1000, XK_Shift_R }, {"Press key \"CapsLock\"", "CapsLock", 1000, XK_Caps_Lock }, {"Press key \"Numlock\"", "NumLock", 1000, XK_Num_Lock } }; static KETKeyMessage ket_cursors_keys[] = { {"Press key \"Home\"", "Home", 1000, XK_Home }, {"Press key \"End\"", "End", 1000, XK_End }, {"Press key \"Up\"", "Up", 1000, XK_Up }, {"Press key \"Down\"", "Down", 1000, XK_Down }, {"Press key \"Left\"", "Left", 1000, XK_Left }, {"Press key \"Right\"", "Right", 1000, XK_Right }, {"Press key \"Page Up\"", "Page Up", 1000, XK_Page_Up }, {"Press key \"Page Down\"", "Page Down", 1000, XK_Page_Down }, {"Press key \"Backspace\"", "BackSpace", 1000, XK_BackSpace }, {"Press key \"Delete\"", "Delete", 1000, XK_Delete }, {"Press key \"Escape\"", "Escape", 1000, XK_Escape } }; static KETKeyMessage ket_grab_keys[] = { {"Press key \"A\"", "A", 1000, XK_a }, {"Press key \"B\"", "B", 1000, XK_b }, {"Press key \"C\"", "C", 1000, XK_c }, {"Press key \"D\"", "D", 1000, XK_d }, {"Press key \"E\"", "E", 1000, XK_e }, {"Press key \"F\"", "F", 1000, XK_f }, {"Press key \"G\"", "G", 1000, XK_g }, {"Press key \"H\"", "H", 1000, XK_h }, {"Press key \"I\"", "I", 1000, XK_i }, {"Press key \"J\"", "J", 1000, XK_j }, {"Press key \"K\"", "K", 1000, XK_k }, {"Press key \"L\"", "L", 1000, XK_l }, {"Press key \"M\"", "M", 1000, XK_m }, {"Press key \"N\"", "N", 1000, XK_n }, {"Press key \"O\"", "O", 1000, XK_o }, {"Press key \"P\"", "P", 1000, XK_p }, {"Press key \"Q\"", "Q", 1000, XK_q }, {"Press key \"R\"", "R", 1000, XK_r }, {"Press key \"S\"", "S", 1000, XK_s }, {"Press key \"T\"", "T", 1000, XK_t }, {"Press key \"U\"", "U", 1000, XK_u }, {"Press key \"V\"", "V", 1000, XK_v }, {"Press key \"W\"", "W", 1000, XK_w }, {"Press key \"X\"", "X", 1000, XK_x }, {"Press key \"Y\"", "Y", 1000, XK_y }, {"Press key \"Z\"", "Z", 1000, XK_z }, {"Press key \"0\"", "0", 1000, XK_0 }, {"Press key \"1\"", "1", 1000, XK_1 }, {"Press key \"2\"", "2", 1000, XK_2 }, {"Press key \"3\"", "3", 1000, XK_3 }, {"Press key \"4\"", "4", 1000, XK_4 }, {"Press key \"5\"", "5", 1000, XK_5 }, {"Press key \"6\"", "6", 1000, XK_6 }, {"Press key \"7\"", "7", 1000, XK_7 }, {"Press key \"8\"", "8", 1000, XK_8 }, {"Press key \"9\"", "9", 1000, XK_9 }, {"Press key \"F1\"", "F1", 1000, XK_F1 }, {"Press key \"F2\"", "F2", 1000, XK_F2 }, {"Press key \"F3\"", "F3", 1000, XK_F3 }, {"Press key \"F4\"", "F4", 1000, XK_F4 }, {"Press key \"F5\"", "F5", 1000, XK_F5 }, {"Press key \"F6\"", "F6", 1000, XK_F6 }, {"Press key \"F7\"", "F7", 1000, XK_F7 }, {"Press key \"F8\"", "F8", 1000, XK_F8 }, {"Press key \"F9\"", "F9", 1000, XK_F9 }, {"Press key \"F10\"", "F10", 1000, XK_F10 }, {"Press key \"F11\"", "F11", 1000, XK_F11 }, {"Press key \"F12\"", "F12", 1000, XK_F12 } }; static void ket_error () { gdk_beep (); } static void ket_write_message_for_first (GPtrArray *array) { KETKeyMessage *key_msg; gint i, length; g_assert (array && array->len); key_msg = g_ptr_array_index (array, 0); g_print ("\n %s ", key_msg->message); length = KET_LINE_LENGTH - strlen (key_msg->message); for (i = 0; i < length; i++) g_print ("."); g_print (" "); } static gboolean ket_write_result (gboolean res, gboolean force) { static gint tries = 0; gboolean next = TRUE; if (res) { g_print ("succeeded"); tries = 0; } else if (tries == KET_NO_OF_TRIES - 1 || force) { ket_error (); g_print ("failed"); tries = 0; } else { ket_error (); tries++; next = FALSE; } return next; } static gboolean ket_wait_timeout (gpointer data); static void ket_move_to_next (GPtrArray *array) { g_assert (array && array->len); ket_index++; g_ptr_array_remove_index (array, 0); if (array->len) { ket_write_message_for_first (array); g_timeout_add (KET_TIME_MAX, ket_wait_timeout, GINT_TO_POINTER (ket_index)); } else SPI_event_quit (); } static void ket_write_result_and_move_to_next (GPtrArray *array, gboolean result) { if (ket_write_result (result, FALSE)) ket_move_to_next (array); } static gboolean ket_wait_timeout (gpointer data) { gint index = GPOINTER_TO_INT (data); if (ket_index == index) { ket_write_result (FALSE, TRUE); SPI_event_quit (); /* ket_move_to_next (ket_keys_array); ????? */ } return FALSE; } static void ket_mouse_move_nothing (gint x, gint y) { } static void ket_grab_print (const gchar *key, KEKeyModifier m) { g_assert (key); g_print ("\ngrab:\"%s\" with modifiers:%d added as command", key, m); ke_command_add (key, m); } static void ket_command_print (const gchar *key, KEKeyModifier m) { g_assert (key); g_print ("\ncommand:\"%s\" with modifiers:%d", key, m); if (key[0] == 'Q' && key[1] == '\0') SPI_event_quit (); if (key[0] == 'S' && key[1] == '\0' && !ket_keyboard_grabbing) { g_print ("Keyboard grabbing started"); ket_keyboard_grabbing = TRUE; ke_start_keyboard_grab (); } if (key[0] == 'E' && key[1] == '\0' && ket_keyboard_grabbing) { g_print ("Keyboard grabbing stoped"); ket_keyboard_grabbing = FALSE; ke_stop_keyboard_grab (); } } static void ket_hit_print () { g_print ("\nhit"); } static void ket_cursor_print (const gchar *cursor) { g_assert (cursor); g_print ("\ncursor:\"%s\"", cursor); } static void ket_modifier_print (const gchar *modifier, KEKeyAction action) { g_assert (modifier); g_print ("\nmodifier:\"%s\"", modifier); } static void ket_layer_back_print (gint layer) { g_print ("\nback to layer:%02d", layer); } static void ket_layer_changed_print (gint layer) { g_print ("\nchange to layer:%02d", layer); } static void ket_layer_key_print (gint layer, gint key) { g_print ("\nlayer:%02d key:%02d", layer, key); } static void ket_mouse_move_print (gint x, gint y) { g_print ("\nmouse: x:%02d y:%02d", x, y); } #define KET_CHECK_AUTO(expr) \ { \ KETKeyMessage *key_msg; \ \ g_assert (ket_keys_array && ket_keys_array->len); \ \ key_msg = g_ptr_array_index (ket_keys_array, 0); \ ket_write_result_and_move_to_next (ket_keys_array, expr); \ } static void ket_layer_back_auto (gint layer) { KET_CHECK_AUTO (strcmp (key_msg->key, "Lxx") == 0 && strlen (key_msg->key) == 3); } static void ket_layer_changed_auto (gint layer) { KET_CHECK_AUTO (layer == atoi (key_msg->key + 1) && strlen (key_msg->key) == 3 && strcmp (key_msg->key, "Lxx") != 0); } static void ket_layer_key_auto (gint layer, gint key) { KET_CHECK_AUTO (key == atoi (key_msg->key + 4) && strlen (key_msg->key) == 6); } static void ket_modifier_auto (const gchar *modifier, KEKeyAction action) { if (action != KE_KEY_PRESSED) return; g_assert (modifier); KET_CHECK_AUTO (strcmp (modifier, key_msg->key) == 0); } static void ket_cursor_auto (const gchar *cursor) { g_assert (cursor); KET_CHECK_AUTO (strcmp (cursor, key_msg->key) == 0); } static void ket_grab_auto (const gchar *key, KEKeyModifier m) { g_assert (key); KET_CHECK_AUTO (strcmp (key, key_msg->key) == 0); } static void ket_hit_auto () { KET_CHECK_AUTO (FALSE); } static void ket_add_key_messages_to_array (GPtrArray *array, KETKeyMessage *key_messages, gint len) { gint i; g_assert (array && key_messages); for (i = 0; i < len; i++) g_ptr_array_add (array, &key_messages[i]); } static gboolean ket_generate_key (KeySym keysym) { gboolean rv = FALSE; KeyCode keycode; static Display *display; if (!display) display = GDK_DISPLAY (); if (!display) { g_printerr ("\nInvalid display!"); return FALSE; } keycode = XKeysymToKeycode (display, keysym); if (keycode) rv = SPI_generateKeyboardEvent (keycode, NULL, SPI_KEY_PRESSRELEASE) ? TRUE : FALSE; else g_printerr ("\nUnable to get keycode for keysym \"%ld\"", keysym); return rv; } static gboolean ket_generate_first_key_from_array (gpointer data); static gboolean ket_generate_first_key_from_array_real (gpointer data) { GPtrArray *garray = data; KETKeyMessage *key_info; if (data != ket_keys_array) return FALSE; g_assert (garray && garray->len); key_info = g_ptr_array_index (garray, 0); ket_generate_key (key_info->keysym); if (garray->len) g_idle_add (ket_generate_first_key_from_array, data); return FALSE; } static gboolean ket_generate_first_key_from_array (gpointer data) { GPtrArray *garray = data; KETKeyMessage *key_info; if (data != ket_keys_array) return FALSE; g_assert (garray && garray->len); key_info = g_ptr_array_index (garray, 0); if (strlen (key_info->key) == 3 && strcmp (key_info->key, "Lxx") != 0) /* layer changed */ { ket_generate_key (XK_KP_0); g_usleep (10000); } if (garray->len) g_timeout_add (key_info->delay, ket_generate_first_key_from_array_real, data); return FALSE; } static void ket_test_listen_array (GPtrArray *array) { KECallbacks callbacks; SPI_init (); ket_keys_array = array; ket_index++; callbacks.grab = ket_grab_auto; callbacks.hit = ket_hit_auto; callbacks.cursor = ket_cursor_auto; callbacks.modifier = ket_modifier_auto; callbacks.layer_key = ket_layer_key_auto; callbacks.layer_ch = ket_layer_changed_auto; callbacks.layer_back = ket_layer_back_auto; callbacks.mouse_move = ket_mouse_move_nothing; ke_init (&callbacks); ke_start_keyboard_grab (); g_timeout_add (KET_TIME_MAX, ket_wait_timeout, GINT_TO_POINTER (ket_index)); ket_write_message_for_first (array); SPI_event_main (); ke_stop_keyboard_grab (); ke_terminate (); ket_keys_array = NULL; SPI_exit (); } static void ket_write_test_start_message (gchar *specific) { gint i; g_assert (specific); if (!ket_wait) return; g_print ("\nMove to an ACCESSIBLE window!!!!\n"); for (i = KET_START_TEST_WAIT; i >= 0; i--) { g_print ("The test of \"%s\" will start in %d seconds\r", specific, i); sleep(1); } } static void ket_write_test_end_message (gchar *specific) { g_assert (specific); if (!ket_wait) return; g_print ("\nEnd of \"%s\" testing", specific); } static void ket_array_function (KETProcessArray function, KETKeyMessage *keys, gint len, gchar *specific) { GPtrArray *array; g_assert (function); array = g_ptr_array_new (); ket_add_key_messages_to_array (array, keys, len); ket_write_test_start_message (specific); function (array); ket_write_test_end_message (specific); g_ptr_array_free (array, TRUE); } static void ket_numpad_function (KETProcessArray function) { ket_array_function (function, ket_numpad_keys, G_N_ELEMENTS (ket_numpad_keys), "numpad"); } static void ket_modifiers_function (KETProcessArray function) { ket_array_function (function, ket_modifiers_keys, G_N_ELEMENTS (ket_modifiers_keys), "modifiers"); } static void ket_cursors_function (KETProcessArray function) { ket_array_function (function, ket_cursors_keys, G_N_ELEMENTS (ket_cursors_keys), "cursors"); } static void ket_grab_function (KETProcessArray function) { ket_array_function (function, ket_grab_keys, G_N_ELEMENTS (ket_grab_keys), "grabbing"); } static void ket_all_function (KETProcessArray function) { gchar *specific = "all"; ket_write_test_start_message (specific); ket_wait = FALSE; ket_numpad_function (function); ket_modifiers_function (function); ket_cursors_function (function); ket_grab_function (function); ket_wait = TRUE; ket_write_test_end_message (specific); }; static void ket_test_numpad_listening_auto () { ket_numpad_function (ket_test_listen_array); } static void ket_test_modifiers_listening_auto () { ket_modifiers_function (ket_test_listen_array); } static void ket_test_cursors_listening_auto () { ket_cursors_function (ket_test_listen_array); } static void ket_test_grab_listening_auto () { ket_grab_function (ket_test_listen_array); } static void ket_test_all_listening_auto () { ket_all_function (ket_test_listen_array); }; static void ket_test_generate_and_listen_array (GPtrArray *array) { g_timeout_add (1000, ket_generate_first_key_from_array, array); ket_test_listen_array (array); } static void ket_test_numpad_auto () { ket_numpad_function (ket_test_generate_and_listen_array); } static void ket_test_modifiers_auto () { ket_modifiers_function (ket_test_generate_and_listen_array); } static void ket_test_cursors_auto () { ket_cursors_function (ket_test_generate_and_listen_array); } static void ket_test_grab_auto () { ket_grab_function (ket_test_generate_and_listen_array); } static void ket_test_all_auto () { ket_all_function (ket_test_generate_and_listen_array); }; static void ket_test_user_actions () { KECallbacks callbacks; gchar *specific = "user actions"; ket_write_test_start_message (specific); g_print ("\nInitial commands are:" "\n\t 'Q' - for quit" "\n\t 'S' - start keyboard grabbing" "\n\t 'E' - end keyboard grabbing"); SPI_init (); callbacks.grab = ket_grab_print; callbacks.command = ket_command_print; callbacks.hit = ket_hit_print; callbacks.cursor = ket_cursor_print; callbacks.modifier = ket_modifier_print; callbacks.layer_key = ket_layer_key_print; callbacks.layer_ch = ket_layer_changed_print; callbacks.layer_back = ket_layer_back_print; callbacks.mouse_move = ket_mouse_move_print; ke_init (&callbacks); ke_command_add ("Q", KE_MODIFIER_UNMODIFIED); ke_command_add ("S", KE_MODIFIER_UNMODIFIED); ke_command_add ("E", KE_MODIFIER_UNMODIFIED); ket_keyboard_grabbing = FALSE; SPI_event_main (); ket_write_test_end_message (specific); ke_commands_remove_all (); if (ket_keyboard_grabbing) ke_stop_keyboard_grab (); ke_terminate (); SPI_exit (); } static void ket_test_manual () { SRUTMenuEntry menu[] = { { "Test numpad", '1', ket_test_numpad_listening_auto }, { "Test modifiers", '2', ket_test_modifiers_listening_auto }, { "Test cursors", '3', ket_test_cursors_listening_auto }, { "Test grab", '4', ket_test_grab_listening_auto }, { "Test numpad, modifiers, cursors, grab",'5',ket_test_all_listening_auto } }; srut_run_menu (menu, G_N_ELEMENTS (menu)); } static void ket_test_automatic () { SRUTMenuEntry menu[] = { { "Test numpad", '1', ket_test_numpad_auto }, { "Test modifiers", '2', ket_test_modifiers_auto }, { "Test cursors", '3', ket_test_cursors_auto }, { "Test grab", '4', ket_test_grab_auto }, { "Test numpad, modifiers, cursors, grab",'5',ket_test_all_auto } }; srut_run_menu (menu, G_N_ELEMENTS (menu)); } int main (int argc, char **argv) { SRUTMenuEntry menu[] = { { "Test user actions", '1', ket_test_user_actions }, { "Test all manually", '2', ket_test_manual }, { "Test all automaticaly", '3', ket_test_automatic }, // { "Test robustness", '4', ket_test_robustness } }; gdk_init (&argc, &argv); /* needed because we are using GDK_DISPLAY () */ sru_debug_init (); srut_run_menu (menu, G_N_ELEMENTS (menu)); sru_debug_terminate (); return 0; }