Merge branch 'eekkey' into 'master'

Redesign how keys are handled

See merge request Librem5/squeekboard!117
This commit is contained in:
Dorota Czaplejewicz
2019-08-12 12:10:59 +00:00
44 changed files with 1224 additions and 2186 deletions

View File

@ -1,57 +1,8 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="10" y="10" width="410.0000" height="229"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
<key name="AD06" oref="outline2" />
<key name="AD07" oref="outline2" />
<key name="AD08" oref="outline2" />
<key name="AD09" oref="outline2" />
<key name="AD10" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
<key name="AC10" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="0" name="ABC123" oref="altline" />
<key name="I149" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<outline id="default" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52"/>
@ -117,4 +68,38 @@
<point x="150.5853" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<button name="Shift_L" oref="altline" />
<button name="BackSpace" oref="altline" />
<button name="preferences" oref="altline" />
<button name="show_numbers" oref="altline" keycode="0" />
<button name="show_letters" oref="altline" keycode="0" />
<button name="show_symbols" oref="altline" keycode="0" />
<button name="space" oref="spaceline" />
<button name="return" oref="outline7" />
<view>
<section angle="0">q w e r t y u i o p</section>
<section angle="0">a s d f g h j k l</section>
<section angle="0"> Shift_L z x c v b n m BackSpace </section>
<section angle="0"> show_numbers preferences space period Return </section>
</view>
<view>
<section angle="0">Q W E R T Y U I O P</section>
<section angle="0">A S D F G H J K L</section>
<section angle="0"> Shift_L Z X C V B N M BackSpace </section>
<section angle="0"> show_numbers preferences space period Return </section>
</view>
<view>
<section angle="0">1 2 3 4 5 6 7 8 9 0</section>
<section angle="0">at numbersign dollar percent ampersand minus underscore plus parenleft parenright</section>
<section angle="0"> show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace </section>
<section angle="0"> show_letters preferences space period Return </section>
</view>
<view>
<section angle="0">asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph</section>
<section angle="0">copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright</section>
<section angle="0"> show_numbers backslash slash less greater equal bracketleft bracketright BackSpace </section>
<section angle="0"> show_letters preferences space period Return </section>
</view>
</geometry>

View File

@ -1,42 +1,8 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="BKSP" oref="altline" />
<key name="AB06" oref="outline2" />
<key name="SPCE" oref="spaceline" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<outline id="default" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
@ -48,58 +14,27 @@
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="120.5853" y="0.000000"/>
<point x="120.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<button name="BackSpace" oref="altline" />
<button name="space" oref="spaceline" />
<button name="Return" oref="outline7" />
<view>
<section angle="0">1 2 3 parenleft parenright</section>
<section angle="0">4 5 6 numbersign asterisk</section>
<section angle="0">7 8 9 plus minus</section>
<section angle="0">BackSpace 0 space Return</section>
</view>
</geometry>

View File

@ -2,59 +2,116 @@
<symbols version="0.90">
<key name="AD01">
<symbol label="1">1</symbol>
<symbol label="1">1</symbol>
<symbol label="1">1</symbol>
<symbol label="1">1</symbol>
</key>
<key name="AD02">
<symbol label="2">2</symbol>
<symbol label="2">2</symbol>
<symbol label="2">2</symbol>
<symbol label="2">2</symbol>
</key>
<key name="AD03">
<symbol label="3">3</symbol>
<symbol label="3">3</symbol>
<symbol label="3">3</symbol>
<symbol label="3">3</symbol>
</key>
<key name="AD04">
<symbol label="(">parenleft</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="(">parenleft</symbol>
</key>
<key name="AD05">
<symbol label=")">parenright</symbol>
<symbol label=")">parenright</symbol>
<symbol label=")">parenright</symbol>
<symbol label=")">parenright</symbol>
</key>
<key name="AC01">
<symbol label="4">4</symbol>
<symbol label="4">4</symbol>
<symbol label="4">4</symbol>
<symbol label="4">4</symbol>
</key>
<key name="AC02">
<symbol label="5">5</symbol>
<symbol label="5">5</symbol>
<symbol label="5">5</symbol>
<symbol label="5">5</symbol>
</key>
<key name="AC03">
<symbol label="6">6</symbol>
<symbol label="6">6</symbol>
<symbol label="6">6</symbol>
<symbol label="6">6</symbol>
</key>
<key name="AC04">
<symbol label="#">numbersign</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="#">numbersign</symbol>
</key>
<key name="AC05">
<symbol label="*">asterisk</symbol>
<symbol label="*">asterisk</symbol>
<symbol label="*">asterisk</symbol>
<symbol label="*">asterisk</symbol>
</key>
<key name="AB01">
<symbol label="7">7</symbol>
<symbol label="7">7</symbol>
<symbol label="7">7</symbol>
<symbol label="7">7</symbol>
</key>
<key name="AB02">
<symbol label="8">8</symbol>
<symbol label="8">8</symbol>
<symbol label="8">8</symbol>
<symbol label="8">8</symbol>
</key>
<key name="AB03">
<symbol label="9">9</symbol>
<symbol label="9">9</symbol>
<symbol label="9">9</symbol>
<symbol label="9">9</symbol>
</key>
<key name="AB04">
<symbol label="+">plus</symbol>
<symbol label="+">plus</symbol>
<symbol label="+">plus</symbol>
<symbol label="+">plus</symbol>
</key>
<key name="AB05">
<symbol label="-">minus</symbol>
<symbol label="-">minus</symbol>
<symbol label="-">minus</symbol>
<symbol label="-">minus</symbol>
</key>
<key name="AB06">
<symbol label="0">0</symbol>
<symbol label="0">0</symbol>
<symbol label="0">0</symbol>
<symbol label="0">0</symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
</symbols>

View File

@ -1,5 +1,7 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<symbol label="*">asterisk</symbol>
<symbol label="+/=">show_symbols</symbol>
<key name="AD01">
<symbol label="q">q</symbol>
<symbol label="Q">Q</symbol>
@ -58,7 +60,7 @@
<symbol label="p">p</symbol>
<symbol label="P">P</symbol>
<symbol label="0">0</symbol>
<symbol label="&#9651;">U25B3</symbol>
<symbol label="&#961;">Greek_tau</symbol>
</key>
<key name="AC01">
<symbol label="a">a</symbol>
@ -124,6 +126,9 @@
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="LFSH">
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
@ -175,20 +180,30 @@
</key>
<key name="AB08">
<symbol label=".">period</symbol>
<symbol label=".">period</symbol>
<symbol label=".">period</symbol>
<symbol label=".">period</symbol>
</key>
<key name="ABC123">
<symbol label="123">show-numbers</symbol>
<symbol label="123">show-numbers</symbol>
<symbol label="ABC">show-letters</symbol>
<symbol label="ABC">show-letters</symbol>
<symbol label="123">show_numbers</symbol>
<symbol label="ABC">show_letters</symbol>
</key>
<key name="I149">
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
</symbols>

View File

@ -38,8 +38,6 @@ enum {
PROP_0,
PROP_NAME,
PROP_BOUNDS,
PROP_GROUP,
PROP_LEVEL,
PROP_LAST
};
@ -55,20 +53,10 @@ typedef struct _EekElementPrivate
gchar *name;
EekBounds bounds;
EekElement *parent;
gint group;
gint level;
} EekElementPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekElement, eek_element, G_TYPE_OBJECT)
static void
eek_element_real_symbol_index_changed (EekElement *self,
gint group,
gint level)
{
// g_debug ("symbol-index-changed");
}
static void
eek_element_finalize (GObject *object)
{
@ -95,12 +83,6 @@ eek_element_set_property (GObject *object,
case PROP_BOUNDS:
eek_element_set_bounds (element, g_value_get_boxed (value));
break;
case PROP_GROUP:
eek_element_set_group (element, g_value_get_int (value));
break;
case PROP_LEVEL:
eek_element_set_level (element, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -124,12 +106,6 @@ eek_element_get_property (GObject *object,
eek_element_get_bounds (element, &bounds);
g_value_set_boxed (value, &bounds);
break;
case PROP_GROUP:
g_value_set_int (value, eek_element_get_group (element));
break;
case PROP_LEVEL:
g_value_set_int (value, eek_element_get_level (element));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -143,8 +119,6 @@ eek_element_class_init (EekElementClass *klass)
GParamSpec *pspec;
/* signals */
klass->symbol_index_changed = eek_element_real_symbol_index_changed;
gobject_class->set_property = eek_element_set_property;
gobject_class->get_property = eek_element_get_property;
gobject_class->finalize = eek_element_finalize;
@ -176,65 +150,12 @@ eek_element_class_init (EekElementClass *klass)
g_object_class_install_property (gobject_class,
PROP_BOUNDS,
pspec);
/**
* EekElement:group:
*
* The group value of the symbol index of #EekElement.
*/
pspec = g_param_spec_int ("group",
"Group",
"Group value of the symbol index",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_GROUP,
pspec);
/**
* EekElement:level:
*
* The level value of the symbol index of #EekElement.
*/
pspec = g_param_spec_int ("level",
"Level",
"Level value of the symbol index",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_LEVEL,
pspec);
/**
* EekElement::symbol-index-changed:
* @element: an #EekElement
* @group: row index of the symbol matrix of keys on @element
* @level: column index of the symbol matrix of keys on @element
*
* The ::symbol-index-changed signal is emitted each time the
* global configuration of group/level index changes.
*/
signals[SYMBOL_INDEX_CHANGED] =
g_signal_new (I_("symbol-index-changed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekElementClass, symbol_index_changed),
NULL,
NULL,
_eek_marshal_VOID__INT_INT,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_INT);
}
static void
eek_element_init (EekElement *self)
{
EekElementPrivate *priv = eek_element_get_instance_private (self);
priv->group = -1;
priv->level = -1;
(void)self;
}
/**
@ -428,144 +349,3 @@ eek_element_set_size (EekElement *element,
bounds.height = height;
eek_element_set_bounds (element, &bounds);
}
/**
* eek_element_set_symbol_index:
* @element: an #EekElement
* @group: row index of the symbol matrix
* @level: column index of the symbol matrix
*
* Set the default index of the symbol matrices of @element. The
* setting affects the child, if child does not have the index set, as
* well as this element. To unset, pass -1 as group/level.
*/
void
eek_element_set_symbol_index (EekElement *element,
gint group,
gint level)
{
gboolean emit_signal;
g_return_if_fail (EEK_IS_ELEMENT(element));
emit_signal = group != eek_element_get_group (element) ||
level != eek_element_get_level (element);
eek_element_set_group (element, group);
eek_element_set_level (element, level);
if (emit_signal)
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0, group, level);
}
/**
* eek_element_get_symbol_index:
* @element: an #EekElement
* @group: a pointer where the group value of the symbol index will be stored
* @level: a pointer where the level value of the symbol index will be stored
*
* Get the default index of the symbol matrices of @element.
* If the index is not set, -1 will be returned.
*/
void
eek_element_get_symbol_index (EekElement *element,
gint *group,
gint *level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (group != NULL || level != NULL);
if (group != NULL)
*group = eek_element_get_group (element);
if (level != NULL)
*level = eek_element_get_level (element);
}
/**
* eek_element_set_group:
* @element: an #EekElement
* @group: group index of @element
*
* Set the group value of the default symbol index of @element. To
* unset, pass -1 as @group.
*
* See also: eek_element_set_symbol_index()
*/
void
eek_element_set_group (EekElement *element,
gint group)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->group != group) {
priv->group = group;
g_object_notify (G_OBJECT(element), "group");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
group, priv->level);
}
}
/**
* eek_element_set_level:
* @element: an #EekElement
* @level: level index of @element
*
* Set the level value of the default symbol index of @element. To
* unset, pass -1 as @level.
*
* See also: eek_element_set_symbol_index()
*/
void
eek_element_set_level (EekElement *element,
gint level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->level != level) {
priv->level = level;
g_object_notify (G_OBJECT(element), "level");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
priv->group, level);
}
}
/**
* eek_element_get_group:
* @element: an #EekElement
*
* Return the group value of the default symbol index of @element.
* If the value is not set, -1 will be returned.
*
* See also: eek_element_get_symbol_index()
*/
gint
eek_element_get_group (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->group;
}
/**
* eek_element_get_level:
* @element: an #EekElement
*
* Return the level value of the default symbol index of @element.
* If the value is not set, -1 will be returned.
*
* See also: eek_element_get_symbol_index()
*/
gint
eek_element_get_level (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->level;
}

View File

@ -36,11 +36,6 @@ struct _EekElementClass
{
/*< private >*/
GObjectClass parent_class;
/* signals */
void (* symbol_index_changed) (EekElement *self,
gint group,
gint level);
};
GType eek_element_get_type (void) G_GNUC_CONST;
@ -70,18 +65,5 @@ void eek_element_get_absolute_position (EekElement *element,
gdouble *x,
gdouble *y);
void eek_element_set_symbol_index (EekElement *element,
gint group,
gint level);
void eek_element_get_symbol_index (EekElement *element,
gint *group,
gint *level);
void eek_element_set_group (EekElement *element,
gint group);
void eek_element_set_level (EekElement *element,
gint level);
gint eek_element_get_group (EekElement *element);
gint eek_element_get_level (EekElement *element);
G_END_DECLS
#endif /* EEK_ELEMENT_H */

View File

