From 51f55fbff83669eeec2be2168d4fc4dc03fb9c5e Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 11 Jan 2020 16:20:09 +0000 Subject: [PATCH 01/10] submission: Move away from virtual-keyboard --- src/lib.rs | 3 +- src/submission.rs | 87 ++++++++++++----------------------------------- src/vkeyboard.rs | 67 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 src/vkeyboard.rs diff --git a/src/lib.rs b/src/lib.rs index 7f422c6a..4b5b9480 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,8 +29,9 @@ mod manager; mod outputs; mod popover; mod resources; -mod submission; mod style; +mod submission; pub mod tests; pub mod util; +mod vkeyboard; mod xdg; diff --git a/src/submission.rs b/src/submission.rs index c931858d..7dd9af31 100644 --- a/src/submission.rs +++ b/src/submission.rs @@ -1,67 +1,22 @@ -/*! Managing the events belonging to virtual-keyboard interface. */ +/*! Managing the state of text input in the application. + * + * This is a library module. + * + * It needs to combine text-input and virtual-keyboard protocols + * to achieve a consistent view of the text-input state, + * and to submit exactly what the user wanted. + * + * It must also not get tripped up by sudden disappearances of interfaces. + * + * The virtual-keyboard interface is always present. + * + * The text-input interface may not be presented, + * and, for simplicity, no further attempt to claim it is made. + * + * The text-input interface may be enabled and disabled at arbitrary times, + * and those events SHOULD NOT cause any lost events. + * */ -use ::keyboard::{ KeyCode, PressType }; - -/// Gathers stuff defined in C or called by C -pub mod c { - use std::os::raw::c_void; - - #[repr(transparent)] - #[derive(Clone, Copy)] - pub struct ZwpVirtualKeyboardV1(*const c_void); - - #[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, - ); - } -} - -#[derive(Clone, Copy)] -pub struct Timestamp(pub u32); - -/// Layout-independent backend. TODO: Have one instance per program or seat -pub struct VirtualKeyboard(pub c::ZwpVirtualKeyboardV1); - -impl VirtualKeyboard { - // TODO: split out keyboard state management - pub fn switch( - &self, - keycodes: &Vec, - action: PressType, - timestamp: Timestamp, - ) { - let keycodes_count = keycodes.len(); - for keycode in keycodes.iter() { - let keycode = keycode - 8; - match (action, keycodes_count) { - // Pressing a key made out of a single keycode is simple: - // press on press, release on release. - (_, 1) => unsafe { - c::eek_virtual_keyboard_v1_key( - self.0, timestamp.0, keycode, action.clone() as u32 - ); - }, - // A key made of multiple keycodes - // has to submit them one after the other - (PressType::Pressed, _) => unsafe { - c::eek_virtual_keyboard_v1_key( - self.0, timestamp.0, keycode, PressType::Pressed as u32 - ); - c::eek_virtual_keyboard_v1_key( - self.0, timestamp.0, keycode, PressType::Released as u32 - ); - }, - // Design choice here: submit multiple all at press time - // and do nothing at release time - (PressType::Released, _) => {}, - } - } - } -} +/// Temporary reexport to keep stuff based directly on virtual-keyboard working +/// until a unified handler appears and prompts a rework. +pub use vkeyboard::*; diff --git a/src/vkeyboard.rs b/src/vkeyboard.rs new file mode 100644 index 00000000..c931858d --- /dev/null +++ b/src/vkeyboard.rs @@ -0,0 +1,67 @@ +/*! Managing the events belonging to virtual-keyboard interface. */ + +use ::keyboard::{ KeyCode, PressType }; + +/// Gathers stuff defined in C or called by C +pub mod c { + use std::os::raw::c_void; + + #[repr(transparent)] + #[derive(Clone, Copy)] + pub struct ZwpVirtualKeyboardV1(*const c_void); + + #[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, + ); + } +} + +#[derive(Clone, Copy)] +pub struct Timestamp(pub u32); + +/// Layout-independent backend. TODO: Have one instance per program or seat +pub struct VirtualKeyboard(pub c::ZwpVirtualKeyboardV1); + +impl VirtualKeyboard { + // TODO: split out keyboard state management + pub fn switch( + &self, + keycodes: &Vec, + action: PressType, + timestamp: Timestamp, + ) { + let keycodes_count = keycodes.len(); + for keycode in keycodes.iter() { + let keycode = keycode - 8; + match (action, keycodes_count) { + // Pressing a key made out of a single keycode is simple: + // press on press, release on release. + (_, 1) => unsafe { + c::eek_virtual_keyboard_v1_key( + self.0, timestamp.0, keycode, action.clone() as u32 + ); + }, + // A key made of multiple keycodes + // has to submit them one after the other + (PressType::Pressed, _) => unsafe { + c::eek_virtual_keyboard_v1_key( + self.0, timestamp.0, keycode, PressType::Pressed as u32 + ); + c::eek_virtual_keyboard_v1_key( + self.0, timestamp.0, keycode, PressType::Released as u32 + ); + }, + // Design choice here: submit multiple all at press time + // and do nothing at release time + (PressType::Released, _) => {}, + } + } + } +} From 785717d477119ba4f0d334d3769cc2be5b20d5c9 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 12 Jan 2020 19:08:40 +0000 Subject: [PATCH 02/10] submission: Create a new wrapper over imservice --- src/imservice.c | 34 ++++++++++++++------ src/imservice.h | 27 ---------------- src/imservice.rs | 80 +++++++++++++++++++++-------------------------- src/layout.rs | 2 +- src/server-main.c | 21 +++++-------- src/submission.h | 19 +++++++++++ src/submission.rs | 62 ++++++++++++++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 95 deletions(-) create mode 100644 src/submission.h diff --git a/src/imservice.c b/src/imservice.c index 595a3546..910ac0e3 100644 --- a/src/imservice.c +++ b/src/imservice.c @@ -1,7 +1,18 @@ -#include "imservice.h" +#include "submission.h" #include +struct imservice; + +void imservice_handle_input_method_activate(void *data, struct zwp_input_method_v2 *input_method); +void imservice_handle_input_method_deactivate(void *data, struct zwp_input_method_v2 *input_method); +void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method, + const char *text, uint32_t cursor, uint32_t anchor); +void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method); +void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose); +void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause); +void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method); + static const struct zwp_input_method_v2_listener input_method_listener = { .activate = imservice_handle_input_method_activate, .deactivate = imservice_handle_input_method_deactivate, @@ -12,17 +23,22 @@ static const struct zwp_input_method_v2_listener input_method_listener = { .unavailable = imservice_handle_unavailable, }; -struct imservice* get_imservice(struct zwp_input_method_manager_v2 *manager, - struct wl_seat *seat, - EekboardContextService *state) { +struct submission* get_submission(struct zwp_input_method_manager_v2 *manager, + struct wl_seat *seat, + EekboardContextService *state) { struct zwp_input_method_v2 *im = zwp_input_method_manager_v2_get_input_method(manager, seat); - struct imservice *imservice = imservice_new(im, state); + return submission_new(im, state); +} - /* Add a listener, passing the imservice instance to make it available to - callbacks. */ +/// Un-inlined +struct zwp_input_method_v2 *imservice_manager_get_input_method(struct zwp_input_method_manager_v2 *manager, + struct wl_seat *seat) { + return zwp_input_method_manager_v2_get_input_method(manager, seat); +} + +/// Un-inlined to let Rust link to it +void imservice_connect_listeners(struct zwp_input_method_v2 *im, struct imservice* imservice) { zwp_input_method_v2_add_listener(im, &input_method_listener, imservice); - - return imservice; } /// Declared explicitly because _destroy is inline, diff --git a/src/imservice.h b/src/imservice.h index 5b879bfb..e69de29b 100644 --- a/src/imservice.h +++ b/src/imservice.h @@ -1,27 +0,0 @@ -#ifndef __IMSERVICE_H -#define __IMSERVICE_H - -#include "input-method-unstable-v2-client-protocol.h" -#include "eek/eek-types.h" -#include "src/server-context-service.h" - -struct imservice; - -struct imservice* get_imservice(struct zwp_input_method_manager_v2 *manager, - struct wl_seat *seat, - EekboardContextService *state); - -// Defined in Rust -struct imservice* imservice_new(struct zwp_input_method_v2 *im, EekboardContextService *state); -void imservice_set_ui(struct imservice *self, ServerContextService *ui_context); - -void imservice_handle_input_method_activate(void *data, struct zwp_input_method_v2 *input_method); -void imservice_handle_input_method_deactivate(void *data, struct zwp_input_method_v2 *input_method); -void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method, - const char *text, uint32_t cursor, uint32_t anchor); -void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method); -void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose); -void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause); -void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method); - -#endif diff --git a/src/imservice.rs b/src/imservice.rs index cc30b01a..72bd33fc 100644 --- a/src/imservice.rs +++ b/src/imservice.rs @@ -12,26 +12,23 @@ use std::convert::TryFrom; /// Gathers stuff defined in C or called by C pub mod c { use super::*; - + use std::os::raw::{c_char, c_void}; + pub use ::submission::c::UIManager; + pub use ::submission::c::StateManager; + // The following defined in C /// struct zwp_input_method_v2* #[repr(transparent)] pub struct InputMethod(*const c_void); - - /// ServerContextService* - #[repr(transparent)] - pub struct UIManager(*const c_void); - - /// EekboardContextService* - #[repr(transparent)] - pub struct StateManager(*const c_void); #[no_mangle] extern "C" { fn imservice_destroy_im(im: *mut c::InputMethod); + #[allow(improper_ctypes)] // IMService will never be dereferenced in C + pub fn imservice_connect_listeners(im: *mut InputMethod, imservice: *const IMService); fn eekboard_context_service_set_hint_purpose(state: *const StateManager, hint: u32, purpose: u32); fn server_context_service_show_keyboard(imservice: *const UIManager); fn server_context_service_hide_keyboard(imservice: *const UIManager); @@ -39,39 +36,6 @@ pub mod c { // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers - #[no_mangle] - pub extern "C" - fn imservice_new( - im: *const InputMethod, - state_manager: *const StateManager - ) -> *mut IMService { - Box::::into_raw(Box::new( - IMService { - im: im, - state_manager: state_manager, - ui_manager: None, - pending: IMProtocolState::default(), - current: IMProtocolState::default(), - preedit_string: String::new(), - serial: Wrapping(0u32), - } - )) - } - - #[no_mangle] - pub extern "C" - fn imservice_set_ui(imservice: *mut IMService, ui_manager: *const UIManager) { - if imservice.is_null() { - panic!("Null imservice pointer"); - } - let imservice: &mut IMService = unsafe { &mut *imservice }; - imservice.ui_manager = if ui_manager.is_null() { - None - } else { - Some(ui_manager) - }; - } - // TODO: is unsafe needed here? #[no_mangle] pub unsafe extern "C" @@ -203,7 +167,7 @@ pub mod c { if let Some(ui) = imservice.ui_manager { server_context_service_hide_keyboard(ui); } - } + } // FIXME: destroy and deallocate @@ -349,12 +313,38 @@ pub struct IMService { /// Owned reference (still created and destroyed in C) pub im: *const c::InputMethod, /// Unowned reference. Be careful, it's shared with C at large - ui_manager: Option<*const c::UIManager>, - /// Unowned reference. Be careful, it's shared with C at large state_manager: *const c::StateManager, + /// Unowned reference. Be careful, it's shared with C at large + pub ui_manager: Option<*const c::UIManager>, pending: IMProtocolState, current: IMProtocolState, // turn current into an idiomatic representation? preedit_string: String, serial: Wrapping, } + +impl IMService { + pub fn new( + im: *mut c::InputMethod, + state_manager: *const c::StateManager, + ) -> Box { + // IMService will be referenced to by C, + // so it needs to stay in the same place in memory via Box + let imservice = Box::new(IMService { + im, + ui_manager: None, + state_manager, + pending: IMProtocolState::default(), + current: IMProtocolState::default(), + preedit_string: String::new(), + serial: Wrapping(0u32), + }); + unsafe { + c::imservice_connect_listeners( + im, + imservice.as_ref() as *const IMService, + ); + } + imservice + } +} diff --git a/src/layout.rs b/src/layout.rs index c01226d5..e0e4ded6 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -244,7 +244,7 @@ pub mod c { pub mod procedures { use super::*; - use ::submission::c::ZwpVirtualKeyboardV1; + use ::vkeyboard::c::ZwpVirtualKeyboardV1; // This is constructed only in C, no need for warnings #[allow(dead_code)] diff --git a/src/server-main.c b/src/server-main.c index b9592eaa..3eecf8f4 100644 --- a/src/server-main.c +++ b/src/server-main.c @@ -28,8 +28,8 @@ #include "eek/eek.h" #include "eekboard/eekboard-context-service.h" #include "dbus.h" -#include "imservice.h" #include "outputs.h" +#include "submission.h" #include "server-context-service.h" #include "wayland.h" @@ -42,7 +42,7 @@ struct squeekboard { DBusHandler *dbus_handler; EekboardContextService *settings_context; ServerContextService *ui_context; - struct imservice *imservice; + struct submission *submission; }; @@ -261,16 +261,11 @@ main (int argc, char **argv) exit (1); } - struct imservice *imservice = NULL; if (instance.wayland.input_method_manager) { - imservice = get_imservice(instance.wayland.input_method_manager, - instance.wayland.seat, - instance.settings_context); - if (imservice) { - instance.imservice = imservice; - } else { - g_warning("Failed to register as an input method"); - } + // Cannot fail + instance.submission = get_submission(instance.wayland.input_method_manager, + instance.wayland.seat, + instance.settings_context); } ServerContextService *ui_context = server_context_service_new(instance.settings_context); @@ -279,8 +274,8 @@ main (int argc, char **argv) exit(1); } instance.ui_context = ui_context; - if (instance.imservice) { - imservice_set_ui(instance.imservice, instance.ui_context); + if (instance.submission) { + submission_set_ui(instance.submission, instance.ui_context); } if (instance.dbus_handler) { dbus_handler_set_ui_context(instance.dbus_handler, instance.ui_context); diff --git a/src/submission.h b/src/submission.h new file mode 100644 index 00000000..e2ebbbfd --- /dev/null +++ b/src/submission.h @@ -0,0 +1,19 @@ +#ifndef __SUBMISSION_H +#define __SUBMISSION_H + +#include "input-method-unstable-v2-client-protocol.h" +#include "virtual-keyboard-unstable-v1-client-protocol.h" +#include "eek/eek-types.h" + +struct submission; + +struct submission* get_submission(struct zwp_input_method_manager_v2 *immanager, + struct zwp_virtual_keyboard_manager_v1 *vkmanager, + struct wl_seat *seat, + EekboardContextService *state); + +// Defined in Rust +struct submission* submission_new(struct zwp_input_method_v2 *im, struct zwp_virtual_keyboard_v1 *vk, EekboardContextService *state); +void submission_set_ui(struct submission *self, ServerContextService *ui_context); +void submission_set_keyboard(struct submission *self, LevelKeyboard *keyboard); +#endif diff --git a/src/submission.rs b/src/submission.rs index 7dd9af31..08541434 100644 --- a/src/submission.rs +++ b/src/submission.rs @@ -20,3 +20,65 @@ /// 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::*; + + use std::os::raw::c_void; + + use ::imservice::c::InputMethod; + + // The following defined in C + + /// ServerContextService* + #[repr(transparent)] + pub struct UIManager(*const c_void); + + /// EekboardContextService* + #[repr(transparent)] + pub struct StateManager(*const c_void); + + #[no_mangle] + pub extern "C" + fn submission_new( + im: *mut InputMethod, + state_manager: *const StateManager + ) -> *mut Submission { + let imservice = if im.is_null() { + None + } else { + Some(IMService::new(im, state_manager)) + }; + // TODO: add vkeyboard too + Box::::into_raw(Box::new( + Submission { + imservice, + } + )) + } + + #[no_mangle] + pub extern "C" + fn submission_set_ui(submission: *mut Submission, ui_manager: *const UIManager) { + if submission.is_null() { + panic!("Null submission pointer"); + } + let submission: &mut Submission = unsafe { &mut *submission }; + if let Some(ref mut imservice) = &mut submission.imservice { + imservice.ui_manager = if ui_manager.is_null() { + None + } else { + Some(ui_manager) + } + }; + } +} + +pub struct Submission { + // used by C callbacks internally, TODO: make use with virtual keyboard + #[allow(dead_code)] + imservice: Option>, +} From e5d416fd4f052d16620dcc0676f0465683b7b83d Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 12 Jan 2020 19:12:29 +0000 Subject: [PATCH 03/10] imservice: Limited scope of unsafe --- src/imservice.rs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/imservice.rs b/src/imservice.rs index 72bd33fc..5da9ee0b 100644 --- a/src/imservice.rs +++ b/src/imservice.rs @@ -38,7 +38,7 @@ pub mod c { // TODO: is unsafe needed here? #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_input_method_activate(imservice: *mut IMService, im: *const InputMethod) { @@ -51,7 +51,7 @@ pub mod c { } #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_input_method_deactivate(imservice: *mut IMService, im: *const InputMethod) { @@ -63,7 +63,7 @@ pub mod c { } #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_surrounding_text(imservice: *mut IMService, im: *const InputMethod, text: *const c_char, cursor: u32, _anchor: u32) @@ -79,7 +79,7 @@ pub mod c { } #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_content_type(imservice: *mut IMService, im: *const InputMethod, hint: u32, purpose: u32) @@ -103,7 +103,7 @@ pub mod c { } #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_text_change_cause(imservice: *mut IMService, im: *const InputMethod, cause: u32) @@ -121,7 +121,7 @@ pub mod c { } #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_commit_state(imservice: *mut IMService, im: *const InputMethod) { @@ -138,34 +138,38 @@ pub mod c { if active_changed { if imservice.current.active { if let Some(ui) = imservice.ui_manager { - server_context_service_show_keyboard(ui); + unsafe { server_context_service_show_keyboard(ui); } + } + unsafe { + eekboard_context_service_set_hint_purpose( + imservice.state_manager, + imservice.current.content_hint.bits(), + imservice.current.content_purpose.clone() as u32, + ); } - eekboard_context_service_set_hint_purpose( - imservice.state_manager, - imservice.current.content_hint.bits(), - imservice.current.content_purpose.clone() as u32); } else { if let Some(ui) = imservice.ui_manager { - server_context_service_hide_keyboard(ui); + unsafe { server_context_service_hide_keyboard(ui); } } } } } + // TODO: this is really untested #[no_mangle] - pub unsafe extern "C" + pub extern "C" fn imservice_handle_unavailable(imservice: *mut IMService, im: *mut InputMethod) { let imservice = check_imservice(imservice, im).unwrap(); - imservice_destroy_im(im); + unsafe { imservice_destroy_im(im); } // no need to care about proper double-buffering, // the keyboard is already decommissioned imservice.current.active = false; if let Some(ui) = imservice.ui_manager { - server_context_service_hide_keyboard(ui); + unsafe { server_context_service_hide_keyboard(ui); } } } From aafecfac02d4033f2b2804693b00db46f41fb9e1 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 12 Jan 2020 19:37:24 +0000 Subject: [PATCH 04/10] EekGtkKeyboard: Use a direct reference to EekboardContext --- eek/eek-gtk-keyboard.c | 18 ++++++++++-------- eek/eek-gtk-keyboard.h | 4 +++- eek/eek-keyboard.c | 1 - eek/eek-keyboard.h | 2 -- src/server-context-service.c | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 43aa8137..2a15fefc 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -54,6 +54,7 @@ enum { typedef struct _EekGtkKeyboardPrivate { EekRenderer *renderer; + EekboardContextService *eekboard_context; // unowned reference LevelKeyboard *keyboard; // unowned reference; it's kept in server-context (FIXME) GdkEventSequence *sequence; // unowned reference @@ -122,7 +123,7 @@ static void depress(EekGtkKeyboard *self, { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - squeek_layout_depress(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, + squeek_layout_depress(priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, x, y, eek_renderer_get_transformation(priv->renderer), time, self); } @@ -130,18 +131,18 @@ 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->keyboard->manager->virtual_keyboard, + squeek_layout_drag(priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, x, y, eek_renderer_get_transformation(priv->renderer), time, - priv->keyboard->manager, self); + priv->eekboard_context, self); } static void release(EekGtkKeyboard *self, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, + squeek_layout_release(priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, eek_renderer_get_transformation(priv->renderer), time, - priv->keyboard->manager, self); + priv->eekboard_context, self); } static gboolean @@ -229,7 +230,7 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self) if (priv->keyboard) { squeek_layout_release_all_only( - priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, + priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, gdk_event_get_time(NULL)); } @@ -264,7 +265,7 @@ eek_gtk_keyboard_dispose (GObject *object) if (priv->keyboard) { squeek_layout_release_all_only( - priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, + priv->keyboard->layout, priv->eekboard_context->virtual_keyboard, gdk_event_get_time(NULL)); priv->keyboard = NULL; } @@ -311,11 +312,12 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self) * Returns: a #GtkWidget */ GtkWidget * -eek_gtk_keyboard_new (LevelKeyboard *keyboard) +eek_gtk_keyboard_new (LevelKeyboard *keyboard, EekboardContextService *eekservice) { 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; return GTK_WIDGET(ret); } diff --git a/eek/eek-gtk-keyboard.h b/eek/eek-gtk-keyboard.h index 35876b51..e9cb7c1a 100644 --- a/eek/eek-gtk-keyboard.h +++ b/eek/eek-gtk-keyboard.h @@ -28,6 +28,8 @@ #include #include +#include "eek/eek-types.h" + typedef struct _LevelKeyboard LevelKeyboard; // including causes weird bugs G_BEGIN_DECLS @@ -45,7 +47,7 @@ struct _EekGtkKeyboardClass }; GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST; -GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard); +GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard, EekboardContextService *eekservice); G_END_DECLS #endif /* EEK_GTK_KEYBOARD_H */ diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 5245eb8e..fbbdfd87 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -52,6 +52,5 @@ void level_keyboard_init(LevelKeyboard *self, struct squeek_layout *layout) { LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout) { LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); level_keyboard_init(keyboard, layout); - keyboard->manager = manager; return keyboard; } diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index ebf63351..c2d291ac 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -41,8 +41,6 @@ struct _LevelKeyboard { size_t keymap_len; // length of the data inside keymap_fd guint id; // as a key to layout choices - - EekboardContextService *manager; // unowned reference }; typedef struct _LevelKeyboard LevelKeyboard; diff --git a/src/server-context-service.c b/src/server-context-service.c index ce2052da..88b12fab 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -224,7 +224,7 @@ make_widget (ServerContextService *context) LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (context->state); - context->widget = eek_gtk_keyboard_new (keyboard); + context->widget = eek_gtk_keyboard_new (keyboard, context->state); gtk_widget_set_has_tooltip (context->widget, TRUE); gtk_container_add (GTK_CONTAINER(context->window), context->widget); From 326bb9319fcc5c4248d0a8e50b7afdf89acb431a Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 12 Jan 2020 20:09:05 +0000 Subject: [PATCH 05/10] submission: Take over virtual_keyboard handling --- eek/eek-gtk-keyboard.c | 21 +++++++++---- eek/eek-gtk-keyboard.h | 3 +- eek/eek-types.h | 1 + eekboard/eekboard-context-service.c | 35 ++++++++++----------- eekboard/eekboard-context-service.h | 7 ++--- src/imservice.c | 14 +++++++-- src/layout.h | 13 +++++--- src/layout.rs | 49 ++++++++++++++--------------- src/server-context-service.c | 10 ++++-- src/server-context-service.h | 3 +- src/server-main.c | 20 +++++++----- src/submission.rs | 21 +++++++++++-- src/vkeyboard.rs | 18 +++++++++-- src/wayland.c | 9 ++++++ 14 files changed, 147 insertions(+), 77 deletions(-) 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); From 0ce19b4269565c1cc88e5cdbb39a9b5df779b909 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Mon, 13 Jan 2020 12:45:59 +0000 Subject: [PATCH 06/10] keyboard: Cleanups of unused code --- eek/eek-keyboard.c | 14 +------------- eek/eek-keyboard.h | 2 +- eek/keymap.h | 8 -------- 3 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 eek/keymap.h diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index fbbdfd87..c4633a1d 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -18,20 +18,8 @@ * 02110-1301 USA */ -/** - * SECTION:eek-keyboard - * @short_description: Base class of a keyboard - * @see_also: #EekSection - * - * The #EekKeyboardClass class represents a keyboard, which consists - * of one or more sections of the #EekSectionClass class. - */ - #include "config.h" -#include -#include "eekboard/eekboard-context-service.h" -#include "keymap.h" #include "eek-keyboard.h" void level_keyboard_deinit(LevelKeyboard *self) { @@ -49,7 +37,7 @@ void level_keyboard_init(LevelKeyboard *self, struct squeek_layout *layout) { self->layout = layout; } -LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout) { +LevelKeyboard *level_keyboard_new(struct squeek_layout *layout) { LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); level_keyboard_init(keyboard, layout); return keyboard; diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index c2d291ac..d36e3a46 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -47,7 +47,7 @@ typedef struct _LevelKeyboard LevelKeyboard; gchar * eek_keyboard_get_keymap (LevelKeyboard *keyboard); -LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout); +LevelKeyboard *level_keyboard_new(struct squeek_layout *layout); void level_keyboard_deinit(LevelKeyboard *self); void level_keyboard_free(LevelKeyboard *self); diff --git a/eek/keymap.h b/eek/keymap.h deleted file mode 100644 index e33c502e..00000000 --- a/eek/keymap.h +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -gboolean -squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap, - guint keyval, - GdkKeymapKey **keys, - guint *n_keys); From 0ef02ebfa330c2b9a4403ccc259fe866dddbc1d5 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Mon, 13 Jan 2020 12:50:05 +0000 Subject: [PATCH 07/10] levelkeyboard: Drop unused manager references --- eek/eek-xml-layout.c | 3 +-- eek/eek-xml-layout.h | 1 - eekboard/eekboard-context-service.c | 7 +++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index 81d0302a..64802b4c 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -30,9 +30,8 @@ LevelKeyboard * eek_xml_layout_real_create_keyboard (const char *keyboard_type, - EekboardContextService *manager, enum squeek_arrangement_kind t) { struct squeek_layout *layout = squeek_load_layout(keyboard_type, t); - return level_keyboard_new(manager, layout); + return level_keyboard_new(layout); } diff --git a/eek/eek-xml-layout.h b/eek/eek-xml-layout.h index ed0bb346..278537e6 100644 --- a/eek/eek-xml-layout.h +++ b/eek/eek-xml-layout.h @@ -30,7 +30,6 @@ G_BEGIN_DECLS LevelKeyboard * eek_xml_layout_real_create_keyboard (const char *keyboard_type, - EekboardContextService *manager, enum squeek_arrangement_kind t); G_END_DECLS #endif /* EEK_XML_LAYOUT_H */ diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index b4e26bcd..e854ebc1 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -81,11 +81,10 @@ struct _EekboardContextServicePrivate { G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT); static LevelKeyboard * -eekboard_context_service_real_create_keyboard (EekboardContextService *self, - const gchar *keyboard_type, +eekboard_context_service_real_create_keyboard (const gchar *keyboard_type, enum squeek_arrangement_kind t) { - LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self, t); + LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, t); if (!keyboard) { g_error("Failed to create a keyboard"); } @@ -220,7 +219,7 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ } // generic part follows - LevelKeyboard *keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout, t); + LevelKeyboard *keyboard = eekboard_context_service_real_create_keyboard(keyboard_layout, t); // set as current LevelKeyboard *previous_keyboard = context->priv->keyboard; context->priv->keyboard = keyboard; From 26dbcdeb62803b84e27fc46ea4ad4f499cbdd80f Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Mon, 13 Jan 2020 13:01:48 +0000 Subject: [PATCH 08/10] keyboard: Gather up keymap handling, drop layout --- eek/eek-keyboard.c | 73 ++++++++++++++++++++++----- eek/eek-keyboard.h | 6 +-- eek/eek-layout.c | 47 ------------------ eek/eek-layout.h | 60 ----------------------- eek/eek-xml-layout.c | 37 -------------- eek/eek-xml-layout.h | 35 ------------- eek/eek.h | 1 - eekboard/eekboard-context-service.c | 76 +---------------------------- src/meson.build | 2 - 9 files changed, 67 insertions(+), 270 deletions(-) delete mode 100644 eek/eek-layout.c delete mode 100644 eek/eek-layout.h delete mode 100644 eek/eek-xml-layout.c delete mode 100644 eek/eek-xml-layout.h diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index c4633a1d..24ef537b 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -20,25 +20,76 @@ #include "config.h" +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include // TODO: this is Linux-specific +#include + + #include "eek-keyboard.h" -void level_keyboard_deinit(LevelKeyboard *self) { +void level_keyboard_free(LevelKeyboard *self) { xkb_keymap_unref(self->keymap); close(self->keymap_fd); squeek_layout_free(self->layout); -} - -void level_keyboard_free(LevelKeyboard *self) { - level_keyboard_deinit(self); g_free(self); } -void level_keyboard_init(LevelKeyboard *self, struct squeek_layout *layout) { - self->layout = layout; -} - -LevelKeyboard *level_keyboard_new(struct squeek_layout *layout) { +LevelKeyboard* +level_keyboard_new (const gchar *keyboard_type, + enum squeek_arrangement_kind t) +{ + struct squeek_layout *layout = squeek_load_layout(keyboard_type, t); LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); - level_keyboard_init(keyboard, layout); + + if (!keyboard) { + g_error("Failed to create a keyboard"); + } + keyboard->layout = layout; + + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!context) { + g_error("No context created"); + } + + const gchar *keymap_str = squeek_layout_get_keymap(keyboard->layout); + + struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str, + XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!keymap) + g_error("Bad keymap:\n%s", keymap_str); + + xkb_context_unref(context); + keyboard->keymap = keymap; + + keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1); + keyboard->keymap_len = strlen(keymap_str) + 1; + + g_autofree char *path = strdup("/eek_keymap-XXXXXX"); + char *r = &path[strlen(path) - 6]; + getrandom(r, 6, GRND_NONBLOCK); + for (unsigned 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"); + } + strncpy(ptr, keymap_str, keyboard->keymap_len); + munmap(ptr, keyboard->keymap_len); return keyboard; } diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index d36e3a46..fab549e1 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -28,7 +28,6 @@ #include #include #include "eek-types.h" -#include "eek-layout.h" #include "src/layout.h" G_BEGIN_DECLS @@ -47,8 +46,9 @@ typedef struct _LevelKeyboard LevelKeyboard; gchar * eek_keyboard_get_keymap (LevelKeyboard *keyboard); -LevelKeyboard *level_keyboard_new(struct squeek_layout *layout); -void level_keyboard_deinit(LevelKeyboard *self); +LevelKeyboard* +level_keyboard_new (const gchar *keyboard_type, + enum squeek_arrangement_kind t); void level_keyboard_free(LevelKeyboard *self); G_END_DECLS diff --git a/eek/eek-layout.c b/eek/eek-layout.c deleted file mode 100644 index ff4f96ca..00000000 --- a/eek/eek-layout.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2010-2011 Daiki Ueno - * Copyright (C) 2010-2011 Red Hat, Inc. - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -/** - * SECTION:eek-layout - * @short_description: Base class of a layout engine - * - * The #EekLayout class is a base class of layout engine which - * arranges keyboard elements. - */ - -#include "config.h" - -#include "eek-layout.h" -#include "eek-keyboard.h" -#include "eekboard/eekboard-context-service.h" -#include "eek-xml-layout.h" - -G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT) - -static void -eek_layout_class_init (EekLayoutClass *klass) -{ - klass->create_keyboard = NULL; -} - -void -eek_layout_init (EekLayout *self) -{ -} diff --git a/eek/eek-layout.h b/eek/eek-layout.h deleted file mode 100644 index 480f1692..00000000 --- a/eek/eek-layout.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010-2011 Daiki Ueno - * Copyright (C) 2010-2011 Red Hat, Inc. - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) -#error "Only can be included directly." -#endif - -#ifndef EEK_LAYOUT_H -#define EEK_LAYOUT_H 1 - -#include -#include "eek-types.h" -#include "src/layout.h" - -G_BEGIN_DECLS - -#define EEK_TYPE_LAYOUT (eek_layout_get_type()) -G_DECLARE_DERIVABLE_TYPE (EekLayout, eek_layout, EEK, LAYOUT, GObject) - -/** - * EekLayoutClass: - * @create_keyboard: virtual function for creating a keyboard - */ -struct _EekLayoutClass -{ - /*< private >*/ - GObjectClass parent_class; - - /*< public >*/ - LevelKeyboard* (* create_keyboard) (EekboardContextService *manager, - EekLayout *self, - gdouble initial_width, - gdouble initial_height); - - /*< private >*/ - /* padding */ - gpointer pdummy[24]; -}; - -GType eek_layout_get_type (void) G_GNUC_CONST; - -G_END_DECLS -#endif /* EEK_LAYOUT_H */ diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c deleted file mode 100644 index 64802b4c..00000000 --- a/eek/eek-xml-layout.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2011 Daiki Ueno - * Copyright (C) 2011 Red Hat, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * SECTION:eek-xml-layout - * @short_description: Layout engine which loads layout information from XML - */ - -#include "config.h" - -#include "eek-keyboard.h" -#include "src/layout.h" - -#include "eek-xml-layout.h" - -LevelKeyboard * -eek_xml_layout_real_create_keyboard (const char *keyboard_type, - enum squeek_arrangement_kind t) -{ - struct squeek_layout *layout = squeek_load_layout(keyboard_type, t); - return level_keyboard_new(layout); -} diff --git a/eek/eek-xml-layout.h b/eek/eek-xml-layout.h deleted file mode 100644 index 278537e6..00000000 --- a/eek/eek-xml-layout.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011 Daiki Ueno - * Copyright (C) 2011 Red Hat, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) -#error "Only can be included directly." -#endif - -#ifndef EEK_XML_LAYOUT_H -#define EEK_XML_LAYOUT_H 1 - -#include "eek-types.h" -#include "src/layout.h" - -G_BEGIN_DECLS - -LevelKeyboard * -eek_xml_layout_real_create_keyboard (const char *keyboard_type, - enum squeek_arrangement_kind t); -G_END_DECLS -#endif /* EEK_XML_LAYOUT_H */ diff --git a/eek/eek.h b/eek/eek.h index c1548121..5ba3d099 100644 --- a/eek/eek.h +++ b/eek/eek.h @@ -23,7 +23,6 @@ #define __EEK_H_INSIDE__ 1 #include "eek-keyboard.h" -#include "eek-layout.h" void eek_init (void); diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index e854ebc1..e9f7b9db 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -16,31 +16,15 @@ * along with this program. If not, see . */ -/** - * SECTION:eekboard-context-service - * @short_description: base server implementation of eekboard input - * context service - * - * The #EekboardService class provides a base server side - * implementation of eekboard input context service. - */ - #include "config.h" -#include #include -#define _XOPEN_SOURCE 500 -#include -#include -#include // TODO: this is Linux-specific -#include #include #include "wayland.h" #include "eek/eek-keyboard.h" -#include "eek/eek-xml-layout.h" #include "src/server-context-service.h" #include "eekboard/eekboard-context-service.h" @@ -80,60 +64,6 @@ struct _EekboardContextServicePrivate { G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT); -static LevelKeyboard * -eekboard_context_service_real_create_keyboard (const gchar *keyboard_type, - enum squeek_arrangement_kind t) -{ - LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, t); - if (!keyboard) { - g_error("Failed to create a keyboard"); - } - - struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!context) { - g_error("No context created"); - } - - const gchar *keymap_str = squeek_layout_get_keymap(keyboard->layout); - - struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str, - XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); - - if (!keymap) - g_error("Bad keymap:\n%s", keymap_str); - - xkb_context_unref(context); - keyboard->keymap = keymap; - - keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1); - keyboard->keymap_len = strlen(keymap_str) + 1; - - g_autofree char *path = strdup("/eek_keymap-XXXXXX"); - char *r = &path[strlen(path) - 6]; - getrandom(r, 6, GRND_NONBLOCK); - for (unsigned 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"); - } - strncpy(ptr, keymap_str, keyboard->keymap_len); - munmap(ptr, keyboard->keymap_len); - return keyboard; -} - static void eekboard_context_service_set_property (GObject *object, guint prop_id, @@ -219,14 +149,12 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ } // generic part follows - LevelKeyboard *keyboard = eekboard_context_service_real_create_keyboard(keyboard_layout, t); + LevelKeyboard *keyboard = level_keyboard_new(keyboard_layout, t); // set as current LevelKeyboard *previous_keyboard = context->priv->keyboard; context->priv->keyboard = keyboard; - // Update the keymap if necessary. - // Done directly here instead of in "keyboard" update handler - // to keep keymap-related actions close together. + // TODO: Update submission on change event if (context->priv->submission) { submission_set_keyboard(context->priv->submission, keyboard); } diff --git a/src/meson.build b/src/meson.build index 0eda4cf2..00d92a89 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,10 +20,8 @@ sources = [ '../eek/eek-element.c', '../eek/eek-gtk-keyboard.c', '../eek/eek-keyboard.c', - '../eek/eek-layout.c', '../eek/eek-renderer.c', '../eek/eek-types.c', - '../eek/eek-xml-layout.c', '../eek/layersurface.c', dbus_src, '../eekboard/eekboard-context-service.c', From 02c24a50d2881ce20ff135b1e9d64109deaddd2b Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Tue, 14 Jan 2020 11:38:44 +0000 Subject: [PATCH 09/10] submission: Remove wildcard reexport --- src/submission.rs | 9 ++++----- src/vkeyboard.rs | 4 +--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/submission.rs b/src/submission.rs index fd82ba83..db7e6cc4 100644 --- a/src/submission.rs +++ b/src/submission.rs @@ -18,11 +18,7 @@ * */ 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 ::vkeyboard::VirtualKeyboard; /// Gathers stuff defined in C or called by C pub mod c { @@ -93,6 +89,9 @@ pub mod c { } } +#[derive(Clone, Copy)] +pub struct Timestamp(pub u32); + pub struct Submission { // used by C callbacks internally, TODO: make use with virtual keyboard #[allow(dead_code)] diff --git a/src/vkeyboard.rs b/src/vkeyboard.rs index 791814e4..aac5d18f 100644 --- a/src/vkeyboard.rs +++ b/src/vkeyboard.rs @@ -2,6 +2,7 @@ use ::keyboard::{ KeyCode, PressType }; use ::layout::c::LevelKeyboard; +use ::submission::Timestamp; /// Gathers stuff defined in C or called by C pub mod c { @@ -28,9 +29,6 @@ pub mod c { } } -#[derive(Clone, Copy)] -pub struct Timestamp(pub u32); - /// Layout-independent backend. TODO: Have one instance per program or seat pub struct VirtualKeyboard(pub c::ZwpVirtualKeyboardV1); From e3f31cc17f1bfb39c431741bfa99086822c62e90 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Tue, 14 Jan 2020 18:16:26 +0000 Subject: [PATCH 10/10] imservice: Rename commit_state to done to match protocol --- src/imservice.c | 4 ++-- src/imservice.rs | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/imservice.c b/src/imservice.c index 1c98aa15..2a6184c8 100644 --- a/src/imservice.c +++ b/src/imservice.c @@ -8,7 +8,7 @@ void imservice_handle_input_method_activate(void *data, struct zwp_input_method_ void imservice_handle_input_method_deactivate(void *data, struct zwp_input_method_v2 *input_method); void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method, const char *text, uint32_t cursor, uint32_t anchor); -void imservice_handle_commit_state(void *data, struct zwp_input_method_v2 *input_method); +void imservice_handle_done(void *data, struct zwp_input_method_v2 *input_method); void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose); void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause); void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method); @@ -19,7 +19,7 @@ static const struct zwp_input_method_v2_listener input_method_listener = { .surrounding_text = imservice_handle_surrounding_text, .text_change_cause = imservice_handle_text_change_cause, .content_type = imservice_handle_content_type, - .done = imservice_handle_commit_state, + .done = imservice_handle_done, .unavailable = imservice_handle_unavailable, }; diff --git a/src/imservice.rs b/src/imservice.rs index 5da9ee0b..f5989a11 100644 --- a/src/imservice.rs +++ b/src/imservice.rs @@ -122,13 +122,12 @@ pub mod c { #[no_mangle] pub extern "C" - fn imservice_handle_commit_state(imservice: *mut IMService, + fn imservice_handle_done(imservice: *mut IMService, im: *const InputMethod) { let imservice = check_imservice(imservice, im).unwrap(); let active_changed = imservice.current.active ^ imservice.pending.active; - - imservice.serial += Wrapping(1u32); + imservice.current = imservice.pending.clone(); imservice.pending = IMProtocolState { active: imservice.current.active,