Use keyboards as views

Got rid of modifiers in the process. Still buggy: dragging over keys.
This commit is contained in:
Dorota Czaplejewicz
2019-08-04 19:38:04 +00:00
parent f745223796
commit cc3f2315a7
11 changed files with 295 additions and 336 deletions

View File

@ -1,10 +1,30 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<geometry version="0.90"> <geometry version="0.90">
<bounds x="10" y="10" width="410.0000" height="229"/> <bounds x="10" y="10" width="410.0000" height="229"/>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05 AD06 AD07 AD08 AD09 AD10</section> <section angle="0">AD01 AD02 AD03 AD04 AD05 AD06 AD07 AD08 AD09 AD10</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05 AC06 AC07 AC08 AC09 AC10</section> <section angle="0">AC01 AC02 AC03 AC04 AC05 AC06 AC07 AC08 AC09 AC10</section>
<section angle="0"> LFSH AB01 AB02 AB03 AB04 AB05 AB06 AB07 BKSP </section> <section angle="0"> LFSH AB01 AB02 AB03 AB04 AB05 AB06 AB07 BKSP </section>
<section angle="0"> ABC123 I149 SPCE AB08 RTRN </section> <section angle="0"> ABC123 I149 SPCE AB08 RTRN </section>
</view>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05 AD06 AD07 AD08 AD09 AD10</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05 AC06 AC07 AC08 AC09 AC10</section>
<section angle="0"> LFSH AB01 AB02 AB03 AB04 AB05 AB06 AB07 BKSP </section>
<section angle="0"> ABC123 I149 SPCE AB08 RTRN </section>
</view>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05 AD06 AD07 AD08 AD09 AD10</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05 AC06 AC07 AC08 AC09 AC10</section>
<section angle="0"> LFSH AB01 AB02 AB03 AB04 AB05 AB06 AB07 BKSP </section>
<section angle="0"> ABC123 I149 SPCE AB08 RTRN </section>
</view>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05 AD06 AD07 AD08 AD09 AD10</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05 AC06 AC07 AC08 AC09 AC10</section>
<section angle="0"> LFSH AB01 AB02 AB03 AB04 AB05 AB06 AB07 BKSP </section>
<section angle="0"> ABC123 I149 SPCE AB08 RTRN </section>
</view>
<button name="LFSH" oref="altline" /> <button name="LFSH" oref="altline" />
<button name="BKSP" oref="altline" /> <button name="BKSP" oref="altline" />
<button name="I149" oref="altline" /> <button name="I149" oref="altline" />

View File

@ -1,10 +1,31 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<geometry version="0.90"> <geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/> <bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05</section> <section angle="0">AD01 AD02 AD03 AD04 AD05</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05</section> <section angle="0">AC01 AC02 AC03 AC04 AC05</section>
<section angle="0">AB01 AB02 AB03 AB04 AB05</section> <section angle="0">AB01 AB02 AB03 AB04 AB05</section>
<section angle="0">BKSP AB06 SPCE RTRN</section> <section angle="0">BKSP AB06 SPCE RTRN</section>
</view>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05</section>
<section angle="0">AB01 AB02 AB03 AB04 AB05</section>
<section angle="0">BKSP AB06 SPCE RTRN</section>
</view>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05</section>
<section angle="0">AB01 AB02 AB03 AB04 AB05</section>
<section angle="0">BKSP AB06 SPCE RTRN</section>
</view>
<view>
<section angle="0">AD01 AD02 AD03 AD04 AD05</section>
<section angle="0">AC01 AC02 AC03 AC04 AC05</section>
<section angle="0">AB01 AB02 AB03 AB04 AB05</section>
<section angle="0">BKSP AB06 SPCE RTRN</section>
</view>
<button name="BKSP" oref="altline" /> <button name="BKSP" oref="altline" />
<button name="SPCE" oref="spaceline" /> <button name="SPCE" oref="spaceline" />
<button name="RTRN" oref="outline7" /> <button name="RTRN" oref="outline7" />

View File

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

View File

