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:
Dorota Czaplejewicz
2019-06-22 15:20:58 +00:00
parent c0fdffac28
commit 9e5629d1e0
27 changed files with 497 additions and 194 deletions

View File

@ -5,7 +5,7 @@ stages:
before_script:
- apt-get -y update
- apt-get -y install gnome-common gtk-doc-tools libglib2.0-dev-bin gobject-introspection libglib2.0-dev libpango1.0-dev libgtk-3-dev libcroco3-dev meson
- apt-get -y install gnome-common gtk-doc-tools libglib2.0-dev-bin gobject-introspection libglib2.0-dev libpango1.0-dev libgtk-3-dev libcroco3-dev libxkbcommon-dev meson
build_meson:
stage: build

View File

@ -21,9 +21,6 @@ Features
- Use Wayland virtual keyboard protocol
- Use Wayland text input protocol
- Use Wayland input method protocol
- Become a Wayland layer shell
- Remove eekboard-client
- Use sm.puri.OSK0 DBus interface
- Pick up DBus interface files from /usr/share
Building

View File

@ -425,15 +425,6 @@ eek_gtk_keyboard_new (EekKeyboard *keyboard)
return g_object_new (EEK_TYPE_GTK_KEYBOARD, "keyboard", keyboard, NULL);
}
static EekColor *
color_from_gdk_color (GdkColor *gdk_color)
{
return eek_color_new (gdk_color->red / (gdouble)0xFFFF,
gdk_color->green / (gdouble)0xFFFF,
gdk_color->blue / (gdouble)0xFFFF,
1.0);
}
static void
magnify_bounds (GtkWidget *self,
EekBounds *bounds,
@ -585,7 +576,7 @@ on_key_cancelled (EekKey *key,
if (!priv->renderer)
return;
render_released_key (self, key);
render_released_key (GTK_WIDGET(self), key);
}
static void

View File

@ -256,18 +256,15 @@ set_modifiers_with_key (EekKeyboard *self,
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
EekSymbol *symbol;
EekModifierType modifier;
eek_key_set_pressed(key, TRUE);
key = EEK_KEY(key);
priv->pressed_keys = g_list_prepend (priv->pressed_keys, key);
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
modifier = eek_symbol_get_modifier_mask (symbol);
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
set_level_from_modifiers (keyboard);
@ -277,11 +274,8 @@ void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestam
guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (keyboard);
// Insert
EekboardContext ec = {0};
Client c = {&ec, 0, {0}};
emit_key_activated(&ec, keycode, symbol, modifiers, &c, TRUE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, TRUE, timestamp);
}
void eek_keyboard_release_key( EekKeyboard *keyboard,
@ -328,11 +322,8 @@ void eek_keyboard_release_key( EekKeyboard *keyboard,
guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (keyboard);
// Insert
EekboardContext ec = {0};
Client c = {&ec, 0, {0}};
emit_key_activated(&ec, keycode, symbol, modifiers, &c, FALSE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, FALSE, timestamp);
}
static void

View File

@ -26,6 +26,7 @@
#define EEK_KEYBOARD_H 1
#include <glib-object.h>
#include <xkbcommon/xkbcommon.h>
#include "eek-container.h"
#include "eek-types.h"
#include "eek-layout.h"
@ -56,6 +57,11 @@ struct _EekKeyboard
EekContainer parent;
EekKeyboardPrivate *priv;
struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd
EekboardContextService *manager; // unowned reference
};
/**
@ -115,12 +121,13 @@ struct _EekModifierKey {
};
typedef struct _EekModifierKey EekModifierKey;
GType eek_keyboard_get_type
(void) G_GNUC_CONST;
EekKeyboard *eek_keyboard_new (EekLayout *layout,
EekKeyboard *eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
GType eek_keyboard_get_type
(void) G_GNUC_CONST;
EekLayout *eek_keyboard_get_layout
(EekKeyboard *keyboard);
void eek_keyboard_get_size

View File

@ -32,6 +32,7 @@
#include "eek-layout.h"
#include "eek-keyboard.h"
#include "eekboard/eekboard-context-service.h"
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT);
@ -55,14 +56,16 @@ eek_layout_init (EekLayout *self)
* Create a new #EekKeyboard based on @layout.
*/
EekKeyboard *
eek_keyboard_new (EekLayout *layout,
eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height)
{
g_assert (EEK_IS_LAYOUT(layout));
g_assert (EEK_LAYOUT_GET_CLASS(layout)->create_keyboard);
return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (layout,
return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (manager,
layout,
initial_width,
initial_height);
}

View File

@ -56,7 +56,8 @@ struct _EekLayoutClass
GObjectClass parent_class;
/*< public >*/
EekKeyboard* (* create_keyboard) (EekLayout *self,
EekKeyboard* (* create_keyboard) (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height);

View File

@ -150,6 +150,8 @@ typedef struct _EekBounds EekBounds;
typedef struct _EekOutline EekOutline;
typedef struct _EekColor EekColor;
typedef struct _EekboardContextService EekboardContextService;
/**
* EekPoint:
* @x: X coordinate of the point

View File

@ -320,21 +320,24 @@ create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
}
static EekKeyboard *
eek_xkb_layout_real_create_keyboard (EekLayout *self,
eek_xkb_layout_real_create_keyboard (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height)
{
EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
EekBounds bounds;
EekKeyboard *keyboard;
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
keyboard->manager = manager;
keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
bounds.x = bounds.y = 0.0;
bounds.width = initial_width;
bounds.height = initial_height;
EekBounds bounds = {
.x = 0.0,
.y = 0.0,
.width = initial_width,
.height = initial_height
};
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
/* resolve modifiers dynamically assigned at run time */
EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (self);
eek_keyboard_set_num_lock_mask (keyboard,
XkbKeysymToModifiers (priv->display,
XK_Num_Lock));

View File

@ -896,27 +896,25 @@ static const GMarkupParser prerequisites_parser = {
};
static EekKeyboard *
eek_xml_layout_real_create_keyboard (EekLayout *self,
eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (self);
EekKeyboard *keyboard;
gchar *filename, *path;
GList *loaded;
GError *error;
gboolean retval;
/* Create an empty keyboard to which geometry and symbols
information are applied. */
keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", layout, NULL);
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", layout, NULL);
keyboard->manager = manager;
/* Read geometry information. */
filename = g_strdup_printf ("%s.xml", layout->priv->desc->geometry);
path = g_build_filename (layout->priv->keyboards_dir, "geometry", filename, NULL);
gchar *filename = g_strdup_printf ("%s.xml", layout->priv->desc->geometry);
gchar *path = g_build_filename (layout->priv->keyboards_dir, "geometry", filename, NULL);
g_free (filename);
error = NULL;
GError *error = NULL;
retval = parse_geometry (path, keyboard, &error);
g_free (path);
if (!retval) {
@ -929,7 +927,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
}
/* Read symbols information. */
loaded = NULL;
GList *loaded = NULL;
retval = parse_symbols_with_prerequisites (layout->priv->keyboards_dir,
layout->priv->desc->symbols,
keyboard,

View File

@ -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);
}

View File

@ -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 */

View File

@ -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.
*/

View File

@ -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 */

View File

@ -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
View 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
View 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);

View File

@ -12,6 +12,7 @@ gen_scanner_client_code = generator(wl_scanner,
wl_protos = [
wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml',
'wlr-layer-shell-unstable-v1.xml',
'virtual-keyboard-unstable-v1.xml',
]
wl_proto_sources = []
foreach proto: wl_protos

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="virtual_keyboard_unstable_v1">
<copyright>
Copyright © 2008-2011 Kristian Høgsberg
Copyright © 2010-2013 Intel Corporation
Copyright © 2012-2013 Collabora, Ltd.
Copyright © 2018 Purism SPC
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.
</copyright>
<interface name="zwp_virtual_keyboard_v1" version="1">
<description summary="virtual keyboard">
The virtual keyboard provides an application with requests which emulate
the behaviour of a physical keyboard.
This interface can be used by clients on its own to provide raw input
events, or it can accompany the input method protocol.
</description>
<request name="keymap">
<description summary="keyboard mapping">
Provide a file descriptor to the compositor which can be
memory-mapped to provide a keyboard mapping description.
Format carries a value from the keymap_format enumeration.
</description>
<arg name="format" type="uint" summary="keymap format"/>
<arg name="fd" type="fd" summary="keymap file descriptor"/>
<arg name="size" type="uint" summary="keymap size, in bytes"/>
</request>
<enum name="error">
<entry name="no_keymap" value="0" summary="No keymap was set"/>
</enum>
<request name="key">
<description summary="key event">
A key was pressed or released.
The time argument is a timestamp with millisecond granularity, with an
undefined base. All requests regarding a single object must share the
same clock.
Keymap must be set before issuing this request.
State carries a value from the key_state enumeration.
</description>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="key" type="uint" summary="key that produced the event"/>
<arg name="state" type="uint" summary="physical state of the key"/>
</request>
<request name="modifiers">
<description summary="modifier and group state">
Notifies the compositor that the modifier and/or group state has
changed, and it should update state.
The client should use wl_keyboard.modifiers event to synchronize its
internal state with seat state.
Keymap must be set before issuing this request.
</description>
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
<arg name="group" type="uint" summary="keyboard layout"/>
</request>
<request name="destroy" type="destructor" since="1">
<description summary="destroy the virtual keyboard keyboard object"/>
</request>
</interface>
<interface name="zwp_virtual_keyboard_manager_v1" version="1">
<description summary="virtual keyboard manager">
A virtual keyboard manager allows an application to provide keyboard
input events as if they came from a physical keyboard.
</description>
<enum name="error">
<entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
</enum>
<request name="create_virtual_keyboard">
<description summary="Create a new virtual keyboard">
Creates a new virtual keyboard associated to a seat.
If the compositor enables a keyboard to perform arbitrary actions, it
should present an error when an untrusted client requests a new
keyboard.
</description>
<arg name="seat" type="object" interface="wl_seat"/>
<arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
</request>
</interface>
</protocol>

View File

@ -88,7 +88,7 @@ enum FocusListenerType {
};
static gboolean
set_keyboards (Client *client,
set_keyboards (SeatEmitter *client,
const gchar * const *keyboards)
{
if (g_strv_length ((gchar **)keyboards) == 0) {
@ -110,7 +110,7 @@ set_keyboards (Client *client,
int
main (int argc, char **argv)
{
Client *client = NULL;
SeatEmitter *client = NULL;
EekboardClient *eekboard;
EekboardContext *context;
GBusType bus_type;

View File

@ -101,7 +101,7 @@ struct _ClientClass {
GObjectClass parent_class;
};
G_DEFINE_TYPE (Client, client, G_TYPE_OBJECT);
G_DEFINE_TYPE (SeatEmitter, client, G_TYPE_OBJECT);
#if ENABLE_FOCUS_LISTENER
#define IS_KEYBOARD_VISIBLE(client) (!client->follows_focus)
@ -128,10 +128,10 @@ static void focus_listener_cb (const AtspiEvent *event,
static gboolean keystroke_listener_cb (const AtspiDeviceEvent *stroke,
void *user_data);
#endif /* HAVE_ATSPI */
static gboolean set_keyboards (Client *client,
static gboolean set_keyboards (SeatEmitter *client,
const gchar * const *keyboard);
static gboolean set_keyboards_from_xkl
(Client *client);
(SeatEmitter *client);
#ifdef HAVE_XTEST
static void update_modifier_keycodes
(Client *client);
@ -143,7 +143,7 @@ client_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
Client *client = CLIENT(object);
SeatEmitter *client = CLIENT(object);
GDBusConnection *connection;
gchar **keyboards;
@ -188,7 +188,7 @@ client_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
Client *client = CLIENT(object);
SeatEmitter *client = CLIENT(object);
switch (prop_id) {
case PROP_EEKBOARD:
@ -206,7 +206,7 @@ client_get_property (GObject *object,
static void
client_dispose (GObject *object)
{
Client *client = CLIENT(object);
SeatEmitter *client = CLIENT(object);
client_disable_xkl (client);
@ -246,7 +246,7 @@ client_dispose (GObject *object)
static void
client_finalize (GObject *object)
{
Client *client = CLIENT(object);
SeatEmitter *client = CLIENT(object);
g_slist_free (client->keyboards);
G_OBJECT_CLASS (client_parent_class)->finalize (object);
@ -301,13 +301,13 @@ client_class_init (ClientClass *klass)
}
static void
client_init (Client *client)
client_init (SeatEmitter *client)
{
client->settings = g_settings_new ("org.fedorahosted.eekboard");
}
gboolean
client_set_keyboards (Client *client,
client_set_keyboards (SeatEmitter *client,
const gchar * const *keyboards)
{
gboolean retval;
@ -318,7 +318,7 @@ client_set_keyboards (Client *client,
}
gboolean
client_enable_xkl (Client *client)
client_enable_xkl (SeatEmitter *client)
{
GdkDisplay *display = gdk_display_get_default ();
gboolean retval;
@ -361,7 +361,7 @@ client_enable_xkl (Client *client)
}
void
client_disable_xkl (Client *client)
client_disable_xkl (SeatEmitter *client)
{
if (client->xkl_engine) {
xkl_engine_stop_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
@ -618,7 +618,7 @@ add_match_rule (GDBusConnection *connection,
}
static gboolean
on_hide_keyboard_timeout (Client *client)
on_hide_keyboard_timeout (SeatEmitter *client)
{
eekboard_client_hide_keyboard (client->eekboard, NULL);
client->hide_keyboard_timeout_id = 0;
@ -631,7 +631,7 @@ focus_message_filter (GDBusConnection *connection,
gboolean incoming,
gpointer user_data)
{
Client *client = user_data;
SeatEmitter *client = user_data;
if (incoming &&
g_strcmp0 (g_dbus_message_get_interface (message),
@ -661,7 +661,7 @@ focus_message_filter (GDBusConnection *connection,
static void
_ibus_connect_focus_handlers (GDBusConnection *connection, gpointer user_data)
{
Client *client = user_data;
SeatEmitter *client = user_data;
add_match_rule (connection,
"type='method_call',"
@ -679,7 +679,7 @@ _ibus_connect_focus_handlers (GDBusConnection *connection, gpointer user_data)
}
gboolean
client_enable_ibus_focus (Client *client)
client_enable_ibus_focus (SeatEmitter *client)
{
if (client->ibus_connection == NULL) {
const gchar *ibus_address;
@ -711,7 +711,7 @@ client_enable_ibus_focus (Client *client)
}
void
client_disable_ibus_focus (Client *client)
client_disable_ibus_focus (SeatEmitter *client)
{
client->follows_focus = FALSE;
@ -725,10 +725,10 @@ client_disable_ibus_focus (Client *client)
}
}
Client *
SeatEmitter *
client_new (GDBusConnection *connection)
{
Client *client = g_object_new (TYPE_CLIENT,
SeatEmitter *client = g_object_new (TYPE_CLIENT,
"connection", connection,
NULL);
if (client->context)
@ -741,7 +741,7 @@ filter_xkl_event (GdkXEvent *xev,
GdkEvent *event,
gpointer user_data)
{
Client *client = user_data;
SeatEmitter *client = user_data;
XEvent *xevent = (XEvent *)xev;
xkl_engine_filter_events (client->xkl_engine, xevent);
@ -752,7 +752,7 @@ static void
on_xkl_config_changed (XklEngine *xklengine,
gpointer user_data)
{
Client *client = user_data;
SeatEmitter *client = user_data;
gboolean retval;
retval = set_keyboards_from_xkl (client);
@ -764,7 +764,7 @@ on_xkl_config_changed (XklEngine *xklengine,
}
static gboolean
set_keyboards (Client *client,
set_keyboards (SeatEmitter *client,
const gchar * const *keyboards)
{
guint keyboard_id;
@ -805,7 +805,7 @@ set_keyboards (Client *client,
}
static gboolean
set_keyboards_from_xkl (Client *client)
set_keyboards_from_xkl (SeatEmitter *client)
{
XklConfigRec *rec;
gchar *layout, *keyboard;
@ -837,7 +837,7 @@ on_xkl_state_changed (XklEngine *xklengine,
gboolean restore,
gpointer user_data)
{
Client *client = user_data;
SeatEmitter *client = user_data;
if (type == GROUP_CHANGED)
eekboard_context_set_group (client->context, value, NULL);
@ -851,7 +851,7 @@ on_xkl_state_changed (XklEngine *xklengine,
- get_keycode_from_gdk_keymap (Caribou: best_keycode_keyval_match)
*/
static guint
get_replaced_keycode (Client *client)
get_replaced_keycode (SeatEmitter *client)
{
guint keycode;
@ -876,7 +876,7 @@ get_replaced_keycode (Client *client)
non-zero keycode), it simply changes the current map with the
specified KEYCODE and KEYSYM. */
static gboolean
replace_keycode (Client *client,
replace_keycode (SeatEmitter *client,
guint keycode,
guint *keysym)
{
@ -904,7 +904,7 @@ 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 *client,
guint keysym,
guint *keycode,
guint *modifiers)
@ -932,7 +932,7 @@ get_keycode_from_gdk_keymap (Client *client,
return TRUE;
}
int WaylandFakeKeyEvent(
int send_virtual_keyboard_key(
Display* dpy,
unsigned int keycode,
Bool is_press,
@ -943,7 +943,7 @@ int WaylandFakeKeyEvent(
/* never actually used? */
static void
send_fake_modifier_key_event (Client *client,
send_fake_modifier_key_event (SeatEmitter *client,
EekModifierType modifiers,
gboolean is_pressed)
{
@ -957,7 +957,7 @@ send_fake_modifier_key_event (Client *client,
printf("Trying to send a modifier %d press %d\n", i, is_pressed);
g_return_if_fail (keycode > 0);
WaylandFakeKeyEvent (xdisplay,
send_virtual_keyboard_key (xdisplay,
keycode,
is_pressed,
CurrentTime);
@ -967,7 +967,7 @@ send_fake_modifier_key_event (Client *client,
}
static void
send_fake_key_event (Client *client,
send_fake_key_event (SeatEmitter *client,
guint xkeysym,
guint keyboard_modifiers)
{
@ -1006,9 +1006,9 @@ send_fake_key_event (Client *client,
modifiers |= keyboard_modifiers;
send_fake_modifier_key_event (client, modifiers, TRUE);
WaylandFakeKeyEvent (xdisplay, keycode, TRUE, 20);
send_virtual_keyboard_key (xdisplay, keycode, TRUE, 20);
//XSync (xdisplay, False);
WaylandFakeKeyEvent (xdisplay, keycode, FALSE, 20);
send_virtual_keyboard_key (xdisplay, keycode, FALSE, 20);
// XSync (xdisplay, False);
send_fake_modifier_key_event (client, modifiers, FALSE);
@ -1017,7 +1017,7 @@ send_fake_key_event (Client *client,
}
static void
send_fake_key_events (Client *client,
send_fake_key_events (SeatEmitter *client,
EekSymbol *symbol,
guint keyboard_modifiers)
{
@ -1063,7 +1063,7 @@ on_key_activated (EekboardContext *context,
guint modifiers,
gpointer user_data)
{
Client *client = user_data;
SeatEmitter *client = user_data;
if (g_strcmp0 (eek_symbol_get_name (symbol), "cycle-keyboard") == 0) {
client->keyboards_head = g_slist_next (client->keyboards_head);
@ -1119,7 +1119,7 @@ update_modifier_keycodes (Client *client)
}
#endif
gboolean
client_enable_xtest (Client *client)
client_enable_xtest (SeatEmitter *client)
{
//GdkDisplay *display = gdk_display_get_default ();
//Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
@ -1156,7 +1156,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 */

View File

@ -29,27 +29,27 @@ G_BEGIN_DECLS
#define IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLIENT))
#define CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CLIENT, ClientClass))
typedef struct _Client Client;
typedef struct _Client SeatEmitter;
Client *client_new (GDBusConnection *connection);
SeatEmitter *client_new (GDBusConnection *connection);
gboolean client_set_keyboards (Client *client,
gboolean client_set_keyboards (SeatEmitter *client,
const gchar * const *keyboard);
gboolean client_enable_xkl (Client *client);
void client_disable_xkl (Client *client);
gboolean client_enable_xkl (SeatEmitter *client);
void client_disable_xkl (SeatEmitter *client);
gboolean client_enable_atspi_focus (Client *client);
void client_disable_atspi_focus (Client *client);
gboolean client_enable_atspi_focus (SeatEmitter *client);
void client_disable_atspi_focus (SeatEmitter *client);
gboolean client_enable_atspi_keystroke (Client *client);
void client_disable_atspi_keystroke (Client *client);
gboolean client_enable_atspi_keystroke (SeatEmitter *client);
void client_disable_atspi_keystroke (SeatEmitter *client);
gboolean client_enable_xtest (Client *client);
void client_disable_xtest (Client *client);
gboolean client_enable_xtest (SeatEmitter *client);
void client_disable_xtest (SeatEmitter *client);
gboolean client_enable_ibus_focus (Client *client);
void client_disable_ibus_focus (Client *client);
gboolean client_enable_ibus_focus (SeatEmitter *client);
void client_disable_ibus_focus (SeatEmitter *client);
G_END_DECLS
#endif /* CLIENT_H */

View File

@ -34,6 +34,7 @@ sources = [
enums,
keysym_entries,
marshalers,
'../eekboard/keymap.c',
'../eekboard/key-emitter.c',
'../eekboard/eekboard-context-service.c',
'../eekboard/eekboard-context.c',
@ -51,7 +52,9 @@ deps = [
dependency('gtk+-3.0', version: '>=3.0'),
dependency('libcroco-0.6'),
dependency('wayland-client', version: '>=1.14'),
dependency('xkbcommon'),
cc.find_library('m'),
cc.find_library('rt'),
# dependency('libxklavier'), # FIXME remove
]

View File

@ -95,6 +95,17 @@ on_notify_keyboard (GObject *object,
const EekKeyboard *keyboard;
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
if (!keyboard) {
g_error("Programmer error: keyboard layout was unset!");
}
// The keymap will get set even if the window is hidden.
// It's not perfect,
// but simpler than adding a check in the window showing procedure
eekboard_context_service_set_keymap(EEKBOARD_CONTEXT_SERVICE(context),
keyboard);
if (context->window) {
if (keyboard == NULL) {
gtk_widget_hide (context->window);
@ -106,8 +117,9 @@ on_notify_keyboard (GObject *object,
g_signal_handler_block (context->window,
context->notify_visible_handler);
update_widget (context);
if (was_visible)
if (was_visible) {
gtk_widget_show_all (context->window);
}
g_signal_handler_unblock (context->window,
context->notify_visible_handler);
}
@ -492,9 +504,9 @@ server_context_service_init (ServerContextService *context)
context);
}
ServerContextService *
EekboardContextService *
server_context_service_new ()
{
return g_object_new (SERVER_TYPE_CONTEXT_SERVICE,
NULL);
return EEKBOARD_CONTEXT_SERVICE(g_object_new (SERVER_TYPE_CONTEXT_SERVICE,
NULL));
}

View File

@ -32,7 +32,7 @@ G_BEGIN_DECLS
/** Manages the liecycle of the window displaying layouts. */
typedef struct _ServerContextService ServerContextService;
ServerContextService *server_context_service_new ();
EekboardContextService *server_context_service_new ();
G_END_DECLS
#endif /* SERVER_CONTEXT_SERVICE_H */

View File

@ -38,6 +38,14 @@
#include <gdk/gdkwayland.h>
/// Global application state
struct squeekboard {
struct squeek_wayland wayland;
EekboardContextService *context;
};
static gboolean opt_system = FALSE;
static gchar *opt_address = NULL;
@ -93,17 +101,25 @@ registry_handle_global (void *data,
const char *interface,
uint32_t version)
{
struct squeek_wayland *wayland = data;
// currently only v1 supported for most interfaces,
// so there's no reason to check for available versions.
// Even when lower version would be served, it would not be supported,
// causing a hard exit
(void)version;
struct squeekboard *instance = data;
if (!strcmp (interface, zwlr_layer_shell_v1_interface.name)) {
wayland->layer_shell = wl_registry_bind (registry, name,
instance->wayland.layer_shell = wl_registry_bind (registry, name,
&zwlr_layer_shell_v1_interface, 1);
} else if (!strcmp (interface, zwp_virtual_keyboard_manager_v1_interface.name)) {
instance->wayland.virtual_keyboard_manager = wl_registry_bind(registry, name,
&zwp_virtual_keyboard_manager_v1_interface, 1);
} else if (!strcmp (interface, "wl_output")) {
struct wl_output *output = wl_registry_bind (registry, name,
&wl_output_interface, 2);
g_ptr_array_add (wayland->outputs, output);
g_ptr_array_add (instance->wayland.outputs, output);
} else if (!strcmp(interface, "wl_seat")) {
wayland->seat = wl_registry_bind(registry, name,
instance->wayland.seat = wl_registry_bind(registry, name,
&wl_seat_interface, 1);
}
}
@ -139,17 +155,33 @@ main (int argc, char **argv)
if (display == NULL) {
g_error ("Failed to get display: %m\n");
exit(1);
}
struct squeek_wayland wayland = {0};
squeek_wayland_init (&wayland);
struct wl_registry *registry = wl_display_get_registry (display);
wl_registry_add_listener (registry, &registry_listener, &wayland);
squeek_wayland_set_global(&wayland);
EekboardContextService *context = create_context();
struct squeekboard instance = {0};
squeek_wayland_init (&instance.wayland);
struct wl_registry *registry = wl_display_get_registry (display);
wl_registry_add_listener (registry, &registry_listener, &instance);
wl_display_roundtrip(display); // wait until the registry is actually populated
squeek_wayland_set_global(&instance.wayland);
if (!instance.wayland.seat) {
g_error("No seat Wayland global available.");
exit(1);
}
if (!instance.wayland.virtual_keyboard_manager) {
g_error("No virtual keyboard manager Wayland global available.");
exit(1);
}
instance.context = create_context();
// set up dbus
// TODO: make dbus errors non-always-fatal
// dbus is not strictly necessary for the useful operation
// if text-input is used, as it can bring the keyboard in and out
GBusType bus_type;
if (opt_system)
bus_type = G_BUS_TYPE_SYSTEM;
@ -191,16 +223,13 @@ main (int argc, char **argv)
break;
}
// TODO: make dbus errors non-always-fatal
// dbus is not strictly necessary for the useful operation
// if text-input is used, as it can bring the keyboard in and out
EekboardService *service = eekboard_service_new (connection, EEKBOARD_SERVICE_PATH);
if (service == NULL) {
g_printerr ("Can't create server\n");
g_printerr ("Can't create dbus server\n");
exit (1);
} else {
eekboard_service_set_context(service, context);
eekboard_service_set_context(service, instance.context);
}
guint owner_id = g_bus_own_name_on_connection (connection,
@ -226,6 +255,6 @@ main (int argc, char **argv)
g_object_unref (connection);
g_main_loop_unref (loop);
squeek_wayland_deinit (&wayland);
squeek_wayland_deinit (&instance.wayland);
return 0;
}

View File

@ -2,12 +2,14 @@
#define WAYLAND_H
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
#include <gmodule.h>
struct squeek_wayland {
struct zwlr_layer_shell_v1 *layer_shell;
struct zwp_virtual_keyboard_manager_v1 *virtual_keyboard_manager;
GPtrArray *outputs; // *wl_output
struct wl_seat *seat;
};