Enable Wayland's virtual-keyboard protocol
This commit includes a little restructuring necessary for keeping wayland objects properly. It doesn't fix broken modifier functionality yet.
This commit is contained in:
		@ -29,8 +29,17 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif  /* HAVE_CONFIG_H */
 | 
			
		||||
 | 
			
		||||
#include "eekboard/key-emitter.h"
 | 
			
		||||
#include "eekboard/eekboard-context-service.h"
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/random.h> // TODO: this is Linux-specific
 | 
			
		||||
#include <xkbcommon/xkbcommon.h>
 | 
			
		||||
 | 
			
		||||
#include "eekboard/key-emitter.h"
 | 
			
		||||
#include "wayland.h"
 | 
			
		||||
//#include "eekboard/eekboard-xklutil.h"
 | 
			
		||||
//#include "eek/eek-xkl.h"
 | 
			
		||||
 | 
			
		||||
@ -116,8 +125,9 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
			
		||||
            g_warning ("can't create keyboard %s: %s",
 | 
			
		||||
                       keyboard_type, error->message);
 | 
			
		||||
            g_error_free (error);
 | 
			
		||||
            keyboard_type = "us";
 | 
			
		||||
            error = NULL;
 | 
			
		||||
            layout = eek_xml_layout_new ("us", &error);
 | 
			
		||||
            layout = eek_xml_layout_new (keyboard_type, &error);
 | 
			
		||||
            if (layout == NULL) {
 | 
			
		||||
                g_error ("failed to create fallback layout: %s", error->message);
 | 
			
		||||
                g_error_free (error);
 | 
			
		||||
@ -125,9 +135,54 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    keyboard = eek_keyboard_new (layout, CSW, CSH);
 | 
			
		||||
    keyboard = eek_keyboard_new (self, layout, CSW, CSH);
 | 
			
		||||
    g_object_unref (layout);
 | 
			
		||||
 | 
			
		||||
    struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 | 
			
		||||
    if (!context) {
 | 
			
		||||
        g_error("No context created");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct xkb_rule_names rules = { 0 };
 | 
			
		||||
    rules.layout = strdup(keyboard_type);
 | 
			
		||||
    struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules,
 | 
			
		||||
        XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
			
		||||
    if (!keymap) {
 | 
			
		||||
        g_error("Bad keymap");
 | 
			
		||||
    }
 | 
			
		||||
    keyboard->keymap = keymap;
 | 
			
		||||
    char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
 | 
			
		||||
    int f = open("km", O_CREAT|O_WRONLY);
 | 
			
		||||
    write(f, keymap_str, strlen(keymap_str) + 1);
 | 
			
		||||
    if (!keymap_str) {
 | 
			
		||||
        g_error("Keymap was not serialized");
 | 
			
		||||
    }
 | 
			
		||||
    keyboard->keymap_len = strlen(keymap_str) + 1;
 | 
			
		||||
    char *path = strdup("/eek_keymap-XXXXXX");
 | 
			
		||||
    char *r = &path[strlen(path) - 6];
 | 
			
		||||
    getrandom(r, 6, GRND_NONBLOCK);
 | 
			
		||||
    for (uint i = 0; i < 6; i++) {
 | 
			
		||||
        r[i] = (r[i] & 0b1111111) | 0b1000000; // A-z
 | 
			
		||||
        r[i] = r[i] > 'z' ? '?' : r[i]; // The randomizer doesn't need to be good...
 | 
			
		||||
    }
 | 
			
		||||
    int keymap_fd = shm_open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
 | 
			
		||||
    if (keymap_fd < 0) {
 | 
			
		||||
        g_error("Failed to set up keymap fd");
 | 
			
		||||
    }
 | 
			
		||||
    keyboard->keymap_fd = keymap_fd;
 | 
			
		||||
    shm_unlink(path);
 | 
			
		||||
    if (ftruncate(keymap_fd, (off_t)keyboard->keymap_len)) {
 | 
			
		||||
        g_error("Failed to increase keymap fd size");
 | 
			
		||||
    }
 | 
			
		||||
    char *ptr = mmap(NULL, keyboard->keymap_len, PROT_WRITE, MAP_SHARED,
 | 
			
		||||
        keymap_fd, 0);
 | 
			
		||||
    if ((void*)ptr == (void*)-1) {
 | 
			
		||||
        g_error("Failed to set up mmap");
 | 
			
		||||
    }
 | 
			
		||||
    strcpy(ptr, keymap_str);
 | 
			
		||||
    munmap(ptr, keyboard->keymap_len);
 | 
			
		||||
    free(keymap_str);
 | 
			
		||||
 | 
			
		||||
    return keyboard;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -233,14 +288,10 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
 | 
			
		||||
    g_variant_iter_free(iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_update_layout(EekboardContextService *context) {
 | 
			
		||||
    EekboardContextServiceClass *klass = EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context);
 | 
			
		||||
    static guint keyboard_id = 0;
 | 
			
		||||
    g_autofree gchar *keyboard_type = NULL;
 | 
			
		||||
    g_autofree gchar *keyboard_layout = NULL;
 | 
			
		||||
 | 
			
		||||
    settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);
 | 
			
		||||
 | 
			
		||||
    if (!keyboard_type) {
 | 
			
		||||
@ -250,10 +301,13 @@ settings_update_layout(EekboardContextService *context) {
 | 
			
		||||
        keyboard_layout = g_strdup("undefined");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // generic part follows
 | 
			
		||||
    static guint keyboard_id = 0;
 | 
			
		||||
    EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
 | 
			
		||||
                                                GUINT_TO_POINTER(keyboard_id));
 | 
			
		||||
    // create a keyboard
 | 
			
		||||
    if (!keyboard) {
 | 
			
		||||
        EekboardContextServiceClass *klass = EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context);
 | 
			
		||||
        keyboard = klass->create_keyboard (context, keyboard_layout);
 | 
			
		||||
        eek_keyboard_set_modifier_behavior (keyboard,
 | 
			
		||||
                                            EEK_MODIFIER_BEHAVIOR_LATCH);
 | 
			
		||||
@ -270,7 +324,6 @@ settings_update_layout(EekboardContextService *context) {
 | 
			
		||||
    context->priv->keyboard = keyboard;
 | 
			
		||||
    // TODO: this used to save the group, why?
 | 
			
		||||
    //group = eek_element_get_group (EEK_ELEMENT(context->priv->keyboard));
 | 
			
		||||
 | 
			
		||||
    g_object_notify (G_OBJECT(context), "keyboard");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -278,16 +331,24 @@ static gboolean
 | 
			
		||||
settings_handle_layout_changed(GSettings *s,
 | 
			
		||||
                               gpointer keys, gint n_keys,
 | 
			
		||||
                               gpointer user_data) {
 | 
			
		||||
    (void)s;
 | 
			
		||||
    (void)keys;
 | 
			
		||||
    (void)n_keys;
 | 
			
		||||
    EekboardContextService *context = user_data;
 | 
			
		||||
    settings_update_layout(context);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_context_service_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE (object);
 | 
			
		||||
    context->virtual_keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
 | 
			
		||||
                squeek_wayland->virtual_keyboard_manager,
 | 
			
		||||
                squeek_wayland->seat);
 | 
			
		||||
    if (!context->virtual_keyboard) {
 | 
			
		||||
        g_error("Programmer error: Failed to receive a virtual keyboard instance");
 | 
			
		||||
    }
 | 
			
		||||
    settings_update_layout(context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -563,3 +624,11 @@ eekboard_context_service_get_fullscreen (EekboardContextService *context)
 | 
			
		||||
{
 | 
			
		||||
    return context->priv->fullscreen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
			
		||||
                                         const EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    zwp_virtual_keyboard_v1_keymap(context->virtual_keyboard,
 | 
			
		||||
        WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
 | 
			
		||||
        keyboard->keymap_fd, keyboard->keymap_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,14 +36,15 @@ G_BEGIN_DECLS
 | 
			
		||||
#define EEKBOARD_IS_CONTEXT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_CONTEXT_SERVICE))
 | 
			
		||||
#define EEKBOARD_CONTEXT_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_CONTEXT_SERVICE, EekboardContextServiceClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardContextService EekboardContextService;
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardContextServiceClass EekboardContextServiceClass;
 | 
			
		||||
typedef struct _EekboardContextServicePrivate EekboardContextServicePrivate;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekboardContextService:
 | 
			
		||||
 *
 | 
			
		||||
 * TODO: Restrict to managing keyboard layouts, and maybe button rerpeats.
 | 
			
		||||
 * TODO: Restrict to managing keyboard layouts, and maybe button repeats,
 | 
			
		||||
 * and the virtual keyboard protocol.
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekboardContextService structure contains only private data
 | 
			
		||||
 * and should only be accessed using the provided API.
 | 
			
		||||
@ -52,6 +53,8 @@ struct _EekboardContextService {
 | 
			
		||||
    GObject parent;
 | 
			
		||||
 | 
			
		||||
    EekboardContextServicePrivate *priv;
 | 
			
		||||
 | 
			
		||||
    struct zwp_virtual_keyboard_v1 *virtual_keyboard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -96,5 +99,8 @@ EekKeyboard  *eekboard_context_service_get_keyboard
 | 
			
		||||
gboolean      eekboard_context_service_get_fullscreen
 | 
			
		||||
                                              (EekboardContextService *context);
 | 
			
		||||
 | 
			
		||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
			
		||||
                                         const EekKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEKBOARD_CONTEXT_SERVICE_H */
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,8 @@ typedef struct _EekboardServicePrivate EekboardServicePrivate;
 | 
			
		||||
/**
 | 
			
		||||
 * EekboardService:
 | 
			
		||||
 *
 | 
			
		||||
 * Manages DBus interaction.
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekboardService structure contains only private data and
 | 
			
		||||
 * should only be accessed using the provided API.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -20,9 +20,24 @@
 | 
			
		||||
/* This file is responsible for managing keycode data and emitting keycodes. */
 | 
			
		||||
 | 
			
		||||
#include "eekboard/key-emitter.h"
 | 
			
		||||
#include "eekboard/keymap.h"
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
 | 
			
		||||
#include "eekboard/eekboard-context-service.h"
 | 
			
		||||
 | 
			
		||||
// TODO: decide whether it's this struct that carries the keyboard around in key-emitter or if the whole manager should be dragged around
 | 
			
		||||
// if this is the carrier, then it should be made part of the manager
 | 
			
		||||
// hint: check which fields need to be persisted between keypresses; which between keyboards
 | 
			
		||||
typedef struct {
 | 
			
		||||
    struct zwp_virtual_keyboard_v1 *virtual_keyboard; // unowned copy
 | 
			
		||||
    struct xkb_keymap *keymap; // unowned copy
 | 
			
		||||
    XkbDescRec *xkb;
 | 
			
		||||
    guint modifier_keycodes[8];
 | 
			
		||||
    gint group;
 | 
			
		||||
} SeatEmitter;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* The following functions for keyboard mapping change are direct
 | 
			
		||||
   translation of the code in Caribou (in libcaribou/xadapter.vala):
 | 
			
		||||
 | 
			
		||||
@ -33,7 +48,7 @@
 | 
			
		||||
 | 
			
		||||
/* Find an unused keycode where a keysym can be assigned. Restricted to Level 1 */
 | 
			
		||||
static guint
 | 
			
		||||
get_replaced_keycode (Client *client)
 | 
			
		||||
get_replaced_keycode (SeatEmitter *client)
 | 
			
		||||
{
 | 
			
		||||
    guint keycode;
 | 
			
		||||
return 0; // FIXME: no xkb allocated yet
 | 
			
		||||
@ -58,7 +73,7 @@ return 0; // FIXME: no xkb allocated yet
 | 
			
		||||
   non-zero keycode), it simply changes the current map with the
 | 
			
		||||
   specified KEYCODE and KEYSYM. */
 | 
			
		||||
static gboolean
 | 
			
		||||
replace_keycode (Client *client,
 | 
			
		||||
replace_keycode (SeatEmitter *emitter,
 | 
			
		||||
                 guint   keycode,
 | 
			
		||||
                 guint  *keysym)
 | 
			
		||||
{
 | 
			
		||||
@ -68,8 +83,8 @@ replace_keycode (Client *client,
 | 
			
		||||
    int keysyms_per_keycode;
 | 
			
		||||
    KeySym *syms;
 | 
			
		||||
return TRUE; // FIXME: no xkb allocated at the moment, pretending all is fine
 | 
			
		||||
    g_return_val_if_fail (client->xkb->min_key_code <= keycode &&
 | 
			
		||||
                          keycode <= client->xkb->max_key_code,
 | 
			
		||||
    g_return_val_if_fail (emitter->xkb->min_key_code <= keycode &&
 | 
			
		||||
                          keycode <= emitter->xkb->max_key_code,
 | 
			
		||||
                          FALSE);
 | 
			
		||||
    g_return_val_if_fail (keysym != NULL, FALSE);
 | 
			
		||||
/*
 | 
			
		||||
@ -87,20 +102,19 @@ return TRUE; // FIXME: no xkb allocated at the moment, pretending all is fine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
get_keycode_from_gdk_keymap (Client *client,
 | 
			
		||||
get_keycode_from_gdk_keymap (SeatEmitter *emitter,
 | 
			
		||||
                             guint           keysym,
 | 
			
		||||
                             guint          *keycode,
 | 
			
		||||
                             guint          *modifiers)
 | 
			
		||||
{
 | 
			
		||||
    GdkKeymap *keymap = gdk_keymap_get_default ();
 | 
			
		||||
    GdkKeymapKey *keys, *best_match = NULL;
 | 
			
		||||
    gint n_keys, i;
 | 
			
		||||
    guint n_keys, i;
 | 
			
		||||
 | 
			
		||||
    if (!gdk_keymap_get_entries_for_keyval (keymap, keysym, &keys, &n_keys))
 | 
			
		||||
    if (!squeek_keymap_get_entries_for_keyval (emitter->keymap, keysym, &keys, &n_keys))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < n_keys; i++)
 | 
			
		||||
        if (keys[i].group == client->context->group)
 | 
			
		||||
        if (keys[i].group == emitter->group)
 | 
			
		||||
            best_match = &keys[i];
 | 
			
		||||
 | 
			
		||||
    if (!best_match) {
 | 
			
		||||
@ -115,69 +129,63 @@ get_keycode_from_gdk_keymap (Client *client,
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int WaylandFakeKeyEvent(
 | 
			
		||||
    Display* dpy,
 | 
			
		||||
int send_virtual_keyboard_key(
 | 
			
		||||
    struct zwp_virtual_keyboard_v1 *keyboard,
 | 
			
		||||
    unsigned int keycode,
 | 
			
		||||
    Bool is_press,
 | 
			
		||||
    unsigned is_press,
 | 
			
		||||
    uint32_t timestamp
 | 
			
		||||
) {
 | 
			
		||||
    printf("%d: Sending fake event %d press %d\n", timestamp, keycode, is_press);
 | 
			
		||||
    zwp_virtual_keyboard_v1_key(keyboard, timestamp, keycode, (unsigned)is_press);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
send_fake_modifier_key_event (Client         *client,
 | 
			
		||||
send_fake_modifier_key_event (SeatEmitter         *emitter,
 | 
			
		||||
                              EekModifierType modifiers,
 | 
			
		||||
                              gboolean        is_pressed,
 | 
			
		||||
                              uint32_t        timestamp)
 | 
			
		||||
{
 | 
			
		||||
    GdkDisplay *display = gdk_display_get_default ();
 | 
			
		||||
    Display *xdisplay = NULL; //GDK_DISPLAY_XDISPLAY (display);
 | 
			
		||||
    unsigned long i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(client->modifier_keycodes); i++) {
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(emitter->modifier_keycodes); i++) {
 | 
			
		||||
        if (modifiers & (1 << i)) {
 | 
			
		||||
            guint keycode = client->modifier_keycodes[i];
 | 
			
		||||
            guint keycode = emitter->modifier_keycodes[i];
 | 
			
		||||
            printf("Trying to send a modifier %ld press %d\n", i, is_pressed);
 | 
			
		||||
            g_return_if_fail (keycode > 0);
 | 
			
		||||
 | 
			
		||||
            WaylandFakeKeyEvent (xdisplay,
 | 
			
		||||
                                 keycode,
 | 
			
		||||
                                 is_pressed,
 | 
			
		||||
                                 timestamp);
 | 
			
		||||
            send_virtual_keyboard_key (emitter->virtual_keyboard,
 | 
			
		||||
                                       keycode,
 | 
			
		||||
                                       is_pressed,
 | 
			
		||||
                                       timestamp);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
send_fake_key_event (Client  *client,
 | 
			
		||||
send_fake_key_event (SeatEmitter *emitter,
 | 
			
		||||
                     guint    xkeysym,
 | 
			
		||||
                     guint    keyboard_modifiers,
 | 
			
		||||
                     gboolean pressed,
 | 
			
		||||
                     uint32_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    GdkDisplay *display = gdk_display_get_default ();
 | 
			
		||||
    Display *xdisplay = NULL; // GDK_DISPLAY_XDISPLAY (display);
 | 
			
		||||
    EekModifierType modifiers;
 | 
			
		||||
    guint keycode;
 | 
			
		||||
    guint old_keysym = xkeysym;
 | 
			
		||||
 | 
			
		||||
    g_return_if_fail (xkeysym > 0);
 | 
			
		||||
 | 
			
		||||
    modifiers = 0;
 | 
			
		||||
    if (!get_keycode_from_gdk_keymap (client, xkeysym, &keycode, &modifiers)) {
 | 
			
		||||
        keycode = get_replaced_keycode (client);
 | 
			
		||||
    guint keycode;
 | 
			
		||||
    if (!get_keycode_from_gdk_keymap (emitter, xkeysym, &keycode, &modifiers)) {
 | 
			
		||||
        keycode = get_replaced_keycode (emitter);
 | 
			
		||||
        if (keycode == 0) {
 | 
			
		||||
            g_warning ("no available keycode to replace");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!replace_keycode (client, keycode, &old_keysym)) {
 | 
			
		||||
        if (!replace_keycode (emitter, keycode, &old_keysym)) {
 | 
			
		||||
            g_warning ("failed to lookup X keysym %X", xkeysym);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Clear level shift modifiers */
 | 
			
		||||
    keyboard_modifiers &= (unsigned)~EEK_SHIFT_MASK;
 | 
			
		||||
    keyboard_modifiers &= (unsigned)~EEK_LOCK_MASK;
 | 
			
		||||
@ -190,16 +198,18 @@ send_fake_key_event (Client  *client,
 | 
			
		||||
 | 
			
		||||
    modifiers |= keyboard_modifiers;
 | 
			
		||||
 | 
			
		||||
    send_fake_modifier_key_event (client, modifiers, TRUE, timestamp);
 | 
			
		||||
    WaylandFakeKeyEvent (xdisplay, keycode, pressed, timestamp);
 | 
			
		||||
    send_fake_modifier_key_event (client, modifiers, FALSE, timestamp);
 | 
			
		||||
    send_fake_modifier_key_event (emitter, modifiers, TRUE, timestamp);
 | 
			
		||||
 | 
			
		||||
    // There's something magical about subtracting/adding 8 to keycodes for some reason
 | 
			
		||||
    send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
 | 
			
		||||
    send_fake_modifier_key_event (emitter, modifiers, FALSE, timestamp);
 | 
			
		||||
 | 
			
		||||
    if (old_keysym != xkeysym)
 | 
			
		||||
        replace_keycode (client, keycode, &old_keysym);
 | 
			
		||||
        replace_keycode (emitter, keycode, &old_keysym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
send_fake_key_events (Client    *client,
 | 
			
		||||
send_fake_key_events (SeatEmitter *emitter,
 | 
			
		||||
                      EekSymbol *symbol,
 | 
			
		||||
                      guint      keyboard_modifiers,
 | 
			
		||||
                      gboolean   pressed,
 | 
			
		||||
@ -239,16 +249,16 @@ send_fake_key_events (Client    *client,
 | 
			
		||||
 | 
			
		||||
    if (EEK_IS_KEYSYM(symbol)) {
 | 
			
		||||
        guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
 | 
			
		||||
        send_fake_key_event (client, xkeysym, keyboard_modifiers, pressed, timestamp);
 | 
			
		||||
        send_fake_key_event (emitter, xkeysym, keyboard_modifiers, pressed, timestamp);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
emit_key_activated (EekboardContext *context,
 | 
			
		||||
emit_key_activated (EekboardContextService *manager,
 | 
			
		||||
                    EekKeyboard     *keyboard,
 | 
			
		||||
                    guint            keycode,
 | 
			
		||||
                    EekSymbol       *symbol,
 | 
			
		||||
                    guint            modifiers,
 | 
			
		||||
                    Client  *client,
 | 
			
		||||
                    gboolean pressed,
 | 
			
		||||
                    uint32_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
@ -279,12 +289,15 @@ emit_key_activated (EekboardContext *context,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
*/
 | 
			
		||||
    send_fake_key_events (client, symbol, modifiers, pressed, timestamp);
 | 
			
		||||
    SeatEmitter emitter = {0};
 | 
			
		||||
    emitter.virtual_keyboard = manager->virtual_keyboard;
 | 
			
		||||
    emitter.keymap = keyboard->keymap;
 | 
			
		||||
    send_fake_key_events (&emitter, symbol, modifiers, pressed, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Finds the first key code for each modifier and saves it in modifier_keycodes */
 | 
			
		||||
static void
 | 
			
		||||
update_modifier_keycodes (Client *client)
 | 
			
		||||
update_modifier_keycodes (SeatEmitter *client)
 | 
			
		||||
{
 | 
			
		||||
    GdkDisplay *display = gdk_display_get_default ();
 | 
			
		||||
    Display *xdisplay = NULL; // GDK_DISPLAY_XDISPLAY (display);
 | 
			
		||||
@ -307,7 +320,7 @@ update_modifier_keycodes (Client *client)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
client_enable_xtest (Client *client)
 | 
			
		||||
client_enable_xtest (SeatEmitter *client)
 | 
			
		||||
{
 | 
			
		||||
    //GdkDisplay *display = gdk_display_get_default ();
 | 
			
		||||
    //Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
 | 
			
		||||
@ -340,7 +353,7 @@ client_enable_xtest (Client *client)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
client_disable_xtest (Client *client)
 | 
			
		||||
client_disable_xtest (SeatEmitter *client)
 | 
			
		||||
{
 | 
			
		||||
    //if (client->xkb) {
 | 
			
		||||
      //  XkbFreeKeyboard (client->xkb, 0, TRUE);	/* free_all = TRUE */
 | 
			
		||||
 | 
			
		||||
@ -7,26 +7,12 @@
 | 
			
		||||
 | 
			
		||||
#include "eek/eek.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    gint group;
 | 
			
		||||
} EekboardContext;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    EekboardContext *context;
 | 
			
		||||
    XkbDescRec *xkb;
 | 
			
		||||
    guint modifier_keycodes[8];
 | 
			
		||||
} Client;
 | 
			
		||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
emit_key_activated (EekboardContext *context,
 | 
			
		||||
emit_key_activated (EekboardContextService *manager, EekKeyboard *keyboard,
 | 
			
		||||
                    guint            keycode,
 | 
			
		||||
                    EekSymbol       *symbol,
 | 
			
		||||
                    guint            modifiers,
 | 
			
		||||
                    Client *client, gboolean pressed, uint32_t timestamp);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
client_enable_xtest (Client *client);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
client_disable_xtest (Client *client);
 | 
			
		||||
                    gboolean pressed, uint32_t timestamp);
 | 
			
		||||
#endif // KEYEMITTER_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										66
									
								
								eekboard/keymap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								eekboard/keymap.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
/* GDK - The GIMP Drawing Kit
 | 
			
		||||
 * Copyright (C) 2000 Red Hat, Inc.
 | 
			
		||||
 * Copyright (C) 2019 Purism, SPC
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Modified for squeekboard based on GTK
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
squeek_keymap_get_entries_for_keyval (struct xkb_keymap     *xkb_keymap,
 | 
			
		||||
                                      guint          keyval,
 | 
			
		||||
                                      GdkKeymapKey **keys,
 | 
			
		||||
                                      guint          *n_keys)
 | 
			
		||||
{
 | 
			
		||||
  GArray *retval;
 | 
			
		||||
  guint keycode;
 | 
			
		||||
  xkb_keycode_t min_keycode, max_keycode;
 | 
			
		||||
  retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
 | 
			
		||||
  min_keycode = xkb_keymap_min_keycode (xkb_keymap);
 | 
			
		||||
  max_keycode = xkb_keymap_max_keycode (xkb_keymap);
 | 
			
		||||
  for (keycode = min_keycode; keycode < max_keycode; keycode++)
 | 
			
		||||
    {
 | 
			
		||||
      xkb_layout_index_t num_layouts, layout;
 | 
			
		||||
      num_layouts = xkb_keymap_num_layouts_for_key (xkb_keymap, keycode);
 | 
			
		||||
      for (layout = 0; layout < num_layouts; layout++)
 | 
			
		||||
        {
 | 
			
		||||
          xkb_layout_index_t num_levels, level;
 | 
			
		||||
          num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
 | 
			
		||||
          for (level = 0; level < num_levels; level++)
 | 
			
		||||
            {
 | 
			
		||||
              const xkb_keysym_t *syms;
 | 
			
		||||
              gint num_syms, sym;
 | 
			
		||||
              num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
 | 
			
		||||
              for (sym = 0; sym < num_syms; sym++)
 | 
			
		||||
                {
 | 
			
		||||
                  if (syms[sym] == keyval)
 | 
			
		||||
                    {
 | 
			
		||||
                      GdkKeymapKey key;
 | 
			
		||||
                      key.keycode = keycode;
 | 
			
		||||
                      key.group = (gint)layout;
 | 
			
		||||
                      key.level = (gint)level;
 | 
			
		||||
                      g_array_append_val (retval, key);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  *n_keys = retval->len;
 | 
			
		||||
  *keys = (GdkKeymapKey*) g_array_free (retval, FALSE);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								eekboard/keymap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								eekboard/keymap.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
#include <xkbcommon/xkbcommon.h>
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
squeek_keymap_get_entries_for_keyval (struct xkb_keymap     *xkb_keymap,
 | 
			
		||||
                                      guint          keyval,
 | 
			
		||||
                                      GdkKeymapKey **keys,
 | 
			
		||||
                                      guint          *n_keys);
 | 
			
		||||
		Reference in New Issue
	
	Block a user