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:
		@ -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 */
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user