diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index d42564b6..0dc3e1f5 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -117,7 +117,8 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, struct button_place place = squeek_view_find_key( view, squeek_button_get_key(head->data) ); - render_pressed_button (self, &place); + if (place.button) + render_pressed_button (self, &place); } /* redraw locked key */ @@ -128,7 +129,8 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, ((EekModifierKey *)head->data)->button ) ); - render_locked_button (self, &place); + if (place.button) + render_locked_button (self, &place); } return FALSE; diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 0e96056d..a8a46dca 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -913,14 +913,6 @@ eek_renderer_get_foreground_color (EekRenderer *renderer, color->alpha = gcolor.alpha; } -struct _FindKeyByPositionCallbackData { - EekPoint point; - EekPoint origin; - gint angle; - struct squeek_button *button; -}; -typedef struct _FindKeyByPositionCallbackData FindKeyByPositionCallbackData; - static gboolean sign (EekPoint *p1, EekPoint *p2, EekPoint *p3) { @@ -968,17 +960,6 @@ eek_are_bounds_inside (EekBounds bounds, EekPoint point, EekPoint origin, int32_ return 0; } -static void -find_button_by_position_row_callback (struct squeek_row *row, - gpointer user_data) -{ - FindKeyByPositionCallbackData *data = user_data; - if (data->button) { - return; - } - data->button = squeek_row_find_button_by_position(row, data->point, data->origin); -} - /** * eek_renderer_find_key_by_position: * @renderer: The renderer normally used to render the key @@ -994,30 +975,13 @@ eek_renderer_find_button_by_position (EekRenderer *renderer, gdouble x, gdouble y) { - FindKeyByPositionCallbackData data; - g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); - EekBounds bounds = squeek_view_get_bounds (view); - /* Transform from widget coordinates to keyboard coordinates */ - x = (x - priv->origin_x)/priv->scale - bounds.x; - y = (y - priv->origin_y)/priv->scale - bounds.y; - - if (x < 0 || - y < 0 || - x > bounds.width || - y > bounds.height) - return NULL; - - data.point.x = x; - data.point.y = y; - data.origin.x = 0; - data.origin.y = 0; - data.button = NULL; - - squeek_view_foreach (view, find_button_by_position_row_callback, - &data); - return data.button; + EekPoint point = { + .x = (x - priv->origin_x)/priv->scale, + .y = (y - priv->origin_y)/priv->scale, + }; + return squeek_view_find_button_by_position(view, point); } diff --git a/src/layout.h b/src/layout.h index 91a5a173..d0615154 100644 --- a/src/layout.h +++ b/src/layout.h @@ -25,7 +25,6 @@ uint32_t squeek_row_contains(struct squeek_row*, struct squeek_button *button); 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); typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data); void squeek_row_foreach(struct squeek_row*, @@ -74,4 +73,6 @@ struct squeek_row *squeek_view_get_row(struct squeek_view *view, void squeek_view_place_contents(struct squeek_view *view, LevelKeyboard *keyboard); + +struct squeek_button *squeek_view_find_button_by_position(struct squeek_view *view, EekPoint point); #endif diff --git a/src/layout.rs b/src/layout.rs index 58d635b7..b21d5d23 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,3 +1,22 @@ +/** + * Layout-related data. + * + * The `View` contains `Row`s and each `Row` contains `Button`s. + * They carry data relevant to their positioning only, + * except the Button, which also carries some data + * about its appearance and function. + * + * The layout is determined bottom-up, by measuring `Button` sizes, + * deriving `Row` sizes from them, and then centering them within the `View`. + * + * That makes the `View` position immutable, + * and therefore different than the other positions. + * + * Note that it might be a better idea + * to make `View` position depend on its contents, + * and let the renderer scale and center it within the widget. + */ + use std::cell::RefCell; use std::rc::Rc; use std::vec::Vec; @@ -310,7 +329,7 @@ pub mod c { } /// Entry points for more complex procedures and algoithms which span multiple modules - mod procedures { + pub mod procedures { use super::*; #[repr(transparent)] @@ -332,7 +351,7 @@ pub mod c { /// Checks if point falls within bounds, /// which are relative to origin and rotated by angle (I think) - fn eek_are_bounds_inside (bounds: Bounds, + pub fn eek_are_bounds_inside (bounds: Bounds, point: Point, origin: Point, angle: i32 @@ -369,36 +388,6 @@ pub mod c { view.place_buttons_with_sizes(sizes); } - #[no_mangle] - pub extern "C" - fn squeek_row_find_button_by_position( - row: *mut Row, point: Point, origin: Point - ) -> *mut Button { - let row = unsafe { &mut *row }; - let row_bounds = row.bounds - .as_ref().expect("Missing bounds on row"); - let origin = Point { - x: origin.x + row_bounds.x, - y: origin.y + row_bounds.y, - }; - let angle = row.angle; - let result = row.buttons.iter_mut().find(|button| { - let bounds = button.bounds - .as_ref().expect("Missing bounds on button") - .clone(); - let point = point.clone(); - let origin = origin.clone(); - unsafe { - eek_are_bounds_inside(bounds, point, origin, angle) == 1 - } - }); - - match result { - Some(button) => button.as_mut() as *mut Button, - None => ptr::null_mut(), - } - } - fn squeek_row_contains(row: &Row, needle: *const Button) -> bool { row.buttons.iter().position( // TODO: wrap Button properly in Rc; this comparison is unreliable @@ -446,6 +435,20 @@ pub mod c { }; ButtonPlace { row, button } } + + + #[no_mangle] + pub extern "C" + fn squeek_view_find_button_by_position( + view: *mut View, point: Point + ) -> *mut Button { + let view = unsafe { &mut *view }; + let result = view.find_button_by_position(point); + match result { + Some(button) => button.as_mut() as *mut Button, + None => ptr::null_mut(), + } + } #[cfg(test)] mod test { @@ -559,12 +562,13 @@ pub struct Size { pub struct Button { oref: c::OutlineRef, /// TODO: abolish Option, buttons should be created with bounds fully formed + /// Position relative to some origin (i.e. parent/row) bounds: Option, /// current state, shared with other buttons pub state: Rc>, } - +// FIXME: derive from the style/margin/padding const BUTTON_SPACING: f64 = 4.0; const ROW_SPACING: f64 = 7.0; @@ -573,6 +577,7 @@ pub struct Row { buttons: Vec>, /// Angle is not really used anywhere... angle: i32, + /// Position relative to some origin (i.e. parent/view origin) bounds: Option, } @@ -621,6 +626,27 @@ impl Row { }; Size { width: total_width, height: max_height } } + + /// Finds the first button that covers the specified point + /// relative to row's position's origin + fn find_button_by_position(&mut self, point: c::Point) + -> Option<&mut Box