Merge branch 'eekkey' into 'master'
Redesign how keys are handled See merge request Librem5/squeekboard!117
This commit is contained in:
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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="△">U25B3</symbol>
|
||||
<symbol label="ρ">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="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
|
||||
<symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
|
||||
<symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
|
||||
<symbol label="☺" 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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
220
eek/eek-key.c
220
eek/eek-key.c
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
/// 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,
|
||||
guint new_level)
|
||||
{
|
||||
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
|
||||
// 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 = 0;
|
||||
modifier_key->key = g_object_ref (key);
|
||||
keyboard->locked_keys =
|
||||
g_list_prepend (keyboard->locked_keys, modifier_key);
|
||||
g_signal_emit_by_name (modifier_key->key, "locked");
|
||||
}
|
||||
|
||||
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;
|
||||
GList *next = g_list_next (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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return new_level;
|
||||
}
|
||||
|
||||
// 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 */
|
||||
|
||||
/* Use the numbers/letters bit from the old level */
|
||||
gint level = priv->old_level & 2;
|
||||
|
||||
guint level = keyboard->level;
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
keyboard->level = set_key_states(keyboard, key, level);
|
||||
|
||||
priv->old_level = level;
|
||||
eek_element_set_level (EEK_ELEMENT(self), level);
|
||||
|
||||
eek_layout_update_layout(self);
|
||||
eek_layout_update_layout(keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
set_modifiers_with_key (EekKeyboard *self,
|
||||
EekKey *key,
|
||||
EekModifierType modifiers)
|
||||
{
|
||||
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) {
|
||||
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
|
||||
modifier_key->modifiers = enabled;
|
||||
modifier_key->key = g_object_ref (key);
|
||||
priv->locked_keys =
|
||||
g_list_prepend (priv->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; ) {
|
||||
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);
|
||||
g_signal_emit_by_name (modifier_key->key, "unlocked");
|
||||
g_list_free1 (head);
|
||||
head = next;
|
||||
} else
|
||||
head = g_list_next (head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
priv->modifiers = modifiers;
|
||||
}
|
||||
|
||||
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp) {
|
||||
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(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_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
|
||||
g_array_free (self->outline_array, TRUE);
|
||||
for (guint i = 0; i < 4; i++) {
|
||||
// free self->view[i];
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
207
eek/eek-keysym.c
207
eek/eek-keysym.c
@ -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;
|
||||
}
|
||||
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;
|
||||
for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++) {
|
||||
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0) {
|
||||
return xkeysym_keysym_entries[i].xkeysym;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_keysym_new_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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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, §ion_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, §ion_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));
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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, §ion_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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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];
|
||||
}
|
||||
@ -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 */
|
||||
@ -30,42 +30,15 @@
|
||||
#include "eek-symbol.h"
|
||||
#include "eek-enumtypes.h"
|
||||
|
||||
void
|
||||
eek_symbol_destroy (EekSymbol *priv)
|
||||
{
|
||||
g_free (priv->name);
|
||||
g_free (priv->label);
|
||||
g_free (priv->icon_name);
|
||||
g_free (priv->tooltip);
|
||||
g_free(priv->text);
|
||||
g_free(priv);
|
||||
}
|
||||
|
||||
EekSymbol *
|
||||
eek_symbol_new (const gchar *name)
|
||||
{
|
||||
EekSymbol *self = g_new0(EekSymbol, 1);
|
||||
eek_symbol_set_name(self, name);
|
||||
self->name = g_strdup (name);
|
||||
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
eek_symbol_set_name (EekSymbol *symbol,
|
||||
const gchar *name)
|
||||
{
|
||||
g_free (symbol->name);
|
||||
symbol->name = g_strdup (name);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
eek_symbol_get_name (EekSymbol *symbol)
|
||||
{
|
||||
if (symbol->name == NULL || *symbol->name == '\0')
|
||||
return NULL;
|
||||
return symbol->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_symbol_set_label:
|
||||
* @symbol: an #EekSymbol
|
||||
@ -81,20 +54,6 @@ eek_symbol_set_label (EekSymbol *symbol,
|
||||
symbol->label = g_strdup (label);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_symbol_get_label:
|
||||
* @symbol: an #EekSymbol
|
||||
*
|
||||
* Get the label text of @symbol.
|
||||
*/
|
||||
const gchar *
|
||||
eek_symbol_get_label (EekSymbol *symbol)
|
||||
{
|
||||
if (symbol->label == NULL || *symbol->label == '\0')
|
||||
return NULL;
|
||||
return symbol->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_symbol_set_modifier_mask:
|
||||
* @symbol: an #EekSymbol
|
||||
@ -118,15 +77,10 @@ eek_symbol_set_modifier_mask (EekSymbol *symbol,
|
||||
EekModifierType
|
||||
eek_symbol_get_modifier_mask (EekSymbol *symbol)
|
||||
{
|
||||
return 0;
|
||||
return symbol->modifier_mask;
|
||||
}
|
||||
|
||||
gboolean
|
||||
eek_symbol_is_modifier (EekSymbol *symbol)
|
||||
{
|
||||
return eek_symbol_get_modifier_mask (symbol) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
eek_symbol_set_icon_name (EekSymbol *symbol,
|
||||
const gchar *icon_name)
|
||||
@ -138,9 +92,7 @@ eek_symbol_set_icon_name (EekSymbol *symbol,
|
||||
const gchar *
|
||||
eek_symbol_get_icon_name (EekSymbol *symbol)
|
||||
{
|
||||
if (symbol->icon_name == NULL || *symbol->icon_name == '\0')
|
||||
return NULL;
|
||||
return symbol->icon_name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@ -154,6 +106,7 @@ eek_symbol_set_tooltip (EekSymbol *symbol,
|
||||
const gchar *
|
||||
eek_symbol_get_tooltip (EekSymbol *symbol)
|
||||
{
|
||||
return NULL;
|
||||
if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
|
||||
return NULL;
|
||||
return symbol->tooltip;
|
||||
|
||||
107
eek/eek-symbol.h
107
eek/eek-symbol.h
@ -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 */
|
||||
@ -150,6 +150,7 @@ typedef struct _EekOutline EekOutline;
|
||||
typedef struct _EekColor EekColor;
|
||||
|
||||
typedef struct _EekboardContextService EekboardContextService;
|
||||
typedef struct _LevelKeyboard LevelKeyboard;
|
||||
|
||||
/**
|
||||
* EekPoint:
|
||||
|
||||
@ -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->label = NULL;
|
||||
}
|
||||
if (data->icon) {
|
||||
eek_symbol_set_icon_name (symbol, data->icon);
|
||||
g_free (data->icon);
|
||||
data->icon = NULL;
|
||||
}
|
||||
if (data->tooltip) {
|
||||
eek_symbol_set_tooltip (symbol, data->tooltip);
|
||||
g_free (data->tooltip);
|
||||
data->tooltip = NULL;
|
||||
}
|
||||
|
||||
data->symbols = g_slist_prepend (data->symbols, symbol);
|
||||
data->keyval = 0;
|
||||
g_free(data->label);
|
||||
data->label = NULL;
|
||||
g_free(data->icon);
|
||||
data->icon = NULL;
|
||||
g_free(data->tooltip);
|
||||
data->tooltip = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
gnome = import('gnome')
|
||||
|
||||
enum_headers = [
|
||||
'eek-symbol.h',
|
||||
'eek-types.h',
|
||||
]
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
23
src/keyboard.h
Normal 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
237
src/keyboard.rs
Normal 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>,
|
||||
}
|
||||
@ -2,3 +2,6 @@
|
||||
mod bitflags;
|
||||
|
||||
mod imservice;
|
||||
mod keyboard;
|
||||
mod symbol;
|
||||
mod util;
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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
24
src/symbol.h
Normal 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
138
src/symbol.rs
Normal 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
49
src/util.rs
Normal 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user