.autom4te.cfg | 3 .gitignore | 1 Makefile.am | 76 NEWS | 86 README | 47 configure.ac | 45 doc/Doxyfile.in | 142 makekeys.py | 44 src/atom.c | 137 src/atom.h | 7 src/context-priv.c | 171 src/context.c | 179 src/context.h | 62 src/keymap-priv.c | 121 src/keymap.c | 83 src/keymap.h | 25 src/keysym-utf.c | 13 src/keysym.c | 56 src/keysym.h | 6 src/ks_tables.h |11765 +++++++++++++++++++++-------------- src/state.c | 20 src/text.c | 8 src/utils.h | 75 src/x11/keymap.c | 1146 +++ src/x11/state.c | 71 src/x11/util.c | 215 src/x11/x11-priv.h | 44 src/xkbcomp/action.c | 91 src/xkbcomp/ast-build.c | 318 src/xkbcomp/ast-build.h | 58 src/xkbcomp/ast.h | 124 src/xkbcomp/compat.c | 61 src/xkbcomp/expr.c | 170 src/xkbcomp/include.c | 36 src/xkbcomp/keycodes.c | 29 src/xkbcomp/keymap-dump.c | 19 src/xkbcomp/keymap.c | 30 src/xkbcomp/keywords.c | 2 src/xkbcomp/keywords.gperf | 2 src/xkbcomp/parser-priv.h | 7 src/xkbcomp/parser.y | 191 src/xkbcomp/rules.c | 123 src/xkbcomp/scanner-utils.h | 11 src/xkbcomp/scanner.c | 68 src/xkbcomp/symbols.c | 122 src/xkbcomp/types.c | 13 src/xkbcomp/xkbcomp-priv.h | 3 test/.gitignore | 5 test/atom.c | 181 test/common.c | 154 test/context.c | 9 test/data/keycodes/empty | 4 test/data/keycodes/evdev-xkbcommon | 1 test/data/keymaps/divide-by-zero.xkb | 6 test/data/keymaps/quartz.xkb | 1139 +++ test/data/rules/base | 13 test/data/rules/evdev | 15 test/data/rules/groups | 5 test/data/symbols/altwin | 8 test/data/symbols/ch | 225 test/data/symbols/compose | 35 test/data/symbols/cz | 184 test/data/symbols/de | 78 test/data/symbols/empty | 4 test/data/symbols/inet | 2 test/data/symbols/level3 | 4 test/data/symbols/level5 | 4 test/data/symbols/ru | 21 test/data/symbols/us | 61 test/data/sync.sh | 4 test/filecomp.c | 1 test/interactive-evdev.c | 114 test/interactive-x11.c | 367 + test/keyseq.c | 55 test/keysym.c | 13 test/rulescomp.c | 10 test/state.c | 114 test/stringcomp.c | 7 test/test.h | 11 test/x11.c | 78 xkbcommon-x11-uninstalled.pc.in | 10 xkbcommon-x11.pc.in | 12 xkbcommon/xkbcommon-keysyms.h | 8 xkbcommon/xkbcommon-names.h | 1 xkbcommon/xkbcommon-x11.h | 166 xkbcommon/xkbcommon.h | 147 86 files changed, 13287 insertions(+), 6115 deletions(-)
New commits: commit be16858c927b0d3023dd20fc35fa0919711a72c7 Author: Ran Benita <ran...@gmail.com> Date: Sun Feb 2 12:13:26 2014 +0200 Bump version to 0.4.0 Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/configure.ac b/configure.ac index 2466021..ff03b76 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ dnl Process this file with autoconf to create configure. # Initialize Autoconf AC_PREREQ([2.62]) -AC_INIT([libxkbcommon], [0.3.2], +AC_INIT([libxkbcommon], [0.4.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=libxkbcommon], [libxkbcommon], [http://xkbcommon.org]) AC_CONFIG_SRCDIR([Makefile.am]) commit a15b4a55350173292b39748ed859299ba2761f1f Author: Ran Benita <ran...@gmail.com> Date: Sun Feb 2 12:08:43 2014 +0200 Update README - Remove outdated information about API/ABI stability. If we ever break API or ABI, we'll do a major release. But currently everything is stable. - Remove outdated warnings about internal symbols. You simply cannot access them... - Briefly mention xkbcommon-x11 existence. - Update git and bug URLs. - Add myself as maintainer :) Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/README b/README index fa8e94c..6b99c46 100644 --- a/README +++ b/README @@ -25,27 +25,17 @@ API While xkbcommon's API is somewhat derived from the classic XKB API as found in <X11/extensions/XKB.h> and friends, it has been substantially reworked to -expose fewer internal details to clients. The only supported API is available -in <xkbcommon/xkbcommon.h>. Any definition not in this header (including -accessing internal structures through the old macros previously available) -should be regarded as an implementation detail and is liable to change at any -time. +expose fewer internal details to clients. The supported API is available +in the <xkbcommon/xkbcommon-*.h> files. Additional support is provided for +X11 (XCB) clients, in the xkbcommon-x11 library, <xkbcommon/xkbcommon-x11.h>. -During its early development, xkbcommon does not promise API or ABI stability. -Regardless, we will attempt to not break ABI during a minor release series, -so applications written against 0.1.0 should be completely compatible with -0.1.3, but not necessarily with 0.2.0. However, new symbols may be introduced -in any release. Thus, anyone packaging xkbcommon should make sure any package -depending on it depends on a release greater than or equal to the version it -was built against (or earlier, if it doesn't use any newly-introduced -symbols), but less than the next major release. - -xkbcommon 1.x will offer full API and ABI stability for its lifetime, with a -soname of libxkbcommon.so.1. Any ABI breaks will wait until xkbcommon 2.0, -which will be libxkbcommon.so.2. - -The xkbcomp command-line tool has also been removed, although this will -likely reappear in a later release. +The xkbcommon API and ABI are stable. We will attempt to not break ABI during +a minor release series, so applications written against 0.1.0 should be +completely compatible with 0.5.3, but not necessarily with 1.0.0. However, new +symbols may be introduced in any release. Thus, anyone packaging xkbcommon +should make sure any package depending on it depends on a release greater than +or equal to the version it was built against (or earlier, if it doesn't use +any newly-introduced symbols), but less than the next major release. Relation to X11 @@ -101,19 +91,24 @@ Development An extremely rudimentary homepage can be found at: http://xkbcommon.org -xkbcommon is maintained in git at freedesktop.org: - git://anongit.freedesktop.org/git/libxkbcommon +xkbcommon is maintained in git at github.com: + https://github.com/xkbcommon/libxkbcommon Patches are always welcome, and may be sent to either xorg-de...@lists.x.org, -or wayland-de...@lists.freedesktop.org. Bugs are tracked in Bugzilla at: - http://bugs.freedesktop.org +or wayland-de...@lists.freedesktop.org. + +Bugs are tracked in Bugzilla at: + https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon +Or in github at: + https://github.com/xkbcommon/libxkbcommon/issues -The maintainer is Daniel Stone, who can be reached at: +The maintainers are Daniel Stone and Ran Benita, who can be reached at: <dan...@fooishbar.org> + <ran...@gmail.com> Credits ======= Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon -off the ground initially, as well as to Ran Benita for subsequent development. +off the ground initially. commit 87e0e47462f54545ee97ada8d156f1f16cc51bd0 Author: Ran Benita <ran...@gmail.com> Date: Sun Feb 2 12:05:35 2014 +0200 Update NEWS Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/NEWS b/NEWS index 93aae00..450b753 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,32 @@ -libxkbcommon 0.3.2 +libxkbcommon 0.4.0 ================== -- Added XKB_KEY_XF86AudioMicMute keysym, to match xproto 7.0.24. +- Add a new add-on library, xkbcommon-x11, to support creating keymaps + with the XKB X11 protocol, by querying the X server directly. + See the xkbcommon/xkbcommon-x11.h header file for more details. + This library requires libxcb-xkb >= 1.10, and is enabled by default. + It can be disabled with the --disable-x11 configure switch. + Distributions are encouraged to split the necessary files for this + library (libxkbcommon-x11.so, xkbcommon-x11.pc, xkbcommon/xkbcommon-x11.h) + to a separate package, such that the main package does not depend on + X11 libraries. + +- Fix the keysym <-> name lookup table to not require huge amounts of + relocations. + +- Fix a bug in the keysym <-> name lookup, whereby lookup might fail in + some rare cases. + +- Reduce memory usage during keymap compilation. + +- New API: + New keysyms from xproto 7.0.25 (German T3 layout keysyms). + XKB_MOD_NAME_NUM for the usual NumLock modifier. + xkb_x11_* types and functions, XKB_X11_* constants. + + +libxkbcommon 0.3.2 +================== - Log messages from the library now look like "xkbcommon: ERROR" by default, instead of xkbcomp-like "Error: ". @@ -14,6 +39,7 @@ libxkbcommon 0.3.2 - Support byacc for generating the parser, in addition to Bison. - New API: + XKB_KEY_XF86AudioMicMute keysym from xproto 7.0.24. XKB_KEYSYM_NO_FLAGS XKB_CONTEXT_NO_FLAGS XKB_MAP_COMPILE_NO_FLAGS commit 70717c5686f0f916bb9a23cbdfc79c8ff1f727da Author: Ran Benita <ran...@gmail.com> Date: Sun Feb 2 11:13:28 2014 +0200 build: add configure summary Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/configure.ac b/configure.ac index 9f5afa0..2466021 100644 --- a/configure.ac +++ b/configure.ac @@ -163,3 +163,22 @@ AC_CONFIG_FILES([ doc/Doxyfile ]) AC_OUTPUT + +AC_MSG_RESULT([ + $PACKAGE_NAME $VERSION + + libxkbcommon: yes + libxkbcommon-x11: ${enable_x11} + documentation: ${build_docs} + + default XKB rules: ${DEFAULT_XKB_RULES} + default XKB model: ${DEFAULT_XKB_MODEL} + default XKB layout: ${DEFAULT_XKB_LAYOUT} + default XKB variant: ${DEFAULT_XKB_VARIANT} + default XKB options: ${DEFAULT_XKB_OPTIONS} + + prefix: ${prefix} + includedir: ${includedir} + lib dir: ${libdir} + XKB config root: ${XKBCONFIGROOT} +]) commit 2f93c78894ba180cc5ba602bf1b03961173db7b8 Author: Ran Benita <ran...@gmail.com> Date: Tue Jul 30 15:06:40 2013 +0300 x11: add a couple of tests Add two tests: ./test/interactive-x11 which is like test/interactive-evdev, but should behave exactly like your X keyboard and react to state and keymap changes - in other words, just like typing in xterm. Press ESC to exit. ./test/x11 which currently should only print out the same keymap as xkbcomp $DISPLAY out.xkb (modulo some whitespace and some constructs we do not support.) Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/Makefile.am b/Makefile.am index 5fc982b..c4d3352 100644 --- a/Makefile.am +++ b/Makefile.am @@ -201,6 +201,21 @@ check_PROGRAMS += \ endif BUILD_LINUX_TESTS +if ENABLE_X11 +TESTS += \ + test/x11 +TESTS_X11_LDADD = $(TESTS_LDADD) $(XCB_XKB_LIBS) libxkbcommon-x11.la +TESTS_X11_CFLAGS = $(XCB_XKB_CFLAGS) + +test_x11_LDADD = $(TESTS_X11_LDADD) +test_x11_CFLAGS = $(TESTS_X11_CFLAGS) +test_interactive_x11_LDADD = $(TESTS_X11_LDADD) +test_interactive_x11_CFLAGS = $(TESTS_X11_CFLAGS) + +check_PROGRAMS += \ + test/interactive-x11 +endif ENABLE_X11 + EXTRA_DIST += \ test/data diff --git a/test/.gitignore b/test/.gitignore index eacfcc7..e4b7758 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -15,3 +15,5 @@ rmlvo-to-kccgst print-compiled-keymap bench-key-proc atom +x11 +interactive-x11 diff --git a/test/interactive-x11.c b/test/interactive-x11.c new file mode 100644 index 0000000..843b4d2 --- /dev/null +++ b/test/interactive-x11.c @@ -0,0 +1,367 @@ +/* + * Copyright © 2013 Ran Benita <ran...@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <locale.h> + +#include "xkbcommon/xkbcommon-x11.h" +#include "test.h" + +#include <xcb/xkb.h> + +/* + * Note: This program only handles the core keyboard device for now. + * It should be straigtforward to change struct keyboard to a list of + * keyboards with device IDs, as in test/interactive-evdev.c. This would + * require: + * + * - Initially listing the keyboard devices. + * - Listening to device changes. + * - Matching events to their devices. + * + * XKB itself knows about xinput1 devices, and most requests and events are + * device-specific. + * + * In order to list the devices and react to changes, you need xinput1/2. + * You also need xinput for the key press/release event, since the core + * protocol key press event does not carry a device ID to match on. + */ + +struct keyboard { + xcb_connection_t *conn; + uint8_t first_xkb_event; + struct xkb_context *ctx; + + struct xkb_keymap *keymap; + struct xkb_state *state; + int32_t device_id; +}; + +static bool terminate; + +static int +select_xkb_events_for_device(xcb_connection_t *conn, int32_t device_id) +{ + static const xcb_xkb_map_part_t required_map_parts = + (XCB_XKB_MAP_PART_KEY_TYPES | + XCB_XKB_MAP_PART_KEY_SYMS | + XCB_XKB_MAP_PART_MODIFIER_MAP | + XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | + XCB_XKB_MAP_PART_KEY_ACTIONS | + XCB_XKB_MAP_PART_VIRTUAL_MODS | + XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); + + static const xcb_xkb_event_type_t required_events = + (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | + XCB_XKB_EVENT_TYPE_MAP_NOTIFY | + XCB_XKB_EVENT_TYPE_STATE_NOTIFY); + + xcb_void_cookie_t cookie = + xcb_xkb_select_events_checked(conn, + device_id, + required_events, + 0, + required_events, + required_map_parts, + required_map_parts, + 0); + + xcb_generic_error_t *error = xcb_request_check(conn, cookie); + if (error) { + free(error); + return -1; + } + + return 0; +} + +static int +update_keymap(struct keyboard *kbd) +{ + struct xkb_keymap *new_keymap; + struct xkb_state *new_state; + + new_keymap = xkb_x11_keymap_new_from_device(kbd->ctx, kbd->conn, + kbd->device_id, 0); + if (!new_keymap) + goto err_out; + + new_state = xkb_x11_state_new_from_device(new_keymap, kbd->conn, + kbd->device_id); + if (!new_state) + goto err_keymap; + + if (kbd->keymap) + printf("Keymap updated!\n"); + + xkb_state_unref(kbd->state); + xkb_keymap_unref(kbd->keymap); + kbd->keymap = new_keymap; + kbd->state = new_state; + return 0; + +err_keymap: + xkb_keymap_unref(new_keymap); +err_out: + return -1; +} + +static int +init_kbd(struct keyboard *kbd, xcb_connection_t *conn, uint8_t first_xkb_event, + int32_t device_id, struct xkb_context *ctx) +{ + int ret; + + kbd->conn = conn; + kbd->first_xkb_event = first_xkb_event; + kbd->ctx = ctx; + kbd->keymap = NULL; + kbd->state = NULL; + kbd->device_id = device_id; + + ret = update_keymap(kbd); + if (ret) + goto err_out; + + ret = select_xkb_events_for_device(conn, device_id); + if (ret) + goto err_state; + + return 0; + +err_state: + xkb_state_unref(kbd->state); + xkb_keymap_unref(kbd->keymap); +err_out: + return -1; +} + +static void +deinit_kbd(struct keyboard *kbd) +{ + xkb_state_unref(kbd->state); + xkb_keymap_unref(kbd->keymap); +} + +static void +process_xkb_event(xcb_generic_event_t *gevent, struct keyboard *kbd) +{ + union xkb_event { + struct { + uint8_t response_type; + uint8_t xkbType; + uint16_t sequence; + xcb_timestamp_t time; + uint8_t deviceID; + } any; + xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify; + xcb_xkb_map_notify_event_t map_notify; + xcb_xkb_state_notify_event_t state_notify; + } *event = (union xkb_event *) gevent; + + if (event->any.deviceID != kbd->device_id) + return; + + /* + * XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap + * updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent + * recompilations. + */ + switch (event->any.xkbType) { + case XCB_XKB_NEW_KEYBOARD_NOTIFY: + if (event->new_keyboard_notify.changed & XCB_XKB_NKN_DETAIL_KEYCODES) + update_keymap(kbd); + break; + + case XCB_XKB_MAP_NOTIFY: + update_keymap(kbd); + break; + + case XCB_XKB_STATE_NOTIFY: + xkb_state_update_mask(kbd->state, + event->state_notify.baseMods, + event->state_notify.latchedMods, + event->state_notify.lockedMods, + event->state_notify.baseGroup, + event->state_notify.latchedGroup, + event->state_notify.lockedGroup); + break; + } +} + +static void +process_event(xcb_generic_event_t *gevent, struct keyboard *kbd) +{ + switch (gevent->response_type) { + case XCB_KEY_PRESS: { + xcb_key_press_event_t *event = (xcb_key_press_event_t *) gevent; + xkb_keycode_t keycode = event->detail; + + test_print_keycode_state(kbd->state, keycode); + + /* Exit on ESC. */ + if (keycode == 9) + terminate = true; + break; + } + default: + if (gevent->response_type == kbd->first_xkb_event) + process_xkb_event(gevent, kbd); + break; + } +} + +static int +loop(xcb_connection_t *conn, struct keyboard *kbd) +{ + while (!terminate) { + xcb_generic_event_t *event; + + switch (xcb_connection_has_error(conn)) { + case 0: + break; + case XCB_CONN_ERROR: + fprintf(stderr, + "Closed connection to X server: connection error\n"); + return -1; + case XCB_CONN_CLOSED_EXT_NOTSUPPORTED: + fprintf(stderr, + "Closed connection to X server: extension not supported\n"); + return -1; + default: + fprintf(stderr, + "Closed connection to X server: error code %d\n", + xcb_connection_has_error(conn)); + return -1; + } + + event = xcb_wait_for_event(conn); + process_event(event, kbd); + free(event); + } + + return 0; +} + +static int +create_capture_window(xcb_connection_t *conn) +{ + xcb_generic_error_t *error; + xcb_void_cookie_t cookie; + xcb_screen_t *screen = + xcb_setup_roots_iterator(xcb_get_setup(conn)).data; + xcb_window_t window = xcb_generate_id(conn); + uint32_t values[2] = { + screen->white_pixel, + XCB_EVENT_MASK_KEY_PRESS, + }; + + cookie = xcb_create_window_checked(conn, XCB_COPY_FROM_PARENT, + window, screen->root, + 10, 10, 100, 100, 1, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, + values); + if ((error = xcb_request_check(conn, cookie)) != NULL) { + free(error); + return -1; + } + + cookie = xcb_map_window_checked(conn, window); + if ((error = xcb_request_check(conn, cookie)) != NULL) { + free(error); + return -1; + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + int ret; + xcb_connection_t *conn; + uint8_t first_xkb_event; + int32_t core_kbd_device_id; + struct xkb_context *ctx; + struct keyboard core_kbd; + + setlocale(LC_ALL, ""); + + conn = xcb_connect(NULL, NULL); + if (!conn || xcb_connection_has_error(conn)) { + fprintf(stderr, "Couldn't connect to X server: error code %d\n", + conn ? xcb_connection_has_error(conn) : -1); + ret = -1; + goto err_out; + } + + ret = xkb_x11_setup_xkb_extension(conn, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + NULL, NULL, &first_xkb_event, NULL); + if (!ret) { + fprintf(stderr, "Couldn't setup XKB extension\n"); + goto err_conn; + } + + ctx = test_get_context(0); + if (!ctx) { + ret = -1; + fprintf(stderr, "Couldn't create xkb context\n"); + goto err_conn; + } + + core_kbd_device_id = xkb_x11_get_core_keyboard_device_id(conn); + if (core_kbd_device_id == -1) { + ret = -1; + fprintf(stderr, "Couldn't find core keyboard device\n"); + goto err_ctx; + } + + ret = init_kbd(&core_kbd, conn, first_xkb_event, core_kbd_device_id, ctx); + if (ret) { + fprintf(stderr, "Couldn't initialize core keyboard device\n"); + goto err_ctx; + } + + ret = create_capture_window(conn); + if (ret) { + fprintf(stderr, "Couldn't create a capture window\n"); + goto err_core_kbd; + } + + system("stty -echo"); + ret = loop(conn, &core_kbd); + system("stty echo"); + +err_core_kbd: + deinit_kbd(&core_kbd); +err_ctx: + xkb_context_unref(ctx); +err_conn: + xcb_disconnect(conn); +err_out: + exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/test/test.h b/test/test.h index ec0b16d..d0104ce 100644 --- a/test/test.h +++ b/test/test.h @@ -30,6 +30,9 @@ #include "xkbcommon/xkbcommon.h" #include "utils.h" +/* Automake test exit code to signify SKIP (à la PASS, FAIL, etc). */ +#define SKIP_TEST 77 + /* The offset between KEY_* numbering, and keycodes in the XKB evdev * dataset. */ #define EVDEV_OFFSET 8 diff --git a/test/x11.c b/test/x11.c new file mode 100644 index 0000000..f16dded --- /dev/null +++ b/test/x11.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2013 Ran Benita <ran...@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "test.h" +#include "xkbcommon/xkbcommon-x11.h" + +int +main(void) +{ + struct xkb_context *ctx = test_get_context(0); + xcb_connection_t *conn; + int ret; + int32_t device_id; + struct xkb_keymap *keymap; + struct xkb_state *state; + char *dump; + + /* + * The next two steps depend on a running X server with XKB support. + * If it fails, it's not necessarily an actual problem with the code. + * So we don't want a FAIL here. + */ + conn = xcb_connect(NULL, NULL); + if (!conn || xcb_connection_has_error(conn)) + return SKIP_TEST; + + ret = xkb_x11_setup_xkb_extension(conn, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + NULL, NULL, NULL, NULL); + if (!ret) + return SKIP_TEST; + + device_id = xkb_x11_get_core_keyboard_device_id(conn); + assert(device_id != -1); + + keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, + XKB_MAP_COMPILE_NO_FLAGS); + assert(keymap); + + state = xkb_x11_state_new_from_device(keymap, conn, device_id); + assert(state); + + dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); + assert(dump); + fputs(dump, stdout); + + /* TODO: Write some X11-specific tests. */ + + free(dump); + xkb_state_unref(state); + xkb_keymap_unref(keymap); + xcb_disconnect(conn); + xkb_context_unref(ctx); + + return 0; +} commit eb34825560edf570d883d3e52a8fe657c17b3d9c Author: Ran Benita <ran...@gmail.com> Date: Sat Jul 20 23:21:44 2013 +0300 x11: add XKB protocol keymap and state creation support These are function to create an xkb_keymap directly from XKB requests to the X server. This opens up the possibility for X clients to use xcb + xcb-xkb + xkbcommon as a proper replacement for Xlib + xkbfile for keyboard support. The X11 support must be enabled with --enable-x11 for now. The functions are in xkbcommon/xkbcommon-x11.h. It depends on a recent libxcb with xkb enabled. The functions are in a new libxkbcommon-x11.so, with a new pkg-config file, etc. so that the packages may be split, and libxkbcommon.so itself remains dependency-free. Why not just use the RMLVO that the server puts in the _XKB_RULES_NAMES property? This does not account for custom keymaps, on-the-fly keymap modifications, remote clients, etc., so is not a proper solution in practice. Also, some servers don't even set it. Now, the client just needs to recreate the keymap in response to a change in the server's keymap (as Xlib clients do with XRefreshKeyboardMapping() and friends). Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/Makefile.am b/Makefile.am index 3168b55..5fc982b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,6 +78,33 @@ libxkbcommon_la_SOURCES = \ src/utils.c \ src/utils.h +if ENABLE_X11 +pkgconfig_DATA += xkbcommon-x11.pc + +xkbcommon_x11includedir = $(xkbcommonincludedir) +xkbcommon_x11include_HEADERS = \ + xkbcommon/xkbcommon-x11.h + +lib_LTLIBRARIES += libxkbcommon-x11.la + +libxkbcommon_x11_la_CFLAGS = $(AM_CFLAGS) $(XCB_XKB_CFLAGS) +libxkbcommon_x11_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/x11 +libxkbcommon_x11_la_LIBADD = libxkbcommon.la $(XCB_XKB_LIBS) + +libxkbcommon_x11_la_SOURCES = \ + src/x11/keymap.c \ + src/x11/state.c \ + src/x11/util.c \ + src/x11/x11-priv.h \ + src/context.h \ + src/context-priv.c \ + src/keymap.h \ + src/keymap-priv.c \ + src/atom.h \ + src/atom.c + +endif ENABLE_X11 + BUILT_SOURCES = \ src/xkbcomp/parser.c \ src/xkbcomp/parser.h diff --git a/configure.ac b/configure.ac index b8e242e..9f5afa0 100644 --- a/configure.ac +++ b/configure.ac @@ -143,10 +143,23 @@ if ! test "x$DEFAULT_XKB_OPTIONS" = x; then [Default XKB options]) fi +AC_ARG_ENABLE([x11], + [AS_HELP_STRING([--disable-x11], + [Disable support for creating keymaps with the X11 protocol (default: enabled)])], + [], [enable_x11=yes]) +if test "x$enable_x11" == xyes; then + PKG_CHECK_MODULES([XCB_XKB], [xcb xcb-xkb >= 1.10], [], + [AC_MSG_ERROR([xkbcommon-x11 requires xcb-xkb >= 1.10 which was not found. \ +You can disable X11 support with --disable-x11.])]) +fi +AM_CONDITIONAL([ENABLE_X11], [test "x$enable_x11" == xyes]) + AC_CONFIG_FILES([ Makefile xkbcommon-uninstalled.pc xkbcommon.pc + xkbcommon-x11.pc + xkbcommon-x11-uninstalled.pc doc/Doxyfile ]) AC_OUTPUT diff --git a/src/utils.h b/src/utils.h index 04fb9c5..81d1cc9 100644 --- a/src/utils.h +++ b/src/utils.h @@ -158,6 +158,22 @@ is_graph(char ch) return ch >= '!' && ch <= '~'; } +/* + * Return the bit position of the most significant bit. + * Note: this is 1-based! It's more useful this way, and returns 0 when + * mask is all 0s. + */ +static inline int +msb_pos(uint32_t mask) +{ + int pos = 0; + while (mask) { + pos++; + mask >>= 1; + } + return pos; +} + bool map_file(FILE *file, const char **string_out, size_t *size_out); diff --git a/src/x11/keymap.c b/src/x11/keymap.c new file mode 100644 index 0000000..968f187 --- /dev/null +++ b/src/x11/keymap.c @@ -0,0 +1,1146 @@ +/* + * Copyright © 2013 Ran Benita + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "x11-priv.h" + +/* + * References for the lonesome traveler: + * Xkb protocol specification: + * http://www.x.org/releases/current/doc/kbproto/xkbproto.html + * The XCB xkb XML protocol file: + * /user/share/xcb/xkb.xml + * The XCB xkb header file: + * /usr/include/xcb/xkb.h + * The old kbproto header files: + * /usr/include/X11/extensions/XKB{,proto,str}.h + * Xlib XKB source code: + * <libX11>/src/xkb/XKBGetMap.c (and friends) + * X server XKB protocol handling: + * <xserver>/xkb/xkb.c + * Man pages: + * XkbGetMap(3), XkbGetCompatMap(3), etc. + */ + +/* Constants from /usr/include/X11/extensions/XKB.h */ +/* XkbNumModifiers. */ +#define NUM_REAL_MODS 8 +/* XkbNumVirtualMods. */ +#define NUM_VMODS 16 +/* XkbNoModifier. */ -- To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/e1wcypc-00076k...@moszumanska.debian.org