From 79b66f81ec9d14ae7d222c4142c60d0c20d65965 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Fri, 16 Aug 2019 18:07:13 +0000 Subject: [PATCH] view: Move button finding to Rust --- eek/eek-gtk-keyboard.c | 4 +- eek/eek-keyboard.c | 34 ----------- eek/eek-keyboard.h | 3 - src/layout.h | 2 +- src/layout.rs | 136 +++++++++++++++++++++++++++++++++++------ 5 files changed, 120 insertions(+), 59 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 79ce33d9..8120b68c 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -114,7 +114,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, /* redraw pressed key */ const GList *list = priv->keyboard->pressed_buttons; for (const GList *head = list; head; head = g_list_next (head)) { - struct button_place place = eek_keyboard_get_button_by_state( + struct button_place place = squeek_view_find_key( view, squeek_button_get_key(head->data) ); render_pressed_button (self, &place); @@ -123,7 +123,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, /* redraw locked key */ list = priv->keyboard->locked_buttons; for (const GList *head = list; head; head = g_list_next (head)) { - struct button_place place = eek_keyboard_get_button_by_state( + struct button_place place = squeek_view_find_key( view, squeek_button_get_key( ((EekModifierKey *)head->data)->button ) diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index e11172da..67e3da59 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -287,37 +287,3 @@ struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard) { return keyboard->views[keyboard->level]; } - -struct GetRowData { - struct squeek_button *button; - struct squeek_row *row; - struct squeek_key *needle; -}; - -void find_key_in_row(struct squeek_row *row, gpointer user_data) { - struct GetRowData *data = user_data; - if (data->button) { - return; - } - data->button = squeek_row_find_key(row, data->needle); - if (data->button) { - data->row = row; - } -} - - -// TODO: return multiple -struct button_place eek_keyboard_get_button_by_state(struct squeek_view *view, - struct squeek_key *key) { - struct GetRowData data = { - .row = NULL, - .button = NULL, - .needle = key, - }; - squeek_view_foreach(view, find_key_in_row, &data); - struct button_place ret = { - .row = data.row, - .button = data.button, - }; - return ret; -} diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index b0eb6ec7..744cfe7d 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -70,9 +70,6 @@ struct button_place { const struct squeek_button *button; }; -struct button_place eek_keyboard_get_button_by_state(struct squeek_view *view, - struct squeek_key *key); - EekOutline *level_keyboard_get_outline (LevelKeyboard *keyboard, guint oref); diff --git a/src/layout.h b/src/layout.h index 95634dbf..1b01af52 100644 --- a/src/layout.h +++ b/src/layout.h @@ -23,7 +23,7 @@ void squeek_row_set_bounds(struct squeek_row* row, EekBounds bounds); uint32_t squeek_row_contains(struct squeek_row*, struct squeek_button *button); -struct squeek_button* squeek_row_find_key(struct squeek_row*, struct squeek_key *state); +struct button_place squeek_view_find_key(struct squeek_view*, struct squeek_key *state); struct squeek_button *squeek_row_find_button_by_position(struct squeek_row *row, EekPoint point, EekPoint origin); diff --git a/src/layout.rs b/src/layout.rs index c112dd9a..a676c3fb 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -309,6 +309,13 @@ pub mod c { #[repr(transparent)] pub struct LevelKeyboard(*const c_void); + + #[repr(C)] + #[derive(PartialEq, Debug)] + pub struct ButtonPlace { + row: *const Row, + button: *const Button, + } #[no_mangle] extern "C" { @@ -352,25 +359,6 @@ pub mod c { row.place_buttons_with_sizes(sizes); } - /// Finds a button sharing this state - #[no_mangle] - pub extern "C" - fn squeek_row_find_key( - row: *mut ::layout::Row, - state: ::keyboard::c::CKeyState, - ) -> *mut Button { - let row = unsafe { &mut *row }; - let needle = state.unwrap(); - let found = row.buttons.iter_mut().find( - |button| Rc::ptr_eq(&button.state, &needle) - ); - Rc::into_raw(needle); // Prevent dropping - match found { - Some(button) => button.as_mut() as *mut Button, - None => ptr::null_mut(), - } - } - #[no_mangle] pub extern "C" fn squeek_row_find_button_by_position( @@ -423,6 +411,31 @@ pub mod c { None => ptr::null_mut(), } } + + #[no_mangle] + pub extern "C" + fn squeek_view_find_key( + view: *const View, + needle: ::keyboard::c::CKeyState, + ) -> ButtonPlace { + let view = unsafe { &*view }; + let state = needle.unwrap(); + + let paths = ::layout::procedures::find_key_paths(view, &state); + + // Iterators used up, can turn the reference back into pointer + Rc::into_raw(state); + + // Can only return 1 entry back to C + let (row, button) = match paths.get(0) { + Some((row, button)) => ( + row.as_ref() as *const Row, + button.as_ref() as *const Button, + ), + None => ( ptr::null(), ptr::null() ), + }; + ButtonPlace { row, button } + } #[cfg(test)] mod test { @@ -441,6 +454,68 @@ pub mod c { let row = Row::new(0); assert_eq!(squeek_row_contains(&row, button), false); } + + #[test] + fn view_has_button() { + let state = Rc::new(RefCell::new(::keyboard::KeyState { + pressed: false, + locked: false, + keycode: 0, + symbol: None, + })); + let state_clone = ::keyboard::c::CKeyState::wrap(state.clone()); + + let button = Box::new(Button { + oref: OutlineRef(0), + bounds: None, + state: state, + }); + let button_ptr = button.as_ref() as *const Button; + + let row = Box::new(Row { + buttons: vec!(button), + angle: 0, + bounds: None + }); + let row_ptr = row.as_ref() as *const Row; + + let view = View { + bounds: Bounds { + x: 0f64, y: 0f64, + width: 0f64, height: 0f64 + }, + rows: vec!(row), + }; + + assert_eq!( + squeek_view_find_key( + &view as *const View, + state_clone.clone(), + ), + ButtonPlace { + row: row_ptr, + button: button_ptr, + } + ); + + let view = View { + bounds: Bounds { + x: 0f64, y: 0f64, + width: 0f64, height: 0f64 + }, + rows: Vec::new(), + }; + assert_eq!( + squeek_view_find_key( + &view as *const View, + state_clone.clone() + ), + ButtonPlace { + row: ptr::null(), + button: ptr::null(), + } + ); + } } } @@ -538,3 +613,26 @@ pub struct View { bounds: c::Bounds, rows: Vec>, } + +mod procedures { + use super::*; + + type Path<'v> = (&'v Box, &'v Box