diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 2d8aa42f..68129885 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -38,7 +38,7 @@ typedef struct _EekRendererPrivate LevelKeyboard *keyboard; PangoContext *pcontext; GtkCssProvider *css_provider; - GtkStyleContext *layout_context; + GtkStyleContext *view_context; GtkStyleContext *button_context; // TODO: maybe move a copy to each button gdouble border_width; @@ -131,7 +131,7 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); EekColor foreground; - eek_renderer_get_foreground_color (priv->layout_context, &foreground); + eek_renderer_get_foreground_color (priv->view_context, &foreground); EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard)); @@ -142,11 +142,11 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) }; /* Paint the background covering the entire widget area */ - gtk_render_background (priv->layout_context, + gtk_render_background (priv->view_context, data.cr, 0, 0, priv->allocation_width, priv->allocation_height); - gtk_render_frame (priv->layout_context, + gtk_render_frame (priv->view_context, data.cr, 0, 0, priv->allocation_width, priv->allocation_height); @@ -500,7 +500,7 @@ eek_renderer_set_property (GObject *object, GParamSpec *pspec) { EekRendererPrivate *priv = eek_renderer_get_instance_private ( - EEK_RENDERER(object)); + EEK_RENDERER(object)); switch (prop_id) { case PROP_PCONTEXT: @@ -596,7 +596,7 @@ static GType new_type(char *name) { ); } -static GType layout_type() { +static GType view_type() { static GType type = 0; if (!type) { type = new_type("sq_view"); @@ -649,31 +649,6 @@ eek_renderer_init (EekRenderer *self) priv->css_provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (priv->css_provider, "/sm/puri/squeekboard/style.css"); - - /* Create a style context for the layout */ - GtkWidgetPath *path = gtk_widget_path_new(); - gtk_widget_path_append_type(path, layout_type()); - - priv->layout_context = gtk_style_context_new(); - gtk_style_context_set_path(priv->layout_context, path); - gtk_widget_path_unref(path); - gtk_style_context_add_provider (priv->layout_context, - GTK_STYLE_PROVIDER(priv->css_provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); - - /* Create a style context for the buttons */ - path = gtk_widget_path_new(); - gtk_widget_path_append_type(path, layout_type()); - gtk_widget_path_append_type(path, button_type()); - priv->button_context = gtk_style_context_new (); - gtk_style_context_set_path(priv->button_context, path); - gtk_widget_path_unref(path); - - gtk_style_context_set_parent(priv->button_context, priv->layout_context); - gtk_style_context_set_state (priv->button_context, GTK_STATE_FLAG_NORMAL); - gtk_style_context_add_provider (priv->button_context, - GTK_STYLE_PROVIDER(priv->css_provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); } static void @@ -702,6 +677,37 @@ eek_renderer_new (LevelKeyboard *keyboard, NULL); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); priv->keyboard = keyboard; + + /* Create a style context for the layout */ + GtkWidgetPath *path = gtk_widget_path_new(); + gtk_widget_path_append_type(path, view_type()); + + priv->view_context = gtk_style_context_new(); + gtk_style_context_set_path(priv->view_context, path); + gtk_widget_path_unref(path); + if (squeek_layout_get_kind(priv->keyboard->layout) == ARRANGEMENT_KIND_WIDE) { + gtk_style_context_add_class(priv->view_context, "wide"); + } + gtk_style_context_add_provider (priv->view_context, + GTK_STYLE_PROVIDER(priv->css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + printf("view: %s\n", gtk_style_context_to_string(priv->view_context, GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE)); + + /* Create a style context for the buttons */ + path = gtk_widget_path_new(); + gtk_widget_path_append_type(path, view_type()); + if (squeek_layout_get_kind(priv->keyboard->layout) == ARRANGEMENT_KIND_WIDE) { + gtk_widget_path_iter_add_class(path, -1, "wide"); + } + gtk_widget_path_append_type(path, button_type()); + priv->button_context = gtk_style_context_new (); + gtk_style_context_set_path(priv->button_context, path); + gtk_widget_path_unref(path); + gtk_style_context_set_parent(priv->button_context, priv->view_context); + gtk_style_context_set_state (priv->button_context, GTK_STATE_FLAG_NORMAL); + gtk_style_context_add_provider (priv->button_context, + GTK_STYLE_PROVIDER(priv->css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); return renderer; } diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index e4f2eb09..fe95e10c 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -32,7 +32,7 @@ LevelKeyboard * eek_xml_layout_real_create_keyboard (const char *keyboard_type, EekboardContextService *manager, - enum layout_type t) + enum squeek_arrangement_kind t) { struct squeek_layout *layout = squeek_load_layout(keyboard_type, t); squeek_layout_place_contents(layout); diff --git a/eek/eek-xml-layout.h b/eek/eek-xml-layout.h index 9b96e445..ed0bb346 100644 --- a/eek/eek-xml-layout.h +++ b/eek/eek-xml-layout.h @@ -31,6 +31,6 @@ G_BEGIN_DECLS LevelKeyboard * eek_xml_layout_real_create_keyboard (const char *keyboard_type, EekboardContextService *manager, - enum layout_type t); + enum squeek_arrangement_kind t); G_END_DECLS #endif /* EEK_XML_LAYOUT_H */ diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index 47ac5f9b..17410c20 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -81,7 +81,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_ static LevelKeyboard * eekboard_context_service_real_create_keyboard (EekboardContextService *self, const gchar *keyboard_type, - enum layout_type t) + enum squeek_arrangement_kind t) { LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self, t); if (!keyboard) { @@ -227,7 +227,7 @@ settings_get_layout(GSettings *settings, char **type, char **layout) } void -eekboard_context_service_update_layout(EekboardContextService *context, enum layout_type t) +eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t) { g_autofree gchar *keyboard_type = NULL; g_autofree gchar *keyboard_layout = NULL; diff --git a/eekboard/eekboard-context-service.h b/eekboard/eekboard-context-service.h index 2dccd498..38e4a9f2 100644 --- a/eekboard/eekboard-context-service.h +++ b/eekboard/eekboard-context-service.h @@ -106,6 +106,6 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context, uint32_t hint, uint32_t purpose); void -eekboard_context_service_update_layout(EekboardContextService *context, enum layout_type t); +eekboard_context_service_update_layout(EekboardContextService *context, enum squeek_arrangement_kind t); G_END_DECLS #endif /* EEKBOARD_CONTEXT_SERVICE_H */ diff --git a/src/data.rs b/src/data.rs index 783943f5..0066b8ec 100644 --- a/src/data.rs +++ b/src/data.rs @@ -17,6 +17,7 @@ use ::keyboard::{ KeyState, PressType, generate_keymap, generate_keycodes, FormattingError }; +use ::layout::ArrangementKind; use ::resources; use ::util::c::as_str; use ::util::hash_map_map; @@ -41,15 +42,16 @@ pub mod c { type_: u32, ) -> *mut ::layout::Layout { let type_ = match type_ { - 0 => LayoutType::Base, - 1 => LayoutType::Wide, + 0 => ArrangementKind::Base, + 1 => ArrangementKind::Wide, _ => panic!("Bad enum value"), }; let name = as_str(&name) .expect("Bad layout name") .expect("Empty layout name"); - let layout = load_layout_with_fallback(&name, type_); + let (kind, layout) = load_layout_data_with_fallback(&name, type_); + let layout = ::layout::Layout::new(layout, kind); Box::into_raw(Box::new(layout)) } } @@ -76,20 +78,6 @@ impl fmt::Display for LoadError { } } -pub enum LayoutType { - Base = 0, - Wide = 1, -} - -impl LayoutType { - fn apply_to_name(&self, name: String) -> String { - match self { - LayoutType::Base => name, - LayoutType::Wide => name + "_wide", - } - } -} - #[derive(Debug, Clone, PartialEq)] enum DataSource { File(PathBuf), @@ -106,41 +94,66 @@ impl fmt::Display for DataSource { } /// Lists possible sources, with 0 as the most preferred one +/// Trying order: native lang of the right kind, native base, +/// fallback lang of the right kind, fallback base fn list_layout_sources( name: &str, - type_: LayoutType, + kind: ArrangementKind, keyboards_path: Option, -) -> Vec { +) -> Vec<(ArrangementKind, DataSource)> { let mut ret = Vec::new(); { - let mut add_by_name = |name: &str| { + fn name_with_arrangement(name: String, kind: &ArrangementKind) + -> String + { + match kind { + ArrangementKind::Base => name, + ArrangementKind::Wide => name + "_wide", + } + } + + let mut add_by_name = |name: &str, kind: &ArrangementKind| { if let Some(path) = keyboards_path.clone() { - ret.push(DataSource::File( - path.join(name.to_owned()).with_extension("yaml") + ret.push(( + kind.clone(), + DataSource::File( + path.join(name.to_owned()).with_extension("yaml") + ) )) } - ret.push(DataSource::Resource(name.into())); + ret.push(( + kind.clone(), + DataSource::Resource(name.into()) + )); }; - match &type_ { - LayoutType::Base => {}, - type_ => add_by_name(&type_.apply_to_name(name.into())), + match &kind { + ArrangementKind::Base => {}, + kind => add_by_name( + &name_with_arrangement(name.into(), &kind), + &kind, + ), }; - add_by_name(name); + add_by_name(name, &ArrangementKind::Base); - match &type_ { - LayoutType::Base => {}, - type_ => add_by_name(&type_.apply_to_name(FALLBACK_LAYOUT_NAME.into())), + match &kind { + ArrangementKind::Base => {}, + kind => add_by_name( + &name_with_arrangement(FALLBACK_LAYOUT_NAME.into(), &kind), + &kind, + ), }; - add_by_name(FALLBACK_LAYOUT_NAME); + add_by_name(FALLBACK_LAYOUT_NAME, &ArrangementKind::Base); } ret } -fn load_layout(source: DataSource) -> Result<::layout::Layout, LoadError> { +fn load_layout_data(source: DataSource) + -> Result<::layout::LayoutData, LoadError> +{ match source { DataSource::File(path) => { Layout::from_file(path.clone()) @@ -158,16 +171,16 @@ fn load_layout(source: DataSource) -> Result<::layout::Layout, LoadError> { } } -fn load_layout_with_fallback( +fn load_layout_data_with_fallback( name: &str, - type_: LayoutType, -) -> ::layout::Layout { + kind: ArrangementKind, +) -> (ArrangementKind, ::layout::LayoutData) { let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR") .map(PathBuf::from) .or_else(|| xdg::data_path("squeekboard/keyboards")); - for source in list_layout_sources(name, type_, path) { - let layout = load_layout(source.clone()); + for (kind, source) in list_layout_sources(name, kind, path) { + let layout = load_layout_data(source.clone()); match layout { Err(e) => match (e, source) { ( @@ -182,7 +195,7 @@ fn load_layout_with_fallback( source, e ), }, - Ok(layout) => return layout, + Ok(layout) => return (kind, layout), } } @@ -292,7 +305,9 @@ impl Layout { serde_yaml::from_reader(infile).map_err(Error::Yaml) } - pub fn build(self) -> Result<::layout::Layout, FormattingError> { + pub fn build(self) + -> Result<::layout::LayoutData, FormattingError> + { let button_names = self.views.values() .flat_map(|rows| { rows.iter() @@ -399,15 +414,12 @@ impl Layout { )}) ); - Ok(::layout::Layout { - current_view: "base".into(), + Ok(::layout::LayoutData { views: views, keymap_str: { CString::new(keymap_str) .expect("Invalid keymap string generated") }, - locked_keys: HashSet::new(), - pressed_keys: HashSet::new(), }) } } @@ -701,13 +713,16 @@ mod tests { /// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME #[test] fn fallbacks_order() { - let sources = list_layout_sources("nb", LayoutType::Base, None); + let sources = list_layout_sources("nb", ArrangementKind::Base, None); assert_eq!( sources, vec!( - DataSource::Resource("nb".into()), - DataSource::Resource(FALLBACK_LAYOUT_NAME.into()), + (ArrangementKind::Base, DataSource::Resource("nb".into())), + ( + ArrangementKind::Base, + DataSource::Resource(FALLBACK_LAYOUT_NAME.into()) + ), ) ); } diff --git a/src/layout.h b/src/layout.h index ea52abfe..ea6ee949 100644 --- a/src/layout.h +++ b/src/layout.h @@ -9,9 +9,9 @@ #include "src/keyboard.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" -enum layout_type { - LAYOUT_TYPE_BASE = 0, - LAYOUT_TYPE_WIDE = 1, +enum squeek_arrangement_kind { + ARRANGEMENT_KIND_BASE = 0, + ARRANGEMENT_KIND_WIDE = 1, }; struct squeek_button; @@ -59,6 +59,7 @@ struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*); struct squeek_layout *squeek_load_layout(const char *name, uint32_t type); const char *squeek_layout_get_keymap(const struct squeek_layout*); +enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *); void squeek_layout_free(struct squeek_layout*); void squeek_layout_release(struct squeek_layout *layout, struct zwp_virtual_keyboard_v1 *virtual_keyboard, uint32_t timestamp, EekGtkKeyboard *ui_keyboard); diff --git a/src/layout.rs b/src/layout.rs index c87b89bf..442dc893 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -203,6 +203,13 @@ pub mod c { layout.keymap_str.as_ptr() } + #[no_mangle] + pub extern "C" + fn squeek_layout_get_kind(layout: *const Layout) -> u32 { + let layout = unsafe { &*layout }; + layout.kind.clone() as u32 + } + #[no_mangle] pub extern "C" fn squeek_layout_free(layout: *mut Layout) { @@ -687,10 +694,18 @@ impl View { } } +/// The physical characteristic of layout for the purpose of styling +#[derive(Clone, PartialEq, Debug)] +pub enum ArrangementKind { + Base = 0, + Wide = 1, +} + // TODO: split into sth like // Arrangement (views) + details (keymap) + State (keys) /// State of the UI, contains the backend as well pub struct Layout { + pub kind: ArrangementKind, pub current_view: String, // Views own the actual buttons which have state // Maybe they should own UI only, @@ -706,6 +721,12 @@ pub struct Layout { pub locked_keys: HashSet<::util::Pointer>>, } +/// A builder structure for picking up layout data from storage +pub struct LayoutData { + pub views: HashMap>, + pub keymap_str: CString, +} + struct NoSuchView; // Unfortunately, changes are not atomic due to mutability :( @@ -713,6 +734,16 @@ struct NoSuchView; // The usage of &mut on Rc> doesn't mean anything special. // Cloning could also be used. impl Layout { + pub fn new(data: LayoutData, kind: ArrangementKind) -> Layout { + Layout { + kind, + current_view: "base".to_owned(), + views: data.views, + keymap_str: data.keymap_str, + pressed_keys: HashSet::new(), + locked_keys: HashSet::new(), + } + } fn get_current_view(&self) -> &Box { self.views.get(&self.current_view).expect("Selected nonexistent view") } diff --git a/src/resources.rs b/src/resources.rs index dfb27863..e33ff433 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -2,7 +2,6 @@ * This could be done using GResource, but that would need additional work. */ - const KEYBOARDS: &[(*const str, *const str)] = &[ ("us", include_str!("../data/keyboards/us.yaml")), ("us_wide", include_str!("../data/keyboards/us_wide.yaml")), diff --git a/src/server-context-service.c b/src/server-context-service.c index d3bcc3e9..137ae0cf 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -43,7 +43,7 @@ struct _ServerContextService { GtkWidget *widget; guint hiding; guint last_requested_height; - enum layout_type last_type; + enum squeek_arrangement_kind last_type; gdouble size_constraint_landscape[2]; gdouble size_constraint_portrait[2]; @@ -128,12 +128,12 @@ calculate_height(int32_t width) return height; } -enum layout_type get_type(uint32_t width, uint32_t height) { +enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) { (void)height; if (width < 540) { - return LAYOUT_TYPE_BASE; + return ARRANGEMENT_KIND_BASE; } - return LAYOUT_TYPE_WIDE; + return ARRANGEMENT_KIND_WIDE; } static void @@ -146,7 +146,7 @@ on_surface_configure(PhoshLayerSurface *surface, ServerContextService *context) "configured-height", &height, NULL); // check if the change would switch types - enum layout_type new_type = get_type((uint32_t)width, (uint32_t)height); + enum squeek_arrangement_kind new_type = get_type((uint32_t)width, (uint32_t)height); if (context->last_type != new_type) { context->last_type = new_type; eekboard_context_service_update_layout(EEKBOARD_CONTEXT_SERVICE(context), context->last_type); @@ -374,7 +374,7 @@ server_context_service_new () return EEKBOARD_CONTEXT_SERVICE(g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL)); } -enum layout_type server_context_service_get_layout_type(EekboardContextService *service) +enum squeek_arrangement_kind server_context_service_get_layout_type(EekboardContextService *service) { return SERVER_CONTEXT_SERVICE(service)->last_type; } diff --git a/src/server-context-service.h b/src/server-context-service.h index abaa5428..2929640a 100644 --- a/src/server-context-service.h +++ b/src/server-context-service.h @@ -34,7 +34,7 @@ G_BEGIN_DECLS typedef struct _ServerContextService ServerContextService; EekboardContextService *server_context_service_new (); -enum layout_type server_context_service_get_layout_type(EekboardContextService*); +enum squeek_arrangement_kind server_context_service_get_layout_type(EekboardContextService*); G_END_DECLS #endif /* SERVER_CONTEXT_SERVICE_H */