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)