Use keyboards as views
Got rid of modifiers in the process. Still buggy: dragging over keys.
This commit is contained in:
@ -1,10 +1,30 @@
|
||||
<?xml version="1.0"?>
|
||||
<geometry version="0.90">
|
||||
<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">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>
|
||||
<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="BKSP" oref="altline" />
|
||||
<button name="I149" oref="altline" />
|
||||
|
||||
@ -1,10 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
<geometry version="0.90">
|
||||
<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">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>
|
||||
<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="SPCE" oref="spaceline" />
|
||||
<button name="RTRN" oref="outline7" />
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -124,6 +124,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,6 +178,9 @@
|
||||
</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>
|
||||
@ -184,11 +190,20 @@
|
||||
</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>
|
||||
|
||||
@ -96,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) {
|
||||
@ -117,18 +115,16 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
uint level = priv->keyboard->level;
|
||||
|
||||
/* redraw pressed key */
|
||||
list = eek_keyboard_get_pressed_keys (level_keyboard_current(priv->keyboard));
|
||||
for (head = list; head; head = g_list_next (head)) {
|
||||
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 (level_keyboard_current(priv->keyboard));
|
||||
for (head = list; head; head = g_list_next (head)) {
|
||||
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;
|
||||
}
|
||||
@ -168,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 (level_keyboard_current(priv->keyboard));
|
||||
list = g_list_copy(priv->keyboard->pressed_keys);
|
||||
|
||||
if (key) {
|
||||
gboolean found = FALSE;
|
||||
@ -200,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 (level_keyboard_current(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);
|
||||
@ -287,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 (level_keyboard_current(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");
|
||||
@ -369,7 +365,7 @@ eek_gtk_keyboard_dispose (GObject *object)
|
||||
if (priv->keyboard) {
|
||||
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)) {
|
||||
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
|
||||
g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard));
|
||||
|
||||
@ -302,7 +302,7 @@ 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 (bool)squeek_key_is_pressed(priv->state);
|
||||
}
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_MODIFIER_BEHAVIOR,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -68,11 +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;
|
||||
char dummy; // won't run otherwise
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
|
||||
@ -129,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;
|
||||
@ -146,118 +137,80 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the state of locked keys based on the key that was activated
|
||||
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);
|
||||
|
||||
/* 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) {
|
||||
// Keys locking rules hardcoded for the time being...
|
||||
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
|
||||
if (g_strcmp0(name, "ABC123") == 0)
|
||||
level ^= 2;
|
||||
}
|
||||
|
||||
level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
|
||||
|
||||
switch (priv->old_level) {
|
||||
case VIEW_LETTERS_UPPER:
|
||||
{
|
||||
/* Redirect upper case letters to numbers instead of symbols, clearing
|
||||
the shift modifier to keep the modifiers in sync with the level */
|
||||
if (level == VIEW_SYMBOLS) {
|
||||
level = VIEW_NUMBERS;
|
||||
priv->modifiers &= ~EEK_SHIFT_MASK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VIEW_SYMBOLS:
|
||||
{
|
||||
/* Redirect symbols to lower case letters instead of upper case,
|
||||
clearing the shift modifier to keep the modifiers in sync with the
|
||||
level */
|
||||
if (level == VIEW_LETTERS_UPPER) {
|
||||
level = VIEW_LETTERS_LOWER;
|
||||
priv->modifiers &= ~EEK_SHIFT_MASK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VIEW_LETTERS_LOWER: /* Direct transitions between views */
|
||||
case VIEW_NUMBERS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
|
||||
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
|
||||
else
|
||||
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
|
||||
|
||||
priv->old_level = level;
|
||||
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) {
|
||||
// Lock the shift whenever it's pressed
|
||||
// TODO: need to lock shift on the destination level
|
||||
if (g_strcmp0(name, "LFSH-0") == 0) {
|
||||
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
|
||||
modifier_key->modifiers = enabled;
|
||||
modifier_key->modifiers = 0;
|
||||
modifier_key->key = g_object_ref (key);
|
||||
priv->locked_keys =
|
||||
g_list_prepend (priv->locked_keys, modifier_key);
|
||||
keyboard->locked_keys =
|
||||
g_list_prepend (keyboard->locked_keys, modifier_key);
|
||||
g_signal_emit_by_name (modifier_key->key, "locked");
|
||||
}
|
||||
} else {
|
||||
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
|
||||
GList *head;
|
||||
for (head = priv->locked_keys; head; ) {
|
||||
|
||||
if (keyboard->level == 1) {
|
||||
// Only shift is locked in this state, unlock on any key press
|
||||
for (GList *head = keyboard->locked_keys; head; ) {
|
||||
EekModifierKey *modifier_key = head->data;
|
||||
if (modifier_key->modifiers & disabled) {
|
||||
GList *next = g_list_next (head);
|
||||
priv->locked_keys =
|
||||
g_list_remove_link (priv->locked_keys, head);
|
||||
keyboard->locked_keys =
|
||||
g_list_remove_link (keyboard->locked_keys, head);
|
||||
g_signal_emit_by_name (modifier_key->key, "unlocked");
|
||||
g_list_free1 (head);
|
||||
head = next;
|
||||
} else
|
||||
head = g_list_next (head);
|
||||
}
|
||||
keyboard->level = 0;
|
||||
}
|
||||
}
|
||||
|
||||
priv->modifiers = modifiers;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
set_key_states(keyboard, key);
|
||||
|
||||
keyboard->level = level;
|
||||
|
||||
eek_layout_update_layout(keyboard);
|
||||
}
|
||||
|
||||
void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp) {
|
||||
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(level_keyboard_current(keyboard));
|
||||
|
||||
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(
|
||||
key, 0, keyboard->level
|
||||
@ -265,18 +218,14 @@ void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timest
|
||||
if (!symbol)
|
||||
return;
|
||||
|
||||
EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol);
|
||||
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
|
||||
set_modifiers_with_key (level_keyboard_current(keyboard), key, priv->modifiers | modifier);
|
||||
set_level_from_modifiers (keyboard, level_keyboard_current(keyboard), key);
|
||||
}
|
||||
set_key_states (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);
|
||||
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,
|
||||
@ -284,9 +233,9 @@ void eek_keyboard_release_key(LevelKeyboard *keyboard,
|
||||
guint32 timestamp) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
@ -297,30 +246,14 @@ void eek_keyboard_release_key(LevelKeyboard *keyboard,
|
||||
if (!symbol)
|
||||
return;
|
||||
|
||||
EekModifierType modifier = squeek_symbol_get_modifier_mask (symbol);
|
||||
switch (priv->modifier_behavior) {
|
||||
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);
|
||||
set_key_states (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 (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
|
||||
@ -332,12 +265,6 @@ eek_keyboard_dispose (GObject *object)
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
@ -395,21 +322,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
|
||||
@ -455,7 +367,6 @@ static void
|
||||
eek_keyboard_init (EekKeyboard *self)
|
||||
{
|
||||
self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
|
||||
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
|
||||
self->scale = 1.0;
|
||||
}
|
||||
|
||||
@ -463,10 +374,12 @@ void level_keyboard_init(LevelKeyboard *self) {
|
||||
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);
|
||||
level_keyboard_init(keyboard);
|
||||
keyboard->view = view;
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
keyboard->views[i] = views[i];
|
||||
}
|
||||
keyboard->manager = manager;
|
||||
keyboard->names = name_key_hash;
|
||||
return keyboard;
|
||||
@ -507,49 +420,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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* @keyboard: an #EekKeyboard
|
||||
@ -568,36 +438,6 @@ level_keyboard_get_outline (LevelKeyboard *keyboard,
|
||||
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:
|
||||
* @keyboard: an #EekKeyboard
|
||||
@ -614,10 +454,11 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
|
||||
|
||||
/* Iterate over the keys in the name-to-key hash table. */
|
||||
GHashTableIter iter;
|
||||
gpointer key_name, key_ptr;
|
||||
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);
|
||||
@ -658,6 +499,5 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
|
||||
|
||||
EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard)
|
||||
{
|
||||
return keyboard->view;
|
||||
//return keyboard->views[keyboard->level];
|
||||
return keyboard->views[keyboard->level];
|
||||
}
|
||||
|
||||
@ -119,22 +119,27 @@ typedef struct _EekModifierKey EekModifierKey;
|
||||
|
||||
/// Keyboard state holder
|
||||
struct _LevelKeyboard {
|
||||
guint id;
|
||||
EekKeyboard *view;
|
||||
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;
|
||||
|
||||
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(EekLayout *layout,
|
||||
LevelKeyboard *eek_keyboard_new(EekboardContextService *manager,
|
||||
EekLayout *layout,
|
||||
gdouble initial_width,
|
||||
gdouble initial_height);
|
||||
GType eek_keyboard_get_type
|
||||
@ -148,17 +153,6 @@ 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);
|
||||
|
||||
@ -169,11 +163,6 @@ EekKey *eek_keyboard_find_key_by_name
|
||||
EekOutline *level_keyboard_get_outline
|
||||
(LevelKeyboard *keyboard,
|
||||
guint oref);
|
||||
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
|
||||
@ -186,7 +175,7 @@ gchar * eek_keyboard_get_keymap
|
||||
(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_free(LevelKeyboard *self);
|
||||
/* Create an #EekSection instance and append it to @keyboard. This
|
||||
|
||||
@ -51,6 +51,7 @@ const double section_spacing = 7.0;
|
||||
struct place_data {
|
||||
double desired_width;
|
||||
double current_offset;
|
||||
// Needed for outline (bounds) retrieval
|
||||
LevelKeyboard *keyboard;
|
||||
};
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ static GList *parse_prerequisites
|
||||
(const gchar *path,
|
||||
GError **error);
|
||||
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);
|
||||
static gboolean parse_symbols_with_prerequisites
|
||||
(const gchar *keyboards_dir,
|
||||
@ -233,7 +233,8 @@ struct _GeometryParseData {
|
||||
GSList *element_stack;
|
||||
|
||||
EekBounds bounds;
|
||||
EekKeyboard *keyboard;
|
||||
EekKeyboard **views;
|
||||
guint view_idx;
|
||||
EekSection *section;
|
||||
EekKey *key;
|
||||
gint num_columns;
|
||||
@ -255,11 +256,11 @@ struct _GeometryParseData {
|
||||
typedef struct _GeometryParseData 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);
|
||||
|
||||
data->keyboard = g_object_ref (keyboard);
|
||||
data->views = views;
|
||||
data->key_oref_hash =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
@ -280,7 +281,6 @@ geometry_parse_data_new (EekKeyboard *keyboard, GHashTable *name_key_hash)
|
||||
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_string_free (data->text, TRUE);
|
||||
@ -291,7 +291,8 @@ static const gchar *geometry_valid_path_list[] = {
|
||||
"geometry",
|
||||
"button/geometry",
|
||||
"bounds/geometry",
|
||||
"section/geometry",
|
||||
"view/geometry",
|
||||
"section/view/geometry",
|
||||
"outline/geometry",
|
||||
"point/outline/geometry",
|
||||
};
|
||||
@ -360,14 +361,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_real_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)
|
||||
@ -384,31 +391,37 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
|
||||
}
|
||||
|
||||
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");
|
||||
if (attribute == NULL) {
|
||||
if (base_name == NULL) {
|
||||
g_set_error (error,
|
||||
G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
|
||||
"no \"name\" attribute for \"button\"");
|
||||
return;
|
||||
}
|
||||
gchar *name = g_strdup (attribute);
|
||||
|
||||
EekKey *key = g_hash_table_lookup(data->name_key_hash, name);
|
||||
attribute = get_attribute (attribute_names, attribute_values,
|
||||
const gchar *oref_name = get_attribute (attribute_names, attribute_values,
|
||||
"oref");
|
||||
if (attribute == NULL) {
|
||||
attribute = g_strdup("default");
|
||||
if (oref_name == NULL) {
|
||||
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,
|
||||
key,
|
||||
g_strdup (attribute));
|
||||
g_strdup (oref_name));
|
||||
|
||||
attribute = get_attribute (attribute_names, attribute_values,
|
||||
"keycode");
|
||||
if (attribute != NULL) {
|
||||
eek_key_set_keycode(key, strtol (attribute, NULL, 10));
|
||||
if (keycode_name != NULL) {
|
||||
eek_key_set_keycode(key, strtol (keycode_name, NULL, 10));
|
||||
}
|
||||
}
|
||||
|
||||
goto out;
|
||||
@ -486,6 +499,11 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
|
||||
|
||||
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;
|
||||
@ -511,8 +529,11 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
|
||||
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++;
|
||||
|
||||
data->key = eek_section_create_key (data->section,
|
||||
@ -533,17 +554,6 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
|
||||
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);
|
||||
|
||||
@ -580,7 +590,7 @@ geometry_text_callback (GMarkupParseContext *pcontext,
|
||||
GError **error)
|
||||
{
|
||||
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 = {
|
||||
@ -597,7 +607,9 @@ struct _SymbolsParseData {
|
||||
|
||||
LevelKeyboard *keyboard;
|
||||
EekKeyboard *view;
|
||||
EekKey *key;
|
||||
guint key_level;
|
||||
const gchar *key_name;
|
||||
|
||||
gchar *label;
|
||||
gchar *icon;
|
||||
gchar *tooltip;
|
||||
@ -651,9 +663,10 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
|
||||
return;
|
||||
|
||||
if (g_strcmp0 (element_name, "key") == 0) {
|
||||
|
||||
data->key_level = 0;
|
||||
attribute = get_attribute (attribute_names, attribute_values,
|
||||
"name");
|
||||
|
||||
if (attribute == NULL) {
|
||||
g_set_error (error,
|
||||
G_MARKUP_ERROR,
|
||||
@ -661,15 +674,7 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
|
||||
"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);
|
||||
}
|
||||
data->key_name = strdup(attribute);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -727,17 +732,23 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
|
||||
|
||||
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 ||
|
||||
g_strcmp0 (element_name, "keysym") == 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(
|
||||
eek_key_get_state(data->key),
|
||||
eek_key_get_state(key),
|
||||
element_name,
|
||||
text,
|
||||
data->keyval,
|
||||
@ -753,6 +764,8 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
|
||||
data->icon = NULL;
|
||||
g_free(data->tooltip);
|
||||
data->tooltip = NULL;
|
||||
|
||||
data->key_level++;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -876,10 +889,6 @@ eek_xml_layout_real_create_keyboard (EekLayout *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 *view = g_object_new (EEK_TYPE_KEYBOARD, NULL);
|
||||
|
||||
/* Read geometry information. */
|
||||
gchar *filename = g_strdup_printf ("%s.xml", priv->desc->geometry);
|
||||
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));
|
||||
|
||||
// char* -> EekKey*
|
||||
GHashTable *name_key_hash =
|
||||
g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
NULL);
|
||||
; // char* -> EekKey*
|
||||
// One view for each level
|
||||
EekKeyboard *views[4] = {0};
|
||||
|
||||
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);
|
||||
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",
|
||||
priv->desc->geometry,
|
||||
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;
|
||||
// FIXME: are symbols shared betwen views?
|
||||
@ -920,7 +934,13 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
||||
&error);
|
||||
g_list_free_full (loaded, g_free);
|
||||
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",
|
||||
priv->desc->symbols,
|
||||
error->message);
|
||||
@ -928,7 +948,9 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eek_layout_place_sections(keyboard, view);
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
eek_layout_place_sections(keyboard, views[i]);
|
||||
}
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
@ -1136,7 +1158,7 @@ add_outline (GArray *outline_array,
|
||||
}
|
||||
|
||||
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;
|
||||
GMarkupParseContext *pcontext;
|
||||
@ -1156,7 +1178,7 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GArray *outline_array,
|
||||
if (input == NULL)
|
||||
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,
|
||||
0,
|
||||
data,
|
||||
|
||||
@ -323,8 +323,6 @@ settings_update_layout(EekboardContextService *context)
|
||||
// create a keyboard
|
||||
if (!keyboard) {
|
||||
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,
|
||||
GUINT_TO_POINTER(keyboard_id),
|
||||
|
||||
Reference in New Issue
Block a user