Merge branch 'drop_key' into 'master'
Simplify renderer See merge request Librem5/squeekboard!272
This commit is contained in:
@ -405,7 +405,7 @@ impl Layout {
|
||||
let views = HashMap::from_iter(
|
||||
self.views.iter().map(|(name, view)| {(
|
||||
name.clone(),
|
||||
Box::new(::layout::View {
|
||||
::layout::View {
|
||||
bounds: ::layout::c::Bounds {
|
||||
x: self.bounds.x,
|
||||
y: self.bounds.y,
|
||||
@ -413,7 +413,7 @@ impl Layout {
|
||||
height: self.bounds.height,
|
||||
},
|
||||
rows: view.iter().map(|row| {
|
||||
Box::new(::layout::Row {
|
||||
::layout::Row {
|
||||
angle: 0,
|
||||
bounds: None,
|
||||
buttons: row.split_ascii_whitespace().map(|name| {
|
||||
@ -427,9 +427,9 @@ impl Layout {
|
||||
&mut warning_handler,
|
||||
))
|
||||
}).collect(),
|
||||
})
|
||||
}
|
||||
}).collect(),
|
||||
})
|
||||
}
|
||||
)})
|
||||
);
|
||||
|
||||
|
||||
126
src/drawing.rs
Normal file
126
src/drawing.rs
Normal file
@ -0,0 +1,126 @@
|
||||
/*! Drawing the UI */
|
||||
|
||||
use cairo;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use ::keyboard;
|
||||
use ::layout::{ Button, Layout };
|
||||
use ::layout::c::{ EekGtkKeyboard, Point };
|
||||
|
||||
use glib::translate::FromGlibPtrNone;
|
||||
use gtk::WidgetExt;
|
||||
|
||||
mod c {
|
||||
use super::*;
|
||||
|
||||
use cairo_sys;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
// This is constructed only in C, no need for warnings
|
||||
#[allow(dead_code)]
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct EekRenderer(*const c_void);
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" {
|
||||
// Button and View inside CButtonPlace are safe to pass to C
|
||||
// as long as they don't outlive the call
|
||||
// and nothing dereferences them
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn eek_render_button(
|
||||
renderer: EekRenderer,
|
||||
cr: *mut cairo_sys::cairo_t,
|
||||
button: *const Button,
|
||||
pressed: u64,
|
||||
locked: u64,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_draw_all_changed(
|
||||
layout: *mut Layout,
|
||||
renderer: EekRenderer,
|
||||
cr: *mut cairo_sys::cairo_t,
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||
|
||||
let view = layout.get_current_view();
|
||||
let view_position = view.bounds.get_position();
|
||||
for row in &view.rows {
|
||||
for button in &row.buttons {
|
||||
let state = RefCell::borrow(&button.state).clone();
|
||||
if state.pressed == keyboard::PressType::Pressed || state.locked {
|
||||
let position = &view_position
|
||||
+ row.bounds.clone().unwrap().get_position()
|
||||
+ button.bounds.get_position();
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
position, button.as_ref(),
|
||||
state.pressed, state.locked,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_draw_layout_base_view(
|
||||
layout: *mut Layout,
|
||||
renderer: EekRenderer,
|
||||
cr: *mut cairo_sys::cairo_t,
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let cr = unsafe { cairo::Context::from_raw_none(cr) };
|
||||
let view = layout.get_current_view();
|
||||
let view_position = view.bounds.get_position();
|
||||
for row in &view.rows {
|
||||
for button in &row.buttons {
|
||||
let position = &view_position
|
||||
+ row.bounds.clone().unwrap().get_position()
|
||||
+ button.bounds.get_position();
|
||||
render_button_at_position(
|
||||
renderer, &cr,
|
||||
position, button.as_ref(),
|
||||
keyboard::PressType::Released, false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders a button at a position (button's own bounds ignored)
|
||||
pub fn render_button_at_position(
|
||||
renderer: c::EekRenderer,
|
||||
cr: &cairo::Context,
|
||||
position: Point,
|
||||
button: &Button,
|
||||
pressed: keyboard::PressType,
|
||||
locked: bool,
|
||||
) {
|
||||
cr.save();
|
||||
cr.translate(position.x, position.y);
|
||||
cr.rectangle(
|
||||
0.0, 0.0,
|
||||
button.bounds.width, button.bounds.height
|
||||
);
|
||||
cr.clip();
|
||||
unsafe {
|
||||
c::eek_render_button(
|
||||
renderer,
|
||||
cairo::Context::to_raw_none(&cr),
|
||||
button as *const Button,
|
||||
pressed as u64,
|
||||
locked as u64,
|
||||
)
|
||||
};
|
||||
cr.restore();
|
||||
}
|
||||
|
||||
pub fn queue_redraw(keyboard: EekGtkKeyboard) {
|
||||
let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) };
|
||||
widget.queue_draw();
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
#ifndef __KEYBOARD_H
|
||||
#define __KEYBOARD_H
|
||||
|
||||
#include "inttypes.h"
|
||||
#include "stdbool.h"
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
|
||||
struct squeek_key;
|
||||
|
||||
uint32_t squeek_key_is_pressed(struct squeek_key *key);
|
||||
uint32_t squeek_key_is_locked(struct squeek_key *key);
|
||||
#endif
|
||||
@ -10,32 +10,8 @@ use ::action::Action;
|
||||
|
||||
use std::io::Write;
|
||||
use std::iter::{ FromIterator, IntoIterator };
|
||||
use ::util::CloneOwned;
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
use super::*;
|
||||
use ::util::c;
|
||||
|
||||
pub type CKeyState = c::Wrapped<KeyState>;
|
||||
|
||||
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_is_pressed(key: CKeyState) -> u32 {
|
||||
//let key = unsafe { Rc::from_raw(key.0) };
|
||||
return key.clone_owned().pressed as u32;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_is_locked(key: CKeyState) -> u32 {
|
||||
return key.clone_owned().locked as u32;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum PressType {
|
||||
Released = 0,
|
||||
Pressed = 1,
|
||||
|
||||
37
src/layout.h
37
src/layout.h
@ -5,8 +5,8 @@
|
||||
#include <glib.h>
|
||||
#include "eek/eek-element.h"
|
||||
#include "eek/eek-gtk-keyboard.h"
|
||||
#include "eek/eek-renderer.h"
|
||||
#include "eek/eek-types.h"
|
||||
#include "src/keyboard.h"
|
||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
|
||||
|
||||
enum squeek_arrangement_kind {
|
||||
@ -14,48 +14,22 @@ enum squeek_arrangement_kind {
|
||||
ARRANGEMENT_KIND_WIDE = 1,
|
||||
};
|
||||
|
||||
struct squeek_button;
|
||||
struct squeek_row;
|
||||
struct squeek_view;
|
||||
struct squeek_layout;
|
||||
|
||||
/// Represents the path to the button within a view
|
||||
struct button_place {
|
||||
const struct squeek_row *row;
|
||||
const struct squeek_button *button;
|
||||
};
|
||||
|
||||
int32_t squeek_row_get_angle(const struct squeek_row*);
|
||||
|
||||
EekBounds squeek_row_get_bounds(const struct squeek_row*);
|
||||
|
||||
typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data);
|
||||
void squeek_row_foreach(struct squeek_row*,
|
||||
ButtonCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
EekBounds squeek_button_get_bounds(const struct squeek_button*);
|
||||
const char *squeek_button_get_label(const struct squeek_button*);
|
||||
const char *squeek_button_get_icon_name(const struct squeek_button*);
|
||||
const char *squeek_button_get_name(const struct squeek_button*);
|
||||
const char *squeek_button_get_outline_name(const struct squeek_button*);
|
||||
|
||||
struct squeek_key *squeek_button_get_key(const struct squeek_button*);
|
||||
uint32_t *squeek_button_has_key(const struct squeek_button* button,
|
||||
const struct squeek_key *key);
|
||||
void squeek_button_print(const struct squeek_button* button);
|
||||
|
||||
|
||||
EekBounds squeek_view_get_bounds(const struct squeek_view*);
|
||||
|
||||
typedef void (*RowCallback) (struct squeek_row *row, gpointer user_data);
|
||||
void squeek_view_foreach(struct squeek_view*,
|
||||
RowCallback callback,
|
||||
gpointer user_data);
|
||||
struct transformation squeek_layout_calculate_transformation(
|
||||
const struct squeek_layout *layout,
|
||||
double allocation_width, double allocation_size);
|
||||
|
||||
void
|
||||
squeek_layout_place_contents(struct squeek_layout*);
|
||||
struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*);
|
||||
|
||||
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
|
||||
const char *squeek_layout_get_keymap(const struct squeek_layout*);
|
||||
@ -75,5 +49,6 @@ void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboar
|
||||
double x_widget, double y_widget,
|
||||
struct transformation widget_to_layout,
|
||||
uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekGtkKeyboard *ui_keyboard);
|
||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
|
||||
void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);
|
||||
#endif
|
||||
|
||||
364
src/layout.rs
364
src/layout.rs
@ -24,6 +24,7 @@ use std::rc::Rc;
|
||||
use std::vec::Vec;
|
||||
|
||||
use ::action::Action;
|
||||
use ::drawing;
|
||||
use ::float_ord::FloatOrd;
|
||||
use ::keyboard::{ KeyState, PressType };
|
||||
use ::submission::{ Timestamp, VirtualKeyboard };
|
||||
@ -34,16 +35,14 @@ use std::borrow::Borrow;
|
||||
pub mod c {
|
||||
use super::*;
|
||||
|
||||
use gtk_sys;
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::{ c_char, c_void };
|
||||
use std::ptr;
|
||||
use gtk_sys;
|
||||
|
||||
use std::ops::Add;
|
||||
|
||||
// The following defined in C
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct UserData(*const c_void);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget);
|
||||
@ -55,10 +54,27 @@ pub mod c {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
impl Add for Point {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
&self + other
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Point> for &Point {
|
||||
type Output = Point;
|
||||
fn add(self, other: Point) -> Point {
|
||||
Point {
|
||||
x: self.x + other.x,
|
||||
y: self.y + other.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Defined in eek-types.h
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Bounds {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
@ -66,62 +82,53 @@ pub mod c {
|
||||
pub height: f64
|
||||
}
|
||||
|
||||
type ButtonCallback = unsafe extern "C" fn(button: *mut ::layout::Button, data: *mut UserData);
|
||||
type RowCallback = unsafe extern "C" fn(row: *mut ::layout::Row, data: *mut UserData);
|
||||
impl Bounds {
|
||||
pub fn get_position(&self) -> Point {
|
||||
Point {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Scale + translate
|
||||
#[repr(C)]
|
||||
pub struct Transformation {
|
||||
pub origin_x: f64,
|
||||
pub origin_y: f64,
|
||||
pub scale: f64,
|
||||
}
|
||||
|
||||
impl Transformation {
|
||||
fn forward(&self, p: Point) -> Point {
|
||||
Point {
|
||||
x: (p.x - self.origin_x) / self.scale,
|
||||
y: (p.y - self.origin_y) / self.scale,
|
||||
}
|
||||
}
|
||||
fn reverse(&self, p: Point) -> Point {
|
||||
Point {
|
||||
x: p.x * self.scale + self.origin_x,
|
||||
y: p.y * self.scale + self.origin_y,
|
||||
}
|
||||
}
|
||||
pub fn reverse_bounds(&self, b: Bounds) -> Bounds {
|
||||
let start = self.reverse(Point { x: b.x, y: b.y });
|
||||
let end = self.reverse(Point {
|
||||
x: b.x + b.width,
|
||||
y: b.y + b.height,
|
||||
});
|
||||
Bounds {
|
||||
x: start.x,
|
||||
y: start.y,
|
||||
width: end.x - start.x,
|
||||
height: end.y - start.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_view_get_bounds(view: *const ::layout::View) -> Bounds {
|
||||
unsafe { &*view }.bounds.clone()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_view_foreach(
|
||||
view: *mut ::layout::View,
|
||||
callback: RowCallback,
|
||||
data: *mut UserData,
|
||||
) {
|
||||
let view = unsafe { &mut *view };
|
||||
for row in view.rows.iter_mut() {
|
||||
let row = row.as_mut() as *mut ::layout::Row;
|
||||
unsafe { callback(row, data) };
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_row_get_angle(row: *const ::layout::Row) -> i32 {
|
||||
let row = unsafe { &*row };
|
||||
row.angle
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_row_get_bounds(row: *const ::layout::Row) -> Bounds {
|
||||
let row = unsafe { &*row };
|
||||
match &row.bounds {
|
||||
Some(bounds) => bounds.clone(),
|
||||
None => panic!("Row doesn't have any bounds yet"),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_row_foreach(
|
||||
row: *mut ::layout::Row,
|
||||
callback: ButtonCallback,
|
||||
data: *mut UserData,
|
||||
) {
|
||||
let row = unsafe { &mut *row };
|
||||
for button in row.buttons.iter_mut() {
|
||||
let button = button.as_mut() as *mut ::layout::Button;
|
||||
unsafe { callback(button, data) };
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_bounds(button: *const ::layout::Button) -> Bounds {
|
||||
@ -129,16 +136,6 @@ pub mod c {
|
||||
button.bounds.clone()
|
||||
}
|
||||
|
||||
/// Borrow a new reference to key state. Doesn't need freeing
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_key(
|
||||
button: *const ::layout::Button
|
||||
) -> ::keyboard::c::CKeyState {
|
||||
let button = unsafe { &*button };
|
||||
::keyboard::c::CKeyState::wrap(button.state.clone())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_label(
|
||||
@ -187,16 +184,26 @@ pub mod c {
|
||||
println!("{:?}", button);
|
||||
}
|
||||
|
||||
/// Positions the layout within the available space
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_get_current_view(layout: *const Layout) -> *const View {
|
||||
fn squeek_layout_calculate_transformation(
|
||||
layout: *const Layout,
|
||||
allocation_width: f64,
|
||||
allocation_height: f64,
|
||||
) -> Transformation {
|
||||
let layout = unsafe { &*layout };
|
||||
let view_name = layout.current_view.clone();
|
||||
layout.views.get(&view_name)
|
||||
.expect("Current view doesn't exist")
|
||||
.as_ref() as *const View
|
||||
let bounds = &layout.get_current_view().bounds;
|
||||
let h_scale = allocation_width / bounds.width;
|
||||
let v_scale = allocation_height / bounds.height;
|
||||
let scale = if h_scale > v_scale { h_scale } else { v_scale };
|
||||
Transformation {
|
||||
origin_x: allocation_width - (scale * bounds.width) / 2.0,
|
||||
origin_y: allocation_height - (scale * bounds.height) / 2.0,
|
||||
scale: scale,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_get_keymap(layout: *const Layout) -> *const c_char {
|
||||
@ -222,7 +229,7 @@ pub mod c {
|
||||
use super::*;
|
||||
|
||||
use ::submission::c::ZwpVirtualKeyboardV1;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct CButtonPlace {
|
||||
@ -238,42 +245,6 @@ pub mod c {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Scale + translate
|
||||
#[repr(C)]
|
||||
pub struct Transformation {
|
||||
origin_x: f64,
|
||||
origin_y: f64,
|
||||
scale: f64,
|
||||
}
|
||||
|
||||
impl Transformation {
|
||||
fn forward(&self, p: Point) -> Point {
|
||||
Point {
|
||||
x: (p.x - self.origin_x) / self.scale,
|
||||
y: (p.y - self.origin_y) / self.scale,
|
||||
}
|
||||
}
|
||||
fn reverse(&self, p: Point) -> Point {
|
||||
Point {
|
||||
x: p.x * self.scale + self.origin_x,
|
||||
y: p.y * self.scale + self.origin_y,
|
||||
}
|
||||
}
|
||||
pub fn reverse_bounds(&self, b: Bounds) -> Bounds {
|
||||
let start = self.reverse(Point { x: b.x, y: b.y });
|
||||
let end = self.reverse(Point {
|
||||
x: b.x + b.width,
|
||||
y: b.y + b.height,
|
||||
});
|
||||
Bounds {
|
||||
x: start.x,
|
||||
y: start.y,
|
||||
width: end.x - start.x,
|
||||
height: end.y - start.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is constructed only in C, no need for warnings
|
||||
#[allow(dead_code)]
|
||||
@ -289,34 +260,6 @@ pub mod c {
|
||||
origin: Point,
|
||||
angle: i32
|
||||
) -> u32;
|
||||
|
||||
// Button and View are safe to pass to C
|
||||
// as long as they don't outlive the call
|
||||
// and nothing dereferences them
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn eek_gtk_on_button_released(
|
||||
button: *const Button,
|
||||
view: *const View,
|
||||
keyboard: EekGtkKeyboard,
|
||||
);
|
||||
|
||||
// Button and View inside CButtonPlace are safe to pass to C
|
||||
// as long as they don't outlive the call
|
||||
// and nothing dereferences them
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn eek_gtk_on_button_pressed(
|
||||
place: CButtonPlace,
|
||||
keyboard: EekGtkKeyboard,
|
||||
);
|
||||
|
||||
// Button and View inside CButtonPlace are safe to pass to C
|
||||
// as long as they don't outlive the call
|
||||
// and nothing dereferences them
|
||||
#[allow(improper_ctypes)]
|
||||
pub fn eek_gtk_render_locked_button(
|
||||
keyboard: EekGtkKeyboard,
|
||||
place: CButtonPlace,
|
||||
);
|
||||
}
|
||||
|
||||
/// Places each button in order, starting from 0 on the left,
|
||||
@ -356,15 +299,16 @@ pub mod c {
|
||||
// because it will be mutated in the loop
|
||||
for key in layout.pressed_keys.clone() {
|
||||
let key: &Rc<RefCell<KeyState>> = key.borrow();
|
||||
ui::release_key(
|
||||
seat::handle_release_key(
|
||||
layout,
|
||||
&virtual_keyboard,
|
||||
&widget_to_layout,
|
||||
time,
|
||||
ui_keyboard,
|
||||
key
|
||||
key,
|
||||
);
|
||||
}
|
||||
drawing::queue_redraw(ui_keyboard);
|
||||
}
|
||||
|
||||
/// Release all buittons but don't redraw
|
||||
@ -403,27 +347,16 @@ pub mod c {
|
||||
let point = widget_to_layout.forward(
|
||||
Point { x: x_widget, y: y_widget }
|
||||
);
|
||||
|
||||
// the immutable reference to `layout` through `view`
|
||||
// must be dropped
|
||||
// before `layout.press_key` borrows it mutably again
|
||||
let state_place = {
|
||||
let view = layout.get_current_view();
|
||||
let place = view.find_button_by_position(point);
|
||||
place.map(|place| {(
|
||||
place.button.state.clone(),
|
||||
place.into(),
|
||||
)})
|
||||
};
|
||||
|
||||
if let Some((mut state, c_place)) = state_place {
|
||||
|
||||
if let Some(position) = layout.get_button_at_point(point) {
|
||||
let mut state = position.button.state.clone();
|
||||
layout.press_key(
|
||||
&VirtualKeyboard(virtual_keyboard),
|
||||
&mut state,
|
||||
Timestamp(time),
|
||||
);
|
||||
|
||||
unsafe { eek_gtk_on_button_pressed(c_place, ui_keyboard) };
|
||||
// maybe TODO: draw on the display buffer here
|
||||
drawing::queue_redraw(ui_keyboard);
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,23 +382,26 @@ pub mod c {
|
||||
);
|
||||
|
||||
let pressed = layout.pressed_keys.clone();
|
||||
let state_place = {
|
||||
let button_info = {
|
||||
let view = layout.get_current_view();
|
||||
let place = view.find_button_by_position(point);
|
||||
place.map(|place| {(
|
||||
place.button.state.clone(),
|
||||
place.into(),
|
||||
place.button.clone(),
|
||||
view.bounds.get_position()
|
||||
+ place.row.bounds.clone().unwrap().get_position()
|
||||
+ place.button.bounds.get_position(),
|
||||
)})
|
||||
};
|
||||
|
||||
if let Some((mut state, c_place)) = state_place {
|
||||
if let Some((mut state, _button, _view_position)) = button_info {
|
||||
let mut found = false;
|
||||
for wrapped_key in pressed {
|
||||
let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
|
||||
if Rc::ptr_eq(&state, &wrapped_key.0) {
|
||||
found = true;
|
||||
} else {
|
||||
ui::release_key(
|
||||
seat::handle_release_key(
|
||||
layout,
|
||||
&virtual_keyboard,
|
||||
&widget_to_layout,
|
||||
@ -477,12 +413,12 @@ pub mod c {
|
||||
}
|
||||
if !found {
|
||||
layout.press_key(&virtual_keyboard, &mut state, time);
|
||||
unsafe { eek_gtk_on_button_pressed(c_place, ui_keyboard) };
|
||||
// maybe TODO: draw on the display buffer here
|
||||
}
|
||||
} else {
|
||||
for wrapped_key in pressed {
|
||||
let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
|
||||
ui::release_key(
|
||||
seat::handle_release_key(
|
||||
layout,
|
||||
&virtual_keyboard,
|
||||
&widget_to_layout,
|
||||
@ -492,33 +428,7 @@ pub mod c {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_draw_all_changed(
|
||||
layout: *mut Layout,
|
||||
ui_keyboard: EekGtkKeyboard,
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
|
||||
for row in &layout.get_current_view().rows {
|
||||
for button in &row.buttons {
|
||||
let c_place = CButtonPlace::from(
|
||||
ButtonPlace { row, button }
|
||||
);
|
||||
let state = RefCell::borrow(&button.state);
|
||||
match (state.pressed, state.locked) {
|
||||
(PressType::Released, false) => {}
|
||||
(PressType::Pressed, _) => unsafe {
|
||||
eek_gtk_on_button_pressed(c_place, ui_keyboard)
|
||||
},
|
||||
(_, true) => unsafe {
|
||||
eek_gtk_render_locked_button(ui_keyboard, c_place)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
drawing::queue_redraw(ui_keyboard);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -545,6 +455,12 @@ pub mod c {
|
||||
}
|
||||
}
|
||||
|
||||
/// Relative to `View`
|
||||
struct ButtonPosition {
|
||||
view_position: c::Point,
|
||||
button: Button,
|
||||
}
|
||||
|
||||
pub struct ButtonPlace<'a> {
|
||||
button: &'a Button,
|
||||
row: &'a Row,
|
||||
@ -654,7 +570,7 @@ pub struct Spacing {
|
||||
pub struct View {
|
||||
/// Position relative to keyboard origin
|
||||
pub bounds: c::Bounds,
|
||||
pub rows: Vec<Box<Row>>,
|
||||
pub rows: Vec<Row>,
|
||||
}
|
||||
|
||||
impl View {
|
||||
@ -749,7 +665,7 @@ pub struct Layout {
|
||||
// Views own the actual buttons which have state
|
||||
// Maybe they should own UI only,
|
||||
// and keys should be owned by a dedicated non-UI-State?
|
||||
pub views: HashMap<String, Box<View>>,
|
||||
pub views: HashMap<String, View>,
|
||||
|
||||
// Non-UI stuff
|
||||
/// xkb keymap applicable to the contained keys. Unchangeable
|
||||
@ -768,7 +684,7 @@ pub struct Layout {
|
||||
|
||||
/// A builder structure for picking up layout data from storage
|
||||
pub struct LayoutData {
|
||||
pub views: HashMap<String, Box<View>>,
|
||||
pub views: HashMap<String, View>,
|
||||
pub keymap_str: CString,
|
||||
}
|
||||
|
||||
@ -789,7 +705,8 @@ impl Layout {
|
||||
locked_keys: HashSet::new(),
|
||||
}
|
||||
}
|
||||
fn get_current_view(&self) -> &Box<View> {
|
||||
|
||||
pub fn get_current_view(&self) -> &View {
|
||||
self.views.get(&self.current_view).expect("Selected nonexistent view")
|
||||
}
|
||||
|
||||
@ -881,12 +798,24 @@ impl Layout {
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
fn get_button_at_point(&self, point: c::Point) -> Option<ButtonPosition> {
|
||||
let view = self.get_current_view();
|
||||
let place = view.find_button_by_position(point);
|
||||
place.map(|place| ButtonPosition {
|
||||
button: place.button.clone(),
|
||||
// Rows have no business being inside a view
|
||||
// if they have no valid bounds.
|
||||
view_position: place.row.bounds.clone().unwrap().get_position()
|
||||
+ place.button.bounds.get_position(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mod procedures {
|
||||
use super::*;
|
||||
|
||||
type Path<'v> = (&'v Box<Row>, &'v Box<Button>);
|
||||
type Path<'v> = (&'v Row, &'v Box<Button>);
|
||||
|
||||
/// Finds all `(row, button)` paths that refer to the specified key `state`
|
||||
pub fn find_key_paths<'v, 's>(
|
||||
@ -917,24 +846,6 @@ mod procedures {
|
||||
c::procedures::eek_are_bounds_inside(bounds, point, origin, angle)
|
||||
}) == 1
|
||||
}
|
||||
|
||||
/// Switch off all UI buttons associated with the (state) key
|
||||
pub fn release_ui_buttons(
|
||||
view: &Box<View>,
|
||||
key: &Rc<RefCell<KeyState>>,
|
||||
ui_keyboard: c::EekGtkKeyboard,
|
||||
) {
|
||||
let paths = ::layout::procedures::find_key_paths(&view, key);
|
||||
for (_row, button) in paths {
|
||||
unsafe {
|
||||
c::procedures::eek_gtk_on_button_released(
|
||||
button.as_ref() as *const Button,
|
||||
view.as_ref() as *const View,
|
||||
ui_keyboard,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
@ -957,12 +868,15 @@ mod procedures {
|
||||
let button = make_button_with_state("1".into(), state);
|
||||
let button_ptr = as_ptr(&button);
|
||||
|
||||
let row = Box::new(Row {
|
||||
let row_bounds = Some(c::Bounds {
|
||||
x: 0.1, y: 2.3,
|
||||
width: 4.5, height: 6.7,
|
||||
});
|
||||
let row = Row {
|
||||
buttons: vec!(button),
|
||||
angle: 0,
|
||||
bounds: None
|
||||
});
|
||||
let row_ptr = as_ptr(&row);
|
||||
bounds: row_bounds.clone(),
|
||||
};
|
||||
|
||||
let view = View {
|
||||
bounds: c::Bounds {
|
||||
@ -974,10 +888,10 @@ mod procedures {
|
||||
|
||||
assert_eq!(
|
||||
find_key_paths(&view, &state_clone.clone()).iter()
|
||||
.map(|(row, button)| { (as_ptr(row), as_ptr(button)) })
|
||||
.map(|(row, button)| { (row.bounds.clone(), as_ptr(button)) })
|
||||
.collect::<Vec<_>>(),
|
||||
vec!(
|
||||
(row_ptr, button_ptr)
|
||||
(row_bounds, button_ptr)
|
||||
)
|
||||
);
|
||||
|
||||
@ -1012,15 +926,15 @@ mod procedures {
|
||||
}
|
||||
}
|
||||
|
||||
/// Top level UI procedures
|
||||
mod ui {
|
||||
/// Top level procedures, dispatching to everything
|
||||
mod seat {
|
||||
use super::*;
|
||||
|
||||
// TODO: turn into release_button
|
||||
pub fn release_key(
|
||||
pub fn handle_release_key(
|
||||
layout: &mut Layout,
|
||||
virtual_keyboard: &VirtualKeyboard,
|
||||
widget_to_layout: &c::procedures::Transformation,
|
||||
widget_to_layout: &c::Transformation,
|
||||
time: Timestamp,
|
||||
ui_keyboard: c::EekGtkKeyboard,
|
||||
key: &Rc<RefCell<KeyState>>,
|
||||
@ -1049,8 +963,6 @@ mod ui {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
procedures::release_ui_buttons(view, key, ui_keyboard);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate cairo;
|
||||
extern crate cairo_sys;
|
||||
extern crate gdk;
|
||||
extern crate gio;
|
||||
extern crate glib;
|
||||
extern crate glib_sys;
|
||||
@ -14,6 +17,7 @@ extern crate xkbcommon;
|
||||
|
||||
mod action;
|
||||
pub mod data;
|
||||
mod drawing;
|
||||
pub mod float_ord;
|
||||
pub mod imservice;
|
||||
mod keyboard;
|
||||
|
||||
Reference in New Issue
Block a user