eekkey: Dropped in favor of Button
Each Button has a KeyState, which may be shared with other buttons. The list of pressed and locked buttons is used as a list of keys, causing a search for the button in the current view.
This commit is contained in:
@ -28,9 +28,20 @@ pub mod c {
|
||||
/// Since C doesn't respect borrowing rules,
|
||||
/// RefCell will enforce them dynamically (only 1 writer/many readers)
|
||||
/// Rc is implied and will ensure timely dropping
|
||||
#[repr(transparent)]
|
||||
pub struct CKeyState(*const RefCell<KeyState>);
|
||||
|
||||
impl Clone for CKeyState {
|
||||
fn clone(&self) -> Self {
|
||||
CKeyState(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl CKeyState {
|
||||
fn unwrap(self) -> Rc<RefCell<KeyState>> {
|
||||
pub fn wrap(state: Rc<RefCell<KeyState>>) -> CKeyState {
|
||||
CKeyState(Rc::into_raw(state))
|
||||
}
|
||||
pub fn unwrap(self) -> Rc<RefCell<KeyState>> {
|
||||
unsafe { Rc::from_raw(self.0) }
|
||||
}
|
||||
fn to_owned(self) -> KeyState {
|
||||
@ -67,7 +78,7 @@ pub mod c {
|
||||
symbol: None,
|
||||
}
|
||||
));
|
||||
CKeyState(Rc::into_raw(state))
|
||||
CKeyState::wrap(state)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -195,8 +206,8 @@ pub mod c {
|
||||
fn squeek_key_get_symbol(key: CKeyState) -> *const symbol::Symbol {
|
||||
key.borrow_mut(|key| {
|
||||
match key.symbol {
|
||||
/// This pointer stays after the function exits,
|
||||
/// so it must reference borrowed data and not any copy
|
||||
// This pointer stays after the function exits,
|
||||
// so it must reference borrowed data and not any copy
|
||||
Some(ref symbol) => symbol as *const symbol::Symbol,
|
||||
None => ptr::null(),
|
||||
}
|
||||
@ -239,13 +250,51 @@ pub mod c {
|
||||
.expect("Couldn't convert string")
|
||||
.into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_key_get_action_name(
|
||||
key_name: *const c_char,
|
||||
key: CKeyState,
|
||||
) -> *const c_char {
|
||||
let key_name = as_cstr(&key_name)
|
||||
.expect("Missing key name")
|
||||
.to_str()
|
||||
.expect("Bad key name");
|
||||
|
||||
let symbol_name = match key.to_owned().symbol {
|
||||
Some(ref symbol) => match &symbol.action {
|
||||
symbol::Action::Submit { text: Some(text), .. } => {
|
||||
Some(
|
||||
text.clone()
|
||||
.into_string().expect("Bad symbol")
|
||||
)
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
None => {
|
||||
eprintln!("Key {} has no symbol", key_name);
|
||||
None
|
||||
},
|
||||
};
|
||||
|
||||
let inner = match symbol_name {
|
||||
Some(name) => format!("[ {} ]", name),
|
||||
_ => format!("[ ]"),
|
||||
};
|
||||
|
||||
CString::new(format!(" key <{}> {{ {} }};\n", key_name, inner))
|
||||
.expect("Couldn't convert string")
|
||||
.into_raw()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyState {
|
||||
pressed: bool,
|
||||
locked: bool,
|
||||
keycode: u32,
|
||||
pub pressed: bool,
|
||||
pub locked: bool,
|
||||
pub keycode: u32,
|
||||
// TODO: remove the optionality of a symbol
|
||||
symbol: Option<symbol::Symbol>,
|
||||
pub symbol: Option<symbol::Symbol>,
|
||||
}
|
||||
|
||||
40
src/layout.h
Normal file
40
src/layout.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __LAYOUT_H
|
||||
#define __LAYOUT_H
|
||||
|
||||
#include "inttypes.h"
|
||||
|
||||
#include "eek/eek-container.h"
|
||||
#include "src/keyboard.h"
|
||||
|
||||
struct squeek_button;
|
||||
|
||||
/*
|
||||
struct squeek_buttons;
|
||||
|
||||
typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data);
|
||||
|
||||
struct squeek_buttons *squeek_buttons_new();
|
||||
void squeek_buttons_free(struct squeek_buttons*);
|
||||
void squeek_buttons_foreach(const struct squeek_buttons*,
|
||||
ButtonCallback callback,
|
||||
gpointer user_data);
|
||||
struct squeek_button *squeek_buttons_find_by_position(
|
||||
const struct squeek_buttons *buttons,
|
||||
double x, double y,
|
||||
double origin_x, double origin_y,
|
||||
double angle);
|
||||
void squeek_buttons_add(struct squeek_buttons*, const struct squeek_button* button);
|
||||
void squeek_buttons_remove_key(struct squeek_buttons*, const struct squeek_key* key);
|
||||
*/
|
||||
struct squeek_button *squeek_button_new(uint32_t keycode, uint32_t oref);
|
||||
struct squeek_button *squeek_button_new_with_state(const struct squeek_button* source);
|
||||
uint32_t squeek_button_get_oref(const struct squeek_button*);
|
||||
EekBounds squeek_button_get_bounds(const struct squeek_button*);
|
||||
void squeek_button_set_bounds(struct squeek_button* button, EekBounds bounds);
|
||||
|
||||
struct squeek_symbol *squeek_button_get_symbol (
|
||||
const struct squeek_button *button);
|
||||
struct squeek_key *squeek_button_get_key(struct squeek_button*);
|
||||
uint32_t *squeek_button_has_key(const struct squeek_button* button,
|
||||
const struct squeek_key *key);
|
||||
#endif
|
||||
147
src/layout.rs
Normal file
147
src/layout.rs
Normal file
@ -0,0 +1,147 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use ::symbol::*;
|
||||
use ::keyboard::*;
|
||||
|
||||
/// Gathers stuff defined in C or called by C
|
||||
pub mod c {
|
||||
use super::*;
|
||||
|
||||
use std::ptr;
|
||||
|
||||
// The following defined in C
|
||||
|
||||
/// The index in the relevant outline table
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct OutlineRef(u32);
|
||||
|
||||
/// Defined in eek-types.h
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct Bounds {
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_new(keycode: u32, oref: u32) -> *mut ::layout::Button {
|
||||
let state: Rc<RefCell<::keyboard::KeyState>> = Rc::new(RefCell::new(
|
||||
::keyboard::KeyState {
|
||||
pressed: false,
|
||||
locked: false,
|
||||
keycode: keycode,
|
||||
symbol: None,
|
||||
}
|
||||
));
|
||||
Box::into_raw(Box::new(::layout::Button {
|
||||
oref: OutlineRef(oref),
|
||||
bounds: None,
|
||||
state: state,
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_new_with_state(source: *mut ::layout::Button) -> *mut ::layout::Button {
|
||||
let source = unsafe { &*source };
|
||||
let button = Box::new(source.clone());
|
||||
Box::into_raw(button)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_oref(button: *const ::layout::Button) -> u32 {
|
||||
let button = unsafe { &*button };
|
||||
button.oref.0
|
||||
}
|
||||
|
||||
// Bounds transparently mapped to C, therefore no pointer needed
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_bounds(button: *const ::layout::Button) -> Bounds {
|
||||
let button = unsafe { &*button };
|
||||
match &button.bounds {
|
||||
Some(bounds) => bounds.clone(),
|
||||
None => panic!("Button doesn't have any bounds yet"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set bounds by consuming the value
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_set_bounds(button: *mut ::layout::Button, bounds: Bounds) {
|
||||
let button = unsafe { &mut *button };
|
||||
button.bounds = Some(bounds);
|
||||
}
|
||||
|
||||
/// Borrow a new reference to key state. Doesn't need freeing
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_key(
|
||||
button: *mut ::layout::Button
|
||||
) -> ::keyboard::c::CKeyState {
|
||||
let button = unsafe { &mut *button };
|
||||
::keyboard::c::CKeyState::wrap(button.state.clone())
|
||||
}
|
||||
|
||||
/// Really should just return the label
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_get_symbol(
|
||||
button: *const ::layout::Button,
|
||||
) -> *const Symbol {
|
||||
let button = unsafe { &*button };
|
||||
let state = button.state.borrow();
|
||||
match state.symbol {
|
||||
Some(ref symbol) => symbol as *const Symbol,
|
||||
None => ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_button_has_key(
|
||||
button: *const ::layout::Button,
|
||||
state: ::keyboard::c::CKeyState,
|
||||
) -> u32 {
|
||||
let button = unsafe { &*button };
|
||||
let state = state.unwrap();
|
||||
let equal = Rc::ptr_eq(&button.state, &state);
|
||||
Rc::into_raw(state); // Prevent dropping
|
||||
equal as u32
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn button_has_key() {
|
||||
let button = squeek_button_new(0, 0);
|
||||
let state = squeek_button_get_key(button);
|
||||
assert_eq!(squeek_button_has_key(button, state.clone()), 1);
|
||||
let other_button = squeek_button_new(0, 0);
|
||||
assert_eq!(squeek_button_has_key(other_button, state.clone()), 0);
|
||||
let other_state = ::keyboard::c::squeek_key_new(0);
|
||||
assert_eq!(squeek_button_has_key(button, other_state), 0);
|
||||
let shared_button = squeek_button_new_with_state(button);
|
||||
assert_eq!(squeek_button_has_key(shared_button, state), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The graphical representation of a button
|
||||
#[derive(Clone)]
|
||||
pub struct Button {
|
||||
oref: c::OutlineRef,
|
||||
/// TODO: abolish Option, buttons should be created with bounds fully formed
|
||||
bounds: Option<c::Bounds>,
|
||||
/// current state, shared with other buttons
|
||||
pub state: Rc<RefCell<KeyState>>,
|
||||
}
|
||||
@ -3,5 +3,6 @@ mod bitflags;
|
||||
|
||||
mod imservice;
|
||||
mod keyboard;
|
||||
mod layout;
|
||||
mod symbol;
|
||||
mod util;
|
||||
|
||||
@ -19,7 +19,6 @@ sources = [
|
||||
'../eek/eek-container.c',
|
||||
'../eek/eek-element.c',
|
||||
'../eek/eek-gtk-keyboard.c',
|
||||
'../eek/eek-key.c',
|
||||
'../eek/eek-keyboard.c',
|
||||
'../eek/eek-keyboard-drawing.c',
|
||||
'../eek/eek-keysym.c',
|
||||
|
||||
Reference in New Issue
Block a user