From 7b41466a77401c339fa9847f5e112c1f6028d99a Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 18 Jul 2019 16:18:00 +0200 Subject: [PATCH 1/3] Start to refactor keyboard section layout --- eek/eek-xml-layout.c | 46 +++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index 7c28b056..6159789c 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -1162,12 +1162,37 @@ static void section_placer(EekElement *element, gpointer user_data) { } static void section_counter(EekElement *element, gpointer user_data) { + double *total_height = user_data; EekBounds section_bounds = {0}; eek_element_get_bounds(element, §ion_bounds); *total_height += section_bounds.height + section_spacing; } +static void place_sections(EekKeyboard *keyboard) +{ + /* Order rows */ + // This needs to be done after outlines, because outlines define key sizes + // TODO: do this only for rows without bounds + + // 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); + + 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); + + double total_height = 0; + eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height); + keyboard_bounds.height = total_height; + eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds); +} + static gboolean parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error) { @@ -1222,26 +1247,7 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error) } g_hash_table_destroy (oref_hash); - /* Order rows */ - // This needs to be done after outlines, because outlines define key sizes - // TODO: do this only for rows without bounds - - // 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); - - 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); - - double total_height = 0; - eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height); - keyboard_bounds.height = total_height; - eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds); + place_sections(keyboard); geometry_parse_data_free (data); return TRUE; From f6d4ca0387d57a6796daef407ca14348fbfbce28 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 18 Jul 2019 17:45:51 +0200 Subject: [PATCH 2/3] Place keys after symbols have been read, skipping blank keys --- eek/eek-layout.c | 61 +++++++++++++++++++++++++++++++++++++++++++ eek/eek-layout.h | 2 ++ eek/eek-section.c | 44 ++++++++++++++++++++++++------- eek/eek-xml-layout.c | 62 +++----------------------------------------- 4 files changed, 100 insertions(+), 69 deletions(-) diff --git a/eek/eek-layout.c b/eek/eek-layout.c index fe1ce293..457883df 100644 --- a/eek/eek-layout.c +++ b/eek/eek-layout.c @@ -67,3 +67,64 @@ eek_keyboard_new (EekboardContextService *manager, initial_width, initial_height); } + +const double section_spacing = 7.0; + +struct place_data { + double desired_width; + double current_offset; + EekKeyboard *keyboard; +}; + +static void +section_placer(EekElement *element, gpointer user_data) +{ + struct place_data *data = (struct place_data*)user_data; + + EekBounds section_bounds = {0}; + eek_element_get_bounds(element, §ion_bounds); + section_bounds.width = data->desired_width; + 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_element_get_bounds(element, §ion_bounds); + section_bounds.y = data->current_offset; + eek_element_set_bounds(element, §ion_bounds); + data->current_offset += section_bounds.height + section_spacing; +} + +static void +section_counter(EekElement *element, gpointer user_data) { + + double *total_height = user_data; + EekBounds section_bounds = {0}; + eek_element_get_bounds(element, §ion_bounds); + *total_height += section_bounds.height + section_spacing; +} + +void +eek_layout_place_sections(EekKeyboard *keyboard) +{ + /* Order rows */ + // This needs to be done after outlines, because outlines define key sizes + // TODO: do this only for rows without bounds + + // 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); + + 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); + + double total_height = 0; + eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height); + keyboard_bounds.height = total_height; + eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds); +} diff --git a/eek/eek-layout.h b/eek/eek-layout.h index 308e0aae..830ef4f2 100644 --- a/eek/eek-layout.h +++ b/eek/eek-layout.h @@ -55,5 +55,7 @@ struct _EekLayoutClass GType eek_layout_get_type (void) G_GNUC_CONST; +void eek_layout_place_sections(EekKeyboard *keyboard); + G_END_DECLS #endif /* EEK_LAYOUT_H */ diff --git a/eek/eek-section.c b/eek/eek-section.c index 400dbb25..1dcfb13b 100644 --- a/eek/eek-section.c +++ b/eek/eek-section.c @@ -482,8 +482,23 @@ eek_section_create_key (EekSection *section, row); } -static void keysizer(EekElement *element, gpointer user_data) { +const double keyspacing = 4.0; + +struct keys_info { + uint count; + double total_width; + double biggest_height; +}; + +static void +keysizer(EekElement *element, gpointer user_data) +{ EekKey *key = EEK_KEY(element); + + /* Skip keys without symbols for the current level. */ + if (!eek_key_get_symbol(key)) + return; + EekKeyboard *keyboard = EEK_KEYBOARD(user_data); uint oref = eek_key_get_oref (key); EekOutline *outline = eek_keyboard_get_outline (keyboard, oref); @@ -514,13 +529,15 @@ static void keysizer(EekElement *element, gpointer user_data) { } } -struct keys_info { - uint count; - double total_width; - double biggest_height; -}; +static void +keycounter (EekElement *element, gpointer user_data) +{ + EekKey *key = EEK_KEY(element); + + /* Skip keys without symbols for the current level. */ + if (!eek_key_get_symbol(key)) + return; -static void keycounter (EekElement *element, gpointer user_data) { struct keys_info *data = user_data; data->count++; EekBounds key_bounds = {0}; @@ -531,9 +548,15 @@ static void keycounter (EekElement *element, gpointer user_data) { } } -const double keyspacing = 4.0; +static void +keyplacer(EekElement *element, gpointer user_data) +{ + EekKey *key = EEK_KEY(element); + + /* Skip keys without symbols for the current level. */ + if (!eek_key_get_symbol(key)) + return; -static void keyplacer(EekElement *element, gpointer user_data) { double *current_offset = user_data; EekBounds key_bounds = {0}; eek_element_get_bounds(element, &key_bounds); @@ -543,7 +566,8 @@ static void keyplacer(EekElement *element, gpointer user_data) { *current_offset += key_bounds.width + keyspacing; } -void eek_section_place_keys(EekSection *section, EekKeyboard *keyboard) +void +eek_section_place_keys(EekSection *section, EekKeyboard *keyboard) { eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard); diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index 6159789c..d8332c42 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -1136,63 +1136,6 @@ eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc) g_slice_free (EekXmlKeyboardDesc, desc); } -struct place_data { - double desired_width; - double current_offset; - EekKeyboard *keyboard; -}; - -const double section_spacing = 7.0; - -static void section_placer(EekElement *element, gpointer user_data) { - struct place_data *data = (struct place_data*)user_data; - - EekBounds section_bounds = {0}; - eek_element_get_bounds(element, §ion_bounds); - section_bounds.width = data->desired_width; - 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_element_get_bounds(element, §ion_bounds); - section_bounds.y = data->current_offset; - eek_element_set_bounds(element, §ion_bounds); - data->current_offset += section_bounds.height + section_spacing; -} - -static void section_counter(EekElement *element, gpointer user_data) { - - double *total_height = user_data; - EekBounds section_bounds = {0}; - eek_element_get_bounds(element, §ion_bounds); - *total_height += section_bounds.height + section_spacing; -} - -static void place_sections(EekKeyboard *keyboard) -{ - /* Order rows */ - // This needs to be done after outlines, because outlines define key sizes - // TODO: do this only for rows without bounds - - // 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); - - 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); - - double total_height = 0; - eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height); - keyboard_bounds.height = total_height; - eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds); -} - static gboolean parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error) { @@ -1247,8 +1190,6 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error) } g_hash_table_destroy (oref_hash); - place_sections(keyboard); - geometry_parse_data_free (data); return TRUE; } @@ -1336,6 +1277,9 @@ parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error) return FALSE; } symbols_parse_data_free (data); + + eek_layout_place_sections(keyboard); + return TRUE; } From 6eb63f6a4c0614fa58e1bfad45e2adb527d6ee33 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 18 Jul 2019 18:35:04 +0200 Subject: [PATCH 3/3] Refactor layout code, rescale and reformat when changing level --- eek/eek-keyboard.c | 3 ++ eek/eek-keyboard.h | 1 + eek/eek-layout.c | 58 +++++++++++++++++++++++++++++ eek/eek-layout.h | 4 ++ eek/eek-xml-layout.c | 51 ++----------------------- eekboard/eekboard-context-service.c | 3 +- 6 files changed, 72 insertions(+), 48 deletions(-) diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 5bbc4f28..cded9354 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -262,6 +262,8 @@ set_level_from_modifiers (EekKeyboard *self, EekKey *key) priv->old_level = level; eek_element_set_level (EEK_ELEMENT(self), level); + + eek_layout_update_layout(self); } static void @@ -528,6 +530,7 @@ eek_keyboard_init (EekKeyboard *self) self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); self->priv->keycodes = g_hash_table_new (g_direct_hash, g_direct_equal); eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0); + self->scale = 1.0; } /** diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index afe72c27..38e277b9 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -62,6 +62,7 @@ struct _EekKeyboard 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 }; diff --git a/eek/eek-layout.c b/eek/eek-layout.c index 457883df..ba36637e 100644 --- a/eek/eek-layout.c +++ b/eek/eek-layout.c @@ -128,3 +128,61 @@ eek_layout_place_sections(EekKeyboard *keyboard) keyboard_bounds.height = total_height; eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds); } + +static void scale_bounds_callback (EekElement *element, + gpointer user_data); + +static void +scale_bounds (EekElement *element, + gdouble scale) +{ + EekBounds bounds; + + eek_element_get_bounds (element, &bounds); + bounds.x *= scale; + bounds.y *= scale; + bounds.width *= scale; + bounds.height *= scale; + eek_element_set_bounds (element, &bounds); + + if (EEK_IS_CONTAINER(element)) + eek_container_foreach_child (EEK_CONTAINER(element), + scale_bounds_callback, + &scale); +} + +static void +scale_bounds_callback (EekElement *element, + gpointer user_data) +{ + scale_bounds (element, *(gdouble *)user_data); +} + +void +eek_layout_scale_keyboard(EekKeyboard *keyboard, gdouble scale) +{ + gsize n_outlines; + + scale_bounds (EEK_ELEMENT(keyboard), scale); + + n_outlines = eek_keyboard_get_n_outlines (keyboard); + for (guint i = 0; i < n_outlines; i++) { + EekOutline *outline = eek_keyboard_get_outline (keyboard, i); + gint j; + + for (j = 0; j < outline->num_points; j++) { + outline->points[j].x *= scale; + outline->points[j].y *= scale; + } + } + + keyboard->scale = scale; +} + +void +eek_layout_update_layout(EekKeyboard *keyboard) +{ + eek_layout_scale_keyboard(keyboard, 1.0 / keyboard->scale); + eek_layout_place_sections(keyboard); + eek_layout_scale_keyboard(keyboard, 1.0 / keyboard->scale); +} diff --git a/eek/eek-layout.h b/eek/eek-layout.h index 830ef4f2..c93046a2 100644 --- a/eek/eek-layout.h +++ b/eek/eek-layout.h @@ -57,5 +57,9 @@ GType eek_layout_get_type (void) G_GNUC_CONST; void eek_layout_place_sections(EekKeyboard *keyboard); +void eek_layout_scale_keyboard(EekKeyboard *keyboard, gdouble scale); + +void eek_layout_update_layout(EekKeyboard *keyboard); + G_END_DECLS #endif /* EEK_LAYOUT_H */ diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index d8332c42..aa41a7d8 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -943,7 +943,9 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager, return NULL; } - /* Fit keyboard in the given width and hight. */ + eek_layout_place_sections(keyboard); + + /* Fit keyboard in the given width and height. */ scale_keyboard (keyboard, initial_width, initial_height); /* Use pre-defined modifier mask here. */ @@ -1277,9 +1279,6 @@ parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error) return FALSE; } symbols_parse_data_free (data); - - eek_layout_place_sections(keyboard); - return TRUE; } @@ -1358,43 +1357,12 @@ parse_keyboards (const gchar *path, GError **error) return keyboards; } -static void scale_bounds_callback (EekElement *element, - gpointer user_data); - -static void -scale_bounds (EekElement *element, - gdouble scale) -{ - EekBounds bounds; - - eek_element_get_bounds (element, &bounds); - bounds.x *= scale; - bounds.y *= scale; - bounds.width *= scale; - bounds.height *= scale; - eek_element_set_bounds (element, &bounds); - - if (EEK_IS_CONTAINER(element)) - eek_container_foreach_child (EEK_CONTAINER(element), - scale_bounds_callback, - &scale); -} - -static void -scale_bounds_callback (EekElement *element, - gpointer user_data) -{ - scale_bounds (element, *(gdouble *)user_data); -} - static void scale_keyboard (EekKeyboard *keyboard, gdouble width, gdouble height) { gdouble scale; EekBounds bounds; - gsize n_outlines; - guint i; eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds); @@ -1403,18 +1371,7 @@ static void scale_keyboard (EekKeyboard *keyboard, else scale = height / bounds.height; - scale_bounds (EEK_ELEMENT(keyboard), scale); - - n_outlines = eek_keyboard_get_n_outlines (keyboard); - for (i = 0; i < n_outlines; i++) { - EekOutline *outline = eek_keyboard_get_outline (keyboard, i); - gint j; - - for (j = 0; j < outline->num_points; j++) { - outline->points[j].x *= scale; - outline->points[j].y *= scale; - } - } + eek_layout_scale_keyboard(keyboard, scale); } static gboolean diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index 94abf292..9869676e 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -282,7 +282,8 @@ settings_get_layout(GSettings *settings, char **type, char **layout) } static void -settings_update_layout(EekboardContextService *context) { +settings_update_layout(EekboardContextService *context) +{ g_autofree gchar *keyboard_type = NULL; g_autofree gchar *keyboard_layout = NULL; settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);