uterm: input: use uxkb directly
authorDavid Herrmann <dh.herrmann@googlemail.com>
Tue, 9 Oct 2012 08:56:00 +0000 (10:56 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Tue, 9 Oct 2012 08:56:00 +0000 (10:56 +0200)
This changes the uterm-input infrastructure to use XKB directly instead of
using a modularized infrastructure. There is no need to use something else
anymore.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
src/uterm_input.c
src/uterm_input.h
src/uterm_input_uxkb.c

index 7c7379e..0d15dd6 100644 (file)
@@ -53,28 +53,6 @@ enum device_feature {
        FEATURE_HAS_LEDS = 0x02,
 };
 
-struct uterm_input_dev {
-       struct shl_dlist list;
-       struct uterm_input *input;
-
-       unsigned int features;
-       int rfd;
-       char *node;
-       struct ev_fd *fd;
-       struct kbd_dev *kbd;
-};
-
-struct uterm_input {
-       unsigned long ref;
-       struct ev_eloop *eloop;
-       int awake;
-
-       struct shl_hook *hook;
-       struct kbd_desc *desc;
-
-       struct shl_dlist devices;
-};
-
 static void input_free_dev(struct uterm_input_dev *dev);
 
 static void notify_key(struct uterm_input_dev *dev,
@@ -89,7 +67,7 @@ static void notify_key(struct uterm_input_dev *dev,
                return;
 
        memset(&ev, 0, sizeof(ev));
-       ret = kbd_dev_process(dev->kbd, value, code, &ev);
+       ret = uxkb_dev_process(dev, value, code, &ev);
        if (ret)
                return;
 
@@ -156,7 +134,7 @@ static int input_wake_up_dev(struct uterm_input_dev *dev)
                }
 
                /* rediscover the keyboard state if sth changed during sleep */
-               kbd_dev_reset(dev->kbd, ledbits);
+               uxkb_dev_reset(dev, ledbits);
 
                ret = ev_eloop_new_fd(dev->input->eloop, &dev->fd,
                                                dev->rfd, EV_READABLE,
@@ -201,7 +179,7 @@ static void input_new_dev(struct uterm_input *input,
        if (!dev->node)
                goto err_free;
 
-       ret = kbd_desc_alloc(input->desc, &dev->kbd);
+       ret = uxkb_dev_init(dev);
        if (ret)
                goto err_node;
 
@@ -216,7 +194,7 @@ static void input_new_dev(struct uterm_input *input,
        return;
 
 err_kbd:
-       kbd_dev_unref(dev->kbd);
+       uxkb_dev_destroy(dev);
 err_node:
        free(dev->node);
 err_free:
@@ -228,7 +206,7 @@ static void input_free_dev(struct uterm_input_dev *dev)
        log_debug("free device %s", dev->node);
        input_sleep_dev(dev);
        shl_dlist_unlink(&dev->list);
-       kbd_dev_unref(dev->kbd);
+       uxkb_dev_destroy(dev);
        free(dev->node);
        free(dev);
 }
@@ -257,11 +235,7 @@ int uterm_input_new(struct uterm_input **out,
        if (ret)
                goto err_free;
 
-       ret = kbd_desc_new(&input->desc,
-                          layout,
-                          variant,
-                          options,
-                          KBD_UXKB);
+       ret = uxkb_desc_init(input, layout, variant, options);
        if (ret)
                goto err_hook;
 
@@ -301,7 +275,7 @@ void uterm_input_unref(struct uterm_input *input)
                input_free_dev(dev);
        }
 
-       kbd_desc_unref(input->desc);
+       uxkb_desc_destroy(input);
        shl_hook_free(input->hook);
        ev_eloop_unref(input->eloop);
        free(input);
@@ -467,28 +441,3 @@ bool uterm_input_is_awake(struct uterm_input *input)
 
        return input->awake > 0;
 }
-
-void uterm_input_keysym_to_string(struct uterm_input *input,
-                                 uint32_t keysym, char *str, size_t size)
-{
-       if (!str || !size)
-               return;
-       if (!input) {
-               *str = 0;
-               return;
-       }
-
-       kbd_desc_keysym_to_string(input->desc, keysym, str, size);
-}
-
-int uterm_input_string_to_keysym(struct uterm_input *input, const char *n,
-                                uint32_t *out)
-{
-       if (!n || !out)
-               return -EINVAL;
-
-       if (input)
-               return kbd_desc_string_to_keysym(input->desc, n, out);
-
-       return uxkb_string_to_keysym(n, out);
-}
index b3d7b02..18e1997 100644 (file)
 #include <stdlib.h>
 #include <xkbcommon/xkbcommon-keysyms.h>
 #include "eloop.h"
+#include "shl_dlist.h"
 #include "uterm.h"
 
-struct kbd_desc;
-struct kbd_dev;
+struct uterm_input_dev {
+       struct shl_dlist list;
+       struct uterm_input *input;
 
-struct kbd_desc_ops {
-       int (*init) (struct kbd_desc **out, const char *layout,
-                    const char *variant, const char *options);
-       void (*ref) (struct kbd_desc *desc);
-       void (*unref) (struct kbd_desc *desc);
-       int (*alloc) (struct kbd_desc *desc, struct kbd_dev **out);
-       void (*keysym_to_string) (uint32_t keysym, char *str, size_t size);
-       int (*string_to_keysym) (const char *n, uint32_t *out);
-};
-
-struct kbd_dev_ops {
-       void (*ref) (struct kbd_dev *dev);
-       void (*unref) (struct kbd_dev *dev);
-       void (*reset) (struct kbd_dev *dev, const unsigned long *ledbits);
-       int (*process) (struct kbd_dev *dev, uint16_t state, uint16_t code,
-                       struct uterm_input_event *out);
-};
-
-struct uxkb_desc {
-       struct xkb_context *ctx;
-       struct xkb_keymap *keymap;
-};
-
-struct uxkb_dev {
+       unsigned int features;
+       int rfd;
+       char *node;
+       struct ev_fd *fd;
        struct xkb_state *state;
 };
 
-static const bool uxkb_available = true;
-extern const struct kbd_desc_ops uxkb_desc_ops;
-extern const struct kbd_dev_ops uxkb_dev_ops;
-
-extern int uxkb_string_to_keysym(const char *n, uint32_t *out);
-
-struct kbd_desc {
+struct uterm_input {
        unsigned long ref;
-       const struct kbd_desc_ops *ops;
-
-       union {
-               struct uxkb_desc uxkb;
-       };
-};
+       struct ev_eloop *eloop;
+       int awake;
 
-struct kbd_dev {
-       unsigned long ref;
-       struct kbd_desc *desc;
-       const struct kbd_dev_ops *ops;
-
-       union {
-               struct uxkb_dev uxkb;
-       };
-};
+       struct shl_hook *hook;
+       struct xkb_context *ctx;
+       struct xkb_keymap *keymap;
 
-enum kbd_mode {
-       KBD_UXKB,
+       struct shl_dlist devices;
 };
 
-static inline int kbd_desc_new(struct kbd_desc **out, const char *layout,
-                              const char *variant, const char *options,
-                              unsigned int mode)
-{
-       const struct kbd_desc_ops *ops;
-
-       switch (mode) {
-       case KBD_UXKB:
-               if (!uxkb_available) {
-                       log_error("XKB KBD backend not available");
-                       return -EOPNOTSUPP;
-               }
-               ops = &uxkb_desc_ops;
-               break;
-       default:
-               log_error("unknown KBD backend %u", mode);
-               return -EINVAL;
-       }
-
-       return ops->init(out, layout, variant, options);
-}
-
-static inline void kbd_desc_ref(struct kbd_desc *desc)
-{
-       if (!desc)
-               return;
-
-       return desc->ops->ref(desc);
-}
-
-static inline void kbd_desc_unref(struct kbd_desc *desc)
-{
-       if (!desc)
-               return;
-
-       return desc->ops->unref(desc);
-}
-
-static inline int kbd_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
-{
-       if (!desc)
-               return -EINVAL;
-
-       return desc->ops->alloc(desc, out);
-}
-
-static inline void kbd_desc_keysym_to_string(struct kbd_desc *desc,
-                                            uint32_t keysym,
-                                            char *str, size_t size)
-{
-       if (!desc)
-               return;
-
-       return desc->ops->keysym_to_string(keysym, str, size);
-}
-
-static inline int kbd_desc_string_to_keysym(struct kbd_desc *desc,
-                                           const char *n,
-                                           uint32_t *out)
-{
-       if (!desc)
-               return -EINVAL;
-
-       return desc->ops->string_to_keysym(n, out);
-}
-
-static inline void kbd_dev_ref(struct kbd_dev *dev)
-{
-       if (!dev)
-               return;
-
-       return dev->ops->ref(dev);
-}
-
-static inline void kbd_dev_unref(struct kbd_dev *dev)
-{
-       if (!dev)
-               return;
-
-       return dev->ops->unref(dev);
-}
-
-static inline void kbd_dev_reset(struct kbd_dev *dev,
-                                const unsigned long *ledbits)
-{
-       if (!dev)
-               return;
-
-       return dev->ops->reset(dev, ledbits);
-}
-
-static inline int kbd_dev_process(struct kbd_dev *dev,
-                                 uint16_t key_state,
-                                 uint16_t code,
-                                 struct uterm_input_event *out)
-{
-       if (!dev)
-               return -EINVAL;
-
-       return dev->ops->process(dev, key_state, code, out);
-}
-
 static inline bool input_bit_is_set(const unsigned long *array, int bit)
 {
        return !!(array[bit / LONG_BIT] & (1LL << (bit % LONG_BIT)));
 }
 
+int uxkb_desc_init(struct uterm_input *input,
+                  const char *layout,
+                  const char *variant,
+                  const char *options);
+void uxkb_desc_destroy(struct uterm_input *input);
+
+int uxkb_dev_init(struct uterm_input_dev *dev);
+void uxkb_dev_destroy(struct uterm_input_dev *dev);
+int uxkb_dev_process(struct uterm_input_dev *dev,
+                    uint16_t key_state,
+                    uint16_t code,
+                    struct uterm_input_event *out);
+void uxkb_dev_reset(struct uterm_input_dev *dev, const unsigned long *ledbits);
+
 #endif /* UTERM_INPUT_H */
index ddc9b67..a046c9a 100644 (file)
 
 #define LOG_SUBSYSTEM "input_uxkb"
 
-static void uxkb_dev_ref(struct kbd_dev *kbd)
+int uxkb_desc_init(struct uterm_input *input,
+                  const char *layout,
+                  const char *variant,
+                  const char *options)
 {
-       if (!kbd || !kbd->ref)
-               return;
+       int ret;
+       struct xkb_rule_names rmlvo = {
+               .rules = "evdev",
+               .model = "evdev",
+               .layout = layout,
+               .variant = variant,
+               .options = options,
+       };
+
+       input->ctx = xkb_context_new(0);
+       if (!input->ctx) {
+               log_error("cannot create XKB context");
+               return -ENOMEM;
+       }
+
+       input->keymap = xkb_map_new_from_names(input->ctx, &rmlvo, 0);
+       if (!input->keymap) {
+               log_warn("failed to create keymap (%s, %s, %s), "
+                        "reverting to default US keymap",
+                        layout, variant, options);
+
+               rmlvo.layout = "us";
+               rmlvo.variant = "";
+               rmlvo.options = "";
+
+               input->keymap = xkb_map_new_from_names(input->ctx, &rmlvo, 0);
+               if (!input->keymap) {
+                       log_warn("failed to create XKB keymap");
+                       ret = -EFAULT;
+                       goto err_ctx;
+               }
+       }
+
+       log_debug("new keyboard description (%s, %s, %s)",
+                 layout, variant, options);
+       return 0;
 
-       ++kbd->ref;
+err_ctx:
+       xkb_context_unref(input->ctx);
+       return ret;
 }
 
-static void uxkb_dev_unref(struct kbd_dev *kbd)
+void uxkb_desc_destroy(struct uterm_input *input)
 {
-       if (!kbd || !kbd->ref || --kbd->ref)
-               return;
+       xkb_map_unref(input->keymap);
+       xkb_context_unref(input->ctx);
+}
+
+int uxkb_dev_init(struct uterm_input_dev *dev)
+{
+       dev->state = xkb_state_new(dev->input->keymap);
+       if (!dev->state)
+               return -ENOMEM;
 
-       xkb_state_unref(kbd->uxkb.state);
-       kbd_desc_unref(kbd->desc);
-       free(kbd);
+       return 0;
+}
+
+void uxkb_dev_destroy(struct uterm_input_dev *dev)
+{
+       xkb_state_unref(dev->state);
 }
 
 #define EVDEV_KEYCODE_OFFSET 8
@@ -63,10 +112,10 @@ enum {
        KEY_REPEATED = 2,
 };
 
-static int uxkb_dev_process(struct kbd_dev *kbd,
-                           uint16_t key_state,
-                           uint16_t code,
-                           struct uterm_input_event *out)
+int uxkb_dev_process(struct uterm_input_dev *dev,
+                    uint16_t key_state,
+                    uint16_t code,
+                    struct uterm_input_event *out)
 {
        struct xkb_state *state;
        struct xkb_keymap *keymap;
@@ -74,10 +123,7 @@ static int uxkb_dev_process(struct kbd_dev *kbd,
        const xkb_keysym_t *keysyms;
        int num_keysyms;
 
-       if (!kbd)
-               return -EINVAL;
-
-       state = kbd->uxkb.state;
+       state = dev->state;
        keymap = xkb_state_get_map(state);
        keycode = code + EVDEV_KEYCODE_OFFSET;
 
@@ -115,7 +161,7 @@ static int uxkb_dev_process(struct kbd_dev *kbd,
  * We don't reset the locked group, this should survive a VT switch, etc. The
  * locked modifiers are reset according to the keyboard LEDs.
  */
-static void uxkb_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
+void uxkb_dev_reset(struct uterm_input_dev *dev, const unsigned long *ledbits)
 {
        unsigned int i;
        struct xkb_state *state;
@@ -128,9 +174,6 @@ static void uxkb_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
                { LED_SCROLLL, XKB_LED_NAME_SCROLL },
        };
 
-       if (!kbd)
-               return;
-
        /* TODO: Urghs, while the input device was closed we might have missed
         * some events that affect internal state. As xkbcommon does not provide
         * a way to reset the internal state, we simply recreate the state. This
@@ -138,13 +181,13 @@ static void uxkb_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
         * It also has a bug that if the CTRL-Release event is skipped, then
         * every further release will never perform a _real_ release. Kind of
         * buggy so we should fix it upstream. */
-       state = xkb_state_new(kbd->desc->uxkb.keymap);
+       state = xkb_state_new(dev->input->keymap);
        if (!state) {
                log_warning("cannot recreate xkb-state");
                return;
        }
-       xkb_state_unref(kbd->uxkb.state);
-       kbd->uxkb.state = state;
+       xkb_state_unref(dev->state);
+       dev->state = state;
 
        for (i = 0; i < sizeof(led_names) / sizeof(*led_names); i++) {
                if (!input_bit_is_set(ledbits, led_names[i].led))
@@ -158,144 +201,3 @@ static void uxkb_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
                 */
        }
 }
-
-static int uxkb_desc_init(struct kbd_desc **out,
-                         const char *layout,
-                         const char *variant,
-                         const char *options)
-{
-       int ret;
-       struct kbd_desc *desc;
-       struct xkb_rule_names rmlvo = {
-               .rules = "evdev",
-               .model = "evdev",
-               .layout = layout,
-               .variant = variant,
-               .options = options,
-       };
-
-       if (!out)
-               return -EINVAL;
-
-       desc = malloc(sizeof(*desc));
-       if (!desc)
-               return -ENOMEM;
-
-       memset(desc, 0, sizeof(*desc));
-       desc->ref = 1;
-       desc->ops = &uxkb_desc_ops;
-
-       desc->uxkb.ctx = xkb_context_new(0);
-       if (!desc->uxkb.ctx) {
-               ret = -ENOMEM;
-               goto err_desc;
-       }
-
-       desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx, &rmlvo, 0);
-       if (!desc->uxkb.keymap) {
-               log_warn("failed to create keymap (%s, %s, %s), "
-                        "reverting to default US keymap",
-                        layout, variant, options);
-
-               rmlvo.layout = "us";
-               rmlvo.variant = "";
-               rmlvo.options = "";
-
-               desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx,
-                                                          &rmlvo, 0);
-               if (!desc->uxkb.keymap) {
-                       log_warn("failed to create keymap");
-                       ret = -EFAULT;
-                       goto err_ctx;
-               }
-       }
-
-       log_debug("new keyboard description (%s, %s, %s)",
-                       layout, variant, options);
-       *out = desc;
-       return 0;
-
-err_ctx:
-       xkb_context_unref(desc->uxkb.ctx);
-err_desc:
-       free(desc);
-       return ret;
-}
-
-static void uxkb_desc_ref(struct kbd_desc *desc)
-{
-       if (!desc || !desc->ref)
-               return;
-
-       ++desc->ref;
-}
-
-static void uxkb_desc_unref(struct kbd_desc *desc)
-{
-       if (!desc || !desc->ref || --desc->ref)
-               return;
-
-       log_debug("destroying keyboard description");
-       xkb_map_unref(desc->uxkb.keymap);
-       xkb_context_unref(desc->uxkb.ctx);
-       free(desc);
-}
-
-static int uxkb_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
-{
-       struct kbd_dev *kbd;
-
-       kbd = malloc(sizeof(*kbd));
-       if (!kbd)
-               return -ENOMEM;
-
-       memset(kbd, 0, sizeof(*kbd));
-       kbd->ref = 1;
-       kbd->desc = desc;
-       kbd->ops = &uxkb_dev_ops;
-
-       kbd->uxkb.state = xkb_state_new(desc->uxkb.keymap);
-       if (!kbd->uxkb.state) {
-               free(kbd);
-               return -ENOMEM;
-       }
-
-       kbd_desc_ref(desc);
-       *out = kbd;
-       return 0;
-}
-
-static void uxkb_keysym_to_string(uint32_t keysym, char *str, size_t size)
-{
-       xkb_keysym_get_name(keysym, str, size);
-}
-
-int uxkb_string_to_keysym(const char *n, uint32_t *out)
-{
-       uint32_t keysym;
-
-       /* TODO: fix xkbcommon upstream to be case-insensitive if case-sensitive
-        * match fails. */
-       keysym = xkb_keysym_from_name(n);
-       if (!keysym)
-               return -EFAULT;
-
-       *out = keysym;
-       return 0;
-}
-
-const struct kbd_desc_ops uxkb_desc_ops = {
-       .init = uxkb_desc_init,
-       .ref = uxkb_desc_ref,
-       .unref = uxkb_desc_unref,
-       .alloc = uxkb_desc_alloc,
-       .keysym_to_string = uxkb_keysym_to_string,
-       .string_to_keysym = uxkb_string_to_keysym,
-};
-
-const struct kbd_dev_ops uxkb_dev_ops = {
-       .ref = uxkb_dev_ref,
-       .unref = uxkb_dev_unref,
-       .reset = uxkb_dev_reset,
-       .process = uxkb_dev_process,
-};