Commit fb93e258 authored by Dorota Czaplejewicz's avatar Dorota Czaplejewicz
Browse files

eekkey: Moved state to KeyState

parent ad86cb53
......@@ -31,6 +31,7 @@
#include "eek-section.h"
#include "eek-keyboard.h"
#include "src/keyboard.h"
#include "src/symbol.h"
#include "eek-key.h"
......@@ -53,9 +54,8 @@ static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekKeyPrivate
{
guint keycode;
struct squeek_symbols *symbols;
gulong oref; // UI outline reference
gboolean is_pressed;
struct squeek_key *state;
gboolean is_locked;
} EekKeyPrivate;
......@@ -89,7 +89,7 @@ eek_key_finalize (GObject *object)
EekKey *self = EEK_KEY (object);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
squeek_symbols_free (priv->symbols);
squeek_key_free (priv->state);
G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
}
......@@ -211,7 +211,7 @@ static void
eek_key_init (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->symbols = squeek_symbols_new ();
priv->state = squeek_key_new (0);
}
/**
......@@ -253,23 +253,6 @@ eek_key_get_keycode (EekKey *key)
return priv->keycode;
}
/**
* eek_key_get_symbol_matrix:
* @key: an #EekKey
*
* Get the symbol matrix of @key.
* Returns: (transfer none): #EekSymbolMatrix or %NULL
*/
struct squeek_symbols *
eek_key_get_symbol_matrix (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->symbols;
}
/**
* eek_key_get_symbol_at_index:
* @key: an #EekKey
......@@ -286,8 +269,8 @@ eek_key_get_symbol_at_index (EekKey *key,
gint group,
guint level)
{
struct squeek_symbols *symbols = eek_key_get_symbol_matrix(key);
return squeek_symbols_get(symbols, level);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return squeek_key_get_symbol(priv->state, level);
}
/**
......@@ -341,7 +324,7 @@ eek_key_is_pressed (EekKey *key)
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_pressed;
return (bool)squeek_key_is_pressed(priv->state);
}
/**
......@@ -366,5 +349,10 @@ void eek_key_set_pressed(EekKey *key, gboolean value)
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->is_pressed = value;
squeek_key_set_pressed(priv->state, value);
}
struct squeek_key *eek_key_get_state(EekKey *key) {
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->state;
}
......@@ -58,8 +58,7 @@ GType eek_key_get_type (void) G_GNUC_CONST;
void eek_key_set_keycode (EekKey *key,
guint keycode);
guint eek_key_get_keycode (EekKey *key);
struct squeek_symbols *
eek_key_get_symbol_matrix (EekKey *key);
struct squeek_key *eek_key_get_state(EekKey *key);
struct squeek_symbol *eek_key_get_symbol_at_index (EekKey *key,
gint group,
guint level);
......
......@@ -763,7 +763,7 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
// FIXME: free
const char *key_str = squeek_key_to_keymap_entry(
(char*)key_name,
eek_key_get_symbol_matrix(key)
eek_key_get_state(key)
);
current = symbols;
symbols = g_strconcat(current, key_str, NULL);
......
......@@ -86,10 +86,6 @@ static void render_key (EekRenderer *self,
cairo_t *cr,
EekKey *key, guint level,
gboolean active);
static void on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data);
struct _CreateKeyboardSurfaceCallbackData {
cairo_t *cr;
......@@ -715,16 +711,6 @@ invalidate (EekRenderer *renderer)
}
}
static void
on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data)
{
EekRenderer *renderer = user_data;
invalidate (renderer);
}
EekRenderer *
eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext,
......
......@@ -30,6 +30,7 @@
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "src/keyboard.h"
#include "src/symbol.h"
#include "squeekboard-resources.h"
......@@ -748,8 +749,8 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
g_strcmp0 (element_name, "keysym") == 0 ||
g_strcmp0 (element_name, "text") == 0) {
squeek_symbols_add(
eek_key_get_symbol_matrix(data->key),
squeek_key_add_symbol(
eek_key_get_state(data->key),
element_name,
text,
data->keyval,
......
#ifndef __KEYBOARD_H
#define __KYBOARD_H
#include "stdbool.h"
#include "inttypes.h"
struct squeek_key;
struct squeek_key *squeek_key_new(uint32_t keycode);
void squeek_key_free(struct squeek_key *key);
void squeek_key_add_symbol(struct squeek_key* key,
const char *element_name,
const char *text, uint32_t keyval,
const char *label, const char *icon,
const char *tooltip);
uint32_t squeek_key_is_pressed(struct squeek_key *key);
void squeek_key_set_pressed(struct squeek_key *key, uint32_t pressed);
struct squeek_symbol *squeek_key_get_symbol(struct squeek_key* key, uint32_t level);
#endif
use std::vec::Vec;
use super::symbol;
/// Gathers stuff defined in C or called by C
pub mod c {
use super::*;
use ::util::c::{ as_cstr, into_cstring };
use std::ffi::CString;
use std::os::raw::c_char;
// The following defined in C
#[no_mangle]
extern "C" {
fn eek_keysym_from_name(name: *const c_char) -> u32;
}
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
// TODO: this will receive data from the filesystem,
// so it should handle garbled strings in the future
#[no_mangle]
pub extern "C"
fn squeek_key_new(keycode: u32) -> *mut KeyState {
Box::into_raw(Box::new(
KeyState {
pressed: false,
keycode: keycode,
symbols: Vec::new(),
}
))
}
#[no_mangle]
pub extern "C"
fn squeek_key_free(key: *mut KeyState) {
unsafe { Box::from_raw(key) }; // gets dropped
}
#[no_mangle]
pub extern "C"
fn squeek_key_is_pressed(key: *const KeyState) -> u32{
let key = unsafe { &*key };
return key.pressed as u32;
}
#[no_mangle]
pub extern "C"
fn squeek_key_set_pressed(key: *mut KeyState, pressed: u32) {
let key = unsafe { &mut *key };
key.pressed = pressed != 0;
}
// TODO: this will receive data from the filesystem,
// so it should handle garbled strings in the future
#[no_mangle]
pub extern "C"
fn squeek_key_add_symbol(
key: *mut KeyState,
element: *const c_char,
text_raw: *const c_char, keyval: u32,
label: *const c_char, icon: *const c_char,
tooltip: *const c_char,
) {
let element = as_cstr(&element)
.expect("Missing element name");
let text = into_cstring(text_raw)
.unwrap_or_else(|e| {
eprintln!("Text unreadable: {}", e);
None
})
.and_then(|text| {
if text.as_bytes() == b"" {
None
} else {
Some(text)
}
});
let icon = into_cstring(icon)
.unwrap_or_else(|e| {
eprintln!("Icon name unreadable: {}", e);
None
});
use symbol::*;
// Only read label if there's no icon
let label = match icon {
Some(icon) => Label::IconName(icon),
None => Label::Text(
into_cstring(label)
.unwrap_or_else(|e| {
eprintln!("Label unreadable: {}", e);
Some(CString::new(" ").unwrap())
})
.unwrap_or_else(|| {
eprintln!("Label missing");
CString::new(" ").unwrap()
})
),
};
let tooltip = into_cstring(tooltip)
.unwrap_or_else(|e| {
eprintln!("Tooltip unreadable: {}", e);
None
});
let symbol = match element.to_bytes() {
b"symbol" => Symbol {
action: Action::Submit {
text: text,
keys: Vec::new(),
},
label: label,
tooltip: tooltip,
},
b"keysym" => {
let keysym = XKeySym(
if keyval == 0 {
unsafe { eek_keysym_from_name(text_raw) }
} else {
keyval
}
);
Symbol {
action: match KeySym::from_u32(keysym.0) {
KeySym::Shift => Action::SetLevel(1),
_ => Action::Submit {
text: text,
keys: vec![keysym],
}
},
label: label,
tooltip: tooltip,
}
},
_ => panic!("unsupported element type {:?}", element),
};
let key = unsafe { &mut *key };
key.symbols.push(symbol);
}
#[no_mangle]
pub extern "C"
fn squeek_key_get_symbol(
key: *const KeyState, index: u32
) -> *const symbol::Symbol {
let key = unsafe { &*key };
let index = index as usize;
&key.symbols[
if index < key.symbols.len() { index } else { 0 }
] as *const symbol::Symbol
}
#[no_mangle]
pub extern "C"
fn squeek_key_to_keymap_entry(
key_name: *const c_char,
key: *const KeyState,
) -> *const c_char {
let key_name = as_cstr(&key_name)
.expect("Missing key name")
.to_str()
.expect("Bad key name");
let key = unsafe { &*key };
let symbol_names = key.symbols.iter()
.map(|symbol| {
match &symbol.action {
symbol::Action::Submit { text: Some(text), .. } => {
Some(
text.clone()
.into_string().expect("Bad symbol")
)
},
_ => None
}
})
.collect::<Vec<_>>();
let inner = match symbol_names.len() {
1 => match &symbol_names[0] {
Some(name) => format!("[ {} ]", name),
_ => format!("[ ]"),
},
4 => {
let first = match (&symbol_names[0], &symbol_names[1]) {
(Some(left), Some(right)) => format!("{}, {}", left, right),
_ => format!(""),
};
let second = match (&symbol_names[2], &symbol_names[3]) {
(Some(left), Some(right)) => format!("{}, {}", left, right),
_ => format!(""),
};
format!("[ {} ], [ {} ]", first, second)
},
_ => panic!("Unsupported number of symbols"),
};
CString::new(format!(" key <{}> {{ {} }};\n", key_name, inner))
.expect("Couldn't convert string")
.into_raw()
}
}
#[derive(Debug)]
pub struct KeyState {
pressed: bool,
keycode: u32,
symbols: Vec<symbol::Symbol>,
}
......@@ -2,4 +2,6 @@
mod bitflags;
mod imservice;
mod keyboard;
mod symbol;
mod util;
......@@ -22,9 +22,5 @@ uint32_t squeek_symbol_get_modifier_mask(struct squeek_symbol* symbol);
void squeek_symbol_print(struct squeek_symbol* symbol);
struct squeek_symbols* squeek_symbols_new();
void squeek_symbols_free(struct squeek_symbols*);
struct squeek_symbol *squeek_symbols_get(struct squeek_symbols*, uint32_t level);
const char* squeek_key_to_keymap_entry(const char *key_name, struct squeek_symbols *symbols);
#endif
use std::boxed::Box;
use std::ffi::CString;
/// Gathers stuff defined in C or called by C
pub mod c {
use super::*;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::ptr;
use std::str::Utf8Error;
fn as_str(s: &*const c_char) -> Result<Option<&str>, Utf8Error> {
if s.is_null() {
Ok(None)
} else {
unsafe {CStr::from_ptr(*s)}
.to_str()
.map(Some)
}
}
fn as_cstr(s: &*const c_char) -> Option<&CStr> {
if s.is_null() {
None
} else {
Some(unsafe {CStr::from_ptr(*s)})
}
}
fn into_cstring(s: *const c_char) -> Result<Option<CString>, std::ffi::NulError> {
if s.is_null() {
Ok(None)
} else {
CString::new(
unsafe {CStr::from_ptr(s)}.to_bytes()
).map(Some)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_null_cstring() {
assert_eq!(into_cstring(ptr::null()), Ok(None))
}
#[test]
fn test_null_str() {
assert_eq!(as_str(&ptr::null()), Ok(None))
}
}
// The following defined in C
#[no_mangle]
extern "C" {
fn eek_keysym_from_name(name: *const c_char) -> u32;
}
// Legacy; Will never be used in Rust as a bit field
enum ModifierMask {
Nothing = 0,
......@@ -72,98 +21,6 @@ pub mod c {
// TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
// Symbols are owned by Rust and will move towards no C manipulation, so it may make sense not to wrap them
// TODO: this will receive data from the filesystem,
// so it should handle garbled strings in the future
#[no_mangle]
pub extern "C"
fn squeek_symbols_add(
v: *mut Vec<Symbol>,
element: *const c_char,
text_raw: *const c_char, keyval: u32,
label: *const c_char, icon: *const c_char,
tooltip: *const c_char,
) {
let element = as_cstr(&element)
.expect("Missing element name");
let text = into_cstring(text_raw)
.unwrap_or_else(|e| {
eprintln!("Text unreadable: {}", e);
None
})
.and_then(|text| {
if text.as_bytes() == b"" {
None
} else {
Some(text)
}
});
let icon = into_cstring(icon)
.unwrap_or_else(|e| {
eprintln!("Icon name unreadable: {}", e);
None
});
// Only read label if there's no icon
let label = match icon {
Some(icon) => Label::IconName(icon),
None => Label::Text(
into_cstring(label)
.unwrap_or_else(|e| {
eprintln!("Label unreadable: {}", e);
Some(CString::new(" ").unwrap())
})
.unwrap_or_else(|| {
eprintln!("Label missing");
CString::new(" ").unwrap()
})
),
};
let tooltip = into_cstring(tooltip)
.unwrap_or_else(|e| {
eprintln!("Tooltip unreadable: {}", e);
None
});
let symbol = match element.to_bytes() {
b"symbol" => Symbol {
action: Action::Submit {
text: text,
keys: Vec::new(),
},
label: label,
tooltip: tooltip,
},
b"keysym" => {
let keysym = XKeySym(
if keyval == 0 {
unsafe { eek_keysym_from_name(text_raw) }
} else {
keyval
}
);
Symbol {
action: match KeySym::from_u32(keysym.0) {
KeySym::Shift => Action::SetLevel(1),
_ => Action::Submit {
text: text,
keys: vec![keysym],
}
},
label: label,
tooltip: tooltip,
}
},
_ => panic!("unsupported element type {:?}", element),
};
let v = unsafe { &mut *v };
v.push(symbol);
}
#[no_mangle]
pub extern "C"
fn squeek_symbol_get_name(symbol: *const Symbol) -> *const c_char {
......@@ -214,88 +71,17 @@ pub mod c {
let symbol = unsafe { &*symbol };
println!("{:?}", symbol);
}
#[no_mangle]
pub extern "C"
fn squeek_symbols_new() -> *const Vec<Symbol> {
Box::into_raw(Box::new(Vec::new()))
}
#[no_mangle]
pub extern "C"
fn squeek_symbols_get(v: *mut Vec<Symbol>, index: u32) -> *const Symbol {
let v = unsafe { &mut *v };
let index = index as usize;
&v[
if index < v.len() { index } else { 0 }
] as *const Symbol
}
#[no_mangle]
pub extern "C"
fn squeek_symbols_free(symbols: *mut Vec<Symbol>) {
unsafe { Box::from_raw(symbols) }; // Will just get dropped, together with the contents
}
#[no_mangle]
pub extern "C"
fn squeek_key_to_keymap_entry(
key_name: *const c_char,
symbols: *const Vec<Symbol>,
) -> *const c_char {
let key_name = as_cstr(&key_name)
.expect("Missing key name")
.to_str()
.expect("Bad key name");
let symbols = unsafe { &*symbols };
let symbol_names = symbols.iter()
.map(|symbol| {
match &symbol.action {
Action::Submit { text: Some(text), .. } => {
Some(
text.clone()
.into_string().expect("Bad symbol")
)
},
_ => None