@ -32,12 +32,13 @@
#include <math.h>
#include <string.h>
#include "eek-gtk-keyboard.h"
#include "eek-renderer.h"
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
#include "src/symbol.h"
#include "eek-gtk-keyboard.h"
enum {
PROP_0,
@ -54,7 +55,7 @@ enum {
typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
EekKeyboard *keyboard;
LevelKeyboard *keyboard;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
@ -64,13 +65,13 @@ typedef struct _EekGtkKeyboardPrivate
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
static void on_key_pressed (EekKey *key,
EekGtkKeyboard *self);
EekGtkKeyboard *self, guint level);
static void on_key_released (EekKey *key,
EekGtkKeyboard *self);
static void render_pressed_key (GtkWidget *widget,
EekKey *key);
EekKey *key, guint level);
static void render_locked_key (GtkWidget *widget,
EekKey *key);
EekKey *key, guint level);
static void render_released_key (GtkWidget *widget,
EekKey *key);
@ -95,8 +96,6 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation;
GList *list, *head;
gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) {
@ -113,19 +112,19 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
eek_renderer_render_keyboard (priv->renderer, cr);
uint level = priv->keyboard->level;
/* redraw pressed key */
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_pressed_key (self, head->data);
const GList *list = priv->keyboard->pressed_keys;
for (const GList *head = list; head; head = g_list_next (head)) {
render_pressed_key (self, head->data, level);
}
g_list_free (list);
/* redraw locked key */
list = eek_keyboard_get_locked_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_locked_key (self, ((EekModifierKey *)head->data)->key);
list = priv->keyboard->locked_keys;
for (const GList *head = list; head; head = g_list_next (head)) {
render_locked_key (self, ((EekModifierKey *)head->data)->key, level);
}
g_list_free (list);
return FALSE;
}
@ -154,7 +153,8 @@ static void depress(EekGtkKeyboard *self,
if (key) {
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
guint level = priv->keyboard->level;
on_key_pressed(key, self, level);
}
}
@ -164,7 +164,7 @@ static void drag(EekGtkKeyboard *self,
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
GList *list, *head;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
list = g_list_copy(priv->keyboard->pressed_keys);
if (key) {
gboolean found = FALSE;
@ -181,7 +181,8 @@ static void drag(EekGtkKeyboard *self,
if (!found) {
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
guint level = priv->keyboard->level;
on_key_pressed(key, self, level);
}
} else {
for (head = list; head; head = g_list_next (head)) {
@ -195,7 +196,7 @@ static void drag(EekGtkKeyboard *self,
static void release(EekGtkKeyboard *self, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
GList *list = eek_keyboard_get_pressed_keys (priv->keyboard);
GList *list = g_list_copy(priv->keyboard->pressed_keys);
for (GList *head = list; head; head = g_list_next (head)) {
EekKey *key = EEK_KEY(head->data);
eek_keyboard_release_key(priv->keyboard, key, time);
@ -282,7 +283,7 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
list = eek_keyboard_get_pressed_keys (priv->keyboard);
list = g_list_copy(priv->keyboard->pressed_keys);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey released");
g_signal_emit_by_name (head->data, "released");
@ -309,8 +310,8 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget,
(gdouble)x,
(gdouble)y);
if (key) {
EekSymbol *symbol = eek_key_get_symbol (key);
const gchar *text = eek_symbol_get_tooltip (symbol);
//struct squeek_symbol *symbol = eek_key_get_symbol_at_index(key, 0, priv->keyboard->level);
const gchar *text = NULL; // FIXME
if (text) {
gtk_tooltip_set_text (tooltip, text);
return TRUE;
@ -321,18 +322,14 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget,
static void
eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
EekKeyboard *keyboard)
LevelKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
if (priv->keyboard == keyboard)
return;
if (priv->keyboard) {
g_object_unref (priv->keyboard);
}
priv->keyboard = g_object_ref (keyboard);
priv->keyboard = keyboard;
}
static void
@ -341,7 +338,7 @@ eek_gtk_keyboard_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboard *keyboard;
LevelKeyboard *keyboard;
switch (prop_id) {
case PROP_KEYBOARD:
@ -368,14 +365,13 @@ eek_gtk_keyboard_dispose (GObject *object)
if (priv->keyboard) {
GList *list, *head;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
list = g_list_copy(priv->keyboard->pressed_keys);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
g_signal_emit_by_name (head->data, "released", priv->keyboard);
g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard));
}
g_list_free (list);
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
}
@ -443,37 +439,18 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self)
* Returns: a #GtkWidget
*/
GtkWidget *
eek_gtk_keyboard_new (EekKeyboard *keyboard)
eek_gtk_keyboard_new (LevelKeyboard *keyboard)
{
return g_object_new (EEK_TYPE_GTK_KEYBOARD, "keyboard", keyboard, NULL);
}
static void
magnify_bounds (GtkWidget *self,
EekBounds *bounds,
EekBounds *large_bounds,
gdouble scale)
{
GtkAllocation allocation;
gdouble x, y;
g_assert (scale >= 1.0);
gtk_widget_get_allocation (self, &allocation);
large_bounds->width = bounds->width * scale;
large_bounds->height = bounds->height * scale;
x = bounds->x - (large_bounds->width - bounds->width) / 2;
y = bounds->y - large_bounds->height;
large_bounds->x = CLAMP(x, 0, allocation.width - large_bounds->width);
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL));
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret);
priv->keyboard = keyboard;
return GTK_WIDGET(ret);
}
static void
render_pressed_key (GtkWidget *widget,
EekKey *key)
EekKey *key,
guint level)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
@ -483,7 +460,7 @@ render_pressed_key (GtkWidget *widget,
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
eek_renderer_render_key (priv->renderer, cr, key, level, 1.0, TRUE);
/*
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
*/
@ -494,7 +471,8 @@ render_pressed_key (GtkWidget *widget,
static void
render_locked_key (GtkWidget *widget,
EekKey *key)
EekKey *key,
guint level)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
@ -504,7 +482,7 @@ render_locked_key (GtkWidget *widget,
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
eek_renderer_render_key (priv->renderer, cr, key, level, 1.0, TRUE);
gdk_window_end_draw_frame (window, context);
@ -532,7 +510,8 @@ render_released_key (GtkWidget *widget,
static void
on_key_pressed (EekKey *key,
EekGtkKeyboard *self)
EekGtkKeyboard *self,
guint level)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
@ -540,7 +519,7 @@ on_key_pressed (EekKey *key,
if (!priv->renderer)
return;
render_pressed_key (GTK_WIDGET(self), key);
render_pressed_key (GTK_WIDGET(self), key, level);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA

View File

@ -45,7 +45,7 @@ struct _EekGtkKeyboardClass
};
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_GTK_KEYBOARD_H */

View File

@ -29,15 +29,15 @@
#include <string.h>
#include "eek-key.h"
#include "eek-section.h"
#include "eek-keyboard.h"
#include "eek-symbol.h"
#include "src/keyboard.h"
#include "src/symbol.h"
#include "eek-key.h"
enum {
PROP_0,
PROP_KEYCODE,
PROP_SYMBOL_MATRIX,
PROP_OREF,
PROP_LAST
};
@ -52,10 +52,8 @@ static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekKeyPrivate
{
guint keycode;
EekSymbolMatrix *symbol_matrix;
gulong oref; // UI outline reference
gboolean is_pressed;
struct squeek_key *state;
gboolean is_locked;
} EekKeyPrivate;
@ -89,7 +87,7 @@ eek_key_finalize (GObject *object)
EekKey *self = EEK_KEY (object);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
eek_symbol_matrix_free (priv->symbol_matrix);
squeek_key_free (priv->state);
G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
}
@ -100,15 +98,7 @@ eek_key_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
EekSymbolMatrix *matrix;
switch (prop_id) {
case PROP_KEYCODE:
eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value));
break;
case PROP_SYMBOL_MATRIX:
matrix = g_value_get_boxed (value);
eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
break;
case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break;
@ -125,13 +115,6 @@ eek_key_get_property (GObject *object,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_KEYCODE:
g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object)));
break;
case PROP_SYMBOL_MATRIX:
g_value_set_boxed (value,
eek_key_get_symbol_matrix (EEK_KEY(object)));
break;
case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break;
@ -155,30 +138,6 @@ eek_key_class_init (EekKeyClass *klass)
klass->locked = eek_key_real_locked;
klass->unlocked = eek_key_real_unlocked;
/**
* EekKey:keycode:
*
* The keycode of #EekKey.
*/
pspec = g_param_spec_uint ("keycode",
"Keycode",
"Keycode of the key",
0, G_MAXUINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_KEYCODE, pspec);
/**
* EekKey:symbol-matrix:
*
* The symbol matrix of #EekKey.
*/
pspec = g_param_spec_boxed ("symbol-matrix",
"Symbol matrix",
"Symbol matrix of the key",
EEK_TYPE_SYMBOL_MATRIX,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec);
/**
* EekKey:oref:
*
@ -232,9 +191,13 @@ static void
eek_key_init (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
priv->state = squeek_key_new (0);
}
void eek_key_share_state(EekKey *self, struct squeek_key *state) {
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->state = state;
}
/**
* eek_key_set_keycode:
* @key: an #EekKey
@ -254,7 +217,7 @@ eek_key_set_keycode (EekKey *key,
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->keycode = keycode;
squeek_key_set_keycode(priv->state, keycode);
}
/**
@ -271,110 +234,7 @@ eek_key_get_keycode (EekKey *key)
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->keycode;
}
/**
* eek_key_set_symbol_matrix:
* @key: an #EekKey
* @matrix: an #EekSymbolMatrix
*
* Set the symbol matrix of @key to @matrix.
*/
void
eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
eek_symbol_matrix_free (priv->symbol_matrix);
priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
}
/**
* eek_key_get_symbol_matrix:
* @key: an #EekKey
*
* Get the symbol matrix of @key.
* Returns: (transfer none): #EekSymbolMatrix or %NULL
*/
EekSymbolMatrix *
eek_key_get_symbol_matrix (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->symbol_matrix;
}
/**
* eek_key_get_symbol:
* @key: an #EekKey
*
* Get the current symbol of @key.
* Return value: (transfer none): the current #EekSymbol or %NULL on failure
*/
EekSymbol *
eek_key_get_symbol (EekKey *key)
{
return eek_key_get_symbol_with_fallback (key, 0, 0);
}
/**
* eek_key_get_symbol_with_fallback:
* @key: an #EekKey
* @fallback_group: fallback group index
* @fallback_level: fallback level index
*
* Get the current symbol of @key.
* Return value: (transfer none): the current #EekSymbol or %NULL on failure
*/
EekSymbol *
eek_key_get_symbol_with_fallback (EekKey *key,
gint fallback_group,
gint fallback_level)
{
gint group, level;
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
g_return_val_if_fail (fallback_group >= 0, NULL);
g_return_val_if_fail (fallback_level >= 0, NULL);
eek_element_get_symbol_index (EEK_ELEMENT(key), &group, &level);
if (group < 0 || level < 0) {
EekElement *section;
section = eek_element_get_parent (EEK_ELEMENT(key));
g_return_val_if_fail (EEK_IS_SECTION (section), NULL);
if (group < 0)
group = eek_element_get_group (section);
if (level < 0)
level = eek_element_get_level (section);
if (group < 0 || level < 0) {
EekElement *keyboard;
keyboard = eek_element_get_parent (section);
g_return_val_if_fail (EEK_IS_KEYBOARD (keyboard), NULL);
if (group < 0)
group = eek_element_get_group (keyboard);
if (level < 0)
level = eek_element_get_level (keyboard);
}
}
return eek_key_get_symbol_at_index (key,
group,
level,
fallback_group,
fallback_level);
return squeek_key_get_keycode(priv->state);
}
/**
@ -388,46 +248,13 @@ eek_key_get_symbol_with_fallback (EekKey *key,
* Get the symbol at (@group, @level) in the symbol matrix of @key.
* Return value: (transfer none): an #EekSymbol at (@group, @level), or %NULL
*/
EekSymbol *
struct squeek_symbol*
eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level)
guint level)
{
EekKeyPrivate *priv = eek_key_get_instance_private (key);
gint num_symbols;
g_return_val_if_fail (fallback_group >= 0, NULL);
g_return_val_if_fail (fallback_level >= 0, NULL);
if (group < 0)
group = fallback_group;
if (level < 0)
level = fallback_level;
if (!priv->symbol_matrix)
return NULL;
num_symbols = priv->symbol_matrix->num_groups *
priv->symbol_matrix->num_levels;
if (num_symbols == 0)
return NULL;
if (group >= priv->symbol_matrix->num_groups) {
if (fallback_group < 0)
return NULL;
group = fallback_group;
}
if (level >= priv->symbol_matrix->num_levels) {
if (fallback_level < 0)
return NULL;
level = fallback_level;
}
return priv->symbol_matrix->data[group * priv->symbol_matrix->num_levels +
level];
return squeek_key_get_symbol(priv->state, level);
}
/**
@ -479,9 +306,9 @@ eek_key_is_pressed (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
EekKeyPrivate *priv = (EekKeyPrivate*)eek_key_get_instance_private (key);
return priv->is_pressed;
return (bool)squeek_key_is_pressed(priv->state);
}
/**
@ -506,13 +333,10 @@ void eek_key_set_pressed(EekKey *key, gboolean value)
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->is_pressed = value;
squeek_key_set_pressed(priv->state, value);
}
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);
struct squeek_key *eek_key_get_state(EekKey *key) {
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->state;
}

View File

@ -26,7 +26,6 @@
#define EEK_KEY_H 1
#include "eek-element.h"
#include "eek-symbol-matrix.h"
G_BEGIN_DECLS
@ -59,19 +58,10 @@ GType eek_key_get_type (void) G_GNUC_CONST;
void eek_key_set_keycode (EekKey *key,
guint keycode);
guint eek_key_get_keycode (EekKey *key);
void eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix);
EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key);
EekSymbol *eek_key_get_symbol (EekKey *key);
EekSymbol *eek_key_get_symbol_with_fallback
(EekKey *key,
gint fallback_group,
gint fallback_level);
EekSymbol *eek_key_get_symbol_at_index (EekKey *key,
struct squeek_key *eek_key_get_state(EekKey *key);
struct squeek_symbol *eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level);
guint level);
void eek_key_set_oref (EekKey *key,
guint oref);
@ -81,8 +71,6 @@ gboolean eek_key_is_pressed (EekKey *key);
gboolean eek_key_is_locked (EekKey *key);
void eek_key_set_pressed (EekKey *key,
gboolean value);
gboolean eek_key_has_label (EekKey *key);
void eek_key_share_state(EekKey *self, struct squeek_key *state);
G_END_DECLS
#endif /* EEK_KEY_H */

View File

