From bafd1e6eb318819140057890fae0414a15eb2390 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 8 Dec 2019 14:32:31 +0000 Subject: [PATCH 1/4] popover: Install emoji layout In order to do that, an additional piece of state (layout switcher) was exposed to the event handlers, a separation between squeekboard-only and system layouts was introduced, along with a Translation structure to prevent mixing up strings. --- data/keyboards/emoji.yaml | 15 +++ eek/eek-gtk-keyboard.c | 7 +- eekboard/eekboard-context-service.c | 27 +++-- src/layout.h | 4 +- src/layout.rs | 10 +- src/lib.rs | 1 + src/locale.rs | 3 + src/manager.rs | 18 ++++ src/popover.rs | 161 ++++++++++++++++++++++------ src/resources.rs | 32 +++++- tests/meson.build | 2 + 11 files changed, 234 insertions(+), 46 deletions(-) create mode 100644 data/keyboards/emoji.yaml create mode 100644 src/manager.rs diff --git a/data/keyboards/emoji.yaml b/data/keyboards/emoji.yaml new file mode 100644 index 00000000..b23ca960 --- /dev/null +++ b/data/keyboards/emoji.yaml @@ -0,0 +1,15 @@ +--- +outlines: + default: { width: 37.46341, height: 52 } + altline: { width: 48.39024, height: 52 } + +views: + base: + - "โ˜บ" + - "โ˜น" + - preferences +buttons: + preferences: + action: "show_prefs" + outline: "altline" + icon: "keyboard-mode-symbolic" diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 96d899b6..43aa8137 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -131,14 +131,17 @@ static void drag(EekGtkKeyboard *self, { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); squeek_layout_drag(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, - x, y, eek_renderer_get_transformation(priv->renderer), time, self); + x, y, eek_renderer_get_transformation(priv->renderer), time, + priv->keyboard->manager, self); } static void release(EekGtkKeyboard *self, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, eek_renderer_get_transformation(priv->renderer), time, self); + squeek_layout_release(priv->keyboard->layout, priv->keyboard->manager->virtual_keyboard, + eek_renderer_get_transformation(priv->renderer), time, + priv->keyboard->manager, self); } static gboolean diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index 1ae28c8a..5dd2a6cd 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -71,6 +71,8 @@ struct _EekboardContextServicePrivate { LevelKeyboard *keyboard; // currently used keyboard GHashTable *keyboard_hash; // a table of available keyboards, per layout + char *overlay; + GSettings *settings; uint32_t hint; uint32_t purpose; @@ -214,15 +216,17 @@ settings_get_layout(GSettings *settings, char **type, char **layout) void eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t) { - g_autofree gchar *keyboard_type = NULL; g_autofree gchar *keyboard_layout = NULL; - settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout); - - if (!keyboard_type) { - keyboard_type = g_strdup("us"); + if (context->priv->overlay) { + keyboard_layout = g_strdup(context->priv->overlay); + } else { + g_autofree gchar *keyboard_type = NULL; + settings_get_layout(context->priv->settings, + &keyboard_type, &keyboard_layout); } + if (!keyboard_layout) { - keyboard_layout = g_strdup("undefined"); + keyboard_layout = g_strdup("us"); } EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context); @@ -262,6 +266,8 @@ settings_handle_layout_changed(GSettings *s, (void)keys; (void)n_keys; EekboardContextService *context = user_data; + free(context->priv->overlay); + context->priv->overlay = NULL; update_layout_and_type(context); return TRUE; } @@ -391,6 +397,8 @@ eekboard_context_service_init (EekboardContextService *self) g_warning ("Could not connect to gsettings updates, layout" " changing unavailable"); } + + self->priv->overlay = NULL; } /** @@ -463,6 +471,7 @@ eekboard_context_service_destroy (EekboardContextService *context) if (context->priv->enabled) { eekboard_context_service_disable (context); } + free(context->priv->overlay); g_signal_emit (context, signals[DESTROYED], 0); } @@ -498,3 +507,9 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context, update_layout_and_type(context); } } + +void +eekboard_context_service_set_overlay(EekboardContextService *context, const char* name) { + context->priv->overlay = strdup(name); + update_layout_and_type(context); +} diff --git a/src/layout.h b/src/layout.h index 6754ef1a..9f1a4a71 100644 --- a/src/layout.h +++ b/src/layout.h @@ -36,6 +36,7 @@ void squeek_layout_free(struct squeek_layout*); void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, struct transformation widget_to_layout, uint32_t timestamp, + EekboardContextService *manager, EekGtkKeyboard *ui_keyboard); void squeek_layout_release_all_only(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp); void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, @@ -45,7 +46,8 @@ void squeek_layout_depress(struct squeek_layout *layout, struct zwp_virtual_keyb void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, double x_widget, double y_widget, struct transformation widget_to_layout, - uint32_t timestamp, EekGtkKeyboard *ui_keyboard); + uint32_t timestamp, EekboardContextService *manager, + EekGtkKeyboard *ui_keyboard); void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr); void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr); #endif diff --git a/src/layout.rs b/src/layout.rs index 950b2349..87a4f217 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -26,6 +26,7 @@ use std::vec::Vec; use ::action::Action; use ::drawing; use ::keyboard::{ KeyState, PressType }; +use ::manager; use ::submission::{ Timestamp, VirtualKeyboard }; use ::util::find_max_double; @@ -258,6 +259,7 @@ pub mod c { virtual_keyboard: ZwpVirtualKeyboardV1, // TODO: receive a reference to the backend widget_to_layout: Transformation, time: u32, + manager: manager::c::Manager, ui_keyboard: EekGtkKeyboard, ) { let time = Timestamp(time); @@ -273,6 +275,7 @@ pub mod c { &widget_to_layout, time, ui_keyboard, + manager, key, ); } @@ -344,6 +347,7 @@ pub mod c { x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, + manager: manager::c::Manager, ui_keyboard: EekGtkKeyboard, ) { let time = Timestamp(time); @@ -378,6 +382,7 @@ pub mod c { &widget_to_layout, time, ui_keyboard, + manager, key, ); } @@ -395,6 +400,7 @@ pub mod c { &widget_to_layout, time, ui_keyboard, + manager, key, ); } @@ -853,6 +859,7 @@ mod seat { widget_to_layout: &c::Transformation, time: Timestamp, ui_keyboard: c::EekGtkKeyboard, + manager: manager::c::Manager, key: &Rc>, ) { layout.release_key(virtual_keyboard, &mut key.clone(), time); @@ -874,7 +881,8 @@ mod seat { }; ::popover::show( ui_keyboard, - widget_to_layout.reverse_bounds(bounds) + widget_to_layout.reverse_bounds(bounds), + manager, ); } } diff --git a/src/lib.rs b/src/lib.rs index 5679656c..7f422c6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ mod layout; mod locale; mod locale_config; mod logging; +mod manager; mod outputs; mod popover; mod resources; diff --git a/src/locale.rs b/src/locale.rs index 8333a24d..4368fc15 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -16,6 +16,9 @@ mod c { } } +#[derive(Clone, Debug, PartialEq)] +pub struct Translation<'a>(pub &'a str); + fn cstring_safe(s: &str) -> CString { CString::new(s) .unwrap_or(CString::new("").unwrap()) diff --git a/src/manager.rs b/src/manager.rs new file mode 100644 index 00000000..3843cc25 --- /dev/null +++ b/src/manager.rs @@ -0,0 +1,18 @@ +/*! Procedures relating to the management of the switching of layouts */ + +pub mod c { + use std::os::raw::{c_char, c_void}; + + /// EekboardContextService* + #[repr(transparent)] + #[derive(Clone, Copy)] + pub struct Manager(*const c_void); + + #[no_mangle] + extern "C" { + pub fn eekboard_context_service_set_overlay( + manager: Manager, + name: *const c_char, + ); + } +} diff --git a/src/popover.rs b/src/popover.rs index d2754036..70d53ff1 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -2,9 +2,11 @@ use gio; use gtk; -use ::layout::c::EekGtkKeyboard; -use ::locale::compare_current_locale; +use std::ffi::CString; +use ::layout::c::{ Bounds, EekGtkKeyboard }; +use ::locale::{ Translation, compare_current_locale }; use ::locale_config::system_locale; +use ::manager; use ::resources; use gio::ActionMapExt; @@ -92,7 +94,7 @@ mod variants { } } -fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder { +fn make_menu_builder(inputs: Vec<(&str, Translation)>) -> gtk::Builder { let mut xml: Vec = Vec::new(); writeln!( xml, @@ -101,7 +103,7 @@ fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder {
" ).unwrap(); - for (input_name, human_name) in inputs { + for (input_name, translation) in inputs { writeln!( xml, " @@ -110,7 +112,7 @@ fn make_menu_builder(inputs: Vec<(&str, &str)>) -> gtk::Builder { layout {} ", - human_name, + translation.0, input_name, ).unwrap(); } @@ -141,16 +143,68 @@ fn set_layout(kind: String, name: String) { settings.apply(); } -pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) { +/// A reference to what the user wants to see +#[derive(PartialEq, Clone, Debug)] +enum LayoutId { + /// Affects the layout in system settings + System { + kind: String, + name: String, + }, + /// Only affects what this input method presents + Local(&'static str), +} + +impl LayoutId { + fn get_name(&self) -> &str { + match &self { + LayoutId::System { kind: _, name } => name.as_str(), + LayoutId::Local(name) => name, + } + } +} + +fn set_visible_layout( + manager: manager::c::Manager, + layout_id: LayoutId, +) { + match layout_id { + LayoutId::System { kind, name } => set_layout(kind, name), + LayoutId::Local(name) => { + let name = CString::new(name).unwrap(); + let name_ptr = name.as_ptr(); + unsafe { + manager::c::eekboard_context_service_set_overlay( + manager, + name_ptr, + ) + } + }, + } +} + +pub fn show( + window: EekGtkKeyboard, + position: Bounds, + manager: manager::c::Manager, +) { unsafe { gtk::set_initialized() }; let window = unsafe { gtk::Widget::from_glib_none(window.0) }; + let overlay_layouts = resources::get_overlays().into_iter() + .map(|name| LayoutId::Local(name)); + let settings = gio::Settings::new("org.gnome.desktop.input-sources"); let inputs = settings.get_value("sources").unwrap(); let inputs = variants::get_tuples(inputs); - let input_names: Vec<&str> = inputs.iter() - .map(|(_kind, name)| name.as_str()) + let system_layouts: Vec = inputs.into_iter() + .map(|(kind, name)| LayoutId::System { kind, name }) + .collect(); + + let all_layouts: Vec = system_layouts.clone() + .into_iter() + .chain(overlay_layouts) .collect(); let translations = system_locale() @@ -162,26 +216,56 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) { ) .and_then(|lang| resources::get_layout_names(lang.as_str())); - // sorted collection of human and machine names - let mut human_names: Vec<(&str, &str)> = match translations { - Some(translations) => { - input_names.iter() - .map(|name| (*name, *translations.get(name).unwrap_or(name))) - .collect() - }, - // display bare codes - None => { - input_names.iter() - .map(|n| (*n, *n)) // turns &&str into &str - .collect() - } - }; + let use_codes: Box Translation> + = Box::new(|name| Translation(name)); - human_names.sort_unstable_by(|(_, human_label_a), (_, human_label_b)| { - compare_current_locale(human_label_a, human_label_b) + let translated_names = all_layouts.iter() + .map(LayoutId::get_name) + // use a different closure depending on whether we have translations + .map(match translations { + Some(translations) => { + let use_translations: Box Translation> + = Box::new(move |name| { + translations.get(name) + .map(|translation| translation.clone()) + .unwrap_or(Translation(name)) + }); + use_translations + }, + None => use_codes, + }); + + // sorted collection of human and machine names + let mut human_names: Vec<(Translation, LayoutId)> = translated_names + .zip(all_layouts.clone().into_iter()) + .collect(); + + human_names.sort_unstable_by(|(tr_a, _), (tr_b, _)| { + compare_current_locale(tr_a.0, tr_b.0) }); - let builder = make_menu_builder(human_names); + // GVariant doesn't natively support `enum`s, + // so the `choices` vector will serve as a lookup table. + let choices_with_translations: Vec<(String, (Translation, LayoutId))> + = human_names.into_iter() + .enumerate() + .map(|(i, human_entry)| {( + format!("{}_{}", i, human_entry.1.get_name()), + human_entry, + )}).collect(); + + + let builder = make_menu_builder( + choices_with_translations.iter() + .map(|(id, (translation, _))| (id.as_str(), translation.clone())) + .collect() + ); + + let choices: Vec<(String, LayoutId)> + = choices_with_translations.into_iter() + .map(|(id, (_tr, layout))| (id, layout)) + .collect(); + // Much more debuggable to populate the model & menu // from a string representation // than add items imperatively @@ -195,16 +279,21 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) { height: position.width.floor() as i32, }); - if let Some(current_name) = input_names.get(0) { - let current_name = current_name.to_variant(); + if let Some(current_layout) = system_layouts.get(0) { + let current_name_variant = choices.iter() + .find( + |(_id, layout)| layout == current_layout + ).unwrap() + .0.to_variant(); let layout_action = gio::SimpleAction::new_stateful( "layout", - Some(current_name.type_()), - ¤t_name, + Some(current_name_variant.type_()), + ¤t_name_variant, ); - layout_action.connect_change_state(|_action, state| { + let menu_inner = menu.clone(); + layout_action.connect_change_state(move |_action, state| { match state { Some(v) => { v.get::() @@ -212,10 +301,20 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) { eprintln!("Variant is not string: {:?}", v); None }) - .map(|state| set_layout("xkb".into(), state)); + .map(|state| { + let (_id, layout) = choices.iter() + .find( + |choices| state == choices.0 + ).unwrap(); + set_visible_layout( + manager, + layout.clone(), + ) + }); }, None => eprintln!("No variant selected"), }; + menu_inner.popdown(); }); let action_group = gio::SimpleActionGroup::new(); diff --git a/src/resources.rs b/src/resources.rs index f49a3d38..751c6ee7 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -3,6 +3,7 @@ */ use std::collections::HashMap; +use ::locale::Translation; use std::iter::FromIterator; @@ -23,6 +24,8 @@ const KEYBOARDS: &[(*const str, *const str)] = &[ ("no", include_str!("../data/keyboards/no.yaml")), ("number", include_str!("../data/keyboards/number.yaml")), ("se", include_str!("../data/keyboards/se.yaml")), + // Overlays + ("emoji", include_str!("../data/keyboards/emoji.yaml")), ]; pub fn get_keyboard(needle: &str) -> Option<&'static str> { @@ -39,6 +42,18 @@ pub fn get_keyboard(needle: &str) -> Option<&'static str> { }) } +const OVERLAY_NAMES: &[*const str] = &[ + "emoji" +]; + +pub fn get_overlays() -> Vec<&'static str> { + OVERLAY_NAMES.iter() + .map(|name| { + let name: *const str = *name; + unsafe { &*name } + }).collect() +} + /// Translations of the layout identifier strings const LAYOUT_NAMES: &[(*const str, *const str)] = &[ ("de-DE", include_str!("../data/langs/de-DE.txt")), @@ -49,7 +64,7 @@ const LAYOUT_NAMES: &[(*const str, *const str)] = &[ ]; pub fn get_layout_names(lang: &str) - -> Option> + -> Option>> { let translations = LAYOUT_NAMES.iter() .find(|(name, _data)| { @@ -63,7 +78,7 @@ pub fn get_layout_names(lang: &str) translations.map(make_mapping) } -fn parse_line(line: &str) -> Option<(&str, &str)> { +fn parse_line(line: &str) -> Option<(&str, Translation)> { let comment = line.trim().starts_with("#"); if comment { None @@ -71,11 +86,11 @@ fn parse_line(line: &str) -> Option<(&str, &str)> { let mut iter = line.splitn(2, " "); let name = iter.next().unwrap(); // will skip empty and unfinished lines - iter.next().map(|tr| (name, tr.trim())) + iter.next().map(|tr| (name, Translation(tr.trim()))) } } -fn make_mapping(data: &str) -> HashMap<&str, &str> { +fn make_mapping(data: &str) -> HashMap<&str, Translation> { HashMap::from_iter( data.split("\n") .filter_map(parse_line) @@ -86,10 +101,17 @@ fn make_mapping(data: &str) -> HashMap<&str, &str> { mod test { use super::*; + #[test] + fn check_overlays_present() { + for name in get_overlays() { + assert!(get_keyboard(name).is_some()); + } + } + #[test] fn mapping_line() { assert_eq!( - Some(("name", "translation")), + Some(("name", Translation("translation"))), parse_line("name translation") ); } diff --git a/tests/meson.build b/tests/meson.build index a0bd391c..205f2e9b 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -58,6 +58,8 @@ foreach layout : [ 'no', 'number', 'se', + + 'emoji', ] test( 'test_layout_' + layout, From 01a8afad0d28a88d5b0843496b13629a2042da88 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 8 Dec 2019 18:15:09 +0000 Subject: [PATCH 2/4] popover: Show overlays as selected --- eekboard/eekboard-context-service.c | 5 +++++ src/manager.rs | 16 ++++++++++++++++ src/popover.rs | 23 +++++++++++++++++------ src/util.rs | 1 + 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index 5dd2a6cd..962be75a 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -513,3 +513,8 @@ eekboard_context_service_set_overlay(EekboardContextService *context, const char context->priv->overlay = strdup(name); update_layout_and_type(context); } + +const char* +eekboard_context_service_get_overlay(EekboardContextService *context) { + return context->priv->overlay; +} diff --git a/src/manager.rs b/src/manager.rs index 3843cc25..42d1ce26 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -1,4 +1,5 @@ /*! Procedures relating to the management of the switching of layouts */ +use ::util; pub mod c { use std::os::raw::{c_char, c_void}; @@ -14,5 +15,20 @@ pub mod c { manager: Manager, name: *const c_char, ); + + pub fn eekboard_context_service_get_overlay( + manager: Manager, + ) -> *const c_char; } } + +/// Returns the overlay name. +/// The result lifetime is "as long as the C copy lives" +pub fn get_overlay(manager: c::Manager) -> Option { + let raw_str = unsafe { + c::eekboard_context_service_get_overlay(manager) + }; + // this string is generated from Rust, should never be invalid + util::c::as_str(&raw_str).unwrap() + .map(String::from) +} diff --git a/src/popover.rs b/src/popover.rs index 70d53ff1..4f0f20ab 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -152,14 +152,14 @@ enum LayoutId { name: String, }, /// Only affects what this input method presents - Local(&'static str), + Local(String), } impl LayoutId { fn get_name(&self) -> &str { match &self { LayoutId::System { kind: _, name } => name.as_str(), - LayoutId::Local(name) => name, + LayoutId::Local(name) => name.as_str(), } } } @@ -171,7 +171,7 @@ fn set_visible_layout( match layout_id { LayoutId::System { kind, name } => set_layout(kind, name), LayoutId::Local(name) => { - let name = CString::new(name).unwrap(); + let name = CString::new(name.as_str()).unwrap(); let name_ptr = name.as_ptr(); unsafe { manager::c::eekboard_context_service_set_overlay( @@ -183,6 +183,17 @@ fn set_visible_layout( } } +/// Takes into account first any overlays, then system layouts from the list +fn get_current_layout( + manager: manager::c::Manager, + system_layouts: &Vec, +) -> Option { + match manager::get_overlay(manager) { + Some(name) => Some(LayoutId::Local(name)), + None => system_layouts.get(0).map(LayoutId::clone), + } +} + pub fn show( window: EekGtkKeyboard, position: Bounds, @@ -192,7 +203,7 @@ pub fn show( let window = unsafe { gtk::Widget::from_glib_none(window.0) }; let overlay_layouts = resources::get_overlays().into_iter() - .map(|name| LayoutId::Local(name)); + .map(|name| LayoutId::Local(name.to_string())); let settings = gio::Settings::new("org.gnome.desktop.input-sources"); let inputs = settings.get_value("sources").unwrap(); @@ -279,10 +290,10 @@ pub fn show( height: position.width.floor() as i32, }); - if let Some(current_layout) = system_layouts.get(0) { + if let Some(current_layout) = get_current_layout(manager, &system_layouts) { let current_name_variant = choices.iter() .find( - |(_id, layout)| layout == current_layout + |(_id, layout)| layout == ¤t_layout ).unwrap() .0.to_variant(); diff --git a/src/util.rs b/src/util.rs index 1553fd19..55a4373f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -21,6 +21,7 @@ pub mod c { use std::borrow::ToOwned; + // The lifetime on input limits the existence of the result pub fn as_str(s: &*const c_char) -> Result, Utf8Error> { if s.is_null() { Ok(None) From 733cbe94eeda3f714ec501d8b778746ac3351596 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 8 Dec 2019 18:39:02 +0000 Subject: [PATCH 3/4] Fix old Rust woes --- src/popover.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/popover.rs b/src/popover.rs index 4f0f20ab..2319fc6d 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -227,27 +227,27 @@ pub fn show( ) .and_then(|lang| resources::get_layout_names(lang.as_str())); - let use_codes: Box Translation> - = Box::new(|name| Translation(name)); - let translated_names = all_layouts.iter() - .map(LayoutId::get_name) - // use a different closure depending on whether we have translations - .map(match translations { - Some(translations) => { - let use_translations: Box Translation> - = Box::new(move |name| { - translations.get(name) - .map(|translation| translation.clone()) - .unwrap_or(Translation(name)) - }); - use_translations - }, - None => use_codes, - }); + .map(LayoutId::get_name); + let translated_names: Vec = match translations { + Some(translations) => { + translated_names + .map(move |name| { + translations.get(name) + .map(|translation| translation.clone()) + .unwrap_or(Translation(name)) + }) + .collect() + }, + None => { + translated_names.map(|name| Translation(name)) + .collect() + }, + }; // sorted collection of human and machine names let mut human_names: Vec<(Translation, LayoutId)> = translated_names + .into_iter() .zip(all_layouts.clone().into_iter()) .collect(); From 50dab14754a6dd826c3352ca3db381984cd3ee90 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Mon, 23 Dec 2019 21:41:13 +0000 Subject: [PATCH 4/4] emoji: Add a passable layout --- data/keyboards/emoji.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data/keyboards/emoji.yaml b/data/keyboards/emoji.yaml index b23ca960..eecce00b 100644 --- a/data/keyboards/emoji.yaml +++ b/data/keyboards/emoji.yaml @@ -1,13 +1,14 @@ --- outlines: - default: { width: 37.46341, height: 52 } - altline: { width: 48.39024, height: 52 } + default: { width: 52, height: 52 } + altline: { width: 52, height: 52 } views: base: - - "โ˜บ" - - "โ˜น" - - preferences + - "๐Ÿ˜€ ๐Ÿ˜ ๐Ÿ˜… ๐Ÿ˜‚ ๐Ÿ˜Š ๐Ÿ˜‡ ๐Ÿ™ƒ" + - "๐Ÿ˜ ๐Ÿ˜˜ ๐Ÿ˜‹ ๐Ÿ˜œ ๐Ÿ˜Ž ๐Ÿฅณ ๐Ÿ˜”" + - "๐Ÿ˜ข ๐Ÿ˜ญ ๐Ÿ˜ก ๐Ÿ˜ฑ ๐Ÿค” ๐Ÿ˜ฌ ๐Ÿ™„" + - "preferences ๐Ÿคจ ๐Ÿค“ ๐Ÿ˜ด ๐Ÿคข ๐Ÿคฎ ๐Ÿ˜ˆ" buttons: preferences: action: "show_prefs"