Merge branch 'make-layout-more-flexible' into 'master'
Make layout handling more flexible See merge request Librem5/squeekboard!85
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
119
eek/eek-layout.c
119
eek/eek-layout.c
@ -67,3 +67,122 @@ 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -55,5 +55,11 @@ struct _EekLayoutClass
|
||||
|
||||
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 */
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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. */
|
||||
@ -1136,38 +1138,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 gboolean
|
||||
parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
|
||||
{
|
||||
@ -1222,27 +1192,6 @@ 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);
|
||||
|
||||
geometry_parse_data_free (data);
|
||||
return TRUE;
|
||||
}
|
||||
@ -1408,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);
|
||||
|
||||
@ -1453,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
|
||||
|
||||
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user