@ -30,18 +30,19 @@
#include "config.h"
#include <glib/gprintf.h>
#include "eek-keyboard.h"
#include "eek-marshalers.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
#include "keymap.h"
#include "src/keyboard.h"
#include "src/symbol.h"
#include "eek-keyboard.h"
enum {
PROP_0,
PROP_MODIFIER_BEHAVIOR,
PROP_LAST
};
@ -66,19 +67,7 @@ static guint signals[LAST_SIGNAL] = { 0, };
struct _EekKeyboardPrivate
{
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
unsigned int old_level;
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
/* Map key names to key objects: */
GHashTable *names;
/* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask;
EekModifierType alt_gr_mask;
char dummy; // won't run otherwise
};
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
@ -115,37 +104,7 @@ on_key_unlocked (EekSection *section,
g_signal_emit (keyboard, signals[KEY_UNLOCKED], 0, key);
}
static void
on_symbol_index_changed (EekSection *section,
gint group,
gint level,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "symbol-index-changed", group, level);
}
static void
section_child_added_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
const gchar *name = eek_element_get_name(element);
g_hash_table_insert (keyboard->priv->names,
(gpointer)name,
element);
}
static void
section_child_removed_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
const gchar *name = eek_element_get_name(element);
g_hash_table_remove (keyboard->priv->names,
name);
}
static EekSection *
EekSection *
eek_keyboard_real_create_section (EekKeyboard *self)
{
EekSection *section;
@ -153,12 +112,6 @@ eek_keyboard_real_create_section (EekKeyboard *self)
section = g_object_new (EEK_TYPE_SECTION, NULL);
g_return_val_if_fail (section, NULL);
g_signal_connect (G_OBJECT(section), "child-added",
G_CALLBACK(section_child_added_cb), self);
g_signal_connect (G_OBJECT(section), "child-removed",
G_CALLBACK(section_child_removed_cb), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section));
return section;
@ -171,10 +124,6 @@ eek_keyboard_set_property (GObject *object,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_MODIFIER_BEHAVIOR:
eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(object),
g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -188,183 +137,117 @@ eek_keyboard_get_property (GObject *object,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_MODIFIER_BEHAVIOR:
g_value_set_enum (value,
eek_keyboard_get_modifier_behavior (EEK_KEYBOARD(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_level_from_modifiers (EekKeyboard *self, EekKey *key)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
/* Use the numbers/letters bit from the old level */
gint level = priv->old_level & 2;
/* Handle non-emitting keys */
if (key) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "ABC123") == 0)
level ^= 2;
}
level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
switch (priv->old_level) {
case VIEW_LETTERS_UPPER:
{
/* Redirect upper case letters to numbers instead of symbols, clearing
the shift modifier to keep the modifiers in sync with the level */
if (level == VIEW_SYMBOLS) {
level = VIEW_NUMBERS;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_SYMBOLS:
{
/* Redirect symbols to lower case letters instead of upper case,
clearing the shift modifier to keep the modifiers in sync with the
level */
if (level == VIEW_LETTERS_UPPER) {
level = VIEW_LETTERS_LOWER;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_LETTERS_LOWER: /* Direct transitions between views */
case VIEW_NUMBERS:
default:
break;
}
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
else
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
priv->old_level = level;
eek_element_set_level (EEK_ELEMENT(self), level);
eek_layout_update_layout(self);
}
static void
set_modifiers_with_key (EekKeyboard *self,
/// Updates the state of locked keys based on the key that was activated
/// FIXME: make independent of what the key are named,
/// and instead refer to the contained symbols
static guint
set_key_states (LevelKeyboard *keyboard,
EekKey *key,
EekModifierType modifiers)
guint new_level)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
EekModifierType enabled = (priv->modifiers ^ modifiers) & modifiers;
EekModifierType disabled = (priv->modifiers ^ modifiers) & priv->modifiers;
if (enabled != 0) {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
// Keys locking rules hardcoded for the time being...
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
// Lock the shift whenever it's pressed on the baselevel
// TODO: need to lock shift on the destination level
if (g_strcmp0(name, "Shift_L") == 0 && keyboard->level == 0) {
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = enabled;
modifier_key->modifiers = 0;
modifier_key->key = g_object_ref (key);
priv->locked_keys =
g_list_prepend (priv->locked_keys, modifier_key);
keyboard->locked_keys =
g_list_prepend (keyboard->locked_keys, modifier_key);
g_signal_emit_by_name (modifier_key->key, "locked");
}
} else {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
GList *head;
for (head = priv->locked_keys; head; ) {
if (keyboard->level == 1) {
// Only shift is locked in this state, unlock on any key press
for (GList *head = keyboard->locked_keys; head; ) {
EekModifierKey *modifier_key = head->data;
if (modifier_key->modifiers & disabled) {
GList *next = g_list_next (head);
priv->locked_keys =
g_list_remove_link (priv->locked_keys, head);
keyboard->locked_keys =
g_list_remove_link (keyboard->locked_keys, head);
g_signal_emit_by_name (modifier_key->key, "unlocked");
g_list_free1 (head);
head = next;
} else
head = g_list_next (head);
}
return 0;
}
}
priv->modifiers = modifiers;
return new_level;
}
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
// FIXME: unhardcode, parse some user information as to which key triggers which view (level)
static void
set_level_from_press (LevelKeyboard *keyboard, EekKey *key)
{
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
guint level = keyboard->level;
/* Handle non-emitting keys */
if (key) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "show_numbers") == 0) {
level = 2;
} else if (g_strcmp0(name, "show_letters") == 0) {
level = 0;
} else if (g_strcmp0(name, "show_symbols") == 0) {
level = 3;
} else if (g_strcmp0(name, "Shift_L") == 0) {
level ^= 1;
}
}
keyboard->level = set_key_states(keyboard, key, level);
eek_layout_update_layout(keyboard);
}
void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp) {
eek_key_set_pressed(key, TRUE);
priv->pressed_keys = g_list_prepend (priv->pressed_keys, key);
keyboard->pressed_keys = g_list_prepend (keyboard->pressed_keys, key);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
struct squeek_symbol *symbol = eek_key_get_symbol_at_index(
key, 0, keyboard->level
);
if (!symbol)
return;
EekModifierType modifier = eek_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);
}
// Only take action about setting level *after* the key has taken effect, i.e. on release
//set_level_from_press (keyboard, key);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = eek_key_get_keycode (key);
EekModifierType modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, TRUE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, 0, TRUE, timestamp);
}
void eek_keyboard_release_key( EekKeyboard *keyboard,
void eek_keyboard_release_key(LevelKeyboard *keyboard,
EekKey *key,
guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
for (GList *head = priv->pressed_keys; head; head = g_list_next (head)) {
for (GList *head = keyboard->pressed_keys; head; head = g_list_next (head)) {
if (head->data == key) {
priv->pressed_keys = g_list_remove_link (priv->pressed_keys, head);
keyboard->pressed_keys = g_list_remove_link (keyboard->pressed_keys, head);
g_list_free1 (head);
break;
}
}
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
struct squeek_symbol *symbol = eek_key_get_symbol_at_index(
key, 0, keyboard->level);
if (!symbol)
return;
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (!symbol)
return;
modifier = eek_symbol_get_modifier_mask (symbol);
switch (priv->modifier_behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier);
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
if (modifier)
set_modifiers_with_key (keyboard, key, priv->modifiers ^ modifier);
else
set_modifiers_with_key (keyboard, key,
(priv->modifiers ^ modifier) & modifier);
break;
}
set_level_from_modifiers (keyboard, key);
set_level_from_press (keyboard, key);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, FALSE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, 0, FALSE, timestamp);
}
static void
@ -376,25 +259,27 @@ eek_keyboard_dispose (GObject *object)
static void
eek_keyboard_finalize (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
guint i;
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
}
g_list_free (priv->pressed_keys);
g_list_free_full (priv->locked_keys,
(GDestroyNotify) eek_modifier_key_free);
g_hash_table_destroy (priv->names);
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
void level_keyboard_deinit(LevelKeyboard *self) {
g_hash_table_destroy (self->names);
for (guint i = 0; i < self->outline_array->len; i++) {
EekOutline *outline = &g_array_index (self->outline_array,
EekOutline,
i);
g_slice_free1 (sizeof (EekPoint) * outline->num_points,
outline->points);
}
g_array_free (priv->outline_array, TRUE);
g_array_free (self->outline_array, TRUE);
for (guint i = 0; i < 4; i++) {
// free self->view[i];
}
}
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
void level_keyboard_free(LevelKeyboard *self) {
level_keyboard_deinit(self);
g_free(self);
}
static void
@ -405,8 +290,6 @@ eek_keyboard_real_child_added (EekContainer *self,
G_CALLBACK(on_key_locked), self);
g_signal_connect (element, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
g_signal_connect (element, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
@ -422,9 +305,6 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
klass->create_section = eek_keyboard_real_create_section;
/* signals */
container_class->child_added = eek_keyboard_real_child_added;
@ -435,21 +315,6 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize;
/**
* EekKeyboard:modifier-behavior:
*
* The modifier handling mode of #EekKeyboard.
*/
pspec = g_param_spec_enum ("modifier-behavior",
"Modifier behavior",
"Modifier handling mode of the keyboard",
EEK_TYPE_MODIFIER_BEHAVIOR,
EEK_MODIFIER_BEHAVIOR_NONE,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_MODIFIER_BEHAVIOR,
pspec);
/**
* EekKeyboard::key-locked:
* @keyboard: an #EekKeyboard
@ -495,26 +360,22 @@ static void
eek_keyboard_init (EekKeyboard *self)
{
self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
self->priv->names = g_hash_table_new (g_str_hash, g_str_equal);
eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
self->scale = 1.0;
}
/**
* eek_keyboard_create_section:
* @keyboard: an #EekKeyboard
*
* Create an #EekSection instance and append it to @keyboard. This
* function is rarely called by application but called by #EekLayout
* implementation.
*/
EekSection *
eek_keyboard_create_section (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return EEK_KEYBOARD_GET_CLASS(keyboard)->create_section (keyboard);
void level_keyboard_init(LevelKeyboard *self) {
self->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
}
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_key_hash) {
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
level_keyboard_init(keyboard);
for (uint i = 0; i < 4; i++) {
keyboard->views[i] = views[i];
}
keyboard->manager = manager;
keyboard->names = name_key_hash;
return keyboard;
}
/**
@ -526,12 +387,10 @@ eek_keyboard_create_section (EekKeyboard *keyboard)
* Return value: (transfer none): #EekKey whose name is @name
*/
EekKey *
eek_keyboard_find_key_by_name (EekKeyboard *keyboard,
eek_keyboard_find_key_by_name (LevelKeyboard *keyboard,
const gchar *name)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_hash_table_lookup (keyboard->priv->names,
name);
return g_hash_table_lookup (keyboard->names, name);
}
/**
@ -554,82 +413,6 @@ eek_keyboard_get_size (EekKeyboard *keyboard,
*height = bounds.height;
}
/**
* eek_keyboard_set_modifier_behavior:
* @keyboard: an #EekKeyboard
* @modifier_behavior: modifier behavior of @keyboard
*
* Set the modifier handling mode of @keyboard.
*/
void
eek_keyboard_set_modifier_behavior (EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifier_behavior = modifier_behavior;
}
/**
* eek_keyboard_get_modifier_behavior:
* @keyboard: an #EekKeyboard
*
* Get the modifier handling mode of @keyboard.
* Returns: #EekModifierBehavior
*/
EekModifierBehavior
eek_keyboard_get_modifier_behavior (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->modifier_behavior;
}
void
eek_keyboard_set_modifiers (EekKeyboard *keyboard,
EekModifierType modifiers)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifiers = modifiers;
set_level_from_modifiers (keyboard, NULL);
}
/**
* eek_keyboard_get_modifiers:
* @keyboard: an #EekKeyboard
*
* Get the current modifier status of @keyboard.
* Returns: #EekModifierType
*/
EekModifierType
eek_keyboard_get_modifiers (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->modifiers;
}
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned integer ID of the registered outline, for
* later reference
*/
guint
eek_keyboard_add_outline (EekKeyboard *keyboard,
EekOutline *outline)
{
EekOutline *_outline;
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
_outline = eek_outline_copy (outline);
g_array_append_val (keyboard->priv->outline_array, *_outline);
/* don't use eek_outline_free here, so as to keep _outline->points */
g_slice_free (EekOutline, _outline);
return keyboard->priv->outline_array->len - 1;
}
/**
* eek_keyboard_get_outline:
* @keyboard: an #EekKeyboard
@ -639,117 +422,13 @@ eek_keyboard_add_outline (EekKeyboard *keyboard,
* Returns: an #EekOutline, which should not be released
*/
EekOutline *
eek_keyboard_get_outline (EekKeyboard *keyboard,
level_keyboard_get_outline (LevelKeyboard *keyboard,
guint oref)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
if (oref > keyboard->priv->outline_array->len)
if (oref > keyboard->outline_array->len)
return NULL;
return &g_array_index (keyboard->priv->outline_array, EekOutline, oref);
}
/**
* eek_keyboard_get_n_outlines:
* @keyboard: an #EekKeyboard
*
* Get the number of outlines defined in @keyboard.
* Returns: integer
*/
gsize
eek_keyboard_get_n_outlines (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->outline_array->len;
}
/**
* eek_keyboard_set_num_lock_mask:
* @keyboard: an #EekKeyboard
* @num_lock_mask: an #EekModifierType
*
* Set modifier mask used as Num_Lock.
*/
void
eek_keyboard_set_num_lock_mask (EekKeyboard *keyboard,
EekModifierType num_lock_mask)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->num_lock_mask = num_lock_mask;
}
/**
* eek_keyboard_get_num_lock_mask:
* @keyboard: an #EekKeyboard
*
* Get modifier mask used as Num_Lock.
* Returns: an #EekModifierType
*/
EekModifierType
eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->num_lock_mask;
}
/**
* eek_keyboard_set_alt_gr_mask:
* @keyboard: an #EekKeyboard
* @alt_gr_mask: an #EekModifierType
*
* Set modifier mask used as Alt_Gr.
*/
void
eek_keyboard_set_alt_gr_mask (EekKeyboard *keyboard,
EekModifierType alt_gr_mask)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->alt_gr_mask = alt_gr_mask;
}
/**
* eek_keyboard_get_alt_gr_mask:
* @keyboard: an #EekKeyboard
*
* Get modifier mask used as Alt_Gr.
* Returns: an #EekModifierType
*/
EekModifierType
eek_keyboard_get_alt_gr_mask (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->alt_gr_mask;
}
/**
* eek_keyboard_get_pressed_keys:
* @keyboard: an #EekKeyboard
*
* Get pressed keys.
* Returns: (transfer container) (element-type EekKey): A list of
* pressed keys.
*/
GList *
eek_keyboard_get_pressed_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_list_copy (keyboard->priv->pressed_keys);
}
/**
* eek_keyboard_get_locked_keys:
* @keyboard: an #EekKeyboard
*
* Get locked keys.
* Returns: (transfer container) (element-type Eek.ModifierKey): A list
* of locked keys.
*/
GList *
eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_list_copy (keyboard->priv->locked_keys);
return &g_array_index (keyboard->outline_array, EekOutline, oref);
}
/**
@ -760,7 +439,7 @@ eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
* Returns: a string containing the XKB keymap.
*/
gchar *
eek_keyboard_get_keymap(EekKeyboard *keyboard)
eek_keyboard_get_keymap(LevelKeyboard *keyboard)
{
/* Start the keycodes and symbols sections with their respective headers. */
gchar *keycodes = g_strdup(keymap_keycodes_header);
@ -768,14 +447,15 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
/* Iterate over the keys in the name-to-key hash table. */
GHashTableIter iter;
gpointer key_name, key_ptr;
g_hash_table_iter_init(&iter, keyboard->priv->names);
gchar *key_name;
gpointer key_ptr;
g_hash_table_iter_init(&iter, keyboard->names);
while (g_hash_table_iter_next(&iter, &key_name, &key_ptr)) {
while (g_hash_table_iter_next(&iter, (gpointer)&key_name, &key_ptr)) {
gchar *current, *line;
EekKey *key = EEK_KEY(key_ptr);
int keycode = eek_key_get_keycode(key);
guint keycode = eek_key_get_keycode(key);
/* Don't include invalid keycodes in the keymap. */
if (keycode == EEK_INVALID_KEYCODE)
@ -789,45 +469,13 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
g_free(line);
g_free(current);
/* Find the symbols associated with the key. */
EekSymbolMatrix *matrix = eek_key_get_symbol_matrix(key);
EekSymbol *syms[4];
int i, j;
/* Get the symbols for all the levels defined for the key, then
pad it out with the first symbol for all levels up to the fourth. */
for (i = 0; i < matrix->num_levels; ++i)
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i);
while (i < 4) {
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, 0);
i++;
}
/* The four levels are split into two groups in the keymap.
Generate strings for each of these groups, where an empty group is
treated specially. */
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]),
NULL);
else
groups[i] = "";
}
/* Append a key definition to the symbols section. */
// FIXME: free
const char *key_str = squeek_key_to_keymap_entry(
(char*)key_name,
eek_key_get_state(key)
);
current = symbols;
line = g_strdup_printf(" key <%s> { [ %s ], [ %s ] };\n",
(char *)key_name, groups[0], groups[1]);
g_free(groups[0]);
g_free(groups[1]);
symbols = g_strconcat(current, line, NULL);
g_free(line);
symbols = g_strconcat(current, key_str, NULL);
g_free(current);
}
@ -841,3 +489,8 @@ eek_keyboard_get_keymap(EekKeyboard *keyboard)
g_free(symbols);
return keymap;
}
EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard)
{
return keyboard->views[keyboard->level];
}

