From 81948425d897ecc1257269f5413f664dd6572446 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Thu, 9 Dec 2021 12:41:58 +0000 Subject: [PATCH 1/2] popover: Fix reentrancy problem Calling popover.show() returns control to the main loop, but squeekboard structures are still borrowed meanwhile. That's dangerous and forbidden in Rust. Therefore, this forces the return from the stack and release of the borrows before the glib main loop is invoked again. --- src/popover.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/popover.rs b/src/popover.rs index feec80f1..bee817ee 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -360,5 +360,8 @@ pub fn show( menu.insert_action_group("popup", Some(&action_group)); menu.bind_model(Some(&model), Some("popup")); - menu.popup(); + glib::idle_add_local(move || { + menu.popup(); + Continue(false) + }); } From d64b8cdf1a0d70cf1deab0996b61cdddd760bd84 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Thu, 9 Dec 2021 12:43:36 +0000 Subject: [PATCH 2/2] submission: Wrap the structure in a safe wrapper --- src/drawing.rs | 7 ++++--- src/layout.rs | 33 +++++++++++++++++++-------------- src/submission.rs | 26 ++++++++++++-------------- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/drawing.rs b/src/drawing.rs index 312af9ce..8982dcd4 100644 --- a/src/drawing.rs +++ b/src/drawing.rs @@ -7,7 +7,7 @@ use ::action::{ Action, Modifier }; use ::keyboard; use ::layout::{ Button, Label, LatchedState, Layout }; use ::layout::c::{ Bounds, EekGtkKeyboard, Point }; -use ::submission::Submission; +use ::submission::c::Submission as CSubmission; use glib::translate::FromGlibPtrNone; use gtk::WidgetExt; @@ -76,10 +76,11 @@ mod c { layout: *mut Layout, renderer: EekRenderer, cr: *mut cairo_sys::cairo_t, - submission: *const Submission, + submission: CSubmission, ) { let layout = unsafe { &mut *layout }; - let submission = unsafe { &*submission }; + let submission = submission.clone_ref(); + let submission = submission.borrow(); let cr = unsafe { cairo::Context::from_raw_none(cr) }; let active_modifiers = submission.get_active_modifiers(); diff --git a/src/layout.rs b/src/layout.rs index 14719dd0..368553d0 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -44,6 +44,7 @@ pub mod c { use gtk_sys; use std::os::raw::c_void; + use crate::submission::c::Submission as CSubmission; use std::ops::{ Add, Sub }; @@ -207,7 +208,7 @@ pub mod c { pub extern "C" fn squeek_layout_release( layout: *mut Layout, - submission: *mut Submission, + submission: CSubmission, widget_to_layout: Transformation, time: u32, manager: manager::c::Manager, @@ -215,7 +216,8 @@ pub mod c { ) { let time = Timestamp(time); let layout = unsafe { &mut *layout }; - let submission = unsafe { &mut *submission }; + let submission = submission.clone_ref(); + let mut submission = submission.borrow_mut(); let ui_backend = UIBackend { widget_to_layout, keyboard: ui_keyboard, @@ -227,7 +229,7 @@ pub mod c { let key: &Rc> = key.borrow(); seat::handle_release_key( layout, - submission, + &mut submission, Some(&ui_backend), time, Some(manager), @@ -242,18 +244,19 @@ pub mod c { pub extern "C" fn squeek_layout_release_all_only( layout: *mut Layout, - submission: *mut Submission, + submission: CSubmission, time: u32, ) { let layout = unsafe { &mut *layout }; - let submission = unsafe { &mut *submission }; + let submission = submission.clone_ref(); + let mut submission = submission.borrow_mut(); // 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, - submission, + &mut submission, None, // don't update UI Timestamp(time), None, // don't switch layouts @@ -266,14 +269,15 @@ pub mod c { pub extern "C" fn squeek_layout_depress( layout: *mut Layout, - submission: *mut Submission, + submission: CSubmission, 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 submission = submission.clone_ref(); + let mut submission = submission.borrow_mut(); let point = widget_to_layout.forward( Point { x: x_widget, y: y_widget } ); @@ -284,7 +288,7 @@ pub mod c { if let Some(state) = state { seat::handle_press_key( layout, - submission, + &mut submission, Timestamp(time), &state, ); @@ -303,7 +307,7 @@ pub mod c { pub extern "C" fn squeek_layout_drag( layout: *mut Layout, - submission: *mut Submission, + submission: CSubmission, x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, @@ -312,7 +316,8 @@ pub mod c { ) { let time = Timestamp(time); let layout = unsafe { &mut *layout }; - let submission = unsafe { &mut *submission }; + let submission = submission.clone_ref(); + let mut submission = submission.borrow_mut(); let ui_backend = UIBackend { widget_to_layout, keyboard: ui_keyboard, @@ -340,7 +345,7 @@ pub mod c { } else { seat::handle_release_key( layout, - submission, + &mut submission, Some(&ui_backend), time, Some(manager), @@ -351,7 +356,7 @@ pub mod c { if !found { seat::handle_press_key( layout, - submission, + &mut submission, time, &state, ); @@ -365,7 +370,7 @@ pub mod c { let key: &Rc> = wrapped_key.borrow(); seat::handle_release_key( layout, - submission, + &mut submission, Some(&ui_backend), time, Some(manager), diff --git a/src/submission.rs b/src/submission.rs index 966645c3..59212ba7 100644 --- a/src/submission.rs +++ b/src/submission.rs @@ -48,6 +48,8 @@ pub mod c { #[repr(transparent)] pub struct StateManager(*const c_void); + pub type Submission = Wrapped; + #[no_mangle] pub extern "C" fn submission_new( @@ -55,7 +57,7 @@ pub mod c { vk: ZwpVirtualKeyboardV1, state_manager: *const StateManager, visibility_manager: Wrapped, - ) -> *mut Submission { + ) -> Submission { let imservice = if im.is_null() { None } else { @@ -67,8 +69,8 @@ pub mod c { )) }; // TODO: add vkeyboard too - Box::::into_raw(Box::new( - Submission { + Wrapped::new( + super::Submission { imservice, modifiers_active: Vec::new(), virtual_keyboard: VirtualKeyboard(vk), @@ -76,31 +78,27 @@ pub mod c { keymap_fds: Vec::new(), keymap_idx: None, } - )) + ) } #[no_mangle] pub extern "C" fn submission_use_layout( - submission: *mut Submission, + submission: Submission, layout: *const layout::Layout, time: u32, ) { - if submission.is_null() { - panic!("Null submission pointer"); - } - let submission: &mut Submission = unsafe { &mut *submission }; + let submission = submission.clone_ref(); + let mut submission = submission.borrow_mut(); let layout = unsafe { &*layout }; submission.use_layout(layout, Timestamp(time)); } #[no_mangle] pub extern "C" - fn submission_hint_available(submission: *mut Submission) -> u8 { - if submission.is_null() { - panic!("Null submission pointer"); - } - let submission: &mut Submission = unsafe { &mut *submission }; + fn submission_hint_available(submission: Submission) -> u8 { + let submission = submission.clone_ref(); + let submission = submission.borrow(); let active = submission.imservice.as_ref() .map(|imservice| imservice.is_active()); (Some(true) == active) as u8