Break out symbol handling into Rust
This commit is contained in:
@ -508,11 +508,3 @@ void eek_key_set_pressed(EekKey *key, gboolean value)
|
|||||||
|
|
||||||
priv->is_pressed = 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);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -82,7 +82,5 @@ gboolean eek_key_is_locked (EekKey *key);
|
|||||||
void eek_key_set_pressed (EekKey *key,
|
void eek_key_set_pressed (EekKey *key,
|
||||||
gboolean value);
|
gboolean value);
|
||||||
|
|
||||||
gboolean eek_key_has_label (EekKey *key);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_KEY_H */
|
#endif /* EEK_KEY_H */
|
||||||
|
|||||||
@ -305,7 +305,7 @@ void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestam
|
|||||||
if (!symbol)
|
if (!symbol)
|
||||||
return;
|
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) {
|
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
|
||||||
set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
|
set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
|
||||||
set_level_from_modifiers (keyboard, key);
|
set_level_from_modifiers (keyboard, key);
|
||||||
@ -336,12 +336,10 @@ void eek_keyboard_release_key( EekKeyboard *keyboard,
|
|||||||
if (!symbol)
|
if (!symbol)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
|
|
||||||
|
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
modifier = eek_symbol_get_modifier_mask (symbol);
|
EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol);
|
||||||
switch (priv->modifier_behavior) {
|
switch (priv->modifier_behavior) {
|
||||||
case EEK_MODIFIER_BEHAVIOR_NONE:
|
case EEK_MODIFIER_BEHAVIOR_NONE:
|
||||||
set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier);
|
set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier);
|
||||||
@ -810,11 +808,13 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
|
|||||||
|
|
||||||
gchar *groups[2];
|
gchar *groups[2];
|
||||||
for (i = 0, j = 0; i < 2; ++i, j += 2) {
|
for (i = 0, j = 0; i < 2; ++i, j += 2) {
|
||||||
if (syms[j] && syms[j + 1])
|
if (syms[j] && syms[j + 1]) {
|
||||||
groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]),
|
char *tleft = squeek_symbol_get_name(syms[j]);
|
||||||
eek_symbol_get_name(syms[j + 1]),
|
char *tright = squeek_symbol_get_name(syms[j + 1]);
|
||||||
|
groups[i] = g_strjoin(", ", tleft,
|
||||||
|
tright,
|
||||||
NULL);
|
NULL);
|
||||||
else
|
} else
|
||||||
groups[i] = "";
|
groups[i] = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -228,6 +228,17 @@ eek_keysym_new (guint xkeysym)
|
|||||||
return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (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:
|
* eek_keysym_new_from_name:
|
||||||
* @name: an X keysym name
|
* @name: an X keysym name
|
||||||
@ -237,9 +248,10 @@ eek_keysym_new (guint xkeysym)
|
|||||||
EekSymbol*
|
EekSymbol*
|
||||||
eek_keysym_new_from_name (const gchar *name)
|
eek_keysym_new_from_name (const gchar *name)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
|
guint32 xkeysym = eek_keysym_from_name(name);
|
||||||
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
|
if (xkeysym != 0) {
|
||||||
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
|
return eek_keysym_new(xkeysym);
|
||||||
|
}
|
||||||
|
|
||||||
EekSymbol *ret = eek_symbol_new(name);
|
EekSymbol *ret = eek_symbol_new(name);
|
||||||
eek_symbol_set_label(ret, name);
|
eek_symbol_set_label(ret, name);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ G_BEGIN_DECLS
|
|||||||
EekSymbol *eek_keysym_new (guint xkeysym);
|
EekSymbol *eek_keysym_new (guint xkeysym);
|
||||||
guint eek_keysym_get_xkeysym (EekSymbol *keysym);
|
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_from_name (const gchar *name);
|
||||||
EekSymbol *eek_keysym_new_with_modifier (guint xkeysym,
|
EekSymbol *eek_keysym_new_with_modifier (guint xkeysym,
|
||||||
EekModifierType modifier_mask);
|
EekModifierType modifier_mask);
|
||||||
|
|||||||
@ -231,9 +231,6 @@ render_key (EekRenderer *self,
|
|||||||
PangoRectangle extents = { 0, };
|
PangoRectangle extents = { 0, };
|
||||||
EekColor foreground;
|
EekColor foreground;
|
||||||
|
|
||||||
if (!eek_key_has_label(key))
|
|
||||||
return;
|
|
||||||
|
|
||||||
oref = eek_key_get_oref (key);
|
oref = eek_key_get_oref (key);
|
||||||
outline = eek_keyboard_get_outline (priv->keyboard, oref);
|
outline = eek_keyboard_get_outline (priv->keyboard, oref);
|
||||||
if (outline == NULL)
|
if (outline == NULL)
|
||||||
@ -284,11 +281,11 @@ render_key (EekRenderer *self,
|
|||||||
if (!symbol)
|
if (!symbol)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (eek_symbol_get_icon_name (symbol)) {
|
if (squeek_symbol_get_icon_name (symbol)) {
|
||||||
gint scale = priv->scale_factor;
|
gint scale = priv->scale_factor;
|
||||||
cairo_surface_t *icon_surface =
|
cairo_surface_t *icon_surface =
|
||||||
eek_renderer_get_icon_surface (self,
|
eek_renderer_get_icon_surface (self,
|
||||||
eek_symbol_get_icon_name (symbol),
|
squeek_symbol_get_icon_name (symbol),
|
||||||
16 / priv->scale,
|
16 / priv->scale,
|
||||||
scale);
|
scale);
|
||||||
if (icon_surface) {
|
if (icon_surface) {
|
||||||
@ -397,7 +394,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
|
|||||||
if (!symbol)
|
if (!symbol)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
label = eek_symbol_get_label (symbol);
|
label = squeek_symbol_get_label (symbol);
|
||||||
if (!label)
|
if (!label)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@ -211,8 +211,6 @@ static void
|
|||||||
eek_section_finalize (GObject *object)
|
eek_section_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
EekSection *self = EEK_SECTION (object);
|
EekSection *self = EEK_SECTION (object);
|
||||||
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
|
G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,11 +510,6 @@ keycounter (EekElement *element, gpointer user_data)
|
|||||||
{
|
{
|
||||||
EekKey *key = EEK_KEY(element);
|
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;
|
struct keys_info *data = user_data;
|
||||||
data->count++;
|
data->count++;
|
||||||
EekBounds key_bounds = {0};
|
EekBounds key_bounds = {0};
|
||||||
@ -532,10 +525,6 @@ keyplacer(EekElement *element, gpointer user_data)
|
|||||||
{
|
{
|
||||||
EekKey *key = EEK_KEY(element);
|
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;
|
double *current_offset = user_data;
|
||||||
EekBounds key_bounds = {0};
|
EekBounds key_bounds = {0};
|
||||||
eek_element_get_bounds(element, &key_bounds);
|
eek_element_get_bounds(element, &key_bounds);
|
||||||
|
|||||||
@ -30,42 +30,15 @@
|
|||||||
#include "eek-symbol.h"
|
#include "eek-symbol.h"
|
||||||
#include "eek-enumtypes.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 *
|
EekSymbol *
|
||||||
eek_symbol_new (const gchar *name)
|
eek_symbol_new (const gchar *name)
|
||||||
{
|
{
|
||||||
EekSymbol *self = g_new0(EekSymbol, 1);
|
EekSymbol *self = g_new0(EekSymbol, 1);
|
||||||
eek_symbol_set_name(self, name);
|
self->name = g_strdup (name);
|
||||||
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
|
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
|
||||||
return self;
|
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:
|
* eek_symbol_set_label:
|
||||||
* @symbol: an #EekSymbol
|
* @symbol: an #EekSymbol
|
||||||
@ -81,20 +54,6 @@ eek_symbol_set_label (EekSymbol *symbol,
|
|||||||
symbol->label = g_strdup (label);
|
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:
|
* eek_symbol_set_modifier_mask:
|
||||||
* @symbol: an #EekSymbol
|
* @symbol: an #EekSymbol
|
||||||
@ -118,15 +77,10 @@ eek_symbol_set_modifier_mask (EekSymbol *symbol,
|
|||||||
EekModifierType
|
EekModifierType
|
||||||
eek_symbol_get_modifier_mask (EekSymbol *symbol)
|
eek_symbol_get_modifier_mask (EekSymbol *symbol)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
return symbol->modifier_mask;
|
return symbol->modifier_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
|
||||||
eek_symbol_is_modifier (EekSymbol *symbol)
|
|
||||||
{
|
|
||||||
return eek_symbol_get_modifier_mask (symbol) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
eek_symbol_set_icon_name (EekSymbol *symbol,
|
eek_symbol_set_icon_name (EekSymbol *symbol,
|
||||||
const gchar *icon_name)
|
const gchar *icon_name)
|
||||||
@ -138,9 +92,7 @@ eek_symbol_set_icon_name (EekSymbol *symbol,
|
|||||||
const gchar *
|
const gchar *
|
||||||
eek_symbol_get_icon_name (EekSymbol *symbol)
|
eek_symbol_get_icon_name (EekSymbol *symbol)
|
||||||
{
|
{
|
||||||
if (symbol->icon_name == NULL || *symbol->icon_name == '\0')
|
return NULL;
|
||||||
return NULL;
|
|
||||||
return symbol->icon_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -154,6 +106,7 @@ eek_symbol_set_tooltip (EekSymbol *symbol,
|
|||||||
const gchar *
|
const gchar *
|
||||||
eek_symbol_get_tooltip (EekSymbol *symbol)
|
eek_symbol_get_tooltip (EekSymbol *symbol)
|
||||||
{
|
{
|
||||||
|
return NULL;
|
||||||
if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
|
if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
|
||||||
return NULL;
|
return NULL;
|
||||||
return symbol->tooltip;
|
return symbol->tooltip;
|
||||||
|
|||||||
@ -26,6 +26,8 @@
|
|||||||
#define EEK_SYMBOL_H 1
|
#define EEK_SYMBOL_H 1
|
||||||
|
|
||||||
#include "eek-types.h"
|
#include "eek-types.h"
|
||||||
|
#include "src/symbol.h"
|
||||||
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -91,7 +93,6 @@ EekSymbolCategory eek_symbol_get_category (EekSymbol *symbol);
|
|||||||
EekModifierType eek_symbol_get_modifier_mask (EekSymbol *symbol);
|
EekModifierType eek_symbol_get_modifier_mask (EekSymbol *symbol);
|
||||||
void eek_symbol_set_modifier_mask (EekSymbol *symbol,
|
void eek_symbol_set_modifier_mask (EekSymbol *symbol,
|
||||||
EekModifierType mask);
|
EekModifierType mask);
|
||||||
gboolean eek_symbol_is_modifier (EekSymbol *symbol);
|
|
||||||
void eek_symbol_set_icon_name (EekSymbol *symbol,
|
void eek_symbol_set_icon_name (EekSymbol *symbol,
|
||||||
const gchar *icon_name);
|
const gchar *icon_name);
|
||||||
const gchar *eek_symbol_get_icon_name (EekSymbol *symbol);
|
const gchar *eek_symbol_get_icon_name (EekSymbol *symbol);
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
#include "eek-key.h"
|
#include "eek-key.h"
|
||||||
#include "eek-keysym.h"
|
#include "eek-keysym.h"
|
||||||
#include "eek-text.h"
|
#include "eek-text.h"
|
||||||
|
#include "src/symbol.h"
|
||||||
|
|
||||||
#include "squeekboard-resources.h"
|
#include "squeekboard-resources.h"
|
||||||
|
|
||||||
@ -732,38 +733,25 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
|
|||||||
if (g_strcmp0 (element_name, "symbol") == 0 ||
|
if (g_strcmp0 (element_name, "symbol") == 0 ||
|
||||||
g_strcmp0 (element_name, "keysym") == 0 ||
|
g_strcmp0 (element_name, "keysym") == 0 ||
|
||||||
g_strcmp0 (element_name, "text") == 0) {
|
g_strcmp0 (element_name, "text") == 0) {
|
||||||
EekSymbol *symbol;
|
|
||||||
|
|
||||||
if (g_strcmp0 (element_name, "keysym") == 0) {
|
data->symbols = g_slist_prepend (
|
||||||
EekSymbol *keysym;
|
data->symbols,
|
||||||
if (data->keyval != EEK_INVALID_KEYSYM)
|
squeek_symbol_new(
|
||||||
keysym = eek_keysym_new (data->keyval);
|
element_name,
|
||||||
else
|
text,
|
||||||
keysym = eek_keysym_new_from_name (text);
|
data->keyval,
|
||||||
symbol = keysym;
|
data->label,
|
||||||
} else if (g_strcmp0 (element_name, "text") == 0) {
|
data->icon,
|
||||||
symbol = eek_text_new (text);
|
data->tooltip
|
||||||
} else {
|
)
|
||||||
symbol = eek_symbol_new (text);
|
);
|
||||||
}
|
data->keyval = 0;
|
||||||
|
g_free(data->label);
|
||||||
if (data->label) {
|
data->label = NULL;
|
||||||
eek_symbol_set_label (symbol, data->label);
|
g_free(data->icon);
|
||||||
g_free (data->label);
|
data->icon = NULL;
|
||||||
data->label = NULL;
|
g_free(data->tooltip);
|
||||||
}
|
data->tooltip = 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);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -148,6 +148,10 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
|
|||||||
|
|
||||||
gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
|
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,
|
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
|
||||||
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
|||||||
@ -2,3 +2,4 @@
|
|||||||
mod bitflags;
|
mod bitflags;
|
||||||
|
|
||||||
mod imservice;
|
mod imservice;
|
||||||
|
mod symbol;
|
||||||
|
|||||||
22
src/symbol.h
Normal file
22
src/symbol.h
Normal file
@ -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
|
||||||
276
src/symbol.rs
Normal file
276
src/symbol.rs
Normal file
@ -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<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,
|
||||||
|
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::<Symbol>::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<CString>,
|
||||||
|
/// The key events this symbol submits when submitting text is not possible
|
||||||
|
keys: Vec<XKeySym>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<CString>,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user