View File

@ -59,12 +59,7 @@ struct _EekKeyboard
EekContainer parent;
EekKeyboardPrivate *priv;
struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd
double scale;
EekboardContextService *manager; // unowned reference
};
/**
@ -88,8 +83,6 @@ struct _EekKeyboardClass
gpointer get_symbol_index;
/*< public >*/
EekSection *(* create_section) (EekKeyboard *self);
EekKey *(* find_key_by_name) (EekKeyboard *self,
const gchar *name);
@ -124,8 +117,28 @@ struct _EekModifierKey {
};
typedef struct _EekModifierKey EekModifierKey;
/// Keyboard state holder
struct _LevelKeyboard {
EekKeyboard *views[4];
guint level;
struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd
GArray *outline_array;
EekKeyboard *eek_keyboard_new (EekboardContextService *manager,
GList *pressed_keys;
GList *locked_keys;
/* Map key names to key objects: */
GHashTable *names;
guint id; // as a key to layout choices
EekboardContextService *manager; // unowned reference
};
typedef struct _LevelKeyboard LevelKeyboard;
LevelKeyboard *eek_keyboard_new(EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
@ -140,61 +153,37 @@ void eek_keyboard_set_size
gdouble width,
gdouble height);
void eek_keyboard_set_modifier_behavior
(EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior);
EekModifierBehavior eek_keyboard_get_modifier_behavior
(EekKeyboard *keyboard);
void eek_keyboard_set_modifiers
(EekKeyboard *keyboard,
EekModifierType modifiers);
EekModifierType eek_keyboard_get_modifiers
(EekKeyboard *keyboard);
EekSection *eek_keyboard_create_section
(EekKeyboard *keyboard);
EekKey *eek_keyboard_find_key_by_name
(EekKeyboard *keyboard,
(LevelKeyboard *keyboard,
const gchar *name);
guint eek_keyboard_add_outline
(EekKeyboard *keyboard,
EekOutline *outline);
EekOutline *eek_keyboard_get_outline
(EekKeyboard *keyboard,
EekOutline *level_keyboard_get_outline
(LevelKeyboard *keyboard,
guint oref);
gsize eek_keyboard_get_n_outlines
(EekKeyboard *keyboard);
void eek_keyboard_set_num_lock_mask
(EekKeyboard *keyboard,
EekModifierType num_lock_mask);
EekModifierType eek_keyboard_get_num_lock_mask
(EekKeyboard *keyboard);
void eek_keyboard_set_alt_gr_mask
(EekKeyboard *keyboard,
EekModifierType alt_gr_mask);
EekModifierType eek_keyboard_get_alt_gr_mask
(EekKeyboard *keyboard);
GList *eek_keyboard_get_pressed_keys
(EekKeyboard *keyboard);
GList *eek_keyboard_get_locked_keys
(EekKeyboard *keyboard);
EekModifierKey *eek_modifier_key_copy
(EekModifierKey *modkey);
void eek_modifier_key_free
(EekModifierKey *modkey);
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_release_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp);
gchar * eek_keyboard_get_keymap
(EekKeyboard *keyboard);
(LevelKeyboard *keyboard);
EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard);
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_key_hash);
void level_keyboard_deinit(LevelKeyboard *self);
void level_keyboard_free(LevelKeyboard *self);
/* Create an #EekSection instance and append it to @keyboard. This
* function is rarely called by application but called by #EekLayout
* implementation.
*/
EekSection *
eek_keyboard_real_create_section (EekKeyboard *self);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

View File

@ -25,11 +25,7 @@
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "eek-keysym.h"
#include "eek-serializable.h"
/* modifier keys */
#define EEK_KEYSYM_Shift_L 0xffe1
@ -59,204 +55,13 @@ typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-keysym-entries.h"
static gchar *
unichar_to_utf8 (gunichar uc)
guint32
eek_keysym_from_name (const gchar *name)
{
if (g_unichar_isgraph (uc)) {
gchar *buf;
gint len;
len = g_unichar_to_utf8 (uc, NULL);
buf = g_malloc0 (len + 1);
g_unichar_to_utf8 (uc, buf);
return buf;
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 g_strdup ("");
}
static int
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
{
const EekKeysymEntry *entry0 = key0, *entry1 = key1;
return (gint) (entry0->xkeysym - entry1->xkeysym);
}
static EekKeysymEntry *
find_keysym_entry_by_xkeysym (guint xkeysym,
const EekKeysymEntry *entries,
gint num_entries)
{
EekKeysymEntry key;
key.xkeysym = xkeysym;
return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
keysym_entry_compare_by_xkeysym);
}
static gboolean
get_unichar (guint xkeysym, gunichar *uc) {
/* Check for Latin-1 characters (1:1 mapping) */
if ((xkeysym >= 0x0020 && xkeysym <= 0x007e) ||
(xkeysym >= 0x00a0 && xkeysym <= 0x00ff)) {
*uc = xkeysym;
return TRUE;
}
/* Also check for directly encoded 24-bit UCS characters:
*/
if ((xkeysym & 0xff000000) == 0x01000000) {
*uc = xkeysym & 0x00ffffff;
return TRUE;
}
return FALSE;
}
G_INLINE_FUNC EekModifierType
get_modifier_mask (guint xkeysym)
{
switch (xkeysym) {
case EEK_KEYSYM_Shift_L:
case EEK_KEYSYM_Shift_R:
case EEK_KEYSYM_Caps_Lock:
case EEK_KEYSYM_Shift_Lock:
return EEK_SHIFT_MASK;
case EEK_KEYSYM_ISO_Level3_Shift:
return EEK_BUTTON1_MASK;
case EEK_KEYSYM_Control_L:
case EEK_KEYSYM_Control_R:
return EEK_CONTROL_MASK;
case EEK_KEYSYM_Alt_L:
case EEK_KEYSYM_Alt_R:
return EEK_MOD1_MASK;
case EEK_KEYSYM_Meta_L:
case EEK_KEYSYM_Meta_R:
return EEK_META_MASK;
case EEK_KEYSYM_Super_L:
case EEK_KEYSYM_Super_R:
return EEK_SUPER_MASK;
case EEK_KEYSYM_Hyper_L:
case EEK_KEYSYM_Hyper_R:
return EEK_HYPER_MASK;
}
return 0;
}
/**
* eek_keysym_new_with_modifier:
* @xkeysym: an X keysym value
* @modifier_mask: modifier assigned to @xkeysym
*
* Create an #EekKeysym with given X keysym value @xkeysym and
* modifier @modifier_mask.
*/
EekSymbol *eek_keysym_new_with_modifier(guint xkeysym,
EekModifierType modifier_mask)
{
EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry;
gchar *name, *label;
gunichar uc;
special_entry =
find_keysym_entry_by_xkeysym (xkeysym,
special_keysym_entries,
G_N_ELEMENTS(special_keysym_entries));
xkeysym_entry =
find_keysym_entry_by_xkeysym (xkeysym,
xkeysym_keysym_entries,
G_N_ELEMENTS(xkeysym_keysym_entries));
unicode_entry =
find_keysym_entry_by_xkeysym (xkeysym,
unicode_keysym_entries,
G_N_ELEMENTS(unicode_keysym_entries));
unichar_entry = NULL;
if (get_unichar (xkeysym, &uc)) {
unichar_entry = g_slice_new (EekKeysymEntry);
unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc);
}
name = NULL;
if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name);
} else if (unichar_entry) {
name = g_strdup (unichar_entry->name);
} else if (unicode_entry) {
name = g_strdup (unicode_entry->name);
} else {
name = g_strdup ("");
}
/* label */
if (special_entry)
label = g_strdup (special_entry->name);
else if (unichar_entry)
label = g_strdup (unichar_entry->name);
else if (unicode_entry)
label = g_strdup (unicode_entry->name);
else
label = g_strdup (name);
EekSymbol *keysym = eek_symbol_new(name);
eek_symbol_set_label(keysym, label);
eek_symbol_set_modifier_mask(keysym, modifier_mask);
g_free (name);
g_free (label);
if (unichar_entry) {
g_free ((gpointer) unichar_entry->name);
g_slice_free (EekKeysymEntry, unichar_entry);
}
keysym->xkeysym = xkeysym;
return keysym;
}
/**
* eek_keysym_new:
* @xkeysym: an X keysym value
*
* Create an #EekKeysym with given X keysym value @xkeysym.
*/
EekSymbol*
eek_keysym_new (guint xkeysym)
{
return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym));
}
/**
* eek_keysym_new_from_name:
* @name: an X keysym name
*
* Create an #EekKeysym with an X keysym value looked up by @name.
*/
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);
EekSymbol *ret = eek_symbol_new(name);
eek_symbol_set_label(ret, name);
return ret;
}
/**
* eek_keysym_get_xkeysym:
* @keysym: an #EekKeysym
*
* Get an X keysym value associated with @keysym
*/
guint
eek_keysym_get_xkeysym (EekSymbol *keysym)
{
if (keysym->xkeysym == 0) {
g_warning("Symbol %s was expected to have a valid keysym", keysym->name);
}
return keysym->xkeysym;
}

View File

@ -25,25 +25,8 @@
#ifndef EEK_KEYSYM_H
#define EEK_KEYSYM_H 1
#include <X11/XKBlib.h>
#include "eek-symbol.h"
#include "glib.h"
G_BEGIN_DECLS
/**
* EEK_INVALID_KEYSYM:
*
* Pseudo keysym used for error reporting.
*/
#define EEK_INVALID_KEYSYM (0)
EekSymbol *eek_keysym_new (guint xkeysym);
guint eek_keysym_get_xkeysym (EekSymbol *keysym);
EekSymbol *eek_keysym_new_from_name (const gchar *name);
EekSymbol *eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask);
G_END_DECLS
guint32 eek_keysym_from_name (const gchar *name);
#endif /* EEK_KEYSYM_H */

View File

@ -31,6 +31,7 @@
#include "eek-layout.h"
#include "eek-keyboard.h"
#include "eekboard/eekboard-context-service.h"
#include "eek-xml-layout.h"
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT)
@ -45,35 +46,13 @@ eek_layout_init (EekLayout *self)
{
}
/**
* eek_keyboard_new:
* @layout: an #EekLayout
* @initial_width: initial width of the keyboard
* @initial_height: initial height of the keyboard
*
* Create a new #EekKeyboard based on @layout.
*/
EekKeyboard *
eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height)
{
g_assert (EEK_IS_LAYOUT(layout));
g_assert (EEK_LAYOUT_GET_CLASS(layout)->create_keyboard);
return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (manager,
layout,
initial_width,
initial_height);
}
const double section_spacing = 7.0;
struct place_data {
double desired_width;
double current_offset;
EekKeyboard *keyboard;
// Needed for outline (bounds) retrieval
LevelKeyboard *keyboard;
};
static void
@ -87,7 +66,7 @@ section_placer(EekElement *element, gpointer user_data)
eek_element_set_bounds(element, &section_bounds);
// Sections are rows now. Gather up all the keys and adjust their bounds.
eek_section_place_keys(EEK_SECTION(element), EEK_KEYBOARD(data->keyboard));
eek_section_place_keys(EEK_SECTION(element), data->keyboard);
eek_element_get_bounds(element, &section_bounds);
section_bounds.y = data->current_offset;
@ -105,7 +84,7 @@ section_counter(EekElement *element, gpointer user_data) {
}
void
eek_layout_place_sections(EekKeyboard *keyboard)
eek_layout_place_sections(LevelKeyboard *keyboard, EekKeyboard *level)
{
/* Order rows */
// This needs to be done after outlines, because outlines define key sizes
@ -114,23 +93,23 @@ eek_layout_place_sections(EekKeyboard *keyboard)
// The keyboard width is given by the user via screen size. The height will be given dynamically.
// TODO: calculate max line width beforehand for button centering. Leave keyboard centering to the renderer later
EekBounds keyboard_bounds = {0};
eek_element_get_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
eek_element_get_bounds(EEK_ELEMENT(level), &keyboard_bounds);
struct place_data placer_data = {
.desired_width = keyboard_bounds.width,
.current_offset = 0,
.keyboard = keyboard,
};
eek_container_foreach_child(EEK_CONTAINER(keyboard), section_placer, &placer_data);
eek_container_foreach_child(EEK_CONTAINER(level), section_placer, &placer_data);
double total_height = 0;
eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height);
eek_container_foreach_child(EEK_CONTAINER(level), section_counter, &total_height);
keyboard_bounds.height = total_height;
eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
eek_element_set_bounds(EEK_ELEMENT(level), &keyboard_bounds);
}
void
eek_layout_update_layout(EekKeyboard *keyboard)
eek_layout_update_layout(LevelKeyboard *keyboard)
{
eek_layout_place_sections(keyboard);
eek_layout_place_sections(keyboard, level_keyboard_current(keyboard));
}

