From 785717d477119ba4f0d334d3769cc2be5b20d5c9 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 12 Jan 2020 19:08:40 +0000 Subject: [PATCH] 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>, +}