@ -124,6 +124,9 @@
</key> </key>
<key name="RTRN"> <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>
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key> </key>
<key name="LFSH"> <key name="LFSH">
<keysym keyval="65505" icon="key-shift">Shift_L</keysym> <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
@ -175,6 +178,9 @@
</key> </key>
<key name="AB08"> <key name="AB08">
<symbol label=".">period</symbol> <symbol label=".">period</symbol>
<symbol label=".">period</symbol>
<symbol label=".">period</symbol>
<symbol label=".">period</symbol>
</key> </key>
<key name="ABC123"> <key name="ABC123">
<symbol label="123">show-numbers</symbol> <symbol label="123">show-numbers</symbol>
@ -184,11 +190,20 @@
</key> </key>
<key name="I149"> <key name="I149">
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol> <symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
</key> </key>
<key name="SPCE"> <key name="SPCE">
<symbol label=" ">space</symbol> <symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
<symbol label=" ">space</symbol>
</key> </key>
<key name="BKSP"> <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>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key> </key>
</symbols> </symbols>

View File

@ -96,8 +96,6 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
EekGtkKeyboardPrivate *priv = EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation; GtkAllocation allocation;
GList *list, *head;
gtk_widget_get_allocation (self, &allocation); gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) { if (!priv->renderer) {
@ -117,18 +115,16 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
uint level = priv->keyboard->level; uint level = priv->keyboard->level;
/* redraw pressed key */ /* redraw pressed key */
list = eek_keyboard_get_pressed_keys (level_keyboard_current(priv->keyboard)); const GList *list = priv->keyboard->pressed_keys;
for (head = list; head; head = g_list_next (head)) { for (const GList *head = list; head; head = g_list_next (head)) {
render_pressed_key (self, head->data, level); render_pressed_key (self, head->data, level);
} }
g_list_free (list);
/* redraw locked key */ /* redraw locked key */
list = eek_keyboard_get_locked_keys (level_keyboard_current(priv->keyboard)); list = priv->keyboard->locked_keys;
for (head = list; head; head = g_list_next (head)) { for (const GList *head = list; head; head = g_list_next (head)) {
render_locked_key (self, ((EekModifierKey *)head->data)->key, level); render_locked_key (self, ((EekModifierKey *)head->data)->key, level);
} }
g_list_free (list);
return FALSE; return FALSE;
} }
@ -168,7 +164,7 @@ static void drag(EekGtkKeyboard *self,
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y); EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
GList *list, *head; GList *list, *head;
list = eek_keyboard_get_pressed_keys (level_keyboard_current(priv->keyboard)); list = g_list_copy(priv->keyboard->pressed_keys);
if (key) { if (key) {
gboolean found = FALSE; gboolean found = FALSE;
@ -200,7 +196,7 @@ static void drag(EekGtkKeyboard *self,
static void release(EekGtkKeyboard *self, guint32 time) { static void release(EekGtkKeyboard *self, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
GList *list = eek_keyboard_get_pressed_keys (level_keyboard_current(priv->keyboard)); GList *list = g_list_copy(priv->keyboard->pressed_keys);
for (GList *head = list; head; head = g_list_next (head)) { for (GList *head = list; head; head = g_list_next (head)) {
EekKey *key = EEK_KEY(head->data); EekKey *key = EEK_KEY(head->data);
eek_keyboard_release_key(priv->keyboard, key, time); eek_keyboard_release_key(priv->keyboard, key, time);
@ -287,7 +283,7 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
elements, so that the default handler of elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its EekKeyboard::key-released signal can remove elements from its
internal copy */ internal copy */
list = eek_keyboard_get_pressed_keys (level_keyboard_current(priv->keyboard)); list = g_list_copy(priv->keyboard->pressed_keys);
for (head = list; head; head = g_list_next (head)) { for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey released"); g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey released");
g_signal_emit_by_name (head->data, "released"); g_signal_emit_by_name (head->data, "released");
@ -369,7 +365,7 @@ eek_gtk_keyboard_dispose (GObject *object)
if (priv->keyboard) { if (priv->keyboard) {
GList *list, *head; GList *list, *head;
list = eek_keyboard_get_pressed_keys (level_keyboard_current(priv->keyboard)); list = g_list_copy(priv->keyboard->pressed_keys);
for (head = list; head; head = g_list_next (head)) { for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed"); g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard)); g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard));

View File

@ -302,7 +302,7 @@ eek_key_is_pressed (EekKey *key)
{ {
g_return_val_if_fail (EEK_IS_KEY(key), FALSE); 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 (bool)squeek_key_is_pressed(priv->state); return (bool)squeek_key_is_pressed(priv->state);
} }

View File

@ -43,7 +43,6 @@
enum { enum {
PROP_0, PROP_0,
PROP_MODIFIER_BEHAVIOR,
PROP_LAST PROP_LAST
}; };
@ -68,11 +67,7 @@ static guint signals[LAST_SIGNAL] = { 0, };
struct _EekKeyboardPrivate struct _EekKeyboardPrivate
{ {
EekModifierBehavior modifier_behavior; char dummy; // won't run otherwise
EekModifierType modifiers;
unsigned int old_level;
GList *pressed_keys;
GList *locked_keys;
}; };
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER); G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
@ -129,10 +124,6 @@ eek_keyboard_set_property (GObject *object,
GParamSpec *pspec) GParamSpec *pspec)
{ {
switch (prop_id) { switch (prop_id) {
case PROP_MODIFIER_BEHAVIOR:
eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(object),
g_value_get_enum (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -146,118 +137,80 @@ eek_keyboard_get_property (GObject *object,
GParamSpec *pspec) GParamSpec *pspec)
{ {
switch (prop_id) { switch (prop_id) {
case PROP_MODIFIER_BEHAVIOR:
g_value_set_enum (value,
eek_keyboard_get_modifier_behavior (EEK_KEYBOARD(object)));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
/// Updates the state of locked keys based on the key that was activated
static void static void
set_level_from_modifiers (LevelKeyboard *keyboard, EekKeyboard *self, EekKey *key) set_key_states (LevelKeyboard *keyboard,
EekKey *key)
{ {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self); // Keys locking rules hardcoded for the time being...
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
/* Use the numbers/letters bit from the old level */
guint level = priv->old_level & 2;
/* Handle non-emitting keys */
if (key) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key)); const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "ABC123") == 0) // Lock the shift whenever it's pressed
level ^= 2; // TODO: need to lock shift on the destination level
} if (g_strcmp0(name, "LFSH-0") == 0) {
level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
switch (priv->old_level) {
case VIEW_LETTERS_UPPER:
{
/* Redirect upper case letters to numbers instead of symbols, clearing
the shift modifier to keep the modifiers in sync with the level */
if (level == VIEW_SYMBOLS) {
level = VIEW_NUMBERS;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_SYMBOLS:
{
/* Redirect symbols to lower case letters instead of upper case,
clearing the shift modifier to keep the modifiers in sync with the
level */
if (level == VIEW_LETTERS_UPPER) {
level = VIEW_LETTERS_LOWER;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_LETTERS_LOWER: /* Direct transitions between views */
case VIEW_NUMBERS:
default:
break;
}
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
else
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
priv->old_level = level;
keyboard->level = level;
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); EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = enabled; modifier_key->modifiers = 0;
modifier_key->key = g_object_ref (key); modifier_key->key = g_object_ref (key);
priv->locked_keys = keyboard->locked_keys =
g_list_prepend (priv->locked_keys, modifier_key); g_list_prepend (keyboard->locked_keys, modifier_key);
g_signal_emit_by_name (modifier_key->key, "locked"); g_signal_emit_by_name (modifier_key->key, "locked");
} }
} else {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) { if (keyboard->level == 1) {
GList *head; // Only shift is locked in this state, unlock on any key press
for (head = priv->locked_keys; head; ) { for (GList *head = keyboard->locked_keys; head; ) {
EekModifierKey *modifier_key = head->data; EekModifierKey *modifier_key = head->data;
if (modifier_key->modifiers & disabled) {
GList *next = g_list_next (head); GList *next = g_list_next (head);
priv->locked_keys = keyboard->locked_keys =
g_list_remove_link (priv->locked_keys, head); g_list_remove_link (keyboard->locked_keys, head);
g_signal_emit_by_name (modifier_key->key, "unlocked"); g_signal_emit_by_name (modifier_key->key, "unlocked");
g_list_free1 (head); g_list_free1 (head);
head = next; head = next;
} else
head = g_list_next (head);
} }
keyboard->level = 0;
}
}
static void
set_level_from_press (LevelKeyboard *keyboard, EekKey *key)
{
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
guint level = keyboard->level;
/* Handle non-emitting keys */
if (key) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "ABC123-0") == 0 || g_strcmp0(name, "ABC123-1") == 0) {
level = 2;
} else if (g_strcmp0(name, "ABC123-2") == 0 || g_strcmp0(name, "ABC123-3") == 0) {
level = 0;
} else if (g_strcmp0(name, "LFSH-0") == 0) {
level = 1;
} else if (g_strcmp0(name, "LFSH-1") == 0) {
level = 0;
} else if (g_strcmp0(name, "LFSH-2") == 0) {
level = 3;
} else if (g_strcmp0(name, "LFSH-3") == 0) {
level = 2;
} }
} }
priv->modifiers = modifiers; set_key_states(keyboard, key);
keyboard->level = level;
eek_layout_update_layout(keyboard);
} }
void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp) { void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(level_keyboard_current(keyboard)); EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(level_keyboard_current(keyboard));
eek_key_set_pressed(key, TRUE); 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);
struct squeek_symbol *symbol = eek_key_get_symbol_at_index( struct squeek_symbol *symbol = eek_key_get_symbol_at_index(
key, 0, keyboard->level key, 0, keyboard->level
@ -265,18 +218,14 @@ void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timest
if (!symbol) if (!symbol)
return; return;
EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol); set_key_states (keyboard, key);
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) { set_level_from_press (keyboard, key);
set_modifiers_with_key (level_keyboard_current(keyboard), key, priv->modifiers | modifier);
set_level_from_modifiers (keyboard, level_keyboard_current(keyboard), key);
}
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event // "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = eek_key_get_keycode (key); guint keycode = eek_key_get_keycode (key);
EekModifierType modifiers = eek_keyboard_get_modifiers (level_keyboard_current(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(LevelKeyboard *keyboard, void eek_keyboard_release_key(LevelKeyboard *keyboard,
@ -284,9 +233,9 @@ void eek_keyboard_release_key(LevelKeyboard *keyboard,
guint32 timestamp) { guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(level_keyboard_current(keyboard)); EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(level_keyboard_current(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) { 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); g_list_free1 (head);
break; break;
} }
@ -297,30 +246,14 @@ void eek_keyboard_release_key(LevelKeyboard *keyboard,
if (!symbol) if (!symbol)
return; return;
EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol); set_key_states (keyboard, key);
switch (priv->modifier_behavior) { set_level_from_press (keyboard, key);
case EEK_MODIFIER_BEHAVIOR_NONE:
set_modifiers_with_key (level_keyboard_current(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 (level_keyboard_current(keyboard), key, priv->modifiers ^ modifier);
else
set_modifiers_with_key (level_keyboard_current(keyboard), key,
(priv->modifiers ^ modifier) & modifier);
break;
}
set_level_from_modifiers (keyboard, level_keyboard_current(keyboard), key);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event // "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = eek_key_get_keycode (key); guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (level_keyboard_current(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 static void
@ -332,12 +265,6 @@ eek_keyboard_dispose (GObject *object)
static void static void
eek_keyboard_finalize (GObject *object) eek_keyboard_finalize (GObject *object)
{ {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
g_list_free (priv->pressed_keys);
g_list_free_full (priv->locked_keys,
(GDestroyNotify) eek_modifier_key_free);
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object); G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
} }
@ -395,21 +322,6 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
gobject_class->dispose = eek_keyboard_dispose; gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize; 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: * EekKeyboard::key-locked:
* @keyboard: an #EekKeyboard * @keyboard: an #EekKeyboard
@ -455,7 +367,6 @@ static void
eek_keyboard_init (EekKeyboard *self) eek_keyboard_init (EekKeyboard *self)
{ {
self->priv = EEK_KEYBOARD_GET_PRIVATE(self); self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
self->scale = 1.0; self->scale = 1.0;
} }
@ -463,10 +374,12 @@ void level_keyboard_init(LevelKeyboard *self) {
self->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); self->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
} }
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *view, GHashTable *name_key_hash) { LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_key_hash) {
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
level_keyboard_init(keyboard); level_keyboard_init(keyboard);
keyboard->view = view; for (uint i = 0; i < 4; i++) {
keyboard->views[i] = views[i];
}
keyboard->manager = manager; keyboard->manager = manager;
keyboard->names = name_key_hash; keyboard->names = name_key_hash;
return keyboard; return keyboard;
@ -507,49 +420,6 @@ eek_keyboard_get_size (EekKeyboard *keyboard,
*height = bounds.height; *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;
}
/**
* 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_get_outline: * eek_keyboard_get_outline:
* @keyboard: an #EekKeyboard * @keyboard: an #EekKeyboard
@ -568,36 +438,6 @@ level_keyboard_get_outline (LevelKeyboard *keyboard,
return &g_array_index (keyboard->outline_array, EekOutline, oref); return &g_array_index (keyboard->outline_array, EekOutline, oref);
} }
/**
* 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);
}
/** /**
* eek_keyboard_get_keymap: * eek_keyboard_get_keymap:
* @keyboard: an #EekKeyboard * @keyboard: an #EekKeyboard
@ -614,10 +454,11 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
/* Iterate over the keys in the name-to-key hash table. */ /* Iterate over the keys in the name-to-key hash table. */
GHashTableIter iter; GHashTableIter iter;
gpointer key_name, key_ptr; gchar *key_name;
gpointer key_ptr;
g_hash_table_iter_init(&iter, keyboard->names); 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; gchar *current, *line;
EekKey *key = EEK_KEY(key_ptr); EekKey *key = EEK_KEY(key_ptr);
@ -658,6 +499,5 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard) EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard)
{ {
return keyboard->view; return keyboard->views[keyboard->level];
//return keyboard->views[keyboard->level];
} }

View File

@ -119,22 +119,27 @@ typedef struct _EekModifierKey EekModifierKey;
/// Keyboard state holder /// Keyboard state holder
struct _LevelKeyboard { struct _LevelKeyboard {
guint id; EekKeyboard *views[4];
EekKeyboard *view;
guint level; guint level;
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd size_t keymap_len; // length of the data inside keymap_fd
GArray *outline_array; GArray *outline_array;
GList *pressed_keys;
GList *locked_keys;
/* Map key names to key objects: */ /* Map key names to key objects: */
GHashTable *names; GHashTable *names;
guint id; // as a key to layout choices
EekboardContextService *manager; // unowned reference EekboardContextService *manager; // unowned reference
}; };
typedef struct _LevelKeyboard LevelKeyboard; typedef struct _LevelKeyboard LevelKeyboard;
LevelKeyboard *eek_keyboard_new(EekLayout *layout, LevelKeyboard *eek_keyboard_new(EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width, gdouble initial_width,
gdouble initial_height); gdouble initial_height);
GType eek_keyboard_get_type GType eek_keyboard_get_type
@ -148,17 +153,6 @@ void eek_keyboard_set_size
gdouble width, gdouble width,
gdouble height); 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 EekSection *eek_keyboard_create_section
(EekKeyboard *keyboard); (EekKeyboard *keyboard);
@ -169,11 +163,6 @@ EekKey *eek_keyboard_find_key_by_name
EekOutline *level_keyboard_get_outline EekOutline *level_keyboard_get_outline
(LevelKeyboard *keyboard, (LevelKeyboard *keyboard,
guint oref); guint oref);
GList *eek_keyboard_get_pressed_keys
(EekKeyboard *keyboard);
GList *eek_keyboard_get_locked_keys
(EekKeyboard *keyboard);
EekModifierKey *eek_modifier_key_copy EekModifierKey *eek_modifier_key_copy
(EekModifierKey *modkey); (EekModifierKey *modkey);
void eek_modifier_key_free void eek_modifier_key_free
@ -186,7 +175,7 @@ gchar * eek_keyboard_get_keymap
(LevelKeyboard *keyboard); (LevelKeyboard *keyboard);
EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard); EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard);
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *view, GHashTable *name_key_hash); LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_key_hash);
void level_keyboard_deinit(LevelKeyboard *self); void level_keyboard_deinit(LevelKeyboard *self);
void level_keyboard_free(LevelKeyboard *self); void level_keyboard_free(LevelKeyboard *self);
/* Create an #EekSection instance and append it to @keyboard. This /* Create an #EekSection instance and append it to @keyboard. This

View File

@ -51,6 +51,7 @@ const double section_spacing = 7.0;
struct place_data { struct place_data {
double desired_width; double desired_width;
double current_offset; double current_offset;
// Needed for outline (bounds) retrieval
LevelKeyboard *keyboard; LevelKeyboard *keyboard;
}; };

View File

@ -68,7 +68,7 @@ static GList *parse_prerequisites
(const gchar *path, (const gchar *path,
GError **error); GError **error);
static gboolean parse_geometry (const gchar *path, static gboolean parse_geometry (const gchar *path,
EekKeyboard *keyboard, GArray *outline_array, GHashTable *name_key_hash, EekKeyboard **views, GArray *outline_array, GHashTable *name_key_hash,
GError **error); GError **error);
static gboolean parse_symbols_with_prerequisites static gboolean parse_symbols_with_prerequisites
(const gchar *keyboards_dir, (const gchar *keyboards_dir,
@ -233,7 +233,8 @@ struct _GeometryParseData {
GSList *element_stack; GSList *element_stack;
EekBounds bounds; EekBounds bounds;
EekKeyboard *keyboard; EekKeyboard **views;
guint view_idx;
EekSection *section; EekSection *section;
EekKey *key; EekKey *key;
gint num_columns; gint num_columns;
@ -255,11 +256,11 @@ struct _GeometryParseData {
typedef struct _GeometryParseData GeometryParseData; typedef struct _GeometryParseData GeometryParseData;
static GeometryParseData * static GeometryParseData *
geometry_parse_data_new (EekKeyboard *keyboard, GHashTable *name_key_hash) geometry_parse_data_new (EekKeyboard **views, GHashTable *name_key_hash)
{ {
GeometryParseData *data = g_slice_new0 (GeometryParseData); GeometryParseData *data = g_slice_new0 (GeometryParseData);
data->keyboard = g_object_ref (keyboard); data->views = views;
data->key_oref_hash = data->key_oref_hash =
g_hash_table_new_full (g_direct_hash, g_hash_table_new_full (g_direct_hash,
g_direct_equal, g_direct_equal,
@ -280,7 +281,6 @@ geometry_parse_data_new (EekKeyboard *keyboard, GHashTable *name_key_hash)
static void static void
geometry_parse_data_free (GeometryParseData *data) geometry_parse_data_free (GeometryParseData *data)
{ {
g_object_unref (data->keyboard);
g_hash_table_destroy (data->key_oref_hash); g_hash_table_destroy (data->key_oref_hash);
g_hash_table_destroy (data->oref_outline_hash); g_hash_table_destroy (data->oref_outline_hash);
g_string_free (data->text, TRUE); g_string_free (data->text, TRUE);
@ -291,7 +291,8 @@ static const gchar *geometry_valid_path_list[] = {
"geometry", "geometry",
"button/geometry", "button/geometry",
"bounds/geometry", "bounds/geometry",
"section/geometry", "view/geometry",
"section/view/geometry",
"outline/geometry", "outline/geometry",
"point/outline/geometry", "point/outline/geometry",
}; };
@ -360,14 +361,20 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
return; return;
} }
bounds.height = g_strtod (attribute, NULL); bounds.height = g_strtod (attribute, NULL);
data->bounds = bounds;
if (g_strcmp0 (data->element_stack->data, "geometry") == 0)
eek_element_set_bounds (EEK_ELEMENT(data->keyboard), &bounds);
goto out; 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) { if (g_strcmp0 (element_name, "section") == 0) {
data->section = eek_keyboard_real_create_section (data->keyboard); data->section = eek_keyboard_real_create_section (data->views[data->view_idx]);
attribute = get_attribute (attribute_names, attribute_values, attribute = get_attribute (attribute_names, attribute_values,
"id"); "id");
if (attribute != NULL) if (attribute != NULL)
@ -384,31 +391,37 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
} }
if (g_strcmp0 (element_name, "button") == 0) { if (g_strcmp0 (element_name, "button") == 0) {
attribute = get_attribute (attribute_names, attribute_values, const gchar *base_name = get_attribute (attribute_names, attribute_values,
"name"); "name");
if (attribute == NULL) { if (base_name == NULL) {
g_set_error (error, g_set_error (error,
G_MARKUP_ERROR, G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE, G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"name\" attribute for \"button\""); "no \"name\" attribute for \"button\"");
return; return;
} }
gchar *name = g_strdup (attribute);
EekKey *key = g_hash_table_lookup(data->name_key_hash, name); const gchar *oref_name = get_attribute (attribute_names, attribute_values,
attribute = get_attribute (attribute_names, attribute_values,
"oref"); "oref");
if (attribute == NULL) { if (oref_name == NULL) {
attribute = g_strdup("default"); oref_name = "default";
}
const gchar *keycode_name = get_attribute (attribute_names, attribute_values,
"keycode");
for (uint i = 0; i < 4; i++) {
gchar *name = g_strdup_printf("%s-%d", base_name, i);
EekKey *key = g_hash_table_lookup(data->name_key_hash, name);
if (!key) {
continue; // not all keys have to be defined in every view
} }
g_hash_table_insert (data->key_oref_hash, g_hash_table_insert (data->key_oref_hash,
key, key,
g_strdup (attribute)); g_strdup (oref_name));
attribute = get_attribute (attribute_names, attribute_values, if (keycode_name != NULL) {
"keycode"); eek_key_set_keycode(key, strtol (keycode_name, NULL, 10));
if (attribute != NULL) { }
eek_key_set_keycode(key, strtol (attribute, NULL, 10));
} }
goto out; goto out;
@ -486,6 +499,11 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
const gchar *text = g_strndup (data->text->str, data->text->len); 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) { if (g_strcmp0 (element_name, "section") == 0) {
// Split text on spaces and process each part // Split text on spaces and process each part
unsigned head = 0; unsigned head = 0;
@ -511,8 +529,11 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
break; break;
} }
gchar *name = g_strndup (&text[start], end - start); // Save button name together with its level,
// to account for buttons with the same name in multiple levels
gchar *base_name = g_strndup (&text[start], end - start);
gchar *name = g_strdup_printf("%s-%d", base_name, data->view_idx);
g_free(base_name);
guint keycode = data->keycode++; guint keycode = data->keycode++;
data->key = eek_section_create_key (data->section, data->key = eek_section_create_key (data->section,
@ -533,17 +554,6 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
return; 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) { if (g_strcmp0 (element_name, "outline") == 0) {
EekOutline *outline = g_slice_new (EekOutline); EekOutline *outline = g_slice_new (EekOutline);
@ -580,7 +590,7 @@ geometry_text_callback (GMarkupParseContext *pcontext,
GError **error) GError **error)
{ {
GeometryParseData *data = user_data; GeometryParseData *data = user_data;
g_string_append_len (data->text, text, text_len); g_string_append_len (data->text, text, (gssize)text_len);
} }
static const GMarkupParser geometry_parser = { static const GMarkupParser geometry_parser = {
@ -597,7 +607,9 @@ struct _SymbolsParseData {
LevelKeyboard *keyboard; LevelKeyboard *keyboard;
EekKeyboard *view; EekKeyboard *view;
EekKey *key; guint key_level;
const gchar *key_name;
gchar *label; gchar *label;
gchar *icon; gchar *icon;
gchar *tooltip; gchar *tooltip;
@ -651,9 +663,10 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
return; return;
if (g_strcmp0 (element_name, "key") == 0) { if (g_strcmp0 (element_name, "key") == 0) {
data->key_level = 0;
attribute = get_attribute (attribute_names, attribute_values, attribute = get_attribute (attribute_names, attribute_values,
"name"); "name");
if (attribute == NULL) { if (attribute == NULL) {
g_set_error (error, g_set_error (error,
G_MARKUP_ERROR, G_MARKUP_ERROR,
@ -661,15 +674,7 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
"no \"name\" attribute for \"key\""); "no \"name\" attribute for \"key\"");
return; return;
} }
data->key_name = strdup(attribute);
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);
}
goto out; goto out;
} }
@ -727,17 +732,23 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
text = g_strndup (data->text->str, data->text->len); text = g_strndup (data->text->str, data->text->len);
if (g_strcmp0 (element_name, "key") == 0) {
data->key = NULL;
goto out;
}
if (g_strcmp0 (element_name, "symbol") == 0 || if (g_strcmp0 (element_name, "symbol") == 0 ||
g_strcmp0 (element_name, "keysym") == 0 || g_strcmp0 (element_name, "keysym") == 0 ||
g_strcmp0 (element_name, "text") == 0) { g_strcmp0 (element_name, "text") == 0) {
gchar *name = g_strdup_printf("%s-%d", data->key_name, data->key_level);
EekKey *key = eek_keyboard_find_key_by_name (data->keyboard,
name);
if (key == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
"no such key %s", name);
return;
}
squeek_key_add_symbol( squeek_key_add_symbol(
eek_key_get_state(data->key), eek_key_get_state(key),
element_name, element_name,
text, text,
data->keyval, data->keyval,
@ -753,6 +764,8 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
data->icon = NULL; data->icon = NULL;
g_free(data->tooltip); g_free(data->tooltip);
data->tooltip = NULL; data->tooltip = NULL;
data->key_level++;
goto out; goto out;
} }
@ -876,10 +889,6 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout); EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
gboolean retval; gboolean retval;
/* Create an empty keyboard to which geometry and symbols
information are applied. */
EekKeyboard *view = g_object_new (EEK_TYPE_KEYBOARD, NULL);
/* Read geometry information. */ /* Read geometry information. */
gchar *filename = g_strdup_printf ("%s.xml", priv->desc->geometry); gchar *filename = g_strdup_printf ("%s.xml", priv->desc->geometry);
gchar *path = g_build_filename (priv->keyboards_dir, "geometry", filename, NULL); gchar *path = g_build_filename (priv->keyboards_dir, "geometry", filename, NULL);
@ -887,17 +896,22 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
GArray *outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); GArray *outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
// char* -> EekKey*
GHashTable *name_key_hash = GHashTable *name_key_hash =
g_hash_table_new_full (g_str_hash, g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
NULL); NULL);
; // char* -> EekKey* // One view for each level
EekKeyboard *views[4] = {0};
GError *error = NULL; GError *error = NULL;
retval = parse_geometry (path, view, outline_array, name_key_hash, &error); retval = parse_geometry (path, views, outline_array, name_key_hash, &error);
g_free (path); g_free (path);
if (!retval) { if (!retval) {
g_object_unref (view); for (uint i = 0; i < 4; i++) {
g_object_unref (views[i]);
}
g_warning ("can't parse geometry file %s: %s", g_warning ("can't parse geometry file %s: %s",
priv->desc->geometry, priv->desc->geometry,
error->message); error->message);
@ -906,7 +920,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
} }
LevelKeyboard *keyboard = level_keyboard_new(manager, view, name_key_hash); LevelKeyboard *keyboard = level_keyboard_new(manager, views, name_key_hash);
keyboard->outline_array = outline_array; keyboard->outline_array = outline_array;
// FIXME: are symbols shared betwen views? // FIXME: are symbols shared betwen views?
@ -920,7 +934,13 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
&error); &error);
g_list_free_full (loaded, g_free); g_list_free_full (loaded, g_free);
if (!retval) { if (!retval) {
g_object_unref (view); 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", g_warning ("can't parse symbols file %s: %s",
priv->desc->symbols, priv->desc->symbols,
error->message); error->message);
@ -928,7 +948,9 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
return NULL; return NULL;
} }
eek_layout_place_sections(keyboard, view); for (uint i = 0; i < 4; i++) {
eek_layout_place_sections(keyboard, views[i]);
}
return keyboard; return keyboard;
} }
@ -1136,7 +1158,7 @@ add_outline (GArray *outline_array,
} }
static gboolean static gboolean
parse_geometry (const gchar *path, EekKeyboard *keyboard, GArray *outline_array, GHashTable *name_key_hash, GError **error) parse_geometry (const gchar *path, EekKeyboard **views, GArray *outline_array, GHashTable *name_key_hash, GError **error)
{ {
GeometryParseData *data; GeometryParseData *data;
GMarkupParseContext *pcontext; GMarkupParseContext *pcontext;
@ -1156,7 +1178,7 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GArray *outline_array,
if (input == NULL) if (input == NULL)
return FALSE; return FALSE;
data = geometry_parse_data_new (keyboard, name_key_hash); data = geometry_parse_data_new (views, name_key_hash);
pcontext = g_markup_parse_context_new (&geometry_parser, pcontext = g_markup_parse_context_new (&geometry_parser,
0, 0,
data, data,

View File

@ -323,8 +323,6 @@ settings_update_layout(EekboardContextService *context)
// create a keyboard // create a keyboard
if (!keyboard) { if (!keyboard) {
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout); keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout);
eek_keyboard_set_modifier_behavior (level_keyboard_current(keyboard),
EEK_MODIFIER_BEHAVIOR_LATCH);
g_hash_table_insert (context->priv->keyboard_hash, g_hash_table_insert (context->priv->keyboard_hash,
GUINT_TO_POINTER(keyboard_id), GUINT_TO_POINTER(keyboard_id),