diff options
author | Christoph Reimann <oss@arcor.de> | 2010-08-15 19:16:03 +0200 |
---|---|---|
committer | Christoph Reimann <oss@arcor.de> | 2010-08-15 19:16:03 +0200 |
commit | 901ab8b0893c8a1354e2624d8318023a26f65155 (patch) | |
tree | cde6ad7a3d5289a365ae861d37b1e2c30ff468f6 |
xkb test suite
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | check_xkb.c | 154 | ||||
-rw-r--r-- | configure.ac | 33 | ||||
-rw-r--r-- | xkb_util.c | 176 | ||||
-rw-r--r-- | xkb_util.h | 36 |
5 files changed, 406 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..d296226 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +## Process this file with automake to produce Makefile.in + +TESTS = check_xkb +check_PROGRAMS = check_xkb +check_xkb_SOURCES = check_xkb.c xkb_util.c +check_xkb_CFLAGS = @CHECK_CFLAGS@ @xcb_CFLAGS@ @xcb_xkb_CFLAGS@ @x11_CFLAGS@ +check_xkb_LDADD = @CHECK_LIBS@ @xcb_LIBS@ @xcb_xkb_LIBS@ @x11_LIBS@ diff --git a/check_xkb.c b/check_xkb.c new file mode 100644 index 0000000..20b0b18 --- /dev/null +++ b/check_xkb.c @@ -0,0 +1,154 @@ + +#include <stdlib.h> +#include <stdio.h> + +#include <X11/XKBlib.h> +#include <X11/Xlibint.h> + +#include "xkb_util.h" +#include <xcb/xcb_event.h> + +#include <check.h> + +/* + * check the result of issuing a GetNames request with Xlib and xcb + * test for special case: switch that contains variable size fields + */ +START_TEST(check_xkb_get_names_request) +{ + /* Xlib */ + Display *d = XkbOpenDisplay(NULL, 0, 0, 0, 0, 0); + XkbDescPtr xlib_result, p = XkbGetKeyboard(d, XkbKeycodesNameMask, XkbUseCoreKbd); + + /* xcb */ + xcb_connection_t *c = xcb_connect (NULL, NULL); + xcb_generic_error_t *e = NULL; + xcb_xkb_use_extension_reply_t *reply = xcb_xkb_util_query_extension(c, 1, 0, &e); + xcb_xkb_get_names_reply_t *get_names_reply; + void *names_buffer, *new_buffer = NULL; + xcb_xkb_get_names_value_list_t xcb_result, names; + int l0, l1, l2, i, j, idx, length; + + printf("checking the GetNames request (xcb vs. Xlib)\n"); + + fail_if(e != NULL, "xcb: cannot initialize XKB!?\n"); + + get_names_reply = xcb_xkb_util_get_names (c, XCB_XKB_ID_USE_CORE_KBD, xcb_xkb_util_all_name_details_mask, &names, &e); + fail_if(e != NULL, "xcb: xcb_xkb_get_names failed\n"); + + fail_if(XkbGetNames(d, XkbAllNamesMask, p) != Success, + "Xlib: XkbGetNames() failed\n"); + + /* check if serialize and unpack work properly */ + names_buffer = xcb_xkb_get_names_value_list(get_names_reply); + l0 = xcb_xkb_get_names_value_list_unpack (names_buffer, + get_names_reply->nTypes, + get_names_reply->indicators, + get_names_reply->virtualMods, + get_names_reply->groupNames, + get_names_reply->nKeys, + get_names_reply->nKeyAliases, + get_names_reply->nRadioGroups, + get_names_reply->which, + &names); + l1 = xcb_xkb_get_names_value_list_serialize (&new_buffer, + get_names_reply->nTypes, + get_names_reply->indicators, + get_names_reply->virtualMods, + get_names_reply->groupNames, + get_names_reply->nKeys, + get_names_reply->nKeyAliases, + get_names_reply->nRadioGroups, + get_names_reply->which, + &names); + l2 = xcb_xkb_get_names_value_list_unpack (new_buffer, + get_names_reply->nTypes, + get_names_reply->indicators, + get_names_reply->virtualMods, + get_names_reply->groupNames, + get_names_reply->nKeys, + get_names_reply->nKeyAliases, + get_names_reply->nRadioGroups, + get_names_reply->which, + &names); + free(new_buffer); + fail_unless(l0 == l1, "xcb: serializing a previously unpacked switch gives a different buffer length!"); + fail_unless(l2 == l1, "xcb: unpacking a previously serialized switch gives a different buffer length!"); + + xlib_result = p; + xcb_result = names; + /* 1. check fixed size fields */ + fail_unless(xcb_result.keycodesName == xlib_result->names->keycodes, NULL); + fail_unless(xcb_result.geometryName == xlib_result->names->geometry, NULL); + fail_unless(xcb_result.symbolsName == xlib_result->names->symbols, NULL); + fail_unless(xcb_result.physSymbolsName == xlib_result->names->phys_symbols, NULL); + fail_unless(xcb_result.typesName == xlib_result->names->types, NULL); + fail_unless(xcb_result.compatName == xlib_result->names->compat, NULL); + + /* 2. check some variable size fields */ + /* typeNames */ + length = xcb_xkb_get_names_value_list_type_names_length(get_names_reply, + &xcb_result); + fail_unless(length == xlib_result->map->num_types, NULL); + for(i=0; i<length; i++) { + fail_unless(xcb_result.typeNames[i] == xlib_result->map->types[i].name, NULL); + } + + /* ktLevelNames - the length of the list is calculated with sumof */ + length = xcb_xkb_get_names_value_list_n_levels_per_type_length(get_names_reply, + &xcb_result); + fail_unless(length == xlib_result->map->num_types, NULL); + idx = 0; + for(i=0; i<length; i++) { + int n_levels = xcb_result.nLevelsPerType[i]; + for(j=0; j<n_levels; j++) { + fail_unless(xcb_result.ktLevelNames[idx] == xlib_result->map->types[i].level_names[j], NULL); + idx++; + } + } + + /* groups */ + length = xcb_xkb_get_names_value_list_groups_length(get_names_reply, &xcb_result); + // the number of elements is calculated on-the-fly in Xlib (see _XkbReadAtoms) + for(i=0; i<length; i++) { + fail_unless(xcb_result.groups[i] == xlib_result->names->groups[i], NULL); + } + + /* keyAliases */ + length = xcb_xkb_get_names_value_list_key_aliases_length(get_names_reply, &xcb_result); + fail_unless(length == xlib_result->names->num_key_aliases); + for(i=0; i<length; i++) { + for(j=0; j<4; j++) { + fail_unless(xcb_result.keyAliases[i].real[j] == xlib_result->names->key_aliases[i].real[j]); + fail_unless(xcb_result.keyAliases[i].alias[j] == xlib_result->names->key_aliases[i].alias[j]); + } + } +} +END_TEST + +Suite * +xkb_test_suite (void) +{ + Suite *s = suite_create ("XKB"); + + /* Core test case */ + TCase *tc_core = tcase_create ("Core"); + tcase_add_test (tc_core, check_xkb_get_names_request); + suite_add_tcase (s, tc_core); + + return s; +} + +int +main (void) +{ + int number_failed; + Suite *s = xkb_test_suite (); + SRunner *sr = srunner_create (s); + printf("\n"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + printf("\n"); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..573cd2c --- /dev/null +++ b/configure.ac @@ -0,0 +1,33 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.65]) +AC_INIT([check_xkb], [0.1], [oss@arcor.de]) +AM_INIT_AUTOMAKE("check_xkb", "0.1", "oss@arcor.de") +AC_CONFIG_SRCDIR([check_xkb.c]) +AC_CONFIG_HEADERS([config.h]) +PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) +PKG_CHECK_MODULES([xcb], [xcb >= 1.6]) +PKG_CHECK_MODULES([xcb_xkb], [xcb-xkb]) +PKG_CHECK_MODULES([x11], [x11 >= 1.3]) + +# Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O + +# Checks for libraries. +# FIXME: Replace `main' with a function in `-lxcb': +#AC_CHECK_LIB([xcb], [main]) + +# Checks for header files. +AC_CHECK_HEADERS([stdlib.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT8_T + +# Checks for library functions. + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/xkb_util.c b/xkb_util.c new file mode 100644 index 0000000..728e62d --- /dev/null +++ b/xkb_util.c @@ -0,0 +1,176 @@ + +#include "xkb_util.h" + +/* +// check compile time library version +int +xcb_xkb_util_library_version(int *lib_major_in_out, int *lib_minor_in_out); +*/ + +xcb_xkb_use_extension_reply_t * +xcb_xkb_util_query_extension(xcb_connection_t *c, + uint16_t wantedMajor, + uint16_t wantedMinor, + xcb_generic_error_t **error) { + xcb_xkb_use_extension_cookie_t use_xkb = xcb_xkb_use_extension(c, wantedMajor, wantedMinor); + xcb_flush(c); + return xcb_xkb_use_extension_reply (c, use_xkb, error); +} + +xcb_generic_error_t * +xcb_xkb_util_select_events(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint16_t event_mask, + uint16_t select) { + xcb_void_cookie_t void_cookie; + uint16_t affectMap = 0; + uint16_t map = 0; + + /* sort out the MapNotify event */ + if (event_mask & XCB_XKB_EVENT_TYPE_MAP_NOTIFY) { + affectMap = xcb_xkb_util_all_map_parts_mask; + if (select & XCB_XKB_EVENT_TYPE_MAP_NOTIFY) + map = xcb_xkb_util_all_map_parts_mask; + } + + void_cookie = xcb_xkb_select_events(c, device_spec, event_mask, + event_mask & (~select), /* clear */ + event_mask & select, /* selectAll */ + affectMap, map, NULL); + + return xcb_request_check(c, void_cookie); +} + +xcb_generic_error_t * +xcb_xkb_util_select_event_details(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint16_t event_mask, + uint32_t affect, + uint32_t details) { + xcb_void_cookie_t void_cookie; + uint16_t affectMap = 0; + uint16_t map = 0; + /* for a single event, the switch argument cannot be larger than uint32_t[2] */ + union { + uint8_t i8[2]; + uint16_t i16[2]; + uint32_t i32[2]; + } buffer = {0, 0}; + void *_buffer = 0; + + /* sort out the MapNotify event */ + if (event_mask & XCB_XKB_EVENT_TYPE_MAP_NOTIFY) { + affectMap = (uint16_t)affect; + map = (uint16_t)details | (xcb_xkb_util_all_client_map_parts_mask & affect); + event_mask = XCB_XKB_EVENT_TYPE_MAP_NOTIFY; + } + else { + /* assemble the switch argument manually */ + switch(event_mask) { + case XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY: + case XCB_XKB_EVENT_TYPE_STATE_NOTIFY: + case XCB_XKB_EVENT_TYPE_NAMES_NOTIFY: + case XCB_XKB_EVENT_TYPE_ACCESS_X_NOTIFY: + case XCB_XKB_EVENT_TYPE_EXTENSION_DEVICE_NOTIFY: + buffer.i16[0] = (uint16_t)affect; + buffer.i16[1] = (uint16_t)details; + _buffer = buffer.i16; + break; + case XCB_XKB_EVENT_TYPE_CONTROLS_NOTIFY: + case XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY: + case XCB_XKB_EVENT_TYPE_INDICATOR_MAP_NOTIFY: + buffer.i32[0] = affect; + buffer.i32[1] = details; + _buffer = buffer.i32; + break; + case XCB_XKB_EVENT_TYPE_COMPAT_MAP_NOTIFY: + case XCB_XKB_EVENT_TYPE_BELL_NOTIFY: + case XCB_XKB_EVENT_TYPE_ACTION_MESSAGE: + buffer.i8[0] = (uint8_t)affect; + buffer.i8[1] = (uint8_t)details; + _buffer = buffer.i8; + break; + } + } + + void_cookie = xcb_xkb_select_events(c, device_spec, event_mask, + 0, /* clear */ + 0, /* selectAll */ + affectMap, map, _buffer); + + return xcb_request_check(c, void_cookie); +} + +xcb_xkb_get_names_reply_t * +xcb_xkb_util_get_names (xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint32_t which, + xcb_xkb_get_names_value_list_t *_aux, + xcb_generic_error_t **e) { + xcb_xkb_get_names_cookie_t cookie = xcb_xkb_get_names (c, device_spec, which); + xcb_xkb_get_names_reply_t *reply = xcb_xkb_get_names_reply (c, cookie, e); + void *buffer; + if (!(*e)) { + buffer = xcb_xkb_get_names_value_list(reply); + xcb_xkb_get_names_value_list_unpack (buffer, + reply->nTypes, + reply->indicators, + reply->virtualMods, + reply->groupNames, + reply->nKeys, + reply->nKeyAliases, + reply->nRadioGroups, + reply->which, + _aux); + } + return reply; +} + +xcb_xkb_get_state_reply_t * +xcb_xkb_util_get_state(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + xcb_generic_error_t **e) { + xcb_xkb_get_state_cookie_t cookie = xcb_xkb_get_state (c, device_spec); + return xcb_xkb_get_state_reply (c, cookie, e); +} + + +xcb_xkb_get_map_reply_t * +xcb_xkb_util_get_map(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint16_t map_components, + xcb_xkb_get_map_map_t *_aux, + xcb_generic_error_t **e) { + xcb_xkb_get_map_cookie_t cookie; + xcb_xkb_get_map_reply_t *reply; + void *buffer; + + cookie = xcb_xkb_get_map (c, device_spec, map_components, + 0, /* partial */ + 0, /* firstType */ + 0, /* nTypes */ + 0, /* firstKeySym */ + 0, /* nKeySyms */ + 0, /* firstKeyAction */ + 0, /* nKeyActions */ + 0, /* firstKeyBehavior */ + 0, /* nKeyBehaviors */ + 0, /* virtualMods */ + 0, /* firstKeyExplicit */ + 0, /* nKeyExplicit */ + 0, /* firstModMapKey */ + 0, /* nModMapKeys */ + 0, /* firstVModMapKey */ + 0 /* nVModMapKeys */); + + reply = xcb_xkb_get_map_reply (c, cookie, e); + + if (!(*e)) { + buffer = xcb_xkb_get_map_map(reply); + xcb_xkb_get_map_map_unpack (buffer, reply->nTypes, reply->nKeySyms, reply->nKeyActions, + reply->totalActions, reply->totalKeyBehaviors, reply->nVModMapKeys, + reply->totalKeyExplicit, reply->totalModMapKeys, reply->totalVModMapKeys, + reply->present, _aux); + } + return reply; +} diff --git a/xkb_util.h b/xkb_util.h new file mode 100644 index 0000000..8fd9c0b --- /dev/null +++ b/xkb_util.h @@ -0,0 +1,36 @@ + +#ifndef XKB_UTIL_H +#define XKB_UTIL_H 1 + +#include <xcb/xkb.h> + +#define xcb_xkb_util_all_client_map_parts_mask (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP) +#define xcb_xkb_util_all_server_map_parts_mask (XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_KEY_BEHAVIORS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP) +#define xcb_xkb_util_all_map_parts_mask (xcb_xkb_util_all_client_map_parts_mask|xcb_xkb_util_all_server_map_parts_mask) + +#define xcb_xkb_util_all_name_details_mask (XCB_XKB_NAME_DETAIL_KEYCODES | XCB_XKB_NAME_DETAIL_GEOMETRY | XCB_XKB_NAME_DETAIL_SYMBOLS | XCB_XKB_NAME_DETAIL_PHYS_SYMBOLS | XCB_XKB_NAME_DETAIL_TYPES | XCB_XKB_NAME_DETAIL_COMPAT | XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | XCB_XKB_NAME_DETAIL_INDICATOR_NAMES | XCB_XKB_NAME_DETAIL_KEY_NAMES | XCB_XKB_NAME_DETAIL_KEY_ALIASES | XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES | XCB_XKB_NAME_DETAIL_GROUP_NAMES | XCB_XKB_NAME_DETAIL_RG_NAMES) + + + +xcb_xkb_use_extension_reply_t * xcb_xkb_util_query_extension(xcb_connection_t *c, + uint16_t wantedMajor, + uint16_t wantedMinor, + xcb_generic_error_t **error); +xcb_generic_error_t * xcb_xkb_util_select_events(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint16_t event_mask, + uint16_t select); +xcb_xkb_get_names_reply_t * xcb_xkb_util_get_names (xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint32_t which, + xcb_xkb_get_names_value_list_t *_aux, + xcb_generic_error_t **e); +xcb_xkb_get_state_reply_t * xcb_xkb_util_get_state(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + xcb_generic_error_t **e); +xcb_xkb_get_map_reply_t * xcb_xkb_util_get_map(xcb_connection_t *c, + xcb_xkb_device_spec_t device_spec, + uint16_t map_components, + xcb_xkb_get_map_map_t *_aux, + xcb_generic_error_t **e); +#endif |