diff --git a/eek/eek-key.c b/eek/eek-key.c index 91855c6b..744a8757 100644 --- a/eek/eek-key.c +++ b/eek/eek-key.c @@ -508,11 +508,3 @@ void eek_key_set_pressed(EekKey *key, gboolean value) priv->is_pressed = value; } - -gboolean -eek_key_has_label(EekKey *key) -{ - EekSymbol *symbol = eek_key_get_symbol(key); - return (eek_symbol_get_label(symbol) != NULL) || - (eek_symbol_get_icon_name(symbol) != NULL); -} diff --git a/eek/eek-key.h b/eek/eek-key.h index fb82f889..bcd8e4b4 100644 --- a/eek/eek-key.h +++ b/eek/eek-key.h @@ -82,7 +82,5 @@ gboolean eek_key_is_locked (EekKey *key); void eek_key_set_pressed (EekKey *key, gboolean value); -gboolean eek_key_has_label (EekKey *key); - G_END_DECLS #endif /* EEK_KEY_H */ diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 5319059a..bc44743e 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -305,7 +305,7 @@ void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestam if (!symbol) return; - EekModifierType modifier = eek_symbol_get_modifier_mask (symbol); + EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol); if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) { set_modifiers_with_key (keyboard, key, priv->modifiers | modifier); set_level_from_modifiers (keyboard, key); @@ -336,12 +336,10 @@ void eek_keyboard_release_key( EekKeyboard *keyboard, if (!symbol) return; - EekModifierType modifier = eek_symbol_get_modifier_mask (symbol); - if (!symbol) return; - modifier = eek_symbol_get_modifier_mask (symbol); + EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol); switch (priv->modifier_behavior) { case EEK_MODIFIER_BEHAVIOR_NONE: set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier); @@ -810,11 +808,13 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard) gchar *groups[2]; for (i = 0, j = 0; i < 2; ++i, j += 2) { - if (syms[j] && syms[j + 1]) - groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]), - eek_symbol_get_name(syms[j + 1]), + if (syms[j] && syms[j + 1]) { + char *tleft = squeek_symbol_get_name(syms[j]); + char *tright = squeek_symbol_get_name(syms[j + 1]); + groups[i] = g_strjoin(", ", tleft, + tright, NULL); - else + } else groups[i] = ""; } diff --git a/eek/eek-keysym.c b/eek/eek-keysym.c index 5518e546..0c877ff2 100644 --- a/eek/eek-keysym.c +++ b/eek/eek-keysym.c @@ -228,6 +228,17 @@ eek_keysym_new (guint xkeysym) return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym)); } +guint32 +eek_keysym_from_name (const gchar *name) +{ + for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++) { + if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0) { + return xkeysym_keysym_entries[i].xkeysym; + } + } + return 0; +} + /** * eek_keysym_new_from_name: * @name: an X keysym name @@ -237,9 +248,10 @@ eek_keysym_new (guint xkeysym) EekSymbol* eek_keysym_new_from_name (const gchar *name) { - for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++) - if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0) - return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym); + guint32 xkeysym = eek_keysym_from_name(name); + if (xkeysym != 0) { + return eek_keysym_new(xkeysym); + } EekSymbol *ret = eek_symbol_new(name); eek_symbol_set_label(ret, name); diff --git a/eek/eek-keysym.h b/eek/eek-keysym.h index e257a9c8..e849dd43 100644 --- a/eek/eek-keysym.h +++ b/eek/eek-keysym.h @@ -40,6 +40,7 @@ G_BEGIN_DECLS EekSymbol *eek_keysym_new (guint xkeysym); guint eek_keysym_get_xkeysym (EekSymbol *keysym); +guint32 eek_keysym_from_name (const gchar *name); EekSymbol *eek_keysym_new_from_name (const gchar *name); EekSymbol *eek_keysym_new_with_modifier (guint xkeysym, EekModifierType modifier_mask); diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 5a32e0d3..6c8cf39e 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -231,9 +231,6 @@ render_key (EekRenderer *self, PangoRectangle extents = { 0, }; EekColor foreground; - if (!eek_key_has_label(key)) - return; - oref = eek_key_get_oref (key); outline = eek_keyboard_get_outline (priv->keyboard, oref); if (outline == NULL) @@ -284,11 +281,11 @@ render_key (EekRenderer *self, if (!symbol) return; - if (eek_symbol_get_icon_name (symbol)) { + if (squeek_symbol_get_icon_name (symbol)) { gint scale = priv->scale_factor; cairo_surface_t *icon_surface = eek_renderer_get_icon_surface (self, - eek_symbol_get_icon_name (symbol), + squeek_symbol_get_icon_name (symbol), 16 / priv->scale, scale); if (icon_surface) { @@ -397,7 +394,7 @@ eek_renderer_real_render_key_label (EekRenderer *self, if (!symbol) return; - label = eek_symbol_get_label (symbol); + label = squeek_symbol_get_label (symbol); if (!label) return; diff --git a/eek/eek-section.c b/eek/eek-section.c index 35078e6f..b37b46f2 100644 --- a/eek/eek-section.c +++ b/eek/eek-section.c @@ -211,8 +211,6 @@ static void eek_section_finalize (GObject *object) { EekSection *self = EEK_SECTION (object); - EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self); - G_OBJECT_CLASS (eek_section_parent_class)->finalize (object); } @@ -512,11 +510,6 @@ keycounter (EekElement *element, gpointer user_data) { EekKey *key = EEK_KEY(element); - /* Skip keys without labels for the current level. This causes those - keys to be hidden in the visible layout. */ - if (!eek_key_has_label(key)) - return; - struct keys_info *data = user_data; data->count++; EekBounds key_bounds = {0}; @@ -532,10 +525,6 @@ keyplacer(EekElement *element, gpointer user_data) { EekKey *key = EEK_KEY(element); - /* Skip keys without labels for the current level. */ - if (!eek_key_has_label(key)) - return; - double *current_offset = user_data; EekBounds key_bounds = {0}; eek_element_get_bounds(element, &key_bounds); diff --git a/eek/eek-symbol.c b/eek/eek-symbol.c index c17bb532..7b4b021c 100644 --- a/eek/eek-symbol.c +++ b/eek/eek-symbol.c @@ -30,42 +30,15 @@ #include "eek-symbol.h" #include "eek-enumtypes.h" -void -eek_symbol_destroy (EekSymbol *priv) -{ - g_free (priv->name); - g_free (priv->label); - g_free (priv->icon_name); - g_free (priv->tooltip); - g_free(priv->text); - g_free(priv); -} - EekSymbol * eek_symbol_new (const gchar *name) { EekSymbol *self = g_new0(EekSymbol, 1); - eek_symbol_set_name(self, name); + self->name = g_strdup (name); self->category = EEK_SYMBOL_CATEGORY_UNKNOWN; return self; } -void -eek_symbol_set_name (EekSymbol *symbol, - const gchar *name) -{ - g_free (symbol->name); - symbol->name = g_strdup (name); -} - -const gchar * -eek_symbol_get_name (EekSymbol *symbol) -{ - if (symbol->name == NULL || *symbol->name == '\0') - return NULL; - return symbol->name; -} - /** * eek_symbol_set_label: * @symbol: an #EekSymbol @@ -81,20 +54,6 @@ eek_symbol_set_label (EekSymbol *symbol, symbol->label = g_strdup (label); } -/** - * eek_symbol_get_label: - * @symbol: an #EekSymbol - * - * Get the label text of @symbol. - */ -const gchar * -eek_symbol_get_label (EekSymbol *symbol) -{ - if (symbol->label == NULL || *symbol->label == '\0') - return NULL; - return symbol->label; -} - /** * eek_symbol_set_modifier_mask: * @symbol: an #EekSymbol @@ -118,15 +77,10 @@ eek_symbol_set_modifier_mask (EekSymbol *symbol, EekModifierType eek_symbol_get_modifier_mask (EekSymbol *symbol) { + return 0; return symbol->modifier_mask; } -gboolean -eek_symbol_is_modifier (EekSymbol *symbol) -{ - return eek_symbol_get_modifier_mask (symbol) != 0; -} - void eek_symbol_set_icon_name (EekSymbol *symbol, const gchar *icon_name) @@ -138,9 +92,7 @@ eek_symbol_set_icon_name (EekSymbol *symbol, const gchar * eek_symbol_get_icon_name (EekSymbol *symbol) { - if (symbol->icon_name == NULL || *symbol->icon_name == '\0') - return NULL; - return symbol->icon_name; + return NULL; } void @@ -154,6 +106,7 @@ eek_symbol_set_tooltip (EekSymbol *symbol, const gchar * eek_symbol_get_tooltip (EekSymbol *symbol) { + return NULL; if (symbol->tooltip == NULL || *symbol->tooltip == '\0') return NULL; return symbol->tooltip; diff --git a/eek/eek-symbol.h b/eek/eek-symbol.h index 6a0bcfbc..c520599a 100644 --- a/eek/eek-symbol.h +++ b/eek/eek-symbol.h @@ -26,6 +26,8 @@ #define EEK_SYMBOL_H 1 #include "eek-types.h" +#include "src/symbol.h" + G_BEGIN_DECLS @@ -91,7 +93,6 @@ EekSymbolCategory eek_symbol_get_category (EekSymbol *symbol); EekModifierType eek_symbol_get_modifier_mask (EekSymbol *symbol); void eek_symbol_set_modifier_mask (EekSymbol *symbol, EekModifierType mask); -gboolean eek_symbol_is_modifier (EekSymbol *symbol); void eek_symbol_set_icon_name (EekSymbol *symbol, const gchar *icon_name); const gchar *eek_symbol_get_icon_name (EekSymbol *symbol); diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index c84b2fae..8db81975 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -33,6 +33,7 @@ #include "eek-key.h" #include "eek-keysym.h" #include "eek-text.h" +#include "src/symbol.h" #include "squeekboard-resources.h" @@ -732,38 +733,25 @@ symbols_end_element_callback (GMarkupParseContext *pcontext, if (g_strcmp0 (element_name, "symbol") == 0 || g_strcmp0 (element_name, "keysym") == 0 || g_strcmp0 (element_name, "text") == 0) { - EekSymbol *symbol; - if (g_strcmp0 (element_name, "keysym") == 0) { - EekSymbol *keysym; - if (data->keyval != EEK_INVALID_KEYSYM) - keysym = eek_keysym_new (data->keyval); - else - keysym = eek_keysym_new_from_name (text); - symbol = keysym; - } else if (g_strcmp0 (element_name, "text") == 0) { - symbol = eek_text_new (text); - } else { - symbol = eek_symbol_new (text); - } - - if (data->label) { - eek_symbol_set_label (symbol, data->label); - g_free (data->label); - data->label = NULL; - } - if (data->icon) { - eek_symbol_set_icon_name (symbol, data->icon); - g_free (data->icon); - data->icon = NULL; - } - if (data->tooltip) { - eek_symbol_set_tooltip (symbol, data->tooltip); - g_free (data->tooltip); - data->tooltip = NULL; - } - - data->symbols = g_slist_prepend (data->symbols, symbol); + data->symbols = g_slist_prepend ( + data->symbols, + squeek_symbol_new( + element_name, + text, + data->keyval, + data->label, + data->icon, + data->tooltip + ) + ); + data->keyval = 0; + g_free(data->label); + data->label = NULL; + g_free(data->icon); + data->icon = NULL; + g_free(data->tooltip); + data->tooltip = NULL; goto out; } diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index c5d17645..4b461444 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -148,6 +148,10 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self, gchar *keymap_str = eek_keyboard_get_keymap(keyboard); + int f = open("maprs.map", O_CREAT | O_WRONLY); + write(f, keymap_str, strlen(keymap_str)); + close(f); + struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); diff --git a/src/lib.rs b/src/lib.rs index 64e3ca10..5b3168f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,3 +2,4 @@ mod bitflags; mod imservice; +mod symbol; diff --git a/src/symbol.h b/src/symbol.h new file mode 100644 index 00000000..5f402df5 --- /dev/null +++ b/src/symbol.h @@ -0,0 +1,22 @@ +#ifndef __SYMBOL_H +#define __SYMBOL_H + +#include "stdbool.h" +#include "inttypes.h" +// Defined in Rust + +struct squeek_symbol; + +struct squeek_symbol* squeek_symbol_new(const char *element_name, + const char *text, uint32_t keyval, + const char *label, const char *icon, + const char *tooltip); + + +const char *squeek_symbol_get_name(struct squeek_symbol* symbol); +const char *squeek_symbol_get_label(struct squeek_symbol* symbol); +const char *squeek_symbol_get_icon_name(struct squeek_symbol* symbol); +uint32_t squeek_symbol_get_modifier_mask(struct squeek_symbol* symbol); + +void squeek_symbol_print(struct squeek_symbol* symbol); +#endif diff --git a/src/symbol.rs b/src/symbol.rs new file mode 100644 index 00000000..abca1997 --- /dev/null +++ b/src/symbol.rs @@ -0,0 +1,276 @@ +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, 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, 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, + Shift = 1, + } + + // 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_symbol_new( + element: *const c_char, + text_raw: *const c_char, keyval: u32, + label: *const c_char, icon: *const c_char, + tooltip: *const c_char, + ) -> *mut Symbol { + 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 + }); + + Box::::into_raw(Box::new( + 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), + } + )) + } + + #[no_mangle] + pub extern "C" + fn squeek_symbol_get_name(symbol: *const Symbol) -> *const c_char { + let symbol = unsafe { &*symbol }; + match &symbol.action { + Action::Submit { text: Some(text), .. } => text.as_ptr(), + _ => ptr::null(), + } + } + + #[no_mangle] + pub extern "C" + fn squeek_symbol_get_label(symbol: *const Symbol) -> *const c_char { + let symbol = unsafe { &*symbol }; + match &symbol.label { + Label::Text(text) => text.as_ptr(), + // returning static strings to C is a bit cumbersome + Label::IconName(_) => unsafe { + CStr::from_bytes_with_nul_unchecked(b"icon\0") + }.as_ptr(), + } + } + + #[no_mangle] + pub extern "C" + fn squeek_symbol_get_icon_name(symbol: *const Symbol) -> *const c_char { + let symbol = unsafe { &*symbol }; + match &symbol.label { + Label::Text(_) => ptr::null(), + Label::IconName(name) => name.as_ptr(), + } + } + + // Legacy; throw away + #[no_mangle] + pub extern "C" + fn squeek_symbol_get_modifier_mask(symbol: *const Symbol) -> u32 { + let symbol = unsafe { &*symbol }; + (match &symbol.action { + Action::SetLevel(1) => ModifierMask::Shift, + _ => ModifierMask::Nothing, + }) as u32 + } + + #[no_mangle] + pub extern "C" + fn squeek_symbol_print(symbol: *const Symbol) { + let symbol = unsafe { &*symbol }; + println!("{:?}", symbol); + } +} + +/// Just defines some int->identifier mappings for convenience +#[derive(Debug)] +enum KeySym { + Unknown = 0, + Shift = 0xffe1, +} + +impl KeySym { + fn from_u32(num: u32) -> KeySym { + match num { + 0xffe1 => KeySym::Shift, + _ => KeySym::Unknown, + } + } +} + +#[derive(Debug)] +pub struct XKeySym(u32); + +#[derive(Debug)] +pub enum Label { + /// Text used to display the symbol + Text(CString), + /// Icon name used to render the symbol + IconName(CString), +} + +/// Use to switch layouts +type Level = u8; + +/// Use to send modified keypresses +#[derive(Debug)] +pub enum Modifier { + Control, + Alt, +} + +/// Action to perform on the keypress and, in reverse, on keyrelease +#[derive(Debug)] +pub enum Action { + /// Switch to this level TODO: reverse? + SetLevel(Level), + /// Set this modifier TODO: release? + SetModifier(Modifier), + /// Submit some text + Submit { + /// orig: Canonical name of the symbol + text: Option, + /// The key events this symbol submits when submitting text is not possible + keys: Vec, + }, +} + +/// Contains a static description of a particular key's actions +#[derive(Debug)] +pub struct Symbol { + /// The action that this key performs + action: Action, + /// Label to display to the user + label: Label, + // FIXME: is it used? + tooltip: Option, +}