View File

@ -43,7 +43,7 @@ struct _EekLayoutClass
GObjectClass parent_class;
/*< public >*/
EekKeyboard* (* create_keyboard) (EekboardContextService *manager,
LevelKeyboard* (* create_keyboard) (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height);
@ -55,9 +55,14 @@ struct _EekLayoutClass
GType eek_layout_get_type (void) G_GNUC_CONST;
void eek_layout_place_sections(EekKeyboard *keyboard);
void eek_layout_place_sections(LevelKeyboard *keyboard, EekKeyboard *level);
void eek_layout_update_layout(EekKeyboard *keyboard);
void eek_layout_update_layout(LevelKeyboard *keyboard);
LevelKeyboard *
level_keyboard_from_layout (EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
G_END_DECLS
#endif /* EEK_LAYOUT_H */

View File

@ -23,15 +23,15 @@
#include <math.h>
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>
#include "eek-key.h"
#include "eek-section.h"
#include "src/symbol.h"
#include "eek-renderer.h"
enum {
PROP_0,
PROP_KEYBOARD,
PROP_PCONTEXT,
PROP_STYLE_CONTEXT,
PROP_LAST
@ -39,7 +39,7 @@ enum {
typedef struct _EekRendererPrivate
{
EekKeyboard *keyboard;
LevelKeyboard *keyboard;
PangoContext *pcontext;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
@ -62,7 +62,6 @@ typedef struct _EekRendererPrivate
GHashTable *active_outline_surface_cache;
GHashTable *icons;
cairo_surface_t *keyboard_surface;
gulong symbol_index_changed_handler;
} EekRendererPrivate;
@ -79,21 +78,18 @@ extern void _eek_rounded_polygon (cairo_t *cr,
static void eek_renderer_real_render_key_label (EekRenderer *self,
PangoLayout *layout,
EekKey *key);
EekKey *key, guint level);
static void invalidate (EekRenderer *renderer);
static void render_key (EekRenderer *self,
cairo_t *cr,
EekKey *key,
EekKey *key, guint level,
gboolean active);
static void on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data);
struct _CreateKeyboardSurfaceCallbackData {
cairo_t *cr;
EekRenderer *renderer;
uint level;
};
typedef struct _CreateKeyboardSurfaceCallbackData CreateKeyboardSurfaceCallbackData;
@ -114,7 +110,7 @@ create_keyboard_surface_key_callback (EekElement *element,
bounds.width + 100,
bounds.height + 100);
cairo_clip (data->cr);
render_key (data->renderer, data->cr, EEK_KEY(element), FALSE);
render_key (data->renderer, data->cr, EEK_KEY(element), data->level, FALSE);
cairo_restore (data->cr);
}
@ -152,7 +148,7 @@ render_keyboard_surface (EekRenderer *renderer)
eek_renderer_get_foreground_color (renderer, priv->scontext, &foreground);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(priv->keyboard)), &bounds);
data.cr = cairo_create (priv->keyboard_surface);
data.renderer = renderer;
@ -177,8 +173,9 @@ render_keyboard_surface (EekRenderer *renderer)
foreground.blue,
foreground.alpha);
data.level = priv->keyboard->level;
/* draw sections */
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
eek_container_foreach_child (EEK_CONTAINER(level_keyboard_current(priv->keyboard)),
create_keyboard_surface_section_callback,
&data);
cairo_restore (data.cr);
@ -198,7 +195,7 @@ render_key_outline (EekRenderer *renderer,
guint oref;
oref = eek_key_get_oref (key);
outline = eek_keyboard_get_outline (priv->keyboard, oref);
outline = level_keyboard_get_outline (priv->keyboard, oref);
if (outline == NULL)
return;
@ -218,6 +215,7 @@ static void
render_key (EekRenderer *self,
cairo_t *cr,
EekKey *key,
guint level,
gboolean active)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
@ -225,17 +223,14 @@ render_key (EekRenderer *self,
cairo_surface_t *outline_surface;
EekBounds bounds;
guint oref;
EekSymbol *symbol;
struct squeek_symbol *symbol;
GHashTable *outline_surface_cache;
PangoLayout *layout;
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);
outline = level_keyboard_get_outline (priv->keyboard, oref);
if (outline == NULL)
return;
@ -280,15 +275,15 @@ render_key (EekRenderer *self,
eek_renderer_get_foreground_color (self, priv->key_context, &foreground);
/* render icon (if any) */
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
symbol = eek_key_get_symbol_at_index (key, 0, level);
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) {
@ -316,7 +311,7 @@ render_key (EekRenderer *self,
/* render label */
layout = pango_cairo_create_layout (cr);
eek_renderer_real_render_key_label (self, layout, key);
eek_renderer_real_render_key_label (self, layout, key, level);
pango_layout_get_extents (layout, NULL, &extents);
cairo_save (cr);
@ -383,21 +378,22 @@ eek_renderer_apply_transformation_for_key (EekRenderer *self,
static void
eek_renderer_real_render_key_label (EekRenderer *self,
PangoLayout *layout,
EekKey *key)
EekKey *key,
guint level)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
EekSymbol *symbol;
struct squeek_symbol *symbol;
const gchar *label;
EekBounds bounds;
PangoFontDescription *font;
PangoLayoutLine *line;
gdouble scale;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
symbol = eek_key_get_symbol_at_index(key, 0, level);
if (!symbol)
return;
label = eek_symbol_get_label (symbol);
label = squeek_symbol_get_label (symbol);
if (!label)
return;
@ -464,6 +460,7 @@ static void
eek_renderer_real_render_key (EekRenderer *self,
cairo_t *cr,
EekKey *key,
guint level,
gdouble scale,
gboolean rotate)
{
@ -480,7 +477,7 @@ eek_renderer_real_render_key (EekRenderer *self,
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate);
render_key (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key));
render_key (self, cr, key, level, eek_key_is_pressed (key) || eek_key_is_locked (key));
cairo_restore (cr);
}
@ -526,15 +523,6 @@ eek_renderer_set_property (GObject *object,
EEK_RENDERER(object));
switch (prop_id) {
case PROP_KEYBOARD:
priv->keyboard = g_value_get_object (value);
g_object_ref (priv->keyboard);
priv->symbol_index_changed_handler =
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed),
object);
break;
case PROP_PCONTEXT:
priv->pcontext = g_value_get_object (value);
g_object_ref (priv->pcontext);
@ -555,13 +543,7 @@ eek_renderer_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (
EEK_RENDERER(object));
switch (prop_id) {
case PROP_KEYBOARD:
g_value_set_object (value, priv->keyboard);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -575,11 +557,6 @@ eek_renderer_dispose (GObject *object)
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
if (priv->keyboard) {
if (g_signal_handler_is_connected (priv->keyboard,
priv->symbol_index_changed_handler))
g_signal_handler_disconnect (priv->keyboard,
priv->symbol_index_changed_handler);
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
}
if (priv->pcontext) {
@ -623,15 +600,6 @@ eek_renderer_class_init (EekRendererClass *klass)
gobject_class->dispose = eek_renderer_dispose;
gobject_class->finalize = eek_renderer_finalize;
pspec = g_param_spec_object ("keyboard",
"Keyboard",
"Keyboard",
EEK_TYPE_KEYBOARD,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARD,
pspec);
pspec = g_param_spec_object ("pango-context",
"Pango Context",
"Pango Context",
@ -677,7 +645,6 @@ eek_renderer_init (EekRenderer *self)
NULL,
(GDestroyNotify)cairo_surface_destroy);
priv->keyboard_surface = NULL;
priv->symbol_index_changed_handler = 0;
GtkIconTheme *theme = gtk_icon_theme_get_default ();
@ -723,26 +690,18 @@ invalidate (EekRenderer *renderer)
}
}
static void
on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data)
{
EekRenderer *renderer = user_data;
invalidate (renderer);
}
EekRenderer *
eek_renderer_new (EekKeyboard *keyboard,
eek_renderer_new (LevelKeyboard *keyboard,
PangoContext *pcontext,
GtkStyleContext *scontext)
{
return g_object_new (EEK_TYPE_RENDERER,
"keyboard", keyboard,
EekRenderer *renderer = g_object_new (EEK_TYPE_RENDERER,
"pango-context", pcontext,
"style-context", scontext,
NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
priv->keyboard = keyboard;
return renderer;
}
void
@ -763,7 +722,7 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
/* Calculate a scale factor to use when rendering the keyboard into the
available space. */
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(priv->keyboard)), &bounds);
gdouble w = (bounds.x * 2) + bounds.width;
gdouble h = (bounds.y * 2) + bounds.height;
@ -788,7 +747,7 @@ eek_renderer_get_size (EekRenderer *renderer,
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(priv->keyboard)), &bounds);
if (width)
*width = bounds.width;
if (height)
@ -816,7 +775,7 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
eek_element_get_bounds (EEK_ELEMENT(key), bounds);
eek_element_get_bounds (section, &section_bounds);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard),
eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(priv->keyboard)),
&keyboard_bounds);
if (!rotate) {
@ -940,6 +899,7 @@ void
eek_renderer_render_key (EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
guint level,
gdouble scale,
gboolean rotate)
{
@ -948,7 +908,7 @@ eek_renderer_render_key (EekRenderer *renderer,
g_return_if_fail (scale >= 0.0);
EEK_RENDERER_GET_CLASS(renderer)->
render_key (renderer, cr, key, scale, rotate);
render_key (renderer, cr, key, level, scale, rotate);
}
void
@ -1106,7 +1066,7 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(priv->keyboard)), &bounds);
/* Transform from widget coordinates to keyboard coordinates */
x = (x - priv->origin_x)/priv->scale - bounds.x;
@ -1125,7 +1085,7 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
data.key = NULL;
data.renderer = renderer;
eek_container_find (EEK_CONTAINER(priv->keyboard),
eek_container_find (EEK_CONTAINER(level_keyboard_current(priv->keyboard)),
find_key_by_position_section_callback,
&data);
return data.key;

View File

@ -21,9 +21,10 @@
#ifndef EEK_RENDERER_H
#define EEK_RENDERER_H 1
#include <gtk/gtk.h>
#include <pango/pangocairo.h>
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
G_BEGIN_DECLS
@ -44,6 +45,7 @@ struct _EekRendererClass
void (* render_key) (EekRenderer *self,
cairo_t *cr,
EekKey *key,
guint level,
gdouble scale,
gboolean rotate);
@ -61,7 +63,7 @@ struct _EekRendererClass
};
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
PangoContext *pcontext,
GtkStyleContext *scontext);
void eek_renderer_set_allocation_size
@ -95,7 +97,7 @@ void eek_renderer_render_key_outline
void eek_renderer_render_key (EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
EekKey *key, guint level,
gdouble scale,
gboolean rotate);

View File

@ -32,9 +32,9 @@
#include <string.h>
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
#include "eek-section.h"
enum {
PROP_0,
@ -121,7 +121,8 @@ on_unlocked (EekKey *key,
static EekKey *
eek_section_real_create_key (EekSection *self,
const gchar *name,
gint keycode)
gint keycode,
guint oref)
{
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
@ -130,9 +131,10 @@ eek_section_real_create_key (EekSection *self,
EekKey *key = (EekKey*)g_object_new (EEK_TYPE_KEY,
"name", name,
"keycode", keycode,
NULL);
g_return_val_if_fail (key, NULL);
eek_key_set_keycode(key, keycode);
eek_key_set_oref(key, oref);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key));
@ -140,79 +142,28 @@ eek_section_real_create_key (EekSection *self,
return key;
}
static void
set_level_from_modifiers (EekSection *self)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekKeyboard *keyboard;
EekModifierType num_lock_mask;
gint level = -1;
EekKey *eek_section_create_button(EekSection *self,
const gchar *name,
struct squeek_key *state) {
EekSectionPrivate *priv = (EekSectionPrivate*)eek_section_get_instance_private (self);
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
if (priv->modifiers & num_lock_mask)
level = 1;
eek_element_set_level (EEK_ELEMENT(self), level);
}
EekRow *row = &priv->row;
row->num_columns++;
static void
eek_section_real_key_pressed (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
EekModifierType modifier;
EekKey *key = (EekKey*)g_object_new (EEK_TYPE_KEY,
"name", name,
NULL);
g_return_val_if_fail (key, NULL);
eek_key_share_state(key, state);
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
behavior = eek_keyboard_get_modifier_behavior (keyboard);
modifier = eek_symbol_get_modifier_mask (symbol);
if (behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
priv->modifiers |= modifier;
set_level_from_modifiers (self);
}
}
static void
eek_section_real_key_released (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
EekModifierType modifier;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
behavior = eek_keyboard_get_modifier_behavior (keyboard);
modifier = eek_symbol_get_modifier_mask (symbol);
switch (behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
priv->modifiers &= ~modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
break;
}
set_level_from_modifiers (self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key));
return key;
}
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);
}
@ -278,9 +229,6 @@ eek_section_class_init (EekSectionClass *klass)
klass->create_key = eek_section_real_create_key;
/* signals */
klass->key_pressed = eek_section_real_key_pressed;
klass->key_released = eek_section_real_key_released;
container_class->child_added = eek_section_real_child_added;
container_class->child_removed = eek_section_real_child_removed;
@ -456,12 +404,13 @@ eek_section_get_row (EekSection *section,
EekKey *
eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode)
guint keycode,
guint oref)
{
g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
return EEK_SECTION_GET_CLASS(section)->create_key (section,
return eek_section_real_create_key (section,
name,
keycode);
keycode, oref);
}
const double keyspacing = 4.0;
@ -477,9 +426,9 @@ keysizer(EekElement *element, gpointer user_data)
{
EekKey *key = EEK_KEY(element);
EekKeyboard *keyboard = EEK_KEYBOARD(user_data);
LevelKeyboard *keyboard = user_data;
uint oref = eek_key_get_oref (key);
EekOutline *outline = eek_keyboard_get_outline (keyboard, oref);
EekOutline *outline = level_keyboard_get_outline (keyboard, oref);
if (outline && outline->num_points > 0) {
double minx = outline->points[0].x;
double maxx = minx;
@ -512,11 +461,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 +476,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);
@ -546,7 +486,7 @@ keyplacer(EekElement *element, gpointer user_data)
}
void
eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
eek_section_place_keys(EekSection *section, LevelKeyboard *keyboard)
{
eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);

View File

