summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Reimann <oss@arcor.de>2010-08-15 19:16:03 +0200
committerChristoph Reimann <oss@arcor.de>2010-08-15 19:16:03 +0200
commit901ab8b0893c8a1354e2624d8318023a26f65155 (patch)
treecde6ad7a3d5289a365ae861d37b1e2c30ff468f6
xkb test suite
-rw-r--r--Makefile.am7
-rw-r--r--check_xkb.c154
-rw-r--r--configure.ac33
-rw-r--r--xkb_util.c176
-rw-r--r--xkb_util.h36
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