e - add vkbd for convertibles (tablets, laptops ... phones)

This commit is contained in:
Carsten Haitzler 2017-08-14 19:48:40 +09:00
parent 09a8888f76
commit 074b3fe1eb
37 changed files with 107822 additions and 0 deletions

View File

@ -327,6 +327,13 @@ if freebsd == true
dir_pkgconfig = join_paths(dir_lib, 'data/pkgconfig')
endif
##### edje_cc binary compiler tool
edje_cmd = get_option('edje-cc')
if edje_cmd == ''
edje_cmd = join_paths(dep_edje.get_pkgconfig_variable('prefix'),
'bin', 'edje_cc')
endif
subdir('src/bin')
subdir('src/modules')

View File

@ -15,6 +15,10 @@ option('nls',
default: true,
description: 'enable localization: (default=true)')
option('edje-cc',
type : 'string',
description: 'A path to a edje_cc. Defaults to system edje_cc')
option('pam',
type: 'boolean',
default: true,
@ -236,6 +240,10 @@ option('xkbswitch',
type: 'boolean',
default: true,
description: 'enable xkbswitch module: (default=true)')
option('vkbd',
type: 'boolean',
default: true,
description: 'enable vkbd module: (default=true)')
option('conf',

View File

@ -49,6 +49,7 @@ mods = [
'time',
'luncher',
'teamwork',
'vkbd',
# modules have a custom binary as well
'battery',
'cpufreq',

1
src/modules/vkbd/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
e-module-illume-keyboard.edj

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,567 @@
#include "e.h"
#include "e_kbd_buf.h"
#include "e_kbd_dict.h"
static E_Kbd_Buf_Layout *
_e_kbd_buf_new(void)
{
E_Kbd_Buf_Layout *kbl;
kbl = E_NEW(E_Kbd_Buf_Layout, 1);
kbl->ref =1;
return kbl;
}
static void
_e_kbd_buf_layout_ref(E_Kbd_Buf_Layout *kbl)
{
kbl->ref++;
}
static void
_e_kbd_buf_layout_unref(E_Kbd_Buf_Layout *kbl)
{
kbl->ref--;
if (kbl->ref > 0) return;
while (kbl->keys)
{
E_Kbd_Buf_Key *ky;
ky = kbl->keys->data;
if (ky->key) eina_stringshare_del(ky->key);
if (ky->key_shift) eina_stringshare_del(ky->key_shift);
if (ky->key_capslock) eina_stringshare_del(ky->key_capslock);
if (ky->key_altgr) eina_stringshare_del(ky->key_altgr);
free(ky);
kbl->keys = eina_list_remove_list(kbl->keys, kbl->keys);
}
free(kbl);
}
static void
_e_kbd_buf_string_matches_clear(E_Kbd_Buf *kb)
{
while (kb->string_matches)
{
if (kb->string_matches->data)
eina_stringshare_del(kb->string_matches->data);
kb->string_matches = eina_list_remove_list(kb->string_matches, kb->string_matches);
}
}
static void
_e_kbd_buf_actual_string_clear(E_Kbd_Buf *kb)
{
if (kb->actual_string) eina_stringshare_del(kb->actual_string);
kb->actual_string = NULL;
}
static E_Kbd_Buf_Key *
_e_kbd_buf_at_coord_get(E_Kbd_Buf *kb EINA_UNUSED, E_Kbd_Buf_Layout *kbl, int x, int y)
{
Eina_List *l;
for (l = kbl->keys; l; l = l->next)
{
E_Kbd_Buf_Key *ky;
ky = l->data;
if (ky->key)
{
if ((x >= ky->x) && (y >= ky->y) &&
(x < (ky->x + ky->w)) && (y < (ky->y + ky->h)))
return ky;
}
}
return NULL;
}
static E_Kbd_Buf_Key *
_e_kbd_buf_closest_get(E_Kbd_Buf *kb EINA_UNUSED, E_Kbd_Buf_Layout *kbl, int x, int y)
{
Eina_List *l;
E_Kbd_Buf_Key *ky_closest = NULL;
int dist_closest = 0x7fffffff;
for (l = kbl->keys; l; l = l->next)
{
E_Kbd_Buf_Key *ky;
int dist, dx, dy;
ky = l->data;
if (ky->key)
{
dx = x - (ky->x + (ky->w / 2));
dy = y - (ky->y + (ky->h / 2));
dist = (dx * dx) + (dy * dy);
if (dist < dist_closest)
{
ky_closest = ky;
dist_closest = dist;
}
}
}
return ky_closest;
}
static const char *
_e_kbd_buf_keystroke_key_string_get(E_Kbd_Buf *kb EINA_UNUSED, E_Kbd_Buf_Keystroke *ks, E_Kbd_Buf_Key *ky)
{
const char *str = NULL;
if ((ky) && (ky->key))
{
if (ks->shift)
{
if (ky->key_shift) str = ky->key_shift;
else str = ky->key;
}
else if (ks->capslock)
{
if (ky->key_capslock) str = ky->key_capslock;
else str = ky->key;
}
else str = ky->key;
}
return str;
}
static const char *
_e_kbd_buf_keystroke_string_get(E_Kbd_Buf *kb, E_Kbd_Buf_Keystroke *ks)
{
const char *str = NULL;
if (ks->key) str = ks->key;
else
{
E_Kbd_Buf_Key *ky;
ky = _e_kbd_buf_at_coord_get(kb, ks->layout, ks->x, ks->y);
if (!ky) ky = _e_kbd_buf_closest_get(kb, ks->layout, ks->x, ks->y);
str = _e_kbd_buf_keystroke_key_string_get(kb, ks, ky);
}
return str;
}
static void
_e_kbd_buf_actual_string_update(E_Kbd_Buf *kb)
{
Eina_List *l;
char *actual = NULL;
int actual_len = 0;
unsigned int actual_size = 0;
E_Kbd_Buf_Keystroke *ks;
_e_kbd_buf_actual_string_clear(kb);
EINA_LIST_FOREACH(kb->keystrokes, l, ks)
{
const char *str;
str = _e_kbd_buf_keystroke_string_get(kb, ks);
if (!str) continue;
if (!actual) actual_size += 64, actual = malloc(actual_size);
else if ((actual_len + strlen(str) + 1) > actual_size)
{
actual_size += 64;
actual = realloc(actual, actual_size);
}
strcpy(actual + actual_len, str);
actual_len += strlen(str);
}
kb->actual_string = eina_stringshare_add(actual);
free(actual);
}
static const char *
_e_kbd_buf_matches_find(Eina_List *matches, const char *s)
{
Eina_List *l;
for (l = matches; l; l = l->next)
{
if (!strcmp(l->data, s)) return s;
}
return NULL;
}
static void
_e_kbd_buf_matches_update(E_Kbd_Buf *kb)
{
const char *word;
int pri, i;
E_Kbd_Dict *dicts[3];
_e_kbd_buf_string_matches_clear(kb);
dicts[0] = kb->dict.personal;
dicts[1] = kb->dict.sys;
dicts[2] = kb->dict.data;
for (i = 0; i < 3; i++)
{
if (!dicts[i]) continue;
e_kbd_dict_matches_lookup(dicts[i]);
e_kbd_dict_matches_first(dicts[i]);
for (;;)
{
word = e_kbd_dict_matches_match_get(dicts[i], &pri);
if (!word) break;
if (!_e_kbd_buf_matches_find(kb->string_matches, word))
kb->string_matches = eina_list_append(kb->string_matches,
eina_stringshare_add(word));
e_kbd_dict_matches_next(dicts[i]);
}
}
}
static Eina_Bool
_e_kbd_buf_cb_data_dict_reload(void *data)
{
E_Kbd_Buf *kb;
char buf[PATH_MAX];
kb = data;
kb->dict.data_reload_delay = NULL;
e_kbd_buf_clear(kb);
if (kb->dict.data) e_kbd_dict_free(kb->dict.data);
e_user_dir_concat_static(buf, "dicts-dynamic/data.dic");
kb->dict.data = e_kbd_dict_new(buf);
return ECORE_CALLBACK_CANCEL;
}
static void
_e_kbd_buf_cb_data_dict_change(void *data, Ecore_File_Monitor *em EINA_UNUSED, Ecore_File_Event event EINA_UNUSED, const char *path EINA_UNUSED)
{
E_Kbd_Buf *kb;
kb = data;
if (kb->dict.data_reload_delay) ecore_timer_del(kb->dict.data_reload_delay);
kb->dict.data_reload_delay = ecore_timer_add(2.0, _e_kbd_buf_cb_data_dict_reload, kb);
}
EAPI E_Kbd_Buf *
e_kbd_buf_new(const char *sysdicts, const char *dict)
{
E_Kbd_Buf *kb;
char buf[PATH_MAX];
kb = E_NEW(E_Kbd_Buf, 1);
if (!kb) return NULL;
kb->sysdicts = eina_stringshare_add(sysdicts);
e_user_dir_concat_static(buf, "dicts");
if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
e_user_dir_snprintf(buf, sizeof(buf), "dicts/%s", dict);
kb->dict.sys = e_kbd_dict_new(buf);
if (!kb->dict.sys)
{
snprintf(buf, sizeof(buf), "%s/dicts/%s", kb->sysdicts, dict);
kb->dict.sys = e_kbd_dict_new(buf);
}
e_user_dir_concat_static(buf, "dicts-dynamic");
if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
e_user_dir_concat_static(buf, "dicts-dynamic/personal.dic");
kb->dict.personal = e_kbd_dict_new(buf);
if (!kb->dict.personal)
{
FILE *f;
f = fopen(buf, "w");
if (f)
{
fprintf(f, "\n");
fclose(f);
}
kb->dict.personal = e_kbd_dict_new(buf);
}
e_user_dir_concat_static(buf, "dicts-dynamic/data.dic");
kb->dict.data = e_kbd_dict_new(buf);
kb->dict.data_monitor =
ecore_file_monitor_add(buf, _e_kbd_buf_cb_data_dict_change, kb);
return kb;
}
EAPI void
e_kbd_buf_free(E_Kbd_Buf *kb)
{
e_kbd_buf_clear(kb);
e_kbd_buf_layout_clear(kb);
e_kbd_buf_lookup_cancel(kb);
eina_stringshare_del(kb->sysdicts);
if (kb->dict.sys) e_kbd_dict_free(kb->dict.sys);
if (kb->dict.personal) e_kbd_dict_free(kb->dict.personal);
if (kb->dict.data) e_kbd_dict_free(kb->dict.data);
if (kb->dict.data_monitor) ecore_file_monitor_del(kb->dict.data_monitor);
if (kb->dict.data_reload_delay) ecore_timer_del(kb->dict.data_reload_delay);
free(kb);
}
EAPI void
e_kbd_buf_dict_set(E_Kbd_Buf *kb, const char *dict)
{
char buf[PATH_MAX];
e_kbd_buf_clear(kb);
if (kb->dict.sys) e_kbd_dict_free(kb->dict.sys);
e_user_dir_concat_static(buf, "dicts");
if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
e_user_dir_snprintf(buf, sizeof(buf), "dicts/%s", dict);
kb->dict.sys = e_kbd_dict_new(buf);
if (!kb->dict.sys)
{
snprintf(buf, sizeof(buf), "%s/dicts/%s", kb->sysdicts, dict);
kb->dict.sys = e_kbd_dict_new(buf);
}
}
EAPI void
e_kbd_buf_clear(E_Kbd_Buf *kb)
{
e_kbd_buf_lookup_cancel(kb);
while (kb->keystrokes)
{
E_Kbd_Buf_Keystroke *ks;
ks = kb->keystrokes->data;
if (ks->key) eina_stringshare_del(ks->key);
_e_kbd_buf_layout_unref(ks->layout);
free(ks);
kb->keystrokes = eina_list_remove_list(kb->keystrokes, kb->keystrokes);
}
_e_kbd_buf_string_matches_clear(kb);
if (kb->dict.sys) e_kbd_dict_word_letter_clear(kb->dict.sys);
if (kb->dict.personal) e_kbd_dict_word_letter_clear(kb->dict.personal);
if (kb->dict.data) e_kbd_dict_word_letter_clear(kb->dict.data);
_e_kbd_buf_actual_string_clear(kb);
}
EAPI void
e_kbd_buf_layout_clear(E_Kbd_Buf *kb)
{
if (kb->layout)
{
_e_kbd_buf_layout_unref(kb->layout);
kb->layout = NULL;
}
}
EAPI void
e_kbd_buf_layout_size_set(E_Kbd_Buf *kb, int w, int h)
{
if (!kb->layout) kb->layout = _e_kbd_buf_new();
if (!kb->layout) return;
kb->layout->w = w;
kb->layout->h = h;
}
EAPI void
e_kbd_buf_layout_fuzz_set(E_Kbd_Buf *kb, int fuzz)
{
if (!kb->layout) kb->layout = _e_kbd_buf_new();
if (!kb->layout) return;
kb->layout->fuzz = fuzz;
}
EAPI void
e_kbd_buf_layout_key_add(E_Kbd_Buf *kb, const char *key, const char *key_shift, const char *key_capslock, const char *key_altgr, int x, int y, int w, int h)
{
E_Kbd_Buf_Key *ky;
if (!key) return;
if (!kb->layout) kb->layout = _e_kbd_buf_new();
if (!kb->layout) return;
ky = E_NEW(E_Kbd_Buf_Key, 1);
if (!ky) return;
ky->key = eina_stringshare_add(key);
if (key_shift) ky->key_shift = eina_stringshare_add(key_shift);
if (key_capslock) ky->key_capslock = eina_stringshare_add(key_capslock);
if (key_altgr) ky->key_altgr = eina_stringshare_add(key_altgr);
ky->x = x;
ky->y = y;
ky->w = w;
ky->h = h;
kb->layout->keys = eina_list_append(kb->layout->keys, ky);
}
static void
_e_kbd_buf_keystroke_add(E_Kbd_Buf *kb, E_Kbd_Buf_Keystroke *ks)
{
const char *str;
str = _e_kbd_buf_keystroke_string_get(kb, ks);
if (str)
{
if (kb->dict.sys) e_kbd_dict_word_letter_add(kb->dict.sys, str, 0);
if (kb->dict.personal) e_kbd_dict_word_letter_add(kb->dict.personal, str, 0);
if (kb->dict.data) e_kbd_dict_word_letter_add(kb->dict.data, str, 0);
}
}
EAPI void
e_kbd_buf_pressed_key_add(E_Kbd_Buf *kb, const char *key, int shift, int capslock)
{
E_Kbd_Buf_Keystroke *ks;
e_kbd_buf_lookup_cancel(kb);
if (!key) return;
if (!kb->layout) kb->layout = _e_kbd_buf_new();
if (!kb->layout) return;
ks = E_NEW(E_Kbd_Buf_Keystroke, 1);
if (!ks) return;
ks->key = eina_stringshare_add(key);
if (shift) ks->shift = 1;
if (capslock) ks->capslock = 1;
ks->layout = kb->layout;
_e_kbd_buf_layout_ref(ks->layout);
kb->keystrokes = eina_list_append(kb->keystrokes, ks);
if (kb->dict.sys) e_kbd_dict_word_letter_advance(kb->dict.sys);
if (kb->dict.personal) e_kbd_dict_word_letter_advance(kb->dict.personal);
if (kb->dict.data) e_kbd_dict_word_letter_advance(kb->dict.data);
_e_kbd_buf_keystroke_add(kb, ks);
_e_kbd_buf_actual_string_update(kb);
_e_kbd_buf_matches_update(kb);
}
static void
_e_kbd_buf_keystroke_point_add(E_Kbd_Buf *kb, E_Kbd_Buf_Keystroke *ks)
{
Eina_List *l;
for (l = ks->layout->keys; l; l = l->next)
{
E_Kbd_Buf_Key *ky;
const char *str;
int px, py, dx, dy, d;
ky = l->data;
px = ky->x + (ky->w / 2);
py = ky->y + (ky->h / 2);
dx = ks->x - px;
dy = ks->y - py;
d = sqrt((dx * dx) + (dy * dy));
if (d <= ks->layout->fuzz)
{
str = _e_kbd_buf_keystroke_key_string_get(kb, ks, ky);
if (str)
{
if (kb->dict.sys) e_kbd_dict_word_letter_add(kb->dict.sys, str, d);
if (kb->dict.personal) e_kbd_dict_word_letter_add(kb->dict.personal, str, d);
if (kb->dict.data) e_kbd_dict_word_letter_add(kb->dict.data, str, d);
}
}
}
}
EAPI void
e_kbd_buf_pressed_point_add(E_Kbd_Buf *kb, int x, int y, int shift, int capslock)
{
E_Kbd_Buf_Keystroke *ks;
e_kbd_buf_lookup_cancel(kb);
if (!kb->layout) kb->layout = _e_kbd_buf_new();
if (!kb->layout) return;
ks = E_NEW(E_Kbd_Buf_Keystroke, 1);
if (!ks) return;
ks->x = x;
ks->y = y;
if (shift) ks->shift = 1;
if (capslock) ks->capslock = 1;
ks->layout = kb->layout;
_e_kbd_buf_layout_ref(ks->layout);
kb->keystrokes = eina_list_append(kb->keystrokes, ks);
if (kb->dict.sys) e_kbd_dict_word_letter_advance(kb->dict.sys);
if (kb->dict.personal) e_kbd_dict_word_letter_advance(kb->dict.personal);
if (kb->dict.data) e_kbd_dict_word_letter_advance(kb->dict.data);
_e_kbd_buf_keystroke_point_add(kb, ks);
_e_kbd_buf_actual_string_update(kb);
_e_kbd_buf_matches_update(kb);
}
EAPI const char *
e_kbd_buf_actual_string_get(E_Kbd_Buf *kb)
{
return kb->actual_string;
}
EAPI const Eina_List *
e_kbd_buf_string_matches_get(E_Kbd_Buf *kb)
{
return kb->string_matches;
}
EAPI void
e_kbd_buf_backspace(E_Kbd_Buf *kb)
{
Eina_List *l;
l = eina_list_last(kb->keystrokes);
if (l)
{
E_Kbd_Buf_Keystroke *ks;
ks = l->data;
if (ks->key) eina_stringshare_del(ks->key);
_e_kbd_buf_layout_unref(ks->layout);
free(ks);
kb->keystrokes = eina_list_remove_list(kb->keystrokes, l);
if (kb->dict.sys) e_kbd_dict_word_letter_delete(kb->dict.sys);
if (kb->dict.personal) e_kbd_dict_word_letter_delete(kb->dict.personal);
if (kb->dict.data) e_kbd_dict_word_letter_delete(kb->dict.data);
_e_kbd_buf_actual_string_update(kb);
_e_kbd_buf_matches_update(kb);
}
}
EAPI void
e_kbd_buf_word_use(E_Kbd_Buf *kb, const char *word)
{
if (kb->dict.personal)
e_kbd_dict_word_usage_adjust(kb->dict.personal, word, 1);
}
// FIXME: just faking delayed lookup with timer
static Eina_Bool
_e_kbd_buf_cb_faket(void *data)
{
E_Kbd_Buf *kb;
kb = data;
kb->lookup.faket = NULL;
kb->lookup.func((void *)kb->lookup.data);
kb->lookup.func = NULL;
kb->lookup.data = NULL;
return ECORE_CALLBACK_CANCEL;
}
EAPI void
e_kbd_buf_lookup(E_Kbd_Buf *kb, void (*func) (void *data), const void *data)
{
e_kbd_buf_lookup_cancel(kb);
kb->lookup.func = func;
kb->lookup.data = data;
// FIXME: just faking delayed lookup with timer
kb->lookup.faket = ecore_timer_add(0.1, _e_kbd_buf_cb_faket, kb);
}
EAPI void
e_kbd_buf_lookup_cancel(E_Kbd_Buf *kb)
{
// FIXME: just faking delayed lookup with timer
if (!kb->lookup.faket) return;
ecore_timer_del(kb->lookup.faket);
kb->lookup.faket = NULL;
kb->lookup.func = NULL;
kb->lookup.data = NULL;
}

View File

@ -0,0 +1,73 @@
#ifndef E_KBD_BUF_H
#define E_KBD_BUF_H
#include "e_kbd_dict.h"
typedef struct _E_Kbd_Buf E_Kbd_Buf;
typedef struct _E_Kbd_Buf_Key E_Kbd_Buf_Key;
typedef struct _E_Kbd_Buf_Keystroke E_Kbd_Buf_Keystroke;
typedef struct _E_Kbd_Buf_Layout E_Kbd_Buf_Layout;
struct _E_Kbd_Buf
{
const char *sysdicts;
Eina_List *keystrokes;
Eina_List *string_matches;
const char *actual_string;
E_Kbd_Buf_Layout *layout;
struct {
void (*func) (void *data);
const void *data;
// FIXME: just faking delayed lookup with timer
Ecore_Timer *faket;
} lookup;
struct {
E_Kbd_Dict *sys;
E_Kbd_Dict *personal;
E_Kbd_Dict *data;
Ecore_File_Monitor *data_monitor;
Ecore_Timer *data_reload_delay;
} dict;
};
struct _E_Kbd_Buf_Key
{
int x, y, w, h;
const char *key, *key_shift, *key_capslock, *key_altgr;
};
struct _E_Kbd_Buf_Keystroke
{
const char *key;
int x, y;
E_Kbd_Buf_Layout *layout;
unsigned char shift : 1;
unsigned char capslock : 1;
};
struct _E_Kbd_Buf_Layout
{
int ref;
int w, h;
int fuzz;
Eina_List *keys;
};
EAPI E_Kbd_Buf *e_kbd_buf_new(const char *sysdicts, const char *dicts);
EAPI void e_kbd_buf_free(E_Kbd_Buf *kb);
EAPI void e_kbd_buf_dict_set(E_Kbd_Buf *kb, const char *dict);
EAPI void e_kbd_buf_clear(E_Kbd_Buf *kb);
EAPI void e_kbd_buf_layout_clear(E_Kbd_Buf *kb);
EAPI void e_kbd_buf_layout_size_set(E_Kbd_Buf *kb, int w, int h);
EAPI void e_kbd_buf_layout_fuzz_set(E_Kbd_Buf *kb, int fuzz);
EAPI void e_kbd_buf_layout_key_add(E_Kbd_Buf *kb, const char *key, const char *key_shift, const char *key_capslock, const char *key_altgr, int x, int y, int w, int h);
EAPI void e_kbd_buf_pressed_key_add(E_Kbd_Buf *kb, const char *key, int shift, int capslock);
EAPI void e_kbd_buf_pressed_point_add(E_Kbd_Buf *kb, int x, int y, int shift, int capslock);
EAPI const char *e_kbd_buf_actual_string_get(E_Kbd_Buf *kb);
EAPI const Eina_List *e_kbd_buf_string_matches_get(E_Kbd_Buf *kb);
EAPI void e_kbd_buf_backspace(E_Kbd_Buf *kb);
EAPI void e_kbd_buf_lookup(E_Kbd_Buf *kb, void (*func) (void *data), const void *data);
EAPI void e_kbd_buf_lookup_cancel(E_Kbd_Buf *kb);
EAPI void e_kbd_buf_word_use(E_Kbd_Buf *kb, const char *word);
#endif

View File

@ -0,0 +1,205 @@
#include "e.h"
#include "e_mod_main.h"
#include "e_kbd_cfg.h"
#include "e_kbd_buf.h"
static E_Kbd_Int *cfg_kbd = NULL;
static Eina_List *dicts = NULL;
static Evas_Object *win = NULL;
static void
_cb_close(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
e_kbd_cfg_hide(cfg_kbd);
}
static void
_cb_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
char *s;
EINA_LIST_FREE(dicts, s) eina_stringshare_del(s);
win = NULL;
cfg_kbd = NULL;
}
static void
_cb_size(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
double v = elm_slider_value_get(obj);
il_kbd_cfg->size = v;
e_kbd_int_update(cfg_kbd);
e_config_save_queue();
}
static void
_cb_fill_mode(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
il_kbd_cfg->fill_mode = (int)(uintptr_t)data;
if (il_kbd_cfg->fill_mode == 0) elm_object_text_set(obj, _("Shrink"));
else if (il_kbd_cfg->fill_mode == 1) elm_object_text_set(obj, _("Stretch"));
else if (il_kbd_cfg->fill_mode == 2) elm_object_text_set(obj, _("Fill"));
else if (il_kbd_cfg->fill_mode == 3) elm_object_text_set(obj, _("Float"));
e_kbd_int_update(cfg_kbd);
e_config_save_queue();
}
static void
_cb_dict(void *data, Evas_Object *li EINA_UNUSED, void *event_info EINA_UNUSED)
{
char *s = data;
eina_stringshare_replace(&il_kbd_cfg->dict, s);
e_kbd_buf_dict_set(cfg_kbd->kbuf, il_kbd_cfg->dict);
e_kbd_buf_clear(cfg_kbd->kbuf);
e_config_save_queue();
}
EAPI void
e_kbd_cfg_show(E_Kbd_Int *ki)
{
Evas_Object *o, *box, *fr, *li, *tb;
Elm_Object_Item *it;
Eina_List *files;
char buf[PATH_MAX], *p, *f;
const char *p2;
if (cfg_kbd) return;
cfg_kbd = ki;
win = e_elm_win_util_dialog_add(NULL, "vkbd_config",
_("Virtual Keyboard Settings"));
evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cb_del, NULL);
elm_win_autodel_set(win, EINA_TRUE);
o = fr = elm_frame_add(win);
E_EXPAND(o);
E_FILL(o);
elm_object_style_set(o, "pad_large");
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_win_resize_object_add(win, o);
evas_object_show(o);
box = o = elm_box_add(win);
E_EXPAND(o);
E_FILL(o);
elm_object_content_set(fr, o);
evas_object_show(o);
o = fr = elm_frame_add(win);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_layout_text_set(o, NULL, _("Layout Mode"));
elm_box_pack_end(box, o);
evas_object_show(o);
o = elm_hoversel_add(win);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_hoversel_auto_update_set(o, EINA_TRUE);
elm_hoversel_hover_parent_set(o, win);
if (il_kbd_cfg->fill_mode == 0) elm_object_text_set(o, _("Shrink"));
else if (il_kbd_cfg->fill_mode == 1) elm_object_text_set(o, _("Stretch"));
else if (il_kbd_cfg->fill_mode == 2) elm_object_text_set(o, _("Fill"));
else if (il_kbd_cfg->fill_mode == 3) elm_object_text_set(o, _("Float"));
elm_hoversel_item_add(o, _("Shrink"), NULL, ELM_ICON_NONE, _cb_fill_mode, (void *)(uintptr_t)0);
elm_hoversel_item_add(o, _("Stretch"), NULL, ELM_ICON_NONE, _cb_fill_mode, (void *)(uintptr_t)1);
elm_hoversel_item_add(o, _("Fill"), NULL, ELM_ICON_NONE, _cb_fill_mode, (void *)(uintptr_t)2);
elm_hoversel_item_add(o, _("Float"), NULL, ELM_ICON_NONE, _cb_fill_mode, (void *)(uintptr_t)3);
elm_object_content_set(fr, o);
evas_object_show(o);
o = fr = elm_frame_add(win);
E_EXPAND(o);
E_FILL(o);
elm_layout_text_set(o, NULL, _("Dictionary"));
elm_box_pack_end(box, o);
evas_object_show(o);
o = tb = elm_table_add(win);
E_EXPAND(o);
E_FILL(o);
elm_object_content_set(fr, o);
evas_object_show(o);
o = evas_object_rectangle_add(evas_object_evas_get(win));
E_EXPAND(o);
E_FILL(o);
evas_object_color_set(o, 0, 0, 0, 0);
evas_object_size_hint_min_set(o,
elm_config_scale_get() * 80,
elm_config_scale_get() * 80);
elm_table_pack(tb, o, 0, 0, 1, 1);
o = li = elm_list_add(win);
E_EXPAND(o);
E_FILL(o);
snprintf(buf, sizeof(buf), "%s/dicts", ki->syskbds);
files = ecore_file_ls(buf);
EINA_LIST_FREE(files, f)
{
strncpy(buf, f, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = 0;
p = strrchr(buf, '.');
if ((p) && (!strcasecmp(p, ".dic")))
{
p2 = eina_stringshare_add(buf);
dicts = eina_list_append(dicts, p2);
*p = 0;
it = elm_list_item_append(li, buf, NULL, NULL, _cb_dict, p2);
if (!strcasecmp(p2, il_kbd_cfg->dict))
elm_list_item_selected_set(it, EINA_TRUE);
}
free(f);
}
elm_list_go(o);
elm_table_pack(tb, o, 0, 0, 1, 1);
evas_object_show(o);
o = fr = elm_frame_add(win);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_layout_text_set(o, NULL, _("Sizing"));
elm_box_pack_end(box, o);
evas_object_show(o);
o = elm_slider_add(win);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_slider_unit_format_set(o, "%1.1f");
elm_slider_step_set(o, 0.2);
elm_slider_span_size_set(o, 240);
elm_slider_min_max_set(o, 1.0, 9.0);
elm_slider_value_set(o, il_kbd_cfg->size);
evas_object_smart_callback_add(o, "changed", _cb_size, NULL);
elm_object_content_set(fr, o);
evas_object_show(o);
o = elm_separator_add(win);
elm_separator_horizontal_set(o, EINA_TRUE);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(box, o);
evas_object_show(o);
o = elm_button_add(win);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(o, _("Close"));
evas_object_smart_callback_add(o, "clicked", _cb_close, NULL);
elm_box_pack_end(box, o);
evas_object_show(o);
evas_object_show(win);
evas_smart_objects_calculate(evas_object_evas_get(win));
elm_win_center(win, 1, 1);
}
EAPI void
e_kbd_cfg_hide(E_Kbd_Int *ki)
{
if (!ki) return;
if (cfg_kbd != ki) return;
if (win) evas_object_del(win);
cfg_kbd = NULL;
}

View File

@ -0,0 +1,9 @@
#ifndef E_KBD_CFG_H
#define E_KBD_CFG_H
#include "e_kbd_int.h"
EAPI void e_kbd_cfg_show(E_Kbd_Int *ki);
EAPI void e_kbd_cfg_hide(E_Kbd_Int *ki);
#endif

View File

@ -0,0 +1,880 @@
#include "e.h"
#include "e_kbd_dict.h"
#include <fcntl.h>
#include <sys/mman.h>
#define MAXLATIN 0x100
static unsigned char _e_kbd_normalise_base[MAXLATIN];
static unsigned char _e_kbd_normalise_ready = 0;
static void
_e_kbd_normalise_init(void)
{
int i;
const char *table[][2] =
{
{"À", "a"},
{"Á", "a"},
{"Â", "a"},
{"Ã", "a"},
{"Ä", "a"},
{"Å", "a"},
{"Æ", "a"},
{"Ç", "c"},
{"È", "e"},
{"É", "e"},
{"Ê", "e"},
{"Ë", "e"},
{"Ì", "i"},
{"Í", "i"},
{"Î", "i"},
{"Ï", "i"},
{"Ð", "d"},
{"Ñ", "n"},
{"Ò", "o"},
{"Ó", "o"},
{"Ô", "o"},
{"Õ", "o"},
{"Ö", "o"},
{"×", "x"},
{"Ø", "o"},
{"Ù", "u"},
{"Ú", "u"},
{"Û", "u"},
{"Ü", "u"},
{"Ý", "y"},
{"Þ", "p"},
{"ß", "s"},
{"à", "a"},
{"á", "a"},
{"â", "a"},
{"ã", "a"},
{"ä", "a"},
{"å", "a"},
{"æ", "a"},
{"ç", "c"},
{"è", "e"},
{"é", "e"},
{"ê", "e"},
{"ë", "e"},
{"ì", "i"},
{"í", "i"},
{"î", "i"},
{"ï", "i"},
{"ð", "o"},
{"ñ", "n"},
{"ò", "o"},
{"ó", "o"},
{"ô", "o"},
{"õ", "o"},
{"ö", "o"},
{"ø", "o"},
{"ù", "u"},
{"ú", "u"},
{"û", "u"},
{"ü", "u"},
{"ý", "y"},
{"þ", "p"},
{"ÿ", "y"}
}; // 63 items
if (_e_kbd_normalise_ready) return;
_e_kbd_normalise_ready = 1;
for (i = 0; i < 128; i++)
_e_kbd_normalise_base[i] = tolower(i);
for (;i < MAXLATIN; i++)
{
int glyph, j;
for (j = 0; j < 63; j++)
{
evas_string_char_next_get(table[j][0], 0, &glyph);
if (glyph == i)
{
_e_kbd_normalise_base[i] = *table[j][1];
break;
}
}
}
}
static int
_e_kbd_dict_letter_normalise(int glyph)
{
// FIXME: ö -> o, ä -> a, Ó -> o etc. - ie normalise to latin-1
if (glyph < MAXLATIN) return _e_kbd_normalise_base[glyph];
return tolower(glyph) & 0x7f;
}
static int
_e_kbd_dict_normalized_strncmp(const char *a, const char *b, int len)
{
// FIXME: normalise 2 strings and then compare
if (len < 0) return strcasecmp(a, b);
return strncasecmp(a, b, len);
}
static int
_e_kbd_dict_normalized_strcmp(const char *a, const char *b)
{
return _e_kbd_dict_normalized_strncmp(a, b, -1);
}
static void
_e_kbd_dict_normalized_strcpy(char *dst, const char *src)
{
const char *p;
char *d;
for (p = src, d = dst; *p; p++, d++)
*d = _e_kbd_dict_letter_normalise(*p);
*d = 0;
}
static int
_e_kbd_dict_matches_lookup_cb_sort(const void *d1, const void *d2)
{
const E_Kbd_Dict_Word *kw1, *kw2;
kw1 = d1;
kw2 = d2;
if (kw1->usage < kw2->usage) return 1;
else if (kw1->usage > kw2->usage) return -1;
return 0;
}
static int
_e_kbd_dict_writes_cb_sort(const void *d1, const void *d2)
{
const E_Kbd_Dict_Word *kw1, *kw2;
kw1 = d1;
kw2 = d2;
return _e_kbd_dict_normalized_strcmp(kw1->word, kw2->word);
}
static const char *
_e_kbd_dict_line_next(E_Kbd_Dict *kd, const char *p)
{
const char *e, *pp;
e = kd->file.dict + kd->file.size;
for (pp = p; pp < e; pp++)
if (*pp == '\n') return pp + 1;
return NULL;
}
static char *
_e_kbd_dict_line_parse(E_Kbd_Dict *kd EINA_UNUSED, const char *p, int *usage)
{
const char *ps;
char *wd = NULL;
for (ps = p; !isspace(*ps); ps++);
wd = malloc(ps - p + 1);
if (!wd) return NULL;
strncpy(wd, p, ps - p);
wd[ps - p] = 0;
if (*ps == '\n') *usage = 0;
else
{
ps++;
*usage = atoi(ps);
}
return wd;
}
static void
_e_kbd_dict_lookup_build_line(E_Kbd_Dict *kd EINA_UNUSED, const char *p, const char *eol, int *glyphs)
{
char *s;
int p2;
s = alloca(eol - p + 1);
strncpy(s, p, eol - p);
s[eol - p] = 0;
p2 = evas_string_char_next_get(s, 0, &(glyphs[0]));
if ((p2 > 0) && (glyphs[0] > 0))
evas_string_char_next_get(s, p2, &(glyphs[1]));
}
static void
_e_kbd_dict_lookup_build(E_Kbd_Dict *kd)
{
const char *p, *e, *eol, *base;
int glyphs[2], pglyphs[2];
int i, j, line = 0;
p = base = kd->file.dict;
e = p + kd->file.size;
pglyphs[0] = pglyphs[1] = 0;
for (j = 0; j < 128; j++)
{
for (i = 0; i < 128; i++)
kd->lookup.tuples[j][i] = -1;
}
while (p < e)
{
eol = strchr(p, '\n');
if (!eol) break;
line++;
if ((p - base) >= 0x7fffffff)
{
ERR("DICT %s TOO BIG! must be < 2GB", kd->file.file);
return;
}
if (eol > p)
{
glyphs[0] = glyphs[1] = 0;
_e_kbd_dict_lookup_build_line(kd, p, eol, glyphs);
if ((glyphs[1] != pglyphs[1]) || (glyphs[0] != pglyphs[0]))
{
int v1, v2;
if (isspace(glyphs[0]))
{
glyphs[0] = 0;
glyphs[1] = 0;
}
else if (isspace(glyphs[1]))
glyphs[1] = 0;
if (glyphs[0] == 0)
{
pglyphs[0] = pglyphs[1] = 0;
p = eol + 1;
continue;
}
v1 = _e_kbd_dict_letter_normalise(glyphs[0]);
v2 = _e_kbd_dict_letter_normalise(glyphs[1]);
if (kd->lookup.tuples[v1][v2] == -1)
kd->lookup.tuples[v1][v2] = (unsigned int)(p - base);
pglyphs[0] = v1;
pglyphs[1] = v2;
}
}
p = eol + 1;
}
}
static int
_e_kbd_dict_open(E_Kbd_Dict *kd)
{
struct stat st;
kd->file.fd = open(kd->file.file, O_RDONLY);
if (kd->file.fd < 0) return 0;
if (fstat(kd->file.fd, &st) < 0)
{
close(kd->file.fd);
return 0;
}
kd->file.size = st.st_size;
eina_mmap_safety_enabled_set(EINA_TRUE);
kd->file.dict = mmap(NULL, kd->file.size, PROT_READ, MAP_SHARED,
kd->file.fd, 0);
if ((kd->file.dict== MAP_FAILED) || (!kd->file.dict))
{
close(kd->file.fd);
return 0;
}
return 1;
}
static void
_e_kbd_dict_close(E_Kbd_Dict *kd)
{
if (kd->file.fd < 0) return;
memset(kd->lookup.tuples, 0, sizeof(kd->lookup.tuples));
munmap((void *)kd->file.dict, kd->file.size);
close(kd->file.fd);
kd->file.fd = -1;
kd->file.dict = NULL;
kd->file.size = 0;
}
EAPI E_Kbd_Dict *
e_kbd_dict_new(const char *file)
{
// alloc and load new dict - build quick-lookup table. words MUST be sorted
E_Kbd_Dict *kd;
_e_kbd_normalise_init();
kd = E_NEW(E_Kbd_Dict, 1);
if (!kd) return NULL;
kd->file.file = eina_stringshare_add(file);
if (!kd->file.file)
{
free(kd);
return NULL;
}
kd->file.fd = -1;
if (!_e_kbd_dict_open(kd))
{
eina_stringshare_del(kd->file.file);
free(kd);
return NULL;
}
_e_kbd_dict_lookup_build(kd);
return kd;
}
EAPI void
e_kbd_dict_free(E_Kbd_Dict *kd)
{
// free dict and anything in it
e_kbd_dict_word_letter_clear(kd);
e_kbd_dict_save(kd);
_e_kbd_dict_close(kd);
free(kd);
}
static E_Kbd_Dict_Word *
_e_kbd_dict_changed_write_find(E_Kbd_Dict *kd, const char *word)
{
Eina_List *l;
for (l = kd->changed.writes; l; l = l->next)
{
E_Kbd_Dict_Word *kw;
kw = l->data;
if (!strcmp(kw->word, word)) return kw;
}
return NULL;
}
EAPI void
e_kbd_dict_save(E_Kbd_Dict *kd)
{
FILE *f;
// XXX: disable personal dict saving for now as we don't merge personal
// XXX: and system dict stats very well at all
return;
// save any changes (new words added, usage adjustments).
// all words MUST be sorted
if (!kd->changed.writes) return;
if (kd->changed.flush_timer)
{
ecore_timer_del(kd->changed.flush_timer);
kd->changed.flush_timer = NULL;
}
ecore_file_unlink(kd->file.file);
f = fopen(kd->file.file, "w");
kd->changed.writes = eina_list_sort(kd->changed.writes,
eina_list_count(kd->changed.writes),
_e_kbd_dict_writes_cb_sort);
if (f)
{
const char *p, *pn;
p = kd->file.dict;
while (p)
{
char *wd;
int usage = 0;
pn = _e_kbd_dict_line_next(kd, p);
if (!pn)
{
fclose(f);
return;
}
wd = _e_kbd_dict_line_parse(kd, p, &usage);
if ((wd) && (strlen(wd) > 0))
{
if (kd->changed.writes)
{
int writeline = 0;
while (kd->changed.writes)
{
E_Kbd_Dict_Word *kw;
int cmp;
kw = kd->changed.writes->data;
cmp = _e_kbd_dict_normalized_strcmp(kw->word, wd);
if (cmp < 0)
{
fprintf(f, "%s %i\n", kw->word, kw->usage);
writeline = 1;
eina_stringshare_del(kw->word);
free(kw);
kd->changed.writes = eina_list_remove_list(kd->changed.writes, kd->changed.writes);
}
else if (cmp == 0)
{
fprintf(f, "%s %i\n", wd, kw->usage);
if (!strcmp(kw->word, wd))
writeline = 0;
else
writeline = 1;
eina_stringshare_del(kw->word);
free(kw);
kd->changed.writes = eina_list_remove_list(kd->changed.writes, kd->changed.writes);
break;
}
else if (cmp > 0)
{
writeline = 1;
break;
}
}
if (writeline)
fprintf(f, "%s %i\n", wd, usage);
}
else
fprintf(f, "%s %i\n", wd, usage);
}
free(wd);
p = pn;
if (p >= (kd->file.dict + kd->file.size)) break;
}
while (kd->changed.writes)
{
E_Kbd_Dict_Word *kw;
kw = kd->changed.writes->data;
fprintf(f, "%s %i\n", kw->word, kw->usage);
eina_stringshare_del(kw->word);
free(kw);
kd->changed.writes = eina_list_remove_list(kd->changed.writes, kd->changed.writes);
}
fclose(f);
}
_e_kbd_dict_close(kd);
if (_e_kbd_dict_open(kd)) _e_kbd_dict_lookup_build(kd);
}
static Eina_Bool
_e_kbd_dict_cb_save_flush(void *data)
{
E_Kbd_Dict *kd;
kd = data;
if ((kd->matches.list) || (kd->word.letters) || (kd->matches.deadends) ||
(kd->matches.leads))
return EINA_TRUE;
kd->changed.flush_timer = NULL;
e_kbd_dict_save(kd);
return EINA_FALSE;
}
static void
_e_kbd_dict_changed_write_add(E_Kbd_Dict *kd, const char *word, int usage)
{
E_Kbd_Dict_Word *kw;
kw = E_NEW(E_Kbd_Dict_Word, 1);
kw->word = eina_stringshare_add(word);
kw->usage = usage;
kd->changed.writes = eina_list_prepend(kd->changed.writes, kw);
if (eina_list_count(kd->changed.writes) > 64)
e_kbd_dict_save(kd);
else
{
if (kd->changed.flush_timer)
ecore_timer_del(kd->changed.flush_timer);
kd->changed.flush_timer =
ecore_timer_add(5.0, _e_kbd_dict_cb_save_flush, kd);
}
}
static const char *
_e_kbd_dict_find_pointer(E_Kbd_Dict *kd, const char *p, int baselen, const char *word)
{
const char *pn;
int len;
if (!p) return NULL;
len = strlen(word);
while (p)
{
pn = _e_kbd_dict_line_next(kd, p);
if (!pn) return NULL;
if ((pn - p) > len)
{
if (!_e_kbd_dict_normalized_strncmp(p, word, len))
return p;
}
if (_e_kbd_dict_normalized_strncmp(p, word, baselen))
return NULL;
p = pn;
if (p >= (kd->file.dict + kd->file.size)) break;
}
return NULL;
}
static const char *
_e_kbd_dict_find(E_Kbd_Dict *kd, const char *word)
{
const char *p;
char *tword;
int glyphs[2], p2, v1, v2, i;
/* work backwards in leads. i.e.:
* going
* goin
* goi
* go
* g
*/
tword = alloca(strlen(word) + 1);
_e_kbd_dict_normalized_strcpy(tword, word);
p = eina_hash_find(kd->matches.leads, tword);
if (p) return p;
p2 = strlen(tword);
while (tword[0])
{
p2 = evas_string_char_prev_get(tword, p2, &i);
if (p2 < 0) break;
tword[p2] = 0;
p = eina_hash_find(kd->matches.leads, tword);
if (p)
return _e_kbd_dict_find_pointer(kd, p, p2, word);
}
/* looking at leads going back letters didn't work */
p = kd->file.dict;
if ((p[0] == '\n') && (kd->file.size <= 1)) return NULL;
glyphs[0] = glyphs[1] = 0;
p2 = evas_string_char_next_get(word, 0, &(glyphs[0]));
if ((p2 > 0) && (glyphs[0] > 0))
p2 = evas_string_char_next_get(word, p2, &(glyphs[1]));
v1 = _e_kbd_dict_letter_normalise(glyphs[0]);
if (glyphs[1] != 0)
{
v2 = _e_kbd_dict_letter_normalise(glyphs[1]);
if (kd->lookup.tuples[v1][v2] >= 0)
p = kd->file.dict + kd->lookup.tuples[v1][v2];
}
else
{
for (i = 0; i < 128; i++)
{
if (kd->lookup.tuples[v1][i] >= 0)
p = kd->file.dict + kd->lookup.tuples[v1][i];
if (p) break;
}
}
return _e_kbd_dict_find_pointer(kd, p, p2, word);
}
static const char *
_e_kbd_dict_find_full(E_Kbd_Dict *kd, const char *word)
{
const char *p;
int len;
p = _e_kbd_dict_find(kd, word);
if (!p) return NULL;
len = strlen(word);
if (isspace(p[len])) return p;
return NULL;
}
EAPI void
e_kbd_dict_word_usage_adjust(E_Kbd_Dict *kd, const char *word, int adjust)
{
// add "adjust" to word usage count
E_Kbd_Dict_Word *kw;
kw = _e_kbd_dict_changed_write_find(kd, word);
if (kw)
{
kw->usage += adjust;
if (kd->changed.flush_timer)
ecore_timer_del(kd->changed.flush_timer);
kd->changed.flush_timer = ecore_timer_add(5.0, _e_kbd_dict_cb_save_flush, kd);
}
else
{
const char *line;
int usage = 0;
line = _e_kbd_dict_find_full(kd, word);
if (line)
{
char *wd;
// FIXME: we need to find an EXACT line match - case and all
wd = _e_kbd_dict_line_parse(kd, line, &usage);
free(wd);
}
usage += adjust;
_e_kbd_dict_changed_write_add(kd, word, usage);
}
}
EAPI void
e_kbd_dict_word_delete(E_Kbd_Dict *kd, const char *word)
{
// delete a word from the dictionary
E_Kbd_Dict_Word *kw;
kw = _e_kbd_dict_changed_write_find(kd, word);
if (kw)
kw->usage = -1;
else
{
if (_e_kbd_dict_find_full(kd, word))
_e_kbd_dict_changed_write_add(kd, word, -1);
}
}
EAPI void
e_kbd_dict_word_letter_clear(E_Kbd_Dict *kd)
{
// clear the current word buffer
while (kd->word.letters)
e_kbd_dict_word_letter_delete(kd);
if (kd->matches.deadends)
{
eina_hash_free(kd->matches.deadends);
kd->matches.deadends = NULL;
}
if (kd->matches.leads)
{
eina_hash_free(kd->matches.leads);
kd->matches.leads = NULL;
}
while (kd->matches.list)
{
E_Kbd_Dict_Word *kw;
kw = kd->matches.list->data;
eina_stringshare_del(kw->word);
free(kw);
kd->matches.list = eina_list_remove_list(kd->matches.list, kd->matches.list);
}
}
EAPI void
e_kbd_dict_word_letter_add(E_Kbd_Dict *kd, const char *letter, int dist)
{
// add a letter with a distance (0 == closest) as an option for the current
// letter position - advance starts a new letter position
Eina_List *l, *list;
E_Kbd_Dict_Letter *kl;
l = eina_list_last(kd->word.letters);
if (!l) return;
list = l->data;
kl = E_NEW(E_Kbd_Dict_Letter, 1);
if (!kl) return;
kl->letter = eina_stringshare_add(letter);
kl->dist = dist;
list = eina_list_append(list, kl);
l->data = list;
}
EAPI void
e_kbd_dict_word_letter_advance(E_Kbd_Dict *kd)
{
// start a new letter in the word
kd->word.letters = eina_list_append(kd->word.letters, NULL);
}
EAPI void
e_kbd_dict_word_letter_delete(E_Kbd_Dict *kd)
{
// delete the current letter completely
Eina_List *l, *list;
l = eina_list_last(kd->word.letters);
if (!l) return;
list = l->data;
while (list)
{
E_Kbd_Dict_Letter *kl;
kl = list->data;
eina_stringshare_del(kl->letter);
free(kl);
list = eina_list_remove_list(list, list);
}
kd->word.letters = eina_list_remove_list(kd->word.letters, l);
}
static void
_e_kbd_dict_matches_lookup_do(E_Kbd_Dict *kd, Eina_List *letters, char *buf, char *bufp, int maxdist, int wordlen, int distance, int *searched, int *found)
{
Eina_List *l;
E_Kbd_Dict_Letter *kl;
const char *p;
char *wd;
E_Kbd_Dict_Word *kw;
int usage = 0, len, d;
if (letters)
{
for (l = letters->data; l; l = l->next)
{
kl = l->data;
len = strlen(kl->letter);
strncpy(bufp, kl->letter, len);
bufp[len] = 0;
if (_e_kbd_dict_find(kd, buf))
{
d = kl->dist;
_e_kbd_dict_matches_lookup_do(kd, letters->next,
buf, bufp + len, maxdist,
wordlen,
distance + (d * d * d),
searched, found);
}
}
return;
}
(*searched)++;
p = _e_kbd_dict_find_full(kd, buf);
if (!p) return;
wd = _e_kbd_dict_line_parse(kd, p, &usage);
if (wd)
{
if (_e_kbd_dict_normalized_strcmp(wd, buf))
{
free(wd);
return;
}
kw = E_NEW(E_Kbd_Dict_Word, 1);
if (kw)
{
int w, b, w2, b2, wc, bc;
// match any capitalisation
for (w = 0, b = 0; wd[w] && buf[b];)
{
b2 = evas_string_char_next_get(buf, b, &bc);
w2 = evas_string_char_next_get(wd, w, &wc);
if (isupper(bc)) wd[w] = toupper(wc);
w = w2;
b = b2;
}
kw->word = eina_stringshare_add(wd);
// FIXME: magic combination of distance metric and
// frequency of usage. this is simple now, but could
// be tweaked
// basically a metric to see how far away the keys that
// were actually pressed are away from the letters of
// this word in a physical on-screen sense
kw->accuracy = (maxdist - distance) / wordlen;
// usage is the frequency of usage in the dictionary.
// it its < 1 time, it's assumed to be 1.
if (usage < 1) usage = 1;
// multiply usage by a factor of 100 for better detailed
// sorting. 10 == 1/10th factor
kw->usage = 10 + (usage - 1);
kd->matches.list = eina_list_append(kd->matches.list, kw);
(*found)++;
}
free(wd);
}
}
EAPI void
e_kbd_dict_matches_lookup(E_Kbd_Dict *kd)
{
Eina_List *l, *ll;
E_Kbd_Dict_Word *kw;
E_Kbd_Dict_Letter *kl;
int searched = 0;
int found = 0;
int maxdist = 0, lettermaxdist, wordlen, d, d1, d2;
char *buf;
// find all matches and sort them
wordlen = eina_list_count(kd->word.letters);
buf = alloca((wordlen + 1) * 10);
while (kd->matches.list)
{
kw = kd->matches.list->data;
eina_stringshare_del(kw->word);
free(kw);
kd->matches.list = eina_list_remove_list(kd->matches.list, kd->matches.list);
}
for (l = kd->word.letters; l; l = l->next)
{
lettermaxdist = 0;
for (ll = l->data; ll; ll = ll->next)
{
kl = ll->data;
d = kl->dist;
lettermaxdist += d * d * d;
}
maxdist += lettermaxdist;
}
if (kd->word.letters)
_e_kbd_dict_matches_lookup_do(kd, kd->word.letters, buf, buf, maxdist,
wordlen, 0, &searched, &found);
d1 = 0x7fffffff;
d2 = 0;
for (l = kd->matches.list; l; l = l->next)
{
kw = l->data;
if (kw->accuracy < d1) d1 = kw->accuracy;
if (kw->accuracy > d2) d2 = kw->accuracy;
}
for (l = kd->matches.list; l; l = l->next)
{
int a;
long long tmp;
kw = l->data;
kw->accuracy -= d1;
a = (kw->accuracy + 10) / 10;
printf("-> %s: acc=%i, use=%i -> ", kw->word, a, kw->usage);
tmp = kw->usage + 100;
tmp *= (a * a);
tmp /= 10000;
tmp *= (a * a);
tmp /= 10000;
tmp *= (a * a);
tmp /= 10000;
tmp *= (a * a);
tmp /= 10000;
kw->usage = tmp / 10000;
printf("%i\n", kw->usage);
}
printf("====== searched: %i/%i\n", found, searched);
kd->matches.list = eina_list_sort(kd->matches.list,
eina_list_count(kd->matches.list),
_e_kbd_dict_matches_lookup_cb_sort);
}
EAPI void
e_kbd_dict_matches_first(E_Kbd_Dict *kd)
{
// jump to first match
kd->matches.list_ptr = kd->matches.list;
}
EAPI void
e_kbd_dict_matches_next(E_Kbd_Dict *kd)
{
// jump to next match
kd->matches.list_ptr = kd->matches.list_ptr->next;
}
EAPI const char *
e_kbd_dict_matches_match_get(E_Kbd_Dict *kd, int *pri_ret)
{
// return the word (string utf-8) for the current match
if (kd->matches.list_ptr)
{
E_Kbd_Dict_Word *kw;
kw = kd->matches.list_ptr->data;
if (kw)
{
*pri_ret = kw->usage;
return kw->word;
}
}
return NULL;
}

View File

@ -0,0 +1,62 @@
#ifndef E_KBD_DICT_H
#define E_KBD_DICT_H
typedef struct _E_Kbd_Dict E_Kbd_Dict;
typedef struct _E_Kbd_Dict_Word E_Kbd_Dict_Word;
typedef struct _E_Kbd_Dict_Letter E_Kbd_Dict_Letter;
struct _E_Kbd_Dict_Word
{
const char *word;
int accuracy;
int usage;
};
struct _E_Kbd_Dict_Letter
{
const char *letter;
int dist;
};
struct _E_Kbd_Dict
{
struct {
const char *file;
int fd;
const char *dict;
int size;
} file;
struct {
int tuples[128][128];
} lookup;
struct {
Ecore_Timer *flush_timer;
Eina_List *writes;
} changed;
struct {
Eina_List *letters;
} word;
struct {
Eina_Hash *deadends;
Eina_Hash *leads;
Eina_List *list;
Eina_List *list_ptr;
} matches;
};
EAPI E_Kbd_Dict *e_kbd_dict_new(const char *file);
EAPI void e_kbd_dict_free(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_save(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_word_usage_adjust(E_Kbd_Dict *kd, const char *word, int adjust);
EAPI void e_kbd_dict_word_delete(E_Kbd_Dict *kd, const char *word);
EAPI void e_kbd_dict_word_letter_clear(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_word_letter_add(E_Kbd_Dict *kd, const char *letter, int dist);
EAPI void e_kbd_dict_word_letter_advance(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_word_letter_delete(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_matches_lookup(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_matches_first(E_Kbd_Dict *kd);
EAPI void e_kbd_dict_matches_next(E_Kbd_Dict *kd);
EAPI const char *e_kbd_dict_matches_match_get(E_Kbd_Dict *kd, int *pri_ret);
#endif

1427
src/modules/vkbd/e_kbd_int.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
#ifndef E_KBD_INT_H
#define E_KBD_INT_H
#include "e_kbd_buf.h"
typedef enum _E_Kbd_Int_Type
{
E_KBD_INT_TYPE_UNKNOWN = 0,
E_KBD_INT_TYPE_ALPHA = (1 << 0),
E_KBD_INT_TYPE_NUMERIC = (1 << 1),
E_KBD_INT_TYPE_PIN = (1 << 2),
E_KBD_INT_TYPE_PHONE_NUMBER = (1 << 3),
E_KBD_INT_TYPE_HEX = (1 << 4),
E_KBD_INT_TYPE_TERMINAL = (1 << 5),
E_KBD_INT_TYPE_PASSWORD = (1 << 6),
E_KBD_INT_TYPE_IP = (1 << 7),
E_KBD_INT_TYPE_HOST = (1 << 8),
E_KBD_INT_TYPE_FILE = (1 << 9),
E_KBD_INT_TYPE_URL = (1 << 10),
E_KBD_INT_TYPE_KEYPAD = (1 << 11),
E_KBD_INT_TYPE_J2ME = (1 << 12)
} E_Kbd_Int_Type;
/* The natural text direction of the keyboard */
typedef enum _E_kbd_Int_Direction
{
E_KBD_INT_DIRECTION_LTR = (1 << 0),
E_KBD_INT_DIRECTION_RTL = (1 << 1)
} E_Kbd_Int_Direction;
typedef struct _E_Kbd_Int E_Kbd_Int;
typedef struct _E_Kbd_Int_Key E_Kbd_Int_Key;
typedef struct _E_Kbd_Int_Key_State E_Kbd_Int_Key_State;
typedef struct _E_Kbd_Int_Layout E_Kbd_Int_Layout;
typedef struct _E_Kbd_Int_Match E_Kbd_Int_Match;
typedef struct _E_Kbd_Int_Multi_Info E_Kbd_Int_Multi_Info;
struct _E_Kbd_Int
{
const char *themedir, *syskbds, *sysdicts;
E_Zone *zone;
Evas_Object *base_obj, *layout_obj, *event_obj, *box_obj, *boxgrid_obj;
Eina_List *layouts;
Eina_List *matches;
int x, y, x0, y0;
double px, py;
struct {
char *directory;
const char *file;
int w, h;
int fuzz;
int direction;
E_Kbd_Int_Type type;
Eina_List *keys;
E_Kbd_Int_Key *pressed;
Eina_List *multis;
int state;
} layout;
struct {
Evas_Coord x, y;
int lx, ly;
unsigned char down : 1;
unsigned char stroke : 1;
unsigned char zoom : 1;
unsigned char twofinger : 1;
} down;
E_Kbd_Buf *kbuf;
Eina_Bool visible : 1;
};
struct _E_Kbd_Int_Key
{
int x, y, w, h;
Eina_List *states;
Evas_Object *obj, *zoom_obj, *icon_obj, *zoom_icon_obj;
unsigned char pressed : 1;
unsigned char selected : 1;
unsigned char is_shift : 1;
unsigned char is_multi_shift : 1;
unsigned char is_ctrl : 1;
unsigned char is_alt : 1;
unsigned char is_altgr : 1;
unsigned char is_capslock : 1;
};
struct _E_Kbd_Int_Key_State
{
int state;
const char *label, *icon;
const char *out;
};
struct _E_Kbd_Int_Layout
{
const char *path;
const char *dir;
const char *icon;
const char *name;
int type;
};
struct _E_Kbd_Int_Match
{
E_Kbd_Int *ki;
const char *str;
Evas_Object *obj;
};
struct _E_Kbd_Int_Multi_Info
{
int device;
E_Kbd_Int_Key *ky;
};
EAPI E_Kbd_Int *e_kbd_int_new(int zone_num, const char *zone_id,
const char *themedir, const char *syskbds,
const char *sysdicts);
EAPI void e_kbd_int_free(E_Kbd_Int *ki);
EAPI void e_kbd_int_update(E_Kbd_Int *ki);
EAPI void e_kbd_int_show(E_Kbd_Int *ki);
EAPI void e_kbd_int_hide(E_Kbd_Int *ki);
#endif

View File

@ -0,0 +1,57 @@
#include "e.h"
#include "e_kbd_send.h"
#ifndef HAVE_WAYLAND_ONLY
static const char *
_string_to_keysym(const char *str)
{
if (e_comp_util_has_x())
{
int glyph;
/* utf8 -> glyph id (unicode - ucs4) */
glyph = 0;
evas_string_char_next_get(str, 0, &glyph);
if (glyph <= 0) return NULL;
/* glyph id -> keysym */
if (glyph > 0xff) glyph |= 0x1000000;
return ecore_x_keysym_string_get(glyph);
}
else
{
return NULL;
}
}
#endif
EAPI void
e_kbd_send_string_press(const char *str EINA_UNUSED, Kbd_Mod mod EINA_UNUSED)
{
#ifndef HAVE_WAYLAND_ONLY
if (e_comp_util_has_x())
{
const char *key = NULL;
key = _string_to_keysym(str);
if (!key) return;
e_kbd_send_keysym_press(key, mod);
}
#endif
}
EAPI void
e_kbd_send_keysym_press(const char *key EINA_UNUSED, Kbd_Mod mod EINA_UNUSED)
{
#ifndef HAVE_WAYLAND_ONLY
if (e_comp_util_has_x())
{
if (mod & KBD_MOD_CTRL) ecore_x_test_fake_key_down("Control_L");
if (mod & KBD_MOD_ALT) ecore_x_test_fake_key_down("Alt_L");
if (mod & KBD_MOD_WIN) ecore_x_test_fake_key_down("Super_L");
ecore_x_test_fake_key_press(key);
if (mod & KBD_MOD_WIN) ecore_x_test_fake_key_up("Super_L");
if (mod & KBD_MOD_ALT) ecore_x_test_fake_key_up("Alt_L");
if (mod & KBD_MOD_CTRL) ecore_x_test_fake_key_up("Control_L");
}
#endif
}

View File

@ -0,0 +1,15 @@
#ifndef E_KBD_SEND_H
#define E_KBD_SEND_H
typedef enum _Kbd_Mod
{
KBD_MOD_SHIFT = (1 << 0),
KBD_MOD_CTRL = (1 << 1),
KBD_MOD_ALT = (1 << 2),
KBD_MOD_WIN = (1 << 3)
} Kbd_Mod;
EAPI void e_kbd_send_string_press(const char *str, Kbd_Mod mod);
EAPI void e_kbd_send_keysym_press(const char *key, Kbd_Mod mod);
#endif

View File

@ -0,0 +1,158 @@
#include "e.h"
#include "e_mod_main.h"
#include "e_kbd_int.h"
/* local function prototypes */
static void _il_kbd_stop(void);
static void _il_kbd_start(void);
static Eina_Bool _il_ki_delay_cb(void *data EINA_UNUSED);
/* local variables */
static E_Kbd_Int *ki = NULL;
static Ecore_Timer *ki_delay_timer = NULL;
static E_Config_DD *cd = NULL;
E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Virtual Keyboard" };
Il_Kbd_Config *il_kbd_cfg = NULL;
static void
_cb_act_vkbd_show(E_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
{
if (ki) e_kbd_int_show(ki);
}
static void
_cb_act_vkbd_hide(E_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
{
if (ki) e_kbd_int_hide(ki);
}
static void
_cb_act_vkbd_toggle(E_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
{
if (ki)
{
if (ki->visible) e_kbd_int_hide(ki);
else e_kbd_int_show(ki);
}
}
E_API void *
e_modapi_init(E_Module *m)
{
cd = E_CONFIG_DD_NEW("Il_Kbd_Config", Il_Kbd_Config);
E_CONFIG_VAL(cd, Il_Kbd_Config, dict, STR);
E_CONFIG_VAL(cd, Il_Kbd_Config, zone_id, STR);
E_CONFIG_VAL(cd, Il_Kbd_Config, zone_num, INT);
E_CONFIG_VAL(cd, Il_Kbd_Config, size, DOUBLE);
E_CONFIG_VAL(cd, Il_Kbd_Config, fill_mode, INT);
E_CONFIG_VAL(cd, Il_Kbd_Config, px, DOUBLE);
E_CONFIG_VAL(cd, Il_Kbd_Config, py, DOUBLE);
il_kbd_cfg = e_config_domain_load("module.vkbd", cd);
if (!il_kbd_cfg)
{
il_kbd_cfg = E_NEW(Il_Kbd_Config, 1);
il_kbd_cfg->dict = eina_stringshare_add("English_US.dic");
il_kbd_cfg->zone_num = 0;
il_kbd_cfg->size = 4.0;
il_kbd_cfg->fill_mode = 0;
}
il_kbd_cfg->mod_dir = eina_stringshare_add(m->dir);
il_kbd_cfg->slide_dim = 15;
il_kbd_cfg->act_kbd_show = e_action_add("vkbd_show");
if (il_kbd_cfg->act_kbd_show)
{
il_kbd_cfg->act_kbd_show->func.go = _cb_act_vkbd_show;
e_action_predef_name_set("Virtual Keyboard", _("Show"),
"vkbd_show", NULL, NULL, 0);
}
il_kbd_cfg->act_kbd_hide = e_action_add("vkbd_hide");
if (il_kbd_cfg->act_kbd_hide)
{
il_kbd_cfg->act_kbd_show->func.go = _cb_act_vkbd_hide;
e_action_predef_name_set("Virtual Keyboard", _("Hide"),
"vkbd_hide", NULL, NULL, 0);
}
il_kbd_cfg->act_kbd_toggle = e_action_add("vkbd_toggle");
if (il_kbd_cfg->act_kbd_toggle)
{
il_kbd_cfg->act_kbd_show->func.go = _cb_act_vkbd_toggle;
e_action_predef_name_set("Virtual Keyboard", _("Toggle"),
"vkbd_toggle", NULL, NULL, 0);
}
e_module_delayed_set(m, 1);
ki_delay_timer = ecore_timer_add(1.0, _il_ki_delay_cb, NULL);
return m;
}
E_API int
e_modapi_shutdown(E_Module *m EINA_UNUSED)
{
e_config_domain_save("module.vkbd", cd, il_kbd_cfg);
if (ki_delay_timer)
{
ecore_timer_del(ki_delay_timer);
ki_delay_timer = NULL;
}
_il_kbd_stop();
eina_stringshare_del(il_kbd_cfg->dict);
eina_stringshare_del(il_kbd_cfg->mod_dir);
if (il_kbd_cfg->act_kbd_show)
{
e_action_predef_name_del("Virtual Keyboard", _("Show"));
e_action_del("vkbd_show");
}
if (il_kbd_cfg->act_kbd_hide)
{
e_action_predef_name_del("Virtual Keyboard", _("Hide"));
e_action_del("vkbd_hide");
}
if (il_kbd_cfg->act_kbd_toggle)
{
e_action_predef_name_del("Virtual Keyboard", _("Toggle"));
e_action_del("vkbg_toggle");
}
E_FREE(il_kbd_cfg);
E_CONFIG_DD_FREE(cd);
return 1;
}
E_API int
e_modapi_save(E_Module *m EINA_UNUSED)
{
return e_config_domain_save("module.vkbd", cd, il_kbd_cfg);
}
static void
_il_kbd_stop(void)
{
if (ki) e_kbd_int_free(ki);
ki = NULL;
}
static void
_il_kbd_start(void)
{
ki = e_kbd_int_new(il_kbd_cfg->zone_num,
il_kbd_cfg->zone_id,
il_kbd_cfg->mod_dir,
il_kbd_cfg->mod_dir,
il_kbd_cfg->mod_dir);
ki->px = il_kbd_cfg->px;
ki->py = il_kbd_cfg->py;
e_kbd_int_update(ki);
e_kbd_int_show(ki);
}
static Eina_Bool
_il_ki_delay_cb(void *data EINA_UNUSED)
{
ki_delay_timer = NULL;
_il_kbd_start();
return EINA_FALSE;
}

View File

@ -0,0 +1,26 @@
#ifndef E_MOD_MAIN_H
#define E_MOD_MAIN_H
typedef struct _Il_Kbd_Config Il_Kbd_Config;
struct _Il_Kbd_Config
{
const char *dict;
const char *zone_id;
int zone_num;
double size;
int fill_mode;
double px, py;
// Not User Configurable. Placeholders
E_Action *act_kbd_show;
E_Action *act_kbd_hide;
E_Action *act_kbd_toggle;
const char *mod_dir;
int slide_dim;
int layout;
};
extern EAPI Il_Kbd_Config *il_kbd_cfg;
#endif

View File

@ -0,0 +1,145 @@
##KBDCONF-1.0
kbd 120 30
fuzz 20
# keyboard type
type ALPHA
# an icon for the keyboard so you know which one you have
icon alpha.png
# if the key out is in quotes - "q" for example, then this key is used for
# typing words and can be part of a dictionary match, any other key when
# pressed will end the dictionary match (u can disable dictionary matching in
# a layout by not having any outputs in quotes)
key 0 0 10 10
normal q "q"
shift Q "Q"
capslock Q "Q"
altgr Ω Ω
key 10 0 10 10
normal w "w"
shift W "W"
capslock W "W"
key 20 0 10 10
normal e "e"
shift E "E"
altgr € €
capslock E "E"
key 30 0 10 10
normal r "r"
shift R "R"
capslock R "R"
altgr ® ®
key 40 0 10 10
normal t "t"
shift T "T"
capslock T "T"
key 50 0 10 10
normal y "y"
shift Y "Y"
capslock Y "Y"
key 60 0 10 10
normal u "u"
shift U "U"
capslock U "U"
key 70 0 10 10
normal i "i"
shift I "I"
capslock I "I"
key 80 0 10 10
normal o "o"
shift O "O"
capslock O "O"
key 90 0 10 10
normal p "p"
shift P "P"
capslock P "P"
key 5 10 10 10
normal a "a"
shift A "A"
capslock A "A"
key 15 10 10 10
normal s "s"
shift S "S"
capslock S "S"
key 25 10 10 10
normal d "d"
shift D "D"
capslock D "D"
key 35 10 10 10
normal f "f"
shift F "F"
capslock F "F"
key 45 10 10 10
normal g "g"
shift G "G"
capslock G "G"
key 55 10 10 10
normal h "h"
shift H "H"
capslock H "H"
key 65 10 10 10
normal j "j"
shift J "J"
capslock J "J"
key 75 10 10 10
normal k "k"
shift K "K"
capslock K "K"
key 85 10 10 10
normal l "l"
shift L "L"
capslock L "L"
key 0 20 10 10
normal ⎇
is_altgr
key 10 20 10 10
normal z "z"
shift Z "Z"
capslock Z "Z"
key 20 20 10 10
normal x "x"
shift X "X"
capslock X "X"
key 30 20 10 10
normal c "c"
shift C "C"
capslock C "C"
altgr ¢ ¢
key 40 20 10 10
normal v "v"
shift V "V"
capslock V "V"
key 50 20 10 10
normal b "b"
shift B "B"
capslock B "B"
key 60 20 10 10
normal n "n"
shift N "N"
capslock N "N"
key 70 20 10 10
normal m "m"
shift M "M"
capslock M "M"
altgr µ µ
key 90 20 10 10
normal spanner.png CONFIG
key 100 20 10 10
# normal shift.png
normal ↑
shift ⇈
capslock ⇊
is_multi_shift
key 110 0 10 10
normal . period
shift , comma
key 110 10 10 10
normal ? question
shift ! exclam
key 110 20 10 10
normal ' "'"
shift / slash

View File

@ -0,0 +1,120 @@
##KBDCONF-1.0
kbd 120 30
fuzz 20
# keyboard type
type NUMERIC
# an icon for the keyboard so you know which one you have
icon numeric.png
key 0 0 10 10
normal 1 1
shift ! exclam
key 10 0 10 10
normal 2 2
shift @ at
key 20 0 10 10
normal 3 3
shift # numbersign
key 30 0 10 10
normal 4 4
shift $ dollar
key 40 0 10 10
normal 5 5
shift % percent
key 50 0 10 10
normal 6 6
shift ^ asciicircum
key 60 0 10 10
normal 7 7
shift & ampersand
key 70 0 10 10
normal 8 8
shift * asterisk
key 80 0 10 10
normal 9 9
shift ( parenleft
key 90 0 10 10
normal 0 0
shift ) parenright
key 100 0 10 10
normal [ bracketleft
shift { braceleft
key 110 0 10 10
normal ] bracketright
shift } braceright
key 0 10 10 10
normal tab.png Tab
shift tab.png ISO_Left_Tab
key 10 10 10 10
normal ` grave
shift ~ asciitilde
key 20 10 10 10
normal - "-"
shift _ underscore
key 30 10 10 10
normal = equal
shift + plus
key 40 10 10 10
normal \ backslash
shift | bar
key 50 10 10 10
normal ; semicolon
shift : colon
key 60 10 10 10
normal ' apostrophe
shift " quotedbl
key 70 10 10 10
normal / slash
shift ? question
key 80 10 10 10
normal , comma
shift < less
key 90 10 10 10
normal ß "ß"
shift ¢ "¢"
key 100 10 10 10
normal € "€"
shift £ "£"
key 110 10 10 10
normal ø "ø"
shift Ø "Ø"
key 0 20 10 10
normal ä "ä"
shift Ä "Ä"
key 10 20 10 10
normal ö "ö"
shift Ö "Ö"
key 20 20 10 10
normal ü "ü"
shift Ü "Ü"
key 30 20 10 10
normal é "é"
shift É "É"
key 40 20 10 10
normal è "è"
shift È "È"
key 50 20 10 10
normal ô "ô"
shift Ô "Ô"
key 60 20 10 10
normal ç "ç"
shift Ç "Ç"
key 70 20 10 10
normal à "à"
shift À "À"
key 80 20 10 10
normal ò "ò"
shift Ò "Ò"
key 90 20 10 10
normal ó "ó"
shift Ó "Ó"
key 100 20 10 10
normal ñ "ñ"
shift Ñ "Ñ"
key 110 20 10 10
normal shift.png
is_shift

View File

@ -0,0 +1,275 @@
##KBDCONF-1.0
kbd 150 60
# keyboard type
type TERMINAL
# an icon for the keyboard so you know which one you have
icon qwerty.png
key 0 0 10 10
normal esc Escape
key 10 0 10 10
normal f1 F1
key 20 0 10 10
normal f2 F2
key 30 0 10 10
normal f3 F3
key 40 0 10 10
normal f4 F4
key 50 0 10 10
normal f5 F5
key 60 0 10 10
normal f6 F6
key 70 0 10 10
normal f7 F7
key 80 0 10 10
normal f8 F8
key 90 0 10 10
normal f9 F9
key 100 0 10 10
normal f10 F10
key 110 0 10 10
normal f11 F11
key 120 0 10 10
normal f12 F12
key 130 0 10 10
normal print Print
key 140 0 10 10
normal pause Pause
key 0 10 10 10
normal ` grave
shift ~ asciitilde
capslock ` grave
key 10 10 10 10
normal 1 1
shift ! exclam
capslock 1 1
key 20 10 10 10
normal 2 2
shift @ at
capslock 2 2
key 30 10 10 10
normal 3 3
shift # numbersign
capslock 3 3
key 40 10 10 10
normal 4 4
shift $ dollar
capslock 4 4
key 50 10 10 10
normal 5 5
shift % percent
capslock 5 5
key 60 10 10 10
normal 6 6
shift ^ asciicircum
capslock 6 6
key 70 10 10 10
normal 7 7
shift & ampersand
capslock 7 7
key 80 10 10 10
normal 8 8
shift * asterisk
capslock 8 8
key 90 10 10 10
normal 9 9
shift ( parenleft
capslock 9 9
key 100 10 10 10
normal 0 0
shift ) parenright
capslock 0 0
key 110 10 10 10
normal - minus
shift _ underscore
capslock - minus
key 120 10 10 10
normal = equal
shift + plus
capslock = equal
key 130 10 20 10
normal backspace.png BackSpace
key 0 20 15 10
normal tab.png Tab
shift tab.png ISO_Left_Tab
key 15 20 10 10
normal q q
shift Q Q
capslock Q Q
key 25 20 10 10
normal w w
shift W W
capslock W W
key 35 20 10 10
normal e e
shift E E
capslock E E
key 45 20 10 10
normal r r
shift R R
capslock R R
key 55 20 10 10
normal t t
shift T T
capslock T T
key 65 20 10 10
normal y y
shift Y Y
capslock Y Y
key 75 20 10 10
normal u u
shift U U
capslock U U
key 85 20 10 10
normal i i
shift I I
capslock I I
key 95 20 10 10
normal o o
shift O O
capslock O O
key 105 20 10 10
normal p p
shift P P
capslock P P
key 115 20 10 10
normal [ bracketleft
shift { braceleft
capslock [ bracketleft
key 125 20 10 10
normal ] bracketright
shift } braceright
capslock ] bracketright
key 135 20 15 10
normal \ backslash
shift | bar
capslock \ backslash
key 0 30 20 10
normal caps
capslock CAPS
is_capslock
key 20 30 10 10
normal a a
shift A A
capslock A A
key 30 30 10 10
normal s s
shift S S
capslock S S
key 40 30 10 10
normal d d
shift D D
capslock D D
key 50 30 10 10
normal f f
shift F F
capslock F F
key 60 30 10 10
normal g g
shift G G
capslock G G
key 70 30 10 10
normal h h
shift H H
capslock H H
key 80 30 10 10
normal j j
shift J J
capslock J J
key 90 30 10 10
normal k k
shift K K
capslock K K
key 100 30 10 10
normal l l
shift L L
capslock L L
key 110 30 10 10
normal ; semicolon
shift : colon
capslock ; semicolon
key 120 30 10 10
normal ' apostrophe
shift " quotedbl
capslock ' apostrophe
key 130 30 20 10
normal enter.png Return
key 0 40 25 10
normal shift.png
is_shift
key 25 40 10 10
normal z z
shift Z Z
capslock Z Z
key 35 40 10 10
normal x x
shift X X
capslock X X
key 45 40 10 10
normal c c
shift C C
capslock C C
key 55 40 10 10
normal v v
shift V V
capslock V V
key 65 40 10 10
normal b b
shift B B
capslock B B
key 75 40 10 10
normal n n
shift N N
capslock N N
key 85 40 10 10
normal m m
shift M M
capslock M M
key 95 40 10 10
normal , comma
shift < less
capslock , comma
key 105 40 10 10
normal . period
shift > greater
capslock . period
key 115 40 10 10
normal / slash
shift ? question
capslock / slash
key 125 40 10 10
normal mult Multi_key
key 135 40 15 10
normal del Delete
key 0 50 10 10
normal ctrl
is_ctrl
key 10 50 10 10
normal alt
is_alt
key 20 50 40 10
normal space space
key 60 50 10 10
normal left.png Left
key 70 50 10 10
normal right.png Right
key 80 50 10 10
normal up.png Up
key 90 50 10 10
normal down.png Down
key 100 50 10 10
normal pgup Prior
key 110 50 10 10
normal pgdn Next
key 120 50 10 10
normal home Home
key 130 50 10 10
normal end End
key 140 50 10 10
normal menu Menu

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

View File

@ -0,0 +1,52 @@
src = files(
'e_mod_main.c',
'e_kbd_buf.c',
'e_kbd_cfg.c',
'e_kbd_dict.c',
'e_kbd_int.c',
'e_kbd_send.c',
'e_mod_main.h',
'e_kbd_buf.h',
'e_kbd_cfg.h',
'e_kbd_dict.h',
'e_kbd_int.h',
'e_kbd_send.h'
)
if get_option(m) == true
cmd = [ edje_cmd,
'-id', join_paths(meson.source_root(), 'src' , 'modules', m,
'images'),
'@INPUT@', '@OUTPUT@'
]
edc = 'theme'
custom_target(edc + '.edj',
input : edc + '.edc',
output : edc + '.edj',
command : cmd,
install_dir: _dir,
install : true
)
out = join_paths(_dir, edc + '.edj')
meson.add_install_script(chmod, 'a+r', out)
install_data(['dicts/English_US_Small.dic',
'dicts/English_US.dic'],
install_dir: join_paths(_dir, 'dicts'))
install_data(['keyboards/Default.kbd',
'keyboards/Numbers.kbd',
'keyboards/Terminal.kbd',
'keyboards/alpha.png',
'keyboards/backspace.png',
'keyboards/down.png',
'keyboards/enter.png',
'keyboards/left.png',
'keyboards/numeric.png',
'keyboards/qwerty.png',
'keyboards/right.png',
'keyboards/shift.png',
'keyboards/spanner.png',
'keyboards/tab.png',
'keyboards/up.png'],
install_dir: join_paths(_dir, 'keyboards'))
endif

View File

@ -0,0 +1,6 @@
[Desktop Entry]
Encoding=UTF-8
Type=Link
Name=Virtual Keyboard
Icon=e-module-vkbd
X-Enlightenment-ModuleType=mobile

258
src/modules/vkbd/theme.edc Normal file
View File

@ -0,0 +1,258 @@
collections {
group { name: "e/modules/kbd/base/default";
parts {
part { name: "clip"; type: RECT;
description { state: "default" 0.0;
rel1.offset: -100 -300;
rel2.offset: 99 -1;
visible: 0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
part { name: "bg"; type: RECT;
clip_to: "clip";
description { state: "default" 0.0;
color: 48 48 48 255;
rel1.relative: 0.0 1.0;
rel2.relative: 1.0 2.0;
}
description { state: "visible" 0.0;
inherit: "default" 0.0;
rel1.relative: 0.0 0.0;
rel2.relative: 1.0 1.0;
}
}
part { name: "completion_clip"; type: RECT;
clip_to: "clip";
description { state: "default" 0.0;
rel.to: "bg";
rel1.offset: 4 4;
rel2.to_y: "e.swallow.completion";
rel2.relative: 1.0 1.0;
rel2.offset: -5 -1;
align: 0.5 0.0;
}
}
part { name: "e.swallow.completion"; type: SWALLOW;
clip_to: "completion_clip";
description { state: "default" 0.0;
rel.to: "bg";
rel1.offset: 4 4;
rel2.relative: 1.0 0.0;
rel2.offset: -5 4;
align: 0.5 0.0;
}
}
part { name: "e.swallow.content"; type: SWALLOW;
clip_to: "clip";
description { state: "default" 0.0;
rel.to: "bg";
rel1.to_y: "e.swallow.completion";
rel1.offset: 4 4;
rel1.relative: 0.0 1.0;
rel2.offset: -5 -5;
}
}
}
programs {
program { signal: "e,state,visible"; source: "e";
action: STATE_SET "visible" 0.0;
target: "bg";
target: "clip";
transition: DECELERATE 0.5;
}
program { signal: "e,state,invisible"; source: "e";
action: STATE_SET "default" 0.0;
target: "bg";
target: "clip";
transition: DECELERATE 1.0;
}
}
}
group { name: "e/modules/kbd/key/default";
parts {
part { name: "selshow"; type: RECT;
description { state: "default" 0.0;
visible: 0;
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
part { name: "bg"; type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
rel1.offset: 2 2;
rel2.offset: -3 -3;
color: 80 80 80 255;
}
description { state: "pressed" 0.0;
inherit: "default" 0.0;
color: 128 128 128 255;
rel1.relative: 0.0 -1.0;
}
}
part { name: "sel"; type: RECT;
clip_to: "selshow";
mouse_events: 0;
description { state: "default" 0.0;
rel.to: "bg";
color: 51 153 255 255;
}
description { state: "pressed" 0.0;
inherit: "default" 0.0;
color: 153 204 255 255;
}
}
part { name: "e.text.label"; type: TEXT;
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "bg";
rel1.offset: 2 2;
rel2.to: "bg";
rel2.offset: -3 -3;
color: 255 255 255 160;
text {
font: "Sans";
size: 10;
min: 1 1;
ellipsis: -1;
}
}
description { state: "pressed" 0.0;
inherit: "default" 0.0;
color: 255 255 255 255;
text {
align: 0.5 0.0;
}
}
}
part { name: "e.swallow.content"; type: SWALLOW;
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "bg";
rel1.offset: 2 2;
rel2.to: "bg";
rel2.offset: -3 -3;
}
}
}
programs {
program { signal: "e,state,selected"; source: "e";
action: STATE_SET "selected" 0.0;
target: "selshow";
}
program { signal: "e,state,unselected"; source: "e";
action: STATE_SET "default" 0.0;
target: "selshow";
}
program { signal: "e,state,pressed"; source: "e";
action: STATE_SET "pressed" 0.0;
target: "e.text.label";
target: "bg";
target: "sel";
}
program { signal: "e,state,released"; source: "e";
action: STATE_SET "default" 0.0;
target: "e.text.label";
target: "bg";
target: "sel";
}
}
}
group { name: "e/modules/kbd/match/word";
parts {
part { name: "selshow"; type: RECT;
description { state: "default" 0.0;
visible: 0;
}
description { state: "selected" 0.0;
inherit: "default" 0.0;
visible: 1;
}
}
part { name: "bg"; type: RECT;
description { state: "default" 0.0;
rel1.offset: 2 2;
rel2.offset: -3 -3;
color: 64 64 64 255;
}
description { state: "pressed" 0.0;
inherit: "default" 0.0;
color: 128 128 128 255;
}
}
part { name: "sel"; type: RECT;
clip_to: "selshow";
mouse_events: 0;
description { state: "default" 0.0;
rel.to: "bg";
color: 51 153 255 255;
}
description { state: "pressed" 0.0;
inherit: "default" 0.0;
color: 153 204 255 255;
}
}
part { name: "e.text.label"; type: TEXT;
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "bg";
rel1.offset: 2 2;
rel2.to: "bg";
rel2.offset: -3 -3;
color: 255 255 255 160;
text {
font: "Sans";
size: 10;
min: 1 1;
}
}
description { state: "pressed" 0.0;
inherit: "default" 0.0;
color: 255 255 255 255;
}
}
part { name: "e.swallow.content"; type: SWALLOW;
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "bg";
rel1.offset: 2 2;
rel2.to: "bg";
rel2.offset: -3 -3;
}
}
}
programs {
program { signal: "e,state,selected"; source: "e";
action: STATE_SET "selected" 0.0;
target: "selshow";
}
program { signal: "e,state,unselected"; source: "e";
action: STATE_SET "default" 0.0;
target: "selshow";
}
program { signal: "mouse,down,1"; source: "bg";
action: STATE_SET "pressed" 0.0;
target: "e.text.label";
target: "bg";
target: "sel";
}
program { signal: "mouse,up,1"; source: "bg";
action: STATE_SET "default" 0.0;
target: "e.text.label";
target: "bg";
target: "sel";
}
program { signal: "mouse,clicked,1"; source: "bg";
action: SIGNAL_EMIT "e,action,do,select" "e";
}
}
}
}