@ -28,6 +28,8 @@
#include <glib-object.h>
#include "eek-container.h"
#include "eek-types.h"
#include "eek-keyboard.h"
#include "src/keyboard.h"
G_BEGIN_DECLS
@ -66,10 +68,6 @@ struct _EekSectionClass
gint keycode);
/* signals */
void (* key_pressed) (EekSection *self,
EekKey *key);
void (* key_released) (EekSection *self,
EekKey *key);
void (* key_locked) (EekSection *self,
EekKey *key);
void (* key_unlocked) (EekSection *self,
@ -99,12 +97,11 @@ void eek_section_get_row (EekSection *section,
EekKey *eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode);
EekKey *eek_section_find_key_by_keycode (EekSection *section,
guint keycode);
void eek_section_place_keys (EekSection *section, EekKeyboard *keyboard);
guint keycode, guint oref);
EekKey *eek_section_create_button(EekSection *self,
const gchar *name,
struct squeek_key *state);
void eek_section_place_keys (EekSection *section, LevelKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_SECTION_H */

View File

@ -1,99 +0,0 @@
/*
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "eek-symbol-matrix.h"
EekSymbolMatrix *
eek_symbol_matrix_new (gint num_groups,
gint num_levels)
{
EekSymbolMatrix *matrix = g_slice_new (EekSymbolMatrix);
matrix->num_groups = num_groups;
matrix->num_levels = num_levels;
matrix->data = g_slice_alloc0 (sizeof (EekSymbol *) *
num_groups * num_levels);
return matrix;
}
EekSymbolMatrix *
eek_symbol_matrix_copy (const EekSymbolMatrix *matrix)
{
EekSymbolMatrix *retval;
guint num_symbols = matrix->num_groups * matrix->num_levels;
retval = g_slice_dup (EekSymbolMatrix, matrix);
retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols,
matrix->data);
// FIXME: do a deep copy over the data in EekSymbol
return retval;
}
void
eek_symbol_matrix_free (EekSymbolMatrix *matrix)
{
guint num_symbols = matrix->num_groups * matrix->num_levels;
g_slice_free1 (sizeof (EekSymbol *) * num_symbols, matrix->data);
g_slice_free (EekSymbolMatrix, matrix);
}
GType
eek_symbol_matrix_get_type (void)
{
static GType our_type = 0;
if (our_type == 0)
our_type =
g_boxed_type_register_static ("EekSymbolMatrix",
(GBoxedCopyFunc)eek_symbol_matrix_copy,
(GBoxedFreeFunc)eek_symbol_matrix_free);
return our_type;
}
void
eek_symbol_matrix_set_symbol (EekSymbolMatrix *matrix,
gint group,
gint level,
EekSymbol *symbol)
{
g_return_if_fail (group >= 0 && group < matrix->num_groups);
g_return_if_fail (level >= 0 && level < matrix->num_levels);
matrix->data[group * matrix->num_levels + level] = g_object_ref (symbol);
}
/**
* eek_symbol_matrix_get_symbol:
* @matrix: an #EekSymbolMatrix
* @group: group index of @matrix
* @level: level index of @matrix
*
* Get an #EekSymbol stored in the cell selected by (@group, @level)
* in @matrix.
*
* Return value: (transfer none): an #EekSymbol.
*/
EekSymbol *
eek_symbol_matrix_get_symbol (EekSymbolMatrix *matrix,
gint group,
gint level)
{
g_return_val_if_fail (group >= 0 && group < matrix->num_groups, NULL);
g_return_val_if_fail (level >= 0 && level < matrix->num_levels, NULL);
return matrix->data[group * matrix->num_levels + level];
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef EEK_SYMBOL_MATRIX_H
#define EEK_SYMBOL_MATRIX_H 1
#include "eek-symbol.h"
G_BEGIN_DECLS
/**
* EekSymbolMatrix:
* @data: array of symbols
* @num_groups: the number of groups (rows)
* @num_levels: the number of levels (columns)
*
* Symbol matrix of a key.
*/
struct _EekSymbolMatrix
{
/*< public >*/
gint num_groups;
gint num_levels;
EekSymbol **data;
};
#define EEK_TYPE_SYMBOL_MATRIX (eek_symbol_matrix_get_type ())
GType eek_symbol_matrix_get_type (void) G_GNUC_CONST;
EekSymbolMatrix *eek_symbol_matrix_new (gint num_groups,
gint num_levels);
EekSymbolMatrix *eek_symbol_matrix_copy (const EekSymbolMatrix *matrix);
void eek_symbol_matrix_free (EekSymbolMatrix *matrix);
void eek_symbol_matrix_set_symbol
(EekSymbolMatrix *matrix,
gint group,
gint level,
EekSymbol *symbol);
EekSymbol *eek_symbol_matrix_get_symbol
(EekSymbolMatrix *matrix,
gint group,
gint level);
G_END_DECLS
#endif /* EEK_SYMBOL_MATRIX_H */

View File

@ -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;
}
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;

View File

@ -1,107 +0,0 @@
/*
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_SYMBOL_H
#define EEK_SYMBOL_H 1
#include "eek-types.h"
G_BEGIN_DECLS
/**
* EekSymbolCategory:
* @EEK_SYMBOL_CATEGORY_LETTER: the symbol represents an alphabet letter
* @EEK_SYMBOL_CATEGORY_FUNCTION: the symbol represents a function
* @EEK_SYMBOL_CATEGORY_KEYNAME: the symbol does not have meaning but
* have a name
* @EEK_SYMBOL_CATEGORY_USER0: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER1: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER2: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER3: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER4: reserved for future use
* @EEK_SYMBOL_CATEGORY_UNKNOWN: used for error reporting
* @EEK_SYMBOL_CATEGORY_LAST: the last symbol category
*
* Category of the key symbols.
*/
typedef enum {
EEK_SYMBOL_CATEGORY_LETTER,
EEK_SYMBOL_CATEGORY_FUNCTION,
EEK_SYMBOL_CATEGORY_KEYNAME,
EEK_SYMBOL_CATEGORY_USER0,
EEK_SYMBOL_CATEGORY_USER1,
EEK_SYMBOL_CATEGORY_USER2,
EEK_SYMBOL_CATEGORY_USER3,
EEK_SYMBOL_CATEGORY_USER4,
EEK_SYMBOL_CATEGORY_UNKNOWN,
EEK_SYMBOL_CATEGORY_LAST = EEK_SYMBOL_CATEGORY_UNKNOWN
} EekSymbolCategory;
typedef struct _EekSymbol
{
/// Canonical name of the symbol
gchar *name;
/// Text used to display the symbol
gchar *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
/// Icon name used to render the symbol
gchar *icon_name;
/// Tooltip text
gchar *tooltip;
// May not be present
guint xkeysym;
gchar *text;
} EekSymbol;
EekSymbol *eek_symbol_new (const gchar *name);
void eek_symbol_free (EekSymbol *symbol);
void eek_symbol_set_name (EekSymbol *symbol,
const gchar *name);
const gchar *eek_symbol_get_name (EekSymbol *symbol);
void eek_symbol_set_label (EekSymbol *symbol,
const gchar *label);
const gchar *eek_symbol_get_label (EekSymbol *symbol);
void eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category);
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);
void eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip);
const gchar * eek_symbol_get_tooltip (EekSymbol *symbol);
const gchar *eek_symbol_category_get_name (EekSymbolCategory category);
EekSymbolCategory eek_symbol_category_from_name (const gchar *name);
G_END_DECLS
#endif /* EEK_SYMBOL_H */

View File

@ -150,6 +150,7 @@ typedef struct _EekOutline EekOutline;
typedef struct _EekColor EekColor;
typedef struct _EekboardContextService EekboardContextService;
typedef struct _LevelKeyboard LevelKeyboard;
/**
* EekPoint:

View File

@ -27,15 +27,16 @@
#include <stdlib.h>
#include <string.h>
#include "eek-xml-layout.h"
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-keysym.h"
#include "eek-text.h"
#include "src/keyboard.h"
#include "src/symbol.h"
#include "squeekboard-resources.h"
#include "eek-xml-layout.h"
enum {
PROP_0,
PROP_ID,
@ -67,16 +68,16 @@ static GList *parse_prerequisites
(const gchar *path,
GError **error);
static gboolean parse_geometry (const gchar *path,
EekKeyboard *keyboard,
EekKeyboard **views, GArray *outline_array, GHashTable *name_key_hash,
GError **error);
static gboolean parse_symbols_with_prerequisites
(const gchar *keyboards_dir,
const gchar *name,
EekKeyboard *keyboard,
LevelKeyboard *keyboard,
GList **loaded,
GError **error);
static gboolean parse_symbols (const gchar *path,
EekKeyboard *keyboard,
LevelKeyboard *keyboard,
GError **error);
static gboolean validate (const gchar **valid_path_list,
@ -232,40 +233,49 @@ struct _GeometryParseData {
GSList *element_stack;
EekBounds bounds;
EekKeyboard *keyboard;
EekKeyboard **views;
guint view_idx;
EekSection *section;
EekKey *key;
gint num_columns;
gint num_rows;
EekOrientation orientation;
gdouble corner_radius;
GSList *points;
gchar *name;
EekOutline outline;
gchar *oref;
gint keycode;
gchar *outline_id;
guint keycode;
GHashTable *key_oref_hash;
GHashTable *oref_outline_hash;
GString *text;
GArray *outline_array;
GHashTable *name_key_hash; // char* -> EekKey*
GHashTable *keyname_oref_hash; // char* -> guint
GHashTable *outlineid_oref_hash; // char* -> guint
};
typedef struct _GeometryParseData GeometryParseData;
static GeometryParseData *
geometry_parse_data_new (EekKeyboard *keyboard)
geometry_parse_data_new (EekKeyboard **views, GHashTable *name_key_hash, GArray *outline_array)
{
GeometryParseData *data = g_slice_new0 (GeometryParseData);
data->keyboard = g_object_ref (keyboard);
data->key_oref_hash =
g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
g_free);
data->oref_outline_hash =
data->views = views;
data->outline_array = outline_array;
data->keyname_oref_hash =
g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify)eek_outline_free);
NULL);
data->outlineid_oref_hash =
g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
NULL);
data->name_key_hash = name_key_hash;
data->text = g_string_sized_new (BUFSIZE);
data->keycode = 8;
return data;
}
@ -273,21 +283,19 @@ geometry_parse_data_new (EekKeyboard *keyboard)
static void
geometry_parse_data_free (GeometryParseData *data)
{
g_object_unref (data->keyboard);
g_hash_table_destroy (data->key_oref_hash);
g_hash_table_destroy (data->oref_outline_hash);
g_hash_table_destroy (data->keyname_oref_hash);
g_hash_table_destroy (data->outlineid_oref_hash);
g_string_free (data->text, TRUE);
g_slice_free (GeometryParseData, data);
}
static const gchar *geometry_valid_path_list[] = {
"geometry",
"button/geometry",
"bounds/geometry",
"section/geometry",
"view/geometry",
"section/view/geometry",
"outline/geometry",
"bounds/section/geometry",
"row/section/geometry",
"key/row/section/geometry",
"bounds/key/row/section/geometry",
"point/outline/geometry",
};
@ -355,14 +363,20 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
return;
}
bounds.height = g_strtod (attribute, NULL);
if (g_strcmp0 (data->element_stack->data, "geometry") == 0)
eek_element_set_bounds (EEK_ELEMENT(data->keyboard), &bounds);
data->bounds = bounds;
goto out;
}
if (g_strcmp0 (element_name, "view") == 0) {
/* Create an empty keyboard to which geometry and symbols
information are applied. */
EekKeyboard *view = g_object_new (EEK_TYPE_KEYBOARD, NULL);
eek_element_set_bounds (EEK_ELEMENT(view), &data->bounds);
data->views[data->view_idx] = view;
}
if (g_strcmp0 (element_name, "section") == 0) {
data->section = eek_keyboard_create_section (data->keyboard);
data->section = eek_keyboard_real_create_section (data->views[data->view_idx]);
attribute = get_attribute (attribute_names, attribute_values,
"id");
if (attribute != NULL)
@ -374,62 +388,47 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
angle = strtol (attribute, NULL, 10);
eek_section_set_angle (data->section, angle);
}
goto out;
}
if (g_strcmp0 (element_name, "row") == 0) {
attribute = get_attribute (attribute_names, attribute_values,
"orientation");
if (attribute != NULL)
data->orientation = strtol (attribute, NULL, 10);
eek_section_add_row (data->section,
data->num_columns,
data->orientation);
data->num_rows++;
goto out;
}
if (g_strcmp0 (element_name, "key") == 0) {
guint keycode;
attribute = get_attribute (attribute_names, attribute_values,
if (g_strcmp0 (element_name, "button") == 0) {
const gchar *base_name = get_attribute (attribute_names, attribute_values,
"name");
if (attribute == NULL) {
if (base_name == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"name\" attribute for \"key\"");
"no \"name\" attribute for \"button\"");
return;
}
gchar *name = g_strdup (attribute);
attribute = get_attribute (attribute_names, attribute_values,
"keycode");
if (attribute != NULL)
keycode = strtol (attribute, NULL, 10);
else
keycode = data->keycode++;
data->key = eek_section_create_key (data->section,
name,
keycode);
attribute = get_attribute (attribute_names, attribute_values,
const gchar *oref_name = get_attribute (attribute_names, attribute_values,
"oref");
if (attribute == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"oref\" attribute for \"key\"");
return;
if (oref_name == NULL) {
oref_name = "default";
}
g_hash_table_insert (data->key_oref_hash,
data->key,
g_strdup (attribute));
const gchar *keycode_name = get_attribute (attribute_names, attribute_values,
"keycode");
data->num_columns++;
guint oref = GPOINTER_TO_UINT(g_hash_table_lookup(data->outlineid_oref_hash,
oref_name));
const gchar *name = base_name;
g_hash_table_insert (data->keyname_oref_hash,
g_strdup(name),
GUINT_TO_POINTER(oref));
EekKey *key = g_hash_table_lookup(data->name_key_hash, name);
// never gets used! this section gets executed before any buttons get defined
if (key) {
if (keycode_name != NULL) {
// This sets the keycode for all buttons,
// since they share state
// TODO: get rid of this in the parser;
// this belongs after keymap is defined
eek_key_set_keycode(key, strtol (keycode_name, NULL, 10));
}
}
goto out;
}
@ -443,7 +442,7 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
"no \"id\" attribute for \"outline\"");
return;
}
data->oref = g_strdup (attribute);
data->outline_id = g_strdup (attribute);
attribute = get_attribute (attribute_names, attribute_values,
"corner-radius");
@ -488,6 +487,30 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
out:
data->element_stack = g_slist_prepend (data->element_stack,
g_strdup (element_name));
data->text->len = 0;
}
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned integer ID of the registered outline, for
* later reference
*/
static guint
add_outline (GArray *outline_array,
EekOutline *outline)
{
EekOutline *_outline;
_outline = eek_outline_copy (outline);
g_array_append_val (outline_array, *_outline);
/* don't use eek_outline_free here, so as to keep _outline->points */
g_slice_free (EekOutline, _outline);
return outline_array->len - 1;
}
static void
@ -503,23 +526,72 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
data->element_stack = g_slist_next (data->element_stack);
g_slist_free1 (head);
const gchar *text = g_strndup (data->text->str, data->text->len);
if (g_strcmp0 (element_name, "view") == 0) {
data->view_idx++;
return;
}
if (g_strcmp0 (element_name, "section") == 0) {
// Split text on spaces and process each part
unsigned head = 0;
while (head < strlen(text)) {
// Skip to the first non-space character
for (; head < strlen(text); head++) {
if (text[head] != ' ') {
break;
}
}
unsigned start = head;
// Skip to the first space character
for (; head < strlen(text); head++) {
if (text[head] == ' ') {
break;
}
}
unsigned end = head;
/// Reached the end
if (start == end) {
break;
}
gchar *name = g_strndup (&text[start], end - start);
EekKey *key = g_hash_table_lookup(data->name_key_hash, name);
if (!key) {
// Save button name together with its level,
// to account for buttons with the same name in multiple levels
guint keycode = data->keycode++;
guint oref = GPOINTER_TO_UINT(g_hash_table_lookup(data->keyname_oref_hash, name));
// default value gives idx 0, which is guaranteed to be occupied
key = eek_section_create_key (data->section,
name,
keycode,
oref);
g_hash_table_insert (data->name_key_hash,
g_strdup(name),
key);
} else {
EekKey *new_key = eek_section_create_button(data->section, name, eek_key_get_state(key));
if (!new_key) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"Couldn't create a shared button");
return;
}
eek_key_set_oref(new_key, eek_key_get_oref(key));
}
}
data->section = NULL;
data->num_rows = 0;
return;
}
if (g_strcmp0 (element_name, "key") == 0) {
data->key = NULL;
return;
}
if (g_strcmp0 (element_name, "row") == 0) {
data->num_columns = 0;
data->orientation = EEK_ORIENTATION_HORIZONTAL;
return;
}
if (g_strcmp0 (element_name, "outline") == 0) {
EekOutline *outline = g_slice_new (EekOutline);
@ -539,19 +611,30 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
g_slist_free (data->points);
data->points = NULL;
g_hash_table_insert (data->oref_outline_hash,
g_strdup (data->oref),
outline);
guint oref = add_outline (data->outline_array, outline);
g_free (data->oref);
g_hash_table_insert (data->outlineid_oref_hash,
data->outline_id,
GUINT_TO_POINTER(oref));
return;
}
}
static void
geometry_text_callback (GMarkupParseContext *pcontext,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error)
{
GeometryParseData *data = user_data;
g_string_append_len (data->text, text, (gssize)text_len);
}
static const GMarkupParser geometry_parser = {
geometry_start_element_callback,
geometry_end_element_callback,
0,
geometry_text_callback,
0,
0
};
@ -560,23 +643,22 @@ struct _SymbolsParseData {
GSList *element_stack;
GString *text;
EekKeyboard *keyboard;
EekKey *key;
GSList *symbols;
LevelKeyboard *keyboard;
EekKeyboard *view;
gchar *label;
gchar *icon;
gchar *tooltip;
guint keyval;
gint groups;
};
typedef struct _SymbolsParseData SymbolsParseData;
static SymbolsParseData *
symbols_parse_data_new (EekKeyboard *keyboard)
symbols_parse_data_new (LevelKeyboard *keyboard)
{
SymbolsParseData *data = g_slice_new0 (SymbolsParseData);
data->keyboard = g_object_ref (keyboard);
data->keyboard = keyboard;
data->text = g_string_sized_new (BUFSIZE);
return data;
}
@ -584,13 +666,13 @@ symbols_parse_data_new (EekKeyboard *keyboard)
static void
symbols_parse_data_free (SymbolsParseData *data)
{
g_object_unref (data->keyboard);
g_string_free (data->text, TRUE);
g_slice_free (SymbolsParseData, data);
}
static const gchar *symbols_valid_path_list[] = {
"symbols",
"symbol/symbols",
"include/symbols",
"key/symbols",
"text/key/symbols",
@ -617,37 +699,6 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
error))
return;
if (g_strcmp0 (element_name, "key") == 0) {
attribute = get_attribute (attribute_names, attribute_values,
"name");
if (attribute == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"name\" attribute for \"key\"");
return;
}
data->key = eek_keyboard_find_key_by_name (data->keyboard,
attribute);
if (data->key == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
"no such key %s", attribute);
}
attribute = get_attribute (attribute_names, attribute_values,
"groups");
if (attribute != NULL)
data->groups = strtol (attribute, NULL, 10);
else
data->groups = 1;
data->symbols = NULL;
goto out;
}
if (g_strcmp0 (element_name, "keysym") == 0) {
attribute = get_attribute (attribute_names, attribute_values,
"keyval");
@ -680,7 +731,6 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
data->tooltip = g_strdup (attribute);
}
out:
data->element_stack = g_slist_prepend (data->element_stack,
g_strdup (element_name));
data->text->len = 0;
@ -695,80 +745,44 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
SymbolsParseData *data = user_data;
GSList *head = data->element_stack;
gchar *text;
gint i;
g_free (head->data);
data->element_stack = g_slist_next (data->element_stack);
g_slist_free1 (head);
// TODO: this could all be moved to text handler
text = g_strndup (data->text->str, data->text->len);
if (g_strcmp0 (element_name, "key") == 0) {
if (!data->key) {
return;
}
gint num_symbols = g_slist_length (data->symbols);
gint levels = num_symbols / data->groups;
EekSymbolMatrix *matrix = eek_symbol_matrix_new (data->groups,
levels);
head = data->symbols = g_slist_reverse (data->symbols);
for (i = 0; i < num_symbols; i++) {
if (head && head->data) {
matrix->data[i] = head->data;
head = g_slist_next (head);
} else
matrix->data[i] = NULL;
}
g_slist_free (data->symbols);
data->symbols = NULL;
eek_key_set_symbol_matrix (data->key, matrix);
eek_symbol_matrix_free (matrix);
data->key = NULL;
goto out;
}
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);
gchar *name = text;
EekKey *key = eek_keyboard_find_key_by_name (data->keyboard,
name);
if (key) {
squeek_key_add_symbol(
eek_key_get_state(key),
element_name,
text,
data->keyval,
data->label,
data->icon,
data->tooltip
);
}
if (data->label) {
eek_symbol_set_label (symbol, data->label);
g_free (data->label);
data->keyval = 0;
g_free(data->label);
data->label = NULL;
}
if (data->icon) {
eek_symbol_set_icon_name (symbol, data->icon);
g_free (data->icon);
g_free(data->icon);
data->icon = NULL;
}
if (data->tooltip) {
eek_symbol_set_tooltip (symbol, data->tooltip);
g_free (data->tooltip);
g_free(data->tooltip);
data->tooltip = NULL;
}
data->symbols = g_slist_prepend (data->symbols, symbol);
goto out;
}
if (g_strcmp0 (element_name, "invalid") == 0) {
data->symbols = g_slist_prepend (data->symbols, NULL);
goto out;
}
@ -880,31 +894,37 @@ static const GMarkupParser prerequisites_parser = {
0
};
static EekKeyboard *
eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height)
LevelKeyboard *
eek_xml_layout_real_create_keyboard (EekLayout *self,
EekboardContextService *manager)
{
EekXmlLayout *layout = EEK_XML_LAYOUT (self);
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
gboolean retval;
/* Create an empty keyboard to which geometry and symbols
information are applied. */
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, NULL);
keyboard->manager = manager;
/* Read geometry information. */
gchar *filename = g_strdup_printf ("%s.xml", priv->desc->geometry);
gchar *path = g_build_filename (priv->keyboards_dir, "geometry", filename, NULL);
g_free (filename);
GArray *outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
// char* -> EekKey*
GHashTable *name_key_hash =
g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
NULL);
// One view for each level
EekKeyboard *views[4] = {0};
GError *error = NULL;
retval = parse_geometry (path, keyboard, &error);
retval = parse_geometry (path, views, outline_array, name_key_hash, &error);
g_free (path);
if (!retval) {
g_object_unref (keyboard);
for (uint i = 0; i < 4; i++) {
g_object_unref (views[i]);
}
g_warning ("can't parse geometry file %s: %s",
priv->desc->geometry,
error->message);
@ -912,6 +932,12 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
return NULL;
}
LevelKeyboard *keyboard = level_keyboard_new(manager, views, name_key_hash);
keyboard->outline_array = outline_array;
// FIXME: are symbols shared betwen views?
/* Read symbols information. */
GList *loaded = NULL;
retval = parse_symbols_with_prerequisites (priv->keyboards_dir,
@ -921,7 +947,13 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
&error);
g_list_free_full (loaded, g_free);
if (!retval) {
g_object_unref (keyboard);
for (uint i = 0; i < 4; i++) {
if (views[i]) {
g_object_unref(views[i]);
views[i] = NULL;
}
}
//g_object_unref (view);
g_warning ("can't parse symbols file %s: %s",
priv->desc->symbols,
error->message);
@ -929,11 +961,9 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
return NULL;
}
eek_layout_place_sections(keyboard);
/* Use pre-defined modifier mask here. */
eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK);
eek_keyboard_set_alt_gr_mask (keyboard, EEK_BUTTON1_MASK);
for (uint i = 0; i < 4; i++) {
eek_layout_place_sections(keyboard, views[i]);
}
return keyboard;
}
@ -996,12 +1026,9 @@ eek_xml_layout_finalize (GObject *object)
static void
eek_xml_layout_class_init (EekXmlLayoutClass *klass)
{
EekLayoutClass *layout_class = EEK_LAYOUT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
layout_class->create_keyboard = eek_xml_layout_real_create_keyboard;
gobject_class->set_property = eek_xml_layout_set_property;
gobject_class->get_property = eek_xml_layout_get_property;
gobject_class->finalize = eek_xml_layout_finalize;
@ -1122,13 +1149,10 @@ eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc)
}
static gboolean
parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
parse_geometry (const gchar *path, EekKeyboard **views, GArray *outline_array, GHashTable *name_key_hash, GError **error)
{
GeometryParseData *data;
GMarkupParseContext *pcontext;
GHashTable *oref_hash;
GHashTableIter iter;
gpointer k, v;
GFile *file;
GFileInputStream *input;
gboolean retval;
@ -1142,7 +1166,7 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
if (input == NULL)
return FALSE;
data = geometry_parse_data_new (keyboard);
data = geometry_parse_data_new (views, name_key_hash, outline_array);
pcontext = g_markup_parse_context_new (&geometry_parser,
0,
data,
@ -1157,23 +1181,29 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
}
/* Resolve outline references. */
/*
* GHashTable *oref_hash;
GHashTableIter iter;
gpointer k, v;
oref_hash = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_iter_init (&iter, data->oref_outline_hash);
while (g_hash_table_iter_next (&iter, &k, &v)) {
EekOutline *outline = v;
gulong oref;
oref = eek_keyboard_add_outline (data->keyboard, outline);
oref = add_outline (outline_array, outline);
g_hash_table_insert (oref_hash, k, GUINT_TO_POINTER(oref));
}
}*/
/*
g_hash_table_iter_init (&iter, data->key_oref_hash);
while (g_hash_table_iter_next (&iter, &k, &v)) {
gpointer oref;
if (g_hash_table_lookup_extended (oref_hash, v, NULL, &oref))
eek_key_set_oref (EEK_KEY(k), GPOINTER_TO_UINT(oref));
}
g_hash_table_destroy (oref_hash);
}*/
// g_hash_table_destroy (oref_hash);
geometry_parse_data_free (data);
return TRUE;
@ -1182,7 +1212,7 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
static gboolean
parse_symbols_with_prerequisites (const gchar *keyboards_dir,
const gchar *name,
EekKeyboard *keyboard,
LevelKeyboard *keyboard,
GList **loaded,
GError **error)
{
@ -1232,7 +1262,7 @@ parse_symbols_with_prerequisites (const gchar *keyboards_dir,
}
static gboolean
parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error)
parse_symbols (const gchar *path, LevelKeyboard *keyboard, GError **error)
{
SymbolsParseData *data;
GMarkupParseContext *pcontext;

View File

@ -62,5 +62,8 @@ GList *eek_xml_list_keyboards (void);
EekXmlKeyboardDesc *eek_xml_keyboard_desc_copy (EekXmlKeyboardDesc *desc);
void eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc);
LevelKeyboard *
eek_xml_layout_real_create_keyboard (EekLayout *self,
EekboardContextService *manager);
G_END_DECLS
#endif /* EEK_XML_LAYOUT_H */

View File

@ -26,9 +26,7 @@
#include "eek-section.h"
#include "eek-key.h"
#include "eek-layout.h"
#include "eek-symbol.h"
#include "eek-keysym.h"
#include "eek-text.h"
#include "eek-serializable.h"
void eek_init (void);

View File

@ -1,7 +1,6 @@
gnome = import('gnome')
enum_headers = [
'eek-symbol.h',
'eek-types.h',
]

View File

@ -71,7 +71,7 @@ struct _EekboardContextServicePrivate {
gboolean visible;
gboolean fullscreen;
EekKeyboard *keyboard; // currently used keyboard
LevelKeyboard *keyboard; // currently used keyboard
GHashTable *keyboard_hash; // a table of available keyboards, per layout
// TODO: make use of repeating buttons
@ -86,11 +86,10 @@ struct _EekboardContextServicePrivate {
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
static EekKeyboard *
static LevelKeyboard *
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
const gchar *keyboard_type)
{
EekKeyboard *keyboard;
EekLayout *layout;
GError *error;
@ -135,7 +134,7 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
}
}
}
keyboard = eek_keyboard_new (self, layout, CSW, CSH);
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(layout, self);
if (!keyboard) {
g_error("Failed to create a keyboard");
}
@ -148,6 +147,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);
@ -315,21 +318,16 @@ settings_update_layout(EekboardContextService *context)
// generic part follows
static guint keyboard_id = 0;
EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
LevelKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
GUINT_TO_POINTER(keyboard_id));
// create a keyboard
if (!keyboard) {
EekboardContextServiceClass *klass = EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context);
keyboard = klass->create_keyboard (context, keyboard_layout);
eek_keyboard_set_modifier_behavior (keyboard,
EEK_MODIFIER_BEHAVIOR_LATCH);
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout);
g_hash_table_insert (context->priv->keyboard_hash,
GUINT_TO_POINTER(keyboard_id),
keyboard);
g_object_set_data (G_OBJECT(keyboard),
"keyboard-id",
GUINT_TO_POINTER(keyboard_id));
keyboard->id = keyboard_id;
keyboard_id++;
}
// set as current
@ -370,7 +368,6 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
klass->create_keyboard = eekboard_context_service_real_create_keyboard;
klass->show_keyboard = eekboard_context_service_real_show_keyboard;
klass->hide_keyboard = eekboard_context_service_real_hide_keyboard;
@ -574,7 +571,7 @@ eekboard_context_service_destroy (EekboardContextService *context)
* Get keyboard currently active in @context.
* Returns: (transfer none): an #EekKeyboard
*/
EekKeyboard *
LevelKeyboard *
eekboard_context_service_get_keyboard (EekboardContextService *context)
{
return context->priv->keyboard;
@ -594,7 +591,7 @@ eekboard_context_service_get_fullscreen (EekboardContextService *context)
}
void eekboard_context_service_set_keymap(EekboardContextService *context,
const EekKeyboard *keyboard)
const LevelKeyboard *keyboard)
{
zwp_virtual_keyboard_v1_keymap(context->virtual_keyboard,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,

View File

@ -97,13 +97,12 @@ void eekboard_context_service_show_keyboard
void eekboard_context_service_hide_keyboard
(EekboardContextService *context);
void eekboard_context_service_destroy (EekboardContextService *context);
EekKeyboard *eekboard_context_service_get_keyboard
(EekboardContextService *context);
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
gboolean eekboard_context_service_get_fullscreen
(EekboardContextService *context);
void eekboard_context_service_set_keymap(EekboardContextService *context,
const EekKeyboard *keyboard);
const LevelKeyboard *keyboard);
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint,

View File

@ -22,6 +22,7 @@
#include "eekboard/key-emitter.h"
#include <gdk/gdk.h>
#include <X11/XKBlib.h>
#include "eekboard/eekboard-context-service.h"
@ -84,14 +85,14 @@ update_modifier_info (SeatEmitter *client)
static void
send_fake_key (SeatEmitter *emitter,
EekKeyboard *keyboard,
LevelKeyboard *keyboard,
guint keycode,
guint keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
uint32_t proto_modifiers = 0;
guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
guint level = keyboard->level;
uint32_t group = (level / 2);
if (keyboard_modifiers & EEK_SHIFT_MASK)
@ -104,7 +105,7 @@ send_fake_key (SeatEmitter *emitter,
void
emit_key_activated (EekboardContextService *manager,
EekKeyboard *keyboard,
LevelKeyboard *keyboard,
guint keycode,
EekSymbol *symbol,
EekModifierType modifiers,

View File

@ -39,7 +39,7 @@ enum mod_indices {
};
void
emit_key_activated (EekboardContextService *manager, EekKeyboard *keyboard,
emit_key_activated (EekboardContextService *manager, LevelKeyboard *keyboard,
guint keycode,
EekSymbol *symbol,
guint modifiers,

23
src/keyboard.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __KEYBOARD_H
#define __KYBOARD_H
#include "stdbool.h"
#include "inttypes.h"
struct squeek_key;
struct squeek_key *squeek_key_new(uint32_t keycode);
void squeek_key_free(struct squeek_key *key);
void squeek_key_add_symbol(struct squeek_key* key,
const char *element_name,
const char *text, uint32_t keyval,
const char *label, const char *icon,
const char *tooltip);
uint32_t squeek_key_is_pressed(struct squeek_key *key);
void squeek_key_set_pressed(struct squeek_key *key, uint32_t pressed);
uint32_t squeek_key_get_keycode(struct squeek_key *key);
void squeek_key_set_keycode(struct squeek_key *key, uint32_t keycode);
struct squeek_symbol *squeek_key_get_symbol(struct squeek_key* key, uint32_t level);
const char* squeek_key_to_keymap_entry(const char *key_name, struct squeek_key *key);
#endif

237
src/keyboard.rs Normal file
View File

@ -0,0 +1,237 @@
use std::vec::Vec;
use super::symbol;
/// Gathers stuff defined in C or called by C
pub mod c {
use super::*;
use ::util::c::{ as_cstr, into_cstring };
use std::ffi::CString;
use std::os::raw::c_char;
// The following defined in C
#[no_mangle]
extern "C" {
fn eek_keysym_from_name(name: *const c_char) -> u32;
}
// The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
// TODO: this will receive data from the filesystem,
// so it should handle garbled strings in the future
#[no_mangle]
pub extern "C"
fn squeek_key_new(keycode: u32) -> *mut KeyState {
Box::into_raw(Box::new(
KeyState {
pressed: false,
keycode: keycode,
symbols: Vec::new(),
}
))
}
#[no_mangle]
pub extern "C"
fn squeek_key_free(key: *mut KeyState) {
unsafe { Box::from_raw(key) }; // gets dropped
}
#[no_mangle]
pub extern "C"
fn squeek_key_is_pressed(key: *const KeyState) -> u32 {
let key = unsafe { &*key };
return key.pressed as u32;
}
#[no_mangle]
pub extern "C"
fn squeek_key_set_pressed(key: *mut KeyState, pressed: u32) {
let key = unsafe { &mut *key };
key.pressed = pressed != 0;
}
#[no_mangle]
pub extern "C"
fn squeek_key_get_keycode(key: *const KeyState) -> u32 {
let key = unsafe { &*key };
return key.keycode as u32;
}
#[no_mangle]
pub extern "C"
fn squeek_key_set_keycode(key: *mut KeyState, code: u32) {
let key = unsafe { &mut *key };
key.keycode = code;
}
// TODO: this will receive data from the filesystem,
// so it should handle garbled strings in the future
#[no_mangle]
pub extern "C"
fn squeek_key_add_symbol(
key: *mut KeyState,
element: *const c_char,
text_raw: *const c_char, keyval: u32,
label: *const c_char, icon: *const c_char,
tooltip: *const c_char,
) {
let element = as_cstr(&element)
.expect("Missing element name");
let text = into_cstring(text_raw)
.unwrap_or_else(|e| {
eprintln!("Text unreadable: {}", e);
None
})
.and_then(|text| {
if text.as_bytes() == b"" {
None
} else {
Some(text)
}
});
let key = unsafe { &mut *key };
if key.symbols.len() > 0 {
eprintln!("Key {:?} already has a symbol defined", text);
return;
}
let icon = into_cstring(icon)
.unwrap_or_else(|e| {
eprintln!("Icon name unreadable: {}", e);
None
});
use symbol::*;
// Only read label if there's no icon
let label = match icon {
Some(icon) => Label::IconName(icon),
None => Label::Text(
into_cstring(label)
.unwrap_or_else(|e| {
eprintln!("Label unreadable: {}", e);
Some(CString::new(" ").unwrap())
})
.unwrap_or_else(|| {
eprintln!("Label missing");
CString::new(" ").unwrap()
})
),
};
let tooltip = into_cstring(tooltip)
.unwrap_or_else(|e| {
eprintln!("Tooltip unreadable: {}", e);
None
});
let symbol = match element.to_bytes() {
b"symbol" => Symbol {
action: Action::Submit {
text: text,
keys: Vec::new(),
},
label: label,
tooltip: tooltip,
},
b"keysym" => {
let keysym = XKeySym(
if keyval == 0 {
unsafe { eek_keysym_from_name(text_raw) }
} else {
keyval
}
);
Symbol {
action: match KeySym::from_u32(keysym.0) {
KeySym::Shift => Action::SetLevel(1),
_ => Action::Submit {
text: text,
keys: vec![keysym],
}
},
label: label,
tooltip: tooltip,
}
},
_ => panic!("unsupported element type {:?}", element),
};
key.symbols.push(symbol);
}
#[no_mangle]
pub extern "C"
fn squeek_key_get_symbol(
key: *const KeyState, index: u32
) -> *const symbol::Symbol {
let key = unsafe { &*key };
let index = index as usize;
&key.symbols[
if index < key.symbols.len() { index } else { 0 }
] as *const symbol::Symbol
}
#[no_mangle]
pub extern "C"
fn squeek_key_to_keymap_entry(
key_name: *const c_char,
key: *const KeyState,
) -> *const c_char {
let key_name = as_cstr(&key_name)
.expect("Missing key name")
.to_str()
.expect("Bad key name");
let key = unsafe { &*key };
let symbol_names = key.symbols.iter()
.map(|symbol| {
match &symbol.action {
symbol::Action::Submit { text: Some(text), .. } => {
Some(
text.clone()
.into_string().expect("Bad symbol")
)
},
_ => None
}
})
.collect::<Vec<_>>();
let inner = match symbol_names.len() {
1 => match &symbol_names[0] {
Some(name) => format!("[ {} ]", name),
_ => format!("[ ]"),
},
4 => {
let first = match (&symbol_names[0], &symbol_names[1]) {
(Some(left), Some(right)) => format!("{}, {}", left, right),
_ => format!(""),
};
let second = match (&symbol_names[2], &symbol_names[3]) {
(Some(left), Some(right)) => format!("{}, {}", left, right),
_ => format!(""),
};
format!("[ {} ], [ {} ]", first, second)
},
_ => panic!("Unsupported number of symbols: {}", symbol_names.len()),
};
CString::new(format!(" key <{}> {{ {} }};\n", key_name, inner))
.expect("Couldn't convert string")
.into_raw()
}
}
#[derive(Debug)]
pub struct KeyState {
pressed: bool,
keycode: u32,
symbols: Vec<symbol::Symbol>,
}

View File

@ -2,3 +2,6 @@
mod bitflags;
mod imservice;
mod keyboard;
mod symbol;
mod util;

View File

@ -27,9 +27,6 @@ sources = [
'../eek/eek-renderer.c',
'../eek/eek-section.c',
'../eek/eek-serializable.c',
'../eek/eek-symbol.c',
'../eek/eek-symbol-matrix.c',
'../eek/eek-text.c',
'../eek/eek-types.c',
'../eek/eek-xml-layout.c',
'../eek/layersurface.c',

View File

@ -83,9 +83,7 @@ on_notify_keyboard (GObject *object,
GParamSpec *spec,
ServerContextService *context)
{
const EekKeyboard *keyboard;
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
const LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
if (!keyboard)
g_error("Programmer error: keyboard layout was unset!");
@ -141,13 +139,13 @@ set_geometry (ServerContextService *context)
GdkWindow *root = gdk_screen_get_root_window (screen);
GdkDisplay *display = gdk_display_get_default ();
GdkMonitor *monitor = gdk_display_get_monitor_at_window (display, root);
EekKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
GdkRectangle rect;
EekBounds bounds;
gdk_monitor_get_geometry (monitor, &rect);
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(keyboard)), &bounds);
if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
gint width = rect.width;
@ -228,14 +226,12 @@ destroy_window (ServerContextService *context)
static void
make_widget (ServerContextService *context)
{
EekKeyboard *keyboard;
if (context->widget) {
gtk_widget_destroy(context->widget);
context->widget = NULL;
}
keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
context->widget = eek_gtk_keyboard_new (keyboard);

24
src/symbol.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __SYMBOL_H
#define __SYMBOL_H
#include "stdbool.h"
#include "inttypes.h"
// Defined in Rust
struct squeek_symbol;
struct squeek_symbols;
void squeek_symbols_add(struct squeek_symbols*,
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

138
src/symbol.rs Normal file
View File

@ -0,0 +1,138 @@
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;
// The following defined in C
// 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
// Symbols are owned by Rust and will move towards no C manipulation, so it may make sense not to wrap them
#[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)]
pub enum KeySym {
Unknown = 0,
Shift = 0xffe1,
}
impl KeySym {
pub fn from_u32(num: u32) -> KeySym {
match num {
0xffe1 => KeySym::Shift,
_ => KeySym::Unknown,
}
}
}
#[derive(Debug)]
pub struct XKeySym(pub 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
pub action: Action,
/// Label to display to the user
pub label: Label,
// FIXME: is it used?
pub tooltip: Option<CString>,
}

49
src/util.rs Normal file
View File

@ -0,0 +1,49 @@
pub mod c {
use std::ffi::{ CStr, CString };
use std::os::raw::c_char;
use std::str::Utf8Error;
pub 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)
}
}
pub fn as_cstr(s: &*const c_char) -> Option<&CStr> {
if s.is_null() {
None
} else {
Some(unsafe {CStr::from_ptr(*s)})
}
}
pub 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::*;
use std::ptr;
#[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))
}
}
}

View File

@ -29,12 +29,12 @@ test_create (void)
EekKey *key0, *key1;
keyboard = g_object_new (EEK_TYPE_KEYBOARD, NULL);
section = eek_keyboard_create_section (keyboard);
section = eek_keyboard_real_create_section (keyboard);
g_assert (EEK_IS_SECTION(section));
eek_section_add_row (section, 2, EEK_ORIENTATION_HORIZONTAL);
key0 = eek_section_create_key (section, "key0", 1);
key0 = eek_section_create_key (section, "key0", 1, 0);
g_assert (EEK_IS_KEY(key0));
key1 = eek_section_create_key (section, "key1", 2);
key1 = eek_section_create_key (section, "key1", 2, 0);
g_assert (EEK_IS_KEY(key1));
}

View File

@ -30,7 +30,7 @@ static void
test_output_parse (void)
{
EekLayout *layout;
EekKeyboard *keyboard;
LevelKeyboard *keyboard;
GError *error;
error = NULL;
@ -39,9 +39,9 @@ test_output_parse (void)
/* We don't need the context service to parse an XML file, so we can pass
NULL when creating a keyboard. */
keyboard = eek_keyboard_new (NULL, layout, 640, 480);
keyboard = eek_xml_layout_real_create_keyboard(layout, NULL);
g_object_unref (layout);
g_object_unref (keyboard);
level_keyboard_free(keyboard);
}
int

View File

@ -32,14 +32,14 @@ static void
test_check_xkb (void)
{
EekLayout *layout;
EekKeyboard *keyboard;
LevelKeyboard *keyboard;
GError *error;
error = NULL;
layout = eek_xml_layout_new ("us", &error);
g_assert_no_error (error);
keyboard = eek_keyboard_new (NULL, layout, 640, 480);
keyboard = eek_xml_layout_real_create_keyboard(layout, NULL);
gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
@ -58,7 +58,7 @@ test_check_xkb (void)
}
g_object_unref (layout);
g_object_unref (keyboard);
level_keyboard_free(keyboard);
}
int