views: Change based on layout file
This commit is contained in:
68
src/data.rs
68
src/data.rs
@ -205,7 +205,8 @@ struct ButtonMeta {
|
||||
#[derive(Debug, Deserialize, PartialEq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
enum Action {
|
||||
/// FIXME: start using it
|
||||
#[serde(rename="locking")]
|
||||
Locking { lock_view: String, unlock_view: String },
|
||||
#[serde(rename="set_view")]
|
||||
SetView(String),
|
||||
#[serde(rename="show_prefs")]
|
||||
@ -274,14 +275,11 @@ impl Layout {
|
||||
pressed: false,
|
||||
locked: false,
|
||||
keycode: keycodes.get(*name).map(|k| *k),
|
||||
symbol: ::symbol::Symbol {
|
||||
// FIXME: allow user to switch views
|
||||
action: ::symbol::Action::Submit {
|
||||
text: None,
|
||||
// TODO: derive keysym name & value from button name
|
||||
keys: vec!(),
|
||||
},
|
||||
},
|
||||
symbol: create_symbol(
|
||||
&self.buttons,
|
||||
name,
|
||||
self.views.keys().collect()
|
||||
),
|
||||
}))
|
||||
)});
|
||||
|
||||
@ -334,6 +332,58 @@ impl Layout {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_symbol(
|
||||
button_info: &HashMap<String, ButtonMeta>,
|
||||
name: &str,
|
||||
view_names: Vec<&String>,
|
||||
) -> ::symbol::Symbol {
|
||||
let default_meta = ButtonMeta::default();
|
||||
let symbol_meta = button_info.get(name)
|
||||
.unwrap_or(&default_meta);
|
||||
|
||||
fn filter_view_name(
|
||||
button_name: &str,
|
||||
view_name: String,
|
||||
view_names: &Vec<&String>
|
||||
) -> String {
|
||||
if view_names.contains(&&view_name) {
|
||||
view_name
|
||||
} else {
|
||||
eprintln!(
|
||||
"Button {} switches to missing view {}",
|
||||
button_name,
|
||||
view_name
|
||||
);
|
||||
"base".into()
|
||||
}
|
||||
}
|
||||
|
||||
match &symbol_meta.action {
|
||||
Some(Action::SetView(view_name)) => ::symbol::Symbol {
|
||||
action: ::symbol::Action::SetLevel(
|
||||
filter_view_name(name, view_name.clone(), &view_names)
|
||||
),
|
||||
},
|
||||
Some(Action::Locking { lock_view, unlock_view }) => ::symbol::Symbol {
|
||||
action: ::symbol::Action::LockLevel {
|
||||
lock: filter_view_name(name, lock_view.clone(), &view_names),
|
||||
unlock: filter_view_name(
|
||||
name,
|
||||
unlock_view.clone(),
|
||||
&view_names
|
||||
),
|
||||
},
|
||||
},
|
||||
_ => ::symbol::Symbol {
|
||||
action: ::symbol::Action::Submit {
|
||||
text: None,
|
||||
// TODO: derive keysym name & value from button name
|
||||
keys: vec!(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Since this will receive user-provided data,
|
||||
/// all .expect() on them should be turned into soft fails
|
||||
fn create_button(
|
||||
|
||||
@ -55,8 +55,8 @@ struct squeek_button *squeek_view_find_button_by_position(struct squeek_view *vi
|
||||
void
|
||||
squeek_layout_place_contents(struct squeek_layout*);
|
||||
struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*);
|
||||
uint32_t squeek_layout_get_level(struct squeek_layout*);
|
||||
void squeek_layout_set_level(struct squeek_layout* layout, uint32_t level);
|
||||
void squeek_layout_set_state_from_press(struct squeek_layout* layout, LevelKeyboard *keyboard, struct squeek_button* button);
|
||||
|
||||
|
||||
struct squeek_layout *squeek_load_layout(const char *type);
|
||||
const char *squeek_layout_get_keymap(const struct squeek_layout*);
|
||||
|
||||
@ -224,33 +224,6 @@ pub mod c {
|
||||
.as_ref() as *const View
|
||||
}
|
||||
|
||||
/// FIXME: very temporary way to minimize level impact
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_get_level(layout: *const Layout) -> u32 {
|
||||
let layout = unsafe { &*layout };
|
||||
match layout.current_view.as_str() {
|
||||
"base" => 0,
|
||||
"upper" => 1,
|
||||
"numbers" => 2,
|
||||
"symbols" => 3,
|
||||
_ => 0
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_set_level(layout: *mut Layout, level: u32) {
|
||||
let mut layout = unsafe { &mut*layout };
|
||||
layout.current_view = String::from(match level {
|
||||
0 => "base",
|
||||
1 => "upper",
|
||||
2 => "numbers",
|
||||
3 => "symbols",
|
||||
_ => "base",
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_get_keymap(layout: *const Layout) -> *const c_char {
|
||||
@ -275,6 +248,9 @@ pub mod c {
|
||||
row: *const Row,
|
||||
button: *const Button,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct LevelKeyboard(*const c_void);
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" {
|
||||
@ -285,6 +261,53 @@ pub mod c {
|
||||
origin: Point,
|
||||
angle: i32
|
||||
) -> u32;
|
||||
|
||||
pub fn eek_keyboard_set_button_locked(
|
||||
keyboard: *mut LevelKeyboard,
|
||||
button: *const Button
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C"
|
||||
fn squeek_layout_set_state_from_press(
|
||||
layout: *mut Layout,
|
||||
keyboard: *mut LevelKeyboard,
|
||||
button_ptr: *const Button,
|
||||
) {
|
||||
let layout = unsafe { &mut *layout };
|
||||
let button = unsafe { &*button_ptr };
|
||||
// don't want to leave this borrowed in the function body
|
||||
let state = {
|
||||
let state = button.state.borrow();
|
||||
state.clone()
|
||||
};
|
||||
|
||||
let view_name = match state.symbol.action {
|
||||
::symbol::Action::SetLevel(name) => {
|
||||
Some(name.clone())
|
||||
},
|
||||
::symbol::Action::LockLevel { lock, unlock } => {
|
||||
let mut current_state = button.state.borrow_mut();
|
||||
current_state.locked ^= true;
|
||||
if current_state.locked {
|
||||
unsafe {
|
||||
eek_keyboard_set_button_locked(
|
||||
keyboard,
|
||||
button_ptr
|
||||
)
|
||||
};
|
||||
}
|
||||
Some(if state.locked { unlock } else { lock }.clone())
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(view_name) = view_name {
|
||||
if let Err(_e) = layout.set_view(view_name.clone()) {
|
||||
eprintln!("No such view: {}, ignoring switch", view_name)
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/// Places each button in order, starting from 0 on the left,
|
||||
@ -464,7 +487,7 @@ pub mod c {
|
||||
locked: false,
|
||||
keycode: None,
|
||||
symbol: Symbol {
|
||||
action: Action::SetLevel(0),
|
||||
action: Action::SetLevel("default".into()),
|
||||
}
|
||||
}))
|
||||
}
|
||||
@ -710,6 +733,19 @@ pub struct Layout {
|
||||
pub keymap_str: CString,
|
||||
}
|
||||
|
||||
struct NoSuchView;
|
||||
|
||||
impl Layout {
|
||||
fn set_view(&mut self, view: String) -> Result<(), NoSuchView> {
|
||||
if self.views.contains_key(&view) {
|
||||
self.current_view = view;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(NoSuchView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod procedures {
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ impl KeySym {
|
||||
pub struct XKeySym(pub u32);
|
||||
|
||||
/// Use to switch layouts
|
||||
type Level = u8;
|
||||
type Level = String;
|
||||
|
||||
/// Use to send modified keypresses
|
||||
#[derive(Debug, Clone)]
|
||||
@ -34,8 +34,14 @@ pub enum Modifier {
|
||||
/// Action to perform on the keypress and, in reverse, on keyrelease
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Action {
|
||||
/// Switch to this level TODO: reverse?
|
||||
/// Switch to this view
|
||||
SetLevel(Level),
|
||||
/// Switch to a view and latch
|
||||
LockLevel {
|
||||
lock: Level,
|
||||
/// When unlocked by pressing it or emitting a key
|
||||
unlock: Level,
|
||||
},
|
||||
/// Set this modifier TODO: release?
|
||||
SetModifier(Modifier),
|
||||
/// Submit some text
|
||||
|
||||
Reference in New Issue
Block a user