diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 2a15fefc..94e7531d 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -39,6 +39,7 @@ #include "eekboard/eekboard-context-service.h" #include "src/layout.h" +#include "src/submission.h" enum { PROP_0, @@ -55,6 +56,7 @@ typedef struct _EekGtkKeyboardPrivate { EekRenderer *renderer; EekboardContextService *eekboard_context; // unowned reference + struct submission *submission; // unowned reference LevelKeyboard *keyboard; // unowned reference; it's kept in server-context (FIXME) GdkEventSequence *sequence; // unowned reference @@ -123,7 +125,8 @@ static void depress(EekGtkKeyboard *self, { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - squeek_layout_depress(priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, + squeek_layout_depress(priv->keyboard->layout, + priv->submission, x, y, eek_renderer_get_transformation(priv->renderer), time, self); } @@ -131,7 +134,8 @@ static void drag(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - squeek_layout_drag(priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, + squeek_layout_drag(priv->keyboard->layout, + priv->submission, x, y, eek_renderer_get_transformation(priv->renderer), time, priv->eekboard_context, self); } @@ -140,7 +144,8 @@ static void release(EekGtkKeyboard *self, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - squeek_layout_release(priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, + squeek_layout_release(priv->keyboard->layout, + priv->submission, eek_renderer_get_transformation(priv->renderer), time, priv->eekboard_context, self); } @@ -230,7 +235,8 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self) if (priv->keyboard) { squeek_layout_release_all_only( - priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, + priv->keyboard->layout, + priv->submission, gdk_event_get_time(NULL)); } @@ -265,7 +271,8 @@ eek_gtk_keyboard_dispose (GObject *object) if (priv->keyboard) { squeek_layout_release_all_only( - priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, + priv->keyboard->layout, + priv->submission, gdk_event_get_time(NULL)); priv->keyboard = NULL; } @@ -312,12 +319,14 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self) * Returns: a #GtkWidget */ GtkWidget * -eek_gtk_keyboard_new (LevelKeyboard *keyboard, EekboardContextService *eekservice) +eek_gtk_keyboard_new (LevelKeyboard *keyboard, EekboardContextService *eekservice, + struct submission *submission) { EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL)); EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret); priv->keyboard = keyboard; priv->eekboard_context = eekservice; + priv->submission = submission; return GTK_WIDGET(ret); } diff --git a/eek/eek-gtk-keyboard.h b/eek/eek-gtk-keyboard.h index e9cb7c1a..95647220 100644 --- a/eek/eek-gtk-keyboard.h +++ b/eek/eek-gtk-keyboard.h @@ -30,6 +30,7 @@ #include "eek/eek-types.h" +struct submission; typedef struct _LevelKeyboard LevelKeyboard; // including causes weird bugs G_BEGIN_DECLS @@ -47,7 +48,7 @@ struct _EekGtkKeyboardClass }; GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST; -GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard, EekboardContextService *eekservice); +GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard, EekboardContextService *eekservice, struct submission *submission); G_END_DECLS #endif /* EEK_GTK_KEYBOARD_H */ diff --git a/eek/eek-types.h b/eek/eek-types.h index 6324094b..5d993191 100644 --- a/eek/eek-types.h +++ b/eek/eek-types.h @@ -38,6 +38,7 @@ G_BEGIN_DECLS typedef struct _EekBounds EekBounds; typedef struct _EekboardContextService EekboardContextService; +typedef struct _ServerContextService ServerContextService; typedef struct _LevelKeyboard LevelKeyboard; /** diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index 94a6ae4c..b4e26bcd 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -39,6 +39,7 @@ #include "wayland.h" +#include "eek/eek-keyboard.h" #include "eek/eek-xml-layout.h" #include "src/server-context-service.h" @@ -73,6 +74,8 @@ struct _EekboardContextServicePrivate { // Maybe TODO: it's used only for fetching layout type. // Maybe let UI push the type to this structure? ServerContextService *ui; // unowned reference + /// Needed for keymap changes after keyboard updates + struct submission *submission; // unowned }; G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT); @@ -222,10 +225,12 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ LevelKeyboard *previous_keyboard = context->priv->keyboard; context->priv->keyboard = keyboard; - // 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(context, keyboard); + // Update the keymap if necessary. + // Done directly here instead of in "keyboard" update handler + // to keep keymap-related actions close together. + if (context->priv->submission) { + submission_set_keyboard(context->priv->submission, keyboard); + } g_object_notify (G_OBJECT(context), "keyboard"); @@ -262,12 +267,6 @@ 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"); - } update_layout_and_type(context); } @@ -363,14 +362,6 @@ eekboard_context_service_get_keyboard (EekboardContextService *context) return context->priv->keyboard; } -void eekboard_context_service_set_keymap(EekboardContextService *context, - const LevelKeyboard *keyboard) -{ - zwp_virtual_keyboard_v1_keymap(context->virtual_keyboard, - WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - keyboard->keymap_fd, keyboard->keymap_len); -} - void eekboard_context_service_set_hint_purpose(EekboardContextService *context, uint32_t hint, uint32_t purpose) { @@ -394,7 +385,13 @@ eekboard_context_service_get_overlay(EekboardContextService *context) { return context->priv->overlay; } -EekboardContextService *eekboard_context_service_new() +EekboardContextService *eekboard_context_service_new(void) { return g_object_new (EEKBOARD_TYPE_CONTEXT_SERVICE, NULL); } +void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission) { + context->priv->submission = submission; + if (context->priv->submission) { + submission_set_keyboard(context->priv->submission, context->priv->keyboard); + } +} diff --git a/eekboard/eekboard-context-service.h b/eekboard/eekboard-context-service.h index dab830ce..383a6579 100644 --- a/eekboard/eekboard-context-service.h +++ b/eekboard/eekboard-context-service.h @@ -22,7 +22,8 @@ #ifndef EEKBOARD_CONTEXT_SERVICE_H #define EEKBOARD_CONTEXT_SERVICE_H 1 -#include +#include "src/submission.h" +#include "src/layout.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" #include "text-input-unstable-v3-client-protocol.h" @@ -58,8 +59,6 @@ struct _EekboardContextService { GObject parent; EekboardContextServicePrivate *priv; - - struct zwp_virtual_keyboard_v1 *virtual_keyboard; }; /** @@ -84,10 +83,10 @@ struct _EekboardContextServiceClass { gpointer pdummy[24]; }; -EekboardContextService *eekboard_context_service_new(); GType eekboard_context_service_get_type (void) G_GNUC_CONST; EekboardContextService *eekboard_context_service_new(void); +void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission); void eekboard_context_service_destroy (EekboardContextService *context); LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context); diff --git a/src/imservice.c b/src/imservice.c index 910ac0e3..1c98aa15 100644 --- a/src/imservice.c +++ b/src/imservice.c @@ -23,11 +23,19 @@ static const struct zwp_input_method_v2_listener input_method_listener = { .unavailable = imservice_handle_unavailable, }; -struct submission* get_submission(struct zwp_input_method_manager_v2 *manager, +struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager, + struct zwp_virtual_keyboard_manager_v1 *vkmanager, struct wl_seat *seat, EekboardContextService *state) { - struct zwp_input_method_v2 *im = zwp_input_method_manager_v2_get_input_method(manager, seat); - return submission_new(im, state); + struct zwp_input_method_v2 *im = NULL; + if (immanager) { + im = zwp_input_method_manager_v2_get_input_method(immanager, seat); + } + struct zwp_virtual_keyboard_v1 *vk = NULL; + if (vkmanager) { + vk = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkmanager, seat); + } + return submission_new(im, vk, state); } /// Un-inlined diff --git a/src/layout.h b/src/layout.h index 9f1a4a71..eefcce36 100644 --- a/src/layout.h +++ b/src/layout.h @@ -33,17 +33,22 @@ const char *squeek_layout_get_keymap(const struct squeek_layout*); enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *); void squeek_layout_free(struct squeek_layout*); -void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, +void squeek_layout_release(struct squeek_layout *layout, + struct submission *submission, struct transformation widget_to_layout, uint32_t timestamp, EekboardContextService *manager, EekGtkKeyboard *ui_keyboard); -void squeek_layout_release_all_only(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp); -void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, +void squeek_layout_release_all_only(struct squeek_layout *layout, + struct submission *submission, + uint32_t timestamp); +void squeek_layout_depress(struct squeek_layout *layout, + struct submission *submission, double x_widget, double y_widget, struct transformation widget_to_layout, uint32_t timestamp, EekGtkKeyboard *ui_keyboard); -void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, +void squeek_layout_drag(struct squeek_layout *layout, + struct submission *submission, double x_widget, double y_widget, struct transformation widget_to_layout, uint32_t timestamp, EekboardContextService *manager, diff --git a/src/layout.rs b/src/layout.rs index e0e4ded6..413e924a 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -27,7 +27,7 @@ use ::action::Action; use ::drawing; use ::keyboard::{ KeyState, PressType }; use ::manager; -use ::submission::{ Timestamp, VirtualKeyboard }; +use ::submission::{ Submission, Timestamp }; use ::util::find_max_double; use std::borrow::Borrow; @@ -143,6 +143,11 @@ pub mod c { } } } + + // This is constructed only in C, no need for warnings + #[allow(dead_code)] + #[repr(transparent)] + pub struct LevelKeyboard(*const c_void); // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers @@ -244,19 +249,12 @@ pub mod c { pub mod procedures { use super::*; - use ::vkeyboard::c::ZwpVirtualKeyboardV1; - - // This is constructed only in C, no need for warnings - #[allow(dead_code)] - #[repr(transparent)] - pub struct LevelKeyboard(*const c_void); - /// Release pointer in the specified position #[no_mangle] pub extern "C" fn squeek_layout_release( layout: *mut Layout, - virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend + submission: *mut Submission, widget_to_layout: Transformation, time: u32, manager: manager::c::Manager, @@ -264,7 +262,7 @@ pub mod c { ) { let time = Timestamp(time); let layout = unsafe { &mut *layout }; - let virtual_keyboard = VirtualKeyboard(virtual_keyboard); + let submission = unsafe { &mut *submission }; let ui_backend = UIBackend { widget_to_layout, keyboard: ui_keyboard, @@ -276,7 +274,7 @@ pub mod c { let key: &Rc> = key.borrow(); seat::handle_release_key( layout, - &virtual_keyboard, + submission, Some(&ui_backend), time, Some(manager), @@ -291,18 +289,18 @@ pub mod c { pub extern "C" fn squeek_layout_release_all_only( layout: *mut Layout, - virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend + submission: *mut Submission, time: u32, ) { let layout = unsafe { &mut *layout }; - let virtual_keyboard = VirtualKeyboard(virtual_keyboard); + let submission = unsafe { &mut *submission }; // The list must be copied, // because it will be mutated in the loop for key in layout.pressed_keys.clone() { let key: &Rc> = key.borrow(); seat::handle_release_key( layout, - &virtual_keyboard, + submission, None, // don't update UI Timestamp(time), None, // don't switch layouts @@ -315,13 +313,14 @@ pub mod c { pub extern "C" fn squeek_layout_depress( layout: *mut Layout, - virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend + submission: *mut Submission, x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, ui_keyboard: EekGtkKeyboard, ) { let layout = unsafe { &mut *layout }; + let submission = unsafe { &mut *submission }; let point = widget_to_layout.forward( Point { x: x_widget, y: y_widget } ); @@ -335,7 +334,7 @@ pub mod c { if let Some(state) = state { seat::handle_press_key( layout, - &VirtualKeyboard(virtual_keyboard), + submission, Timestamp(time), &state, ); @@ -351,7 +350,7 @@ pub mod c { pub extern "C" fn squeek_layout_drag( layout: *mut Layout, - virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend + submission: *mut Submission, x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, @@ -360,7 +359,7 @@ pub mod c { ) { let time = Timestamp(time); let layout = unsafe { &mut *layout }; - let virtual_keyboard = VirtualKeyboard(virtual_keyboard); + let submission = unsafe { &mut *submission }; let ui_backend = UIBackend { widget_to_layout, keyboard: ui_keyboard, @@ -389,7 +388,7 @@ pub mod c { } else { seat::handle_release_key( layout, - &virtual_keyboard, + submission, Some(&ui_backend), time, Some(manager), @@ -400,7 +399,7 @@ pub mod c { if !found { seat::handle_press_key( layout, - &virtual_keyboard, + submission, time, &state, ); @@ -411,7 +410,7 @@ pub mod c { let key: &Rc> = wrapped_key.borrow(); seat::handle_release_key( layout, - &virtual_keyboard, + submission, Some(&ui_backend), time, Some(manager), @@ -854,7 +853,7 @@ mod seat { pub fn handle_press_key( layout: &mut Layout, - virtual_keyboard: &VirtualKeyboard, + submission: &mut Submission, time: Timestamp, rckey: &Rc>, ) { @@ -862,7 +861,7 @@ mod seat { eprintln!("Warning: key {:?} was already pressed", rckey); } let mut key = rckey.borrow_mut(); - virtual_keyboard.switch( + submission.virtual_keyboard.switch( &key.keycodes, PressType::Pressed, time, @@ -872,7 +871,7 @@ mod seat { pub fn handle_release_key( layout: &mut Layout, - virtual_keyboard: &VirtualKeyboard, + submission: &mut Submission, ui: Option<&UIBackend>, time: Timestamp, manager: Option, @@ -894,7 +893,7 @@ mod seat { match action { Action::Submit { text: _, keys: _ } => { unstick_locks(layout).apply(); - virtual_keyboard.switch( + submission.virtual_keyboard.switch( &key.keycodes, PressType::Released, time, diff --git a/src/server-context-service.c b/src/server-context-service.c index 88b12fab..77022e62 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -24,6 +24,7 @@ #include "eek/eek-gtk-keyboard.h" #include "eek/layersurface.h" #include "eekboard/eekboard-context-service.h" +#include "submission.h" #include "wayland.h" #include "server-context-service.h" @@ -41,10 +42,12 @@ struct _ServerContextService { GObject parent; EekboardContextService *state; // unowned + /// Needed for instantiating the widget + struct submission *submission; // unowned gboolean visible; PhoshLayerSurface *window; - GtkWidget *widget; + GtkWidget *widget; // nullable guint hiding; guint last_requested_height; enum squeek_arrangement_kind last_type; @@ -224,7 +227,7 @@ make_widget (ServerContextService *context) LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (context->state); - context->widget = eek_gtk_keyboard_new (keyboard, context->state); + context->widget = eek_gtk_keyboard_new (keyboard, context->state, context->submission); gtk_widget_set_has_tooltip (context->widget, TRUE); gtk_container_add (GTK_CONTAINER(context->window), context->widget); @@ -395,9 +398,10 @@ server_context_service_init (ServerContextService *state) { } ServerContextService * -server_context_service_new (EekboardContextService *state) +server_context_service_new (EekboardContextService *state, struct submission *submission) { ServerContextService *ui = g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL); + ui->submission = submission; ui->state = state; g_signal_connect (state, "notify::keyboard", diff --git a/src/server-context-service.h b/src/server-context-service.h index c316f6b7..b6806e2b 100644 --- a/src/server-context-service.h +++ b/src/server-context-service.h @@ -19,6 +19,7 @@ #define SERVER_CONTEXT_SERVICE_H 1 #include "src/layout.h" +#include "src/submission.h" G_BEGIN_DECLS @@ -35,7 +36,7 @@ typedef struct _ServerContextService ServerContextService; GType server_context_service_get_type (void) G_GNUC_CONST; -ServerContextService *server_context_service_new(EekboardContextService *state); +ServerContextService *server_context_service_new(EekboardContextService *state, struct submission *submission); enum squeek_arrangement_kind server_context_service_get_layout_type(ServerContextService *); void server_context_service_show_keyboard (ServerContextService *context); void server_context_service_hide_keyboard (ServerContextService *context); diff --git a/src/server-main.c b/src/server-main.c index 3eecf8f4..0c6ce177 100644 --- a/src/server-main.c +++ b/src/server-main.c @@ -193,6 +193,10 @@ main (int argc, char **argv) exit(1); } + if (!instance.wayland.input_method_manager) { + g_warning("Wayland input method interface not available"); + } + instance.settings_context = eekboard_context_service_new(); // set up dbus @@ -261,14 +265,16 @@ main (int argc, char **argv) exit (1); } - if (instance.wayland.input_method_manager) { - // Cannot fail - instance.submission = get_submission(instance.wayland.input_method_manager, - instance.wayland.seat, - instance.settings_context); - } + instance.submission = get_submission(instance.wayland.input_method_manager, + instance.wayland.virtual_keyboard_manager, + instance.wayland.seat, + instance.settings_context); - ServerContextService *ui_context = server_context_service_new(instance.settings_context); + eekboard_context_service_set_submission(instance.settings_context, instance.submission); + + ServerContextService *ui_context = server_context_service_new( + instance.settings_context, + instance.submission); if (!ui_context) { g_error("Could not initialize GUI"); exit(1); diff --git a/src/submission.rs b/src/submission.rs index 08541434..fd82ba83 100644 --- a/src/submission.rs +++ b/src/submission.rs @@ -17,12 +17,13 @@ * and those events SHOULD NOT cause any lost events. * */ +use ::imservice::IMService; +//use ::vkeyboard::VirtualKeyboard; + /// Temporary reexport to keep stuff based directly on virtual-keyboard working /// until a unified handler appears and prompts a rework. pub use vkeyboard::*; -use ::imservice::IMService; - /// Gathers stuff defined in C or called by C pub mod c { use super::*; @@ -30,6 +31,8 @@ pub mod c { use std::os::raw::c_void; use ::imservice::c::InputMethod; + use ::layout::c::LevelKeyboard; + use ::vkeyboard::c::ZwpVirtualKeyboardV1; // The following defined in C @@ -45,6 +48,7 @@ pub mod c { pub extern "C" fn submission_new( im: *mut InputMethod, + vk: ZwpVirtualKeyboardV1, state_manager: *const StateManager ) -> *mut Submission { let imservice = if im.is_null() { @@ -56,10 +60,12 @@ pub mod c { Box::::into_raw(Box::new( Submission { imservice, + virtual_keyboard: VirtualKeyboard(vk), } )) } + /// Use to initialize the UI reference #[no_mangle] pub extern "C" fn submission_set_ui(submission: *mut Submission, ui_manager: *const UIManager) { @@ -75,10 +81,21 @@ pub mod c { } }; } + + #[no_mangle] + pub extern "C" + fn submission_set_keyboard(submission: *mut Submission, keyboard: LevelKeyboard) { + if submission.is_null() { + panic!("Null submission pointer"); + } + let submission: &mut Submission = unsafe { &mut *submission }; + submission.virtual_keyboard.update_keymap(keyboard); + } } pub struct Submission { // used by C callbacks internally, TODO: make use with virtual keyboard #[allow(dead_code)] imservice: Option>, + pub virtual_keyboard: VirtualKeyboard, } diff --git a/src/vkeyboard.rs b/src/vkeyboard.rs index c931858d..791814e4 100644 --- a/src/vkeyboard.rs +++ b/src/vkeyboard.rs @@ -1,9 +1,11 @@ /*! Managing the events belonging to virtual-keyboard interface. */ use ::keyboard::{ KeyCode, PressType }; +use ::layout::c::LevelKeyboard; /// Gathers stuff defined in C or called by C pub mod c { + use super::*; use std::os::raw::c_void; #[repr(transparent)] @@ -12,14 +14,17 @@ pub mod c { #[no_mangle] extern "C" { - /// Checks if point falls within bounds, - /// which are relative to origin and rotated by angle (I think) pub fn eek_virtual_keyboard_v1_key( virtual_keyboard: ZwpVirtualKeyboardV1, timestamp: u32, keycode: u32, press: u32, ); + + pub fn eek_virtual_keyboard_update_keymap( + virtual_keyboard: ZwpVirtualKeyboardV1, + keyboard: LevelKeyboard, + ); } } @@ -64,4 +69,13 @@ impl VirtualKeyboard { } } } + + pub fn update_keymap(&self, keyboard: LevelKeyboard) { + unsafe { + c::eek_virtual_keyboard_update_keymap( + self.0, + keyboard, + ); + } + } } diff --git a/src/wayland.c b/src/wayland.c index 96b037f4..42ba59df 100644 --- a/src/wayland.c +++ b/src/wayland.c @@ -1,3 +1,5 @@ +#include "eek/eek-keyboard.h" + #include "wayland.h" struct squeek_wayland *squeek_wayland = NULL; @@ -11,6 +13,13 @@ eek_virtual_keyboard_v1_key(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard zwp_virtual_keyboard_v1_key(zwp_virtual_keyboard_v1, time, key, state); } + +void eek_virtual_keyboard_update_keymap(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, const LevelKeyboard *keyboard) { + zwp_virtual_keyboard_v1_keymap(zwp_virtual_keyboard_v1, + WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + keyboard->keymap_fd, keyboard->keymap_len); +} + int squeek_output_add_listener(struct wl_output *wl_output, const struct wl_output_listener *listener, void *data) { return wl_output_add_listener(wl_output, listener, data);