[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

libxkbcommon: Changes to 'upstream-unstable'



 .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 <ran234@gmail.com>
Date:   Sun Feb 2 12:13:26 2014 +0200

    Bump version to 0.4.0
    
    Signed-off-by: Ran Benita <ran234@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 <ran234@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 <ran234@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-devel@lists.x.org,
-or wayland-devel@lists.freedesktop.org.  Bugs are tracked in Bugzilla at:
-    http://bugs.freedesktop.org
+or wayland-devel@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:
     <daniel@fooishbar.org>
+    <ran234@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 <ran234@gmail.com>
Date:   Sun Feb 2 12:05:35 2014 +0200

    Update NEWS
    
    Signed-off-by: Ran Benita <ran234@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 <ran234@gmail.com>
Date:   Sun Feb 2 11:13:28 2014 +0200

    build: add configure summary
    
    Signed-off-by: Ran Benita <ran234@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 <ran234@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 <ran234@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 <ran234@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 <ran234@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 <ran234@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 <ran234@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. */


Reply to: