diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index af3fa54b63af9075a350edfc68cff48035f2cd89..6f51d46bcace276983d51edfbb967c3293c985ea 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -44,11 +44,11 @@ typedef struct _EekGtkKeyboardPrivate { - EekRenderer *renderer; // owned, nullable + EekRenderer *renderer; EekboardContextService *eekboard_context; // unowned reference struct submission *submission; // unowned reference - struct squeek_layout_state *layout; // unowned + struct squeek_layout_state *layout; LevelKeyboard *keyboard; // unowned reference; it's kept in server-context GdkEventSequence *sequence; // unowned reference @@ -93,21 +93,18 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, pcontext); eek_renderer_set_allocation_size (priv->renderer, - priv->keyboard->layout, allocation.width, allocation.height); eek_renderer_set_scale_factor (priv->renderer, gtk_widget_get_scale_factor (self)); } - - eek_renderer_render_keyboard (priv->renderer, priv->submission, cr, priv->keyboard); + eek_renderer_render_keyboard (priv->renderer, priv->submission, cr); return FALSE; } -// Units of pixel size static enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) { (void)height; - if (width < 1080) { + if (width < 540) { return ARRANGEMENT_KIND_BASE; } return ARRANGEMENT_KIND_WIDE; @@ -119,11 +116,11 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); - uint32_t scale = (uint32_t)gtk_widget_get_scale_factor(self); + // check if the change would switch types enum squeek_arrangement_kind new_type = get_type( - (uint32_t)(allocation->width - allocation->x) * scale, - (uint32_t)(allocation->height - allocation->y) * scale); + (uint32_t)(allocation->width - allocation->x), + (uint32_t)(allocation->height - allocation->y)); if (priv->layout->arrangement != new_type) { priv->layout->arrangement = new_type; @@ -132,7 +129,6 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, if (priv->renderer) eek_renderer_set_allocation_size (priv->renderer, - priv->keyboard->layout, allocation->width, allocation->height); @@ -304,7 +300,7 @@ eek_gtk_keyboard_dispose (GObject *object) EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); if (priv->renderer) { - eek_renderer_free(priv->renderer); + g_object_unref (priv->renderer); priv->renderer = NULL; priv->renderer = NULL; } @@ -370,7 +366,7 @@ on_notify_keyboard (GObject *object, EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (self); priv->keyboard = eekboard_context_service_get_keyboard(EEKBOARD_CONTEXT_SERVICE(object)); if (priv->renderer) { - eek_renderer_free(priv->renderer); + g_object_unref(priv->renderer); } priv->renderer = NULL; gtk_widget_queue_draw(GTK_WIDGET(self)); diff --git a/eek/eek-gtk-keyboard.h b/eek/eek-gtk-keyboard.h index 1f07cba3e6f17fed63276978c291fb4feb08e5e3..4506e32d46e732ea15f541b53f7a73336776dd42 100644 --- a/eek/eek-gtk-keyboard.h +++ b/eek/eek-gtk-keyboard.h @@ -32,6 +32,7 @@ struct submission; struct squeek_layout_state; +typedef struct _LevelKeyboard LevelKeyboard; // including causes weird bugs G_BEGIN_DECLS #define EEK_TYPE_GTK_KEYBOARD (eek_gtk_keyboard_get_type()) diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 292a08792a8fad8de59db3498ab75c2fe8b2912f..24ef537be1f370d4cee77a937ea8cc7d273680c6 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -38,8 +38,10 @@ void level_keyboard_free(LevelKeyboard *self) { } LevelKeyboard* -level_keyboard_new (struct squeek_layout *layout) +level_keyboard_new (const gchar *keyboard_type, + enum squeek_arrangement_kind t) { + struct squeek_layout *layout = squeek_load_layout(keyboard_type, t); LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); if (!keyboard) { diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index b1377c4762256e8a474f36e98bc7e8b39a3d96b7..fab549e133baab361a763972e9dc9af128efbe48 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -47,7 +47,8 @@ gchar * eek_keyboard_get_keymap (LevelKeyboard *keyboard); LevelKeyboard* -level_keyboard_new (struct squeek_layout *layout); +level_keyboard_new (const gchar *keyboard_type, + enum squeek_arrangement_kind t); void level_keyboard_free(LevelKeyboard *self); G_END_DECLS diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index ceeeb02dd7bb036e41aa9ea7f2b5e431dd9ab27d..c8d03e48ab9e7e0c87521395e2c97f8a5bada2e7 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -28,6 +28,27 @@ #include "eek-renderer.h" #include "src/style.h" +enum { + PROP_0, + PROP_PCONTEXT, + PROP_LAST +}; + +typedef struct _EekRendererPrivate +{ + LevelKeyboard *keyboard; // unowned + PangoContext *pcontext; // owned + GtkCssProvider *css_provider; // owned + GtkStyleContext *view_context; // owned + GtkStyleContext *button_context; // TODO: maybe move a copy to each button + + gdouble allocation_width; + gdouble allocation_height; + gint scale_factor; /* the outputs scale factor */ + struct transformation widget_to_layout; +} EekRendererPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT) /* eek-keyboard-drawing.c */ static void render_button_label (cairo_t *cr, GtkStyleContext *ctx, @@ -117,7 +138,9 @@ eek_render_button (EekRenderer *self, gboolean pressed, gboolean locked) { - GtkStyleContext *ctx = self->button_context; + EekRendererPrivate *priv = eek_renderer_get_instance_private (self); + + GtkStyleContext *ctx = priv->button_context; /* Set the name of the button on the widget path, using the name obtained from the button's symbol. */ g_autoptr (GtkWidgetPath) path = NULL; @@ -137,7 +160,7 @@ eek_render_button (EekRenderer *self, } gtk_style_context_add_class(ctx, outline_name); - render_button_in_context(self->scale_factor, cr, ctx, button); + render_button_in_context(priv->scale_factor, cr, ctx, button); // Save and restore functions don't work if gtk_render_* was used in between gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL); @@ -195,42 +218,116 @@ render_button_label (cairo_t *cr, void eek_renderer_render_keyboard (EekRenderer *self, struct submission *submission, - cairo_t *cr, - LevelKeyboard *keyboard) + cairo_t *cr) { - g_return_if_fail (self->allocation_width > 0.0); - g_return_if_fail (self->allocation_height > 0.0); + EekRendererPrivate *priv = eek_renderer_get_instance_private (self); + + g_return_if_fail (priv->keyboard); + g_return_if_fail (priv->allocation_width > 0.0); + g_return_if_fail (priv->allocation_height > 0.0); /* Paint the background covering the entire widget area */ - gtk_render_background (self->view_context, + gtk_render_background (priv->view_context, cr, 0, 0, - self->allocation_width, self->allocation_height); + priv->allocation_width, priv->allocation_height); cairo_save(cr); - cairo_translate (cr, self->widget_to_layout.origin_x, self->widget_to_layout.origin_y); - cairo_scale (cr, self->widget_to_layout.scale, self->widget_to_layout.scale); + cairo_translate (cr, priv->widget_to_layout.origin_x, priv->widget_to_layout.origin_y); + cairo_scale (cr, priv->widget_to_layout.scale, priv->widget_to_layout.scale); - squeek_draw_layout_base_view(keyboard->layout, self, cr); - squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission); + squeek_draw_layout_base_view(priv->keyboard->layout, self, cr); + squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr, submission); cairo_restore (cr); } -void -eek_renderer_free (EekRenderer *self) +static void +eek_renderer_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EekRendererPrivate *priv = eek_renderer_get_instance_private ( + EEK_RENDERER(object)); + + switch (prop_id) { + case PROP_PCONTEXT: + priv->pcontext = g_value_get_object (value); + g_object_ref (priv->pcontext); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +eek_renderer_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - if (self->pcontext) { - g_object_unref (self->pcontext); - self->pcontext = NULL; + (void)value; + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } - g_object_unref(self->css_provider); - g_object_unref(self->view_context); - g_object_unref(self->button_context); +} + +static void +eek_renderer_dispose (GObject *object) +{ + EekRenderer *self = EEK_RENDERER (object); + EekRendererPrivate *priv = eek_renderer_get_instance_private (self); + + if (priv->keyboard) { + priv->keyboard = NULL; + } + if (priv->pcontext) { + g_object_unref (priv->pcontext); + priv->pcontext = NULL; + } + // this is where renderer-specific surfaces would be released - free(self); + G_OBJECT_CLASS (eek_renderer_parent_class)->dispose (object); } +static void +eek_renderer_finalize (GObject *object) +{ + EekRenderer *self = EEK_RENDERER(object); + EekRendererPrivate *priv = eek_renderer_get_instance_private (self); + + g_object_unref(priv->css_provider); + g_object_unref(priv->view_context); + g_object_unref(priv->button_context); + G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object); +} + +static void +eek_renderer_class_init (EekRendererClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = eek_renderer_set_property; + gobject_class->get_property = eek_renderer_get_property; + gobject_class->dispose = eek_renderer_dispose; + gobject_class->finalize = eek_renderer_finalize; + + pspec = g_param_spec_object ("pango-context", + "Pango Context", + "Pango Context", + PANGO_TYPE_CONTEXT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE); + g_object_class_install_property (gobject_class, + PROP_PCONTEXT, + pspec); +} + + static GType new_type(char *name) { GTypeInfo info = {0}; info.class_size = sizeof(GtkWidgetClass); @@ -258,75 +355,81 @@ static GType button_type() { } static void -renderer_init (EekRenderer *self) +eek_renderer_init (EekRenderer *self) { - self->pcontext = NULL; - self->allocation_width = 0.0; - self->allocation_height = 0.0; - self->scale_factor = 1; + EekRendererPrivate *priv = eek_renderer_get_instance_private (self); + + priv->keyboard = NULL; + priv->pcontext = NULL; + priv->allocation_width = 0.0; + priv->allocation_height = 0.0; + priv->scale_factor = 1; GtkIconTheme *theme = gtk_icon_theme_get_default (); gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons"); - self->css_provider = squeek_load_style(); + priv->css_provider = squeek_load_style(); } EekRenderer * eek_renderer_new (LevelKeyboard *keyboard, PangoContext *pcontext) { - EekRenderer *renderer = calloc(1, sizeof(EekRenderer)); - renderer_init(renderer); - renderer->pcontext = pcontext; - g_object_ref (renderer->pcontext); + EekRenderer *renderer = g_object_new (EEK_TYPE_RENDERER, + "pango-context", pcontext, + 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()); - renderer->view_context = gtk_style_context_new(); - gtk_style_context_set_path(renderer->view_context, path); + 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(keyboard->layout) == ARRANGEMENT_KIND_WIDE) { - gtk_style_context_add_class(renderer->view_context, "wide"); + 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 (renderer->view_context, - GTK_STYLE_PROVIDER(renderer->css_provider), + gtk_style_context_add_provider (priv->view_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, view_type()); - if (squeek_layout_get_kind(keyboard->layout) == ARRANGEMENT_KIND_WIDE) { + 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()); - renderer->button_context = gtk_style_context_new (); - gtk_style_context_set_path(renderer->button_context, path); + 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(renderer->button_context, renderer->view_context); - gtk_style_context_set_state (renderer->button_context, GTK_STATE_FLAG_NORMAL); - gtk_style_context_add_provider (renderer->button_context, - GTK_STYLE_PROVIDER(renderer->css_provider), + 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; } void eek_renderer_set_allocation_size (EekRenderer *renderer, - struct squeek_layout *layout, gdouble width, gdouble height) { + g_return_if_fail (EEK_IS_RENDERER(renderer)); g_return_if_fail (width > 0.0 && height > 0.0); - renderer->allocation_width = width; - renderer->allocation_height = height; + EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); + + priv->allocation_width = width; + priv->allocation_height = height; - renderer->widget_to_layout = squeek_layout_calculate_transformation( - layout, - renderer->allocation_width, renderer->allocation_height); + priv->widget_to_layout = squeek_layout_calculate_transformation( + priv->keyboard->layout, + priv->allocation_width, priv->allocation_height); // This is where size-dependent surfaces would be released } @@ -334,7 +437,10 @@ eek_renderer_set_allocation_size (EekRenderer *renderer, void eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale) { - renderer->scale_factor = scale; + g_return_if_fail (EEK_IS_RENDERER(renderer)); + + EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); + priv->scale_factor = scale; } cairo_surface_t * @@ -363,5 +469,9 @@ eek_renderer_get_icon_surface (const gchar *icon_name, struct transformation eek_renderer_get_transformation (EekRenderer *renderer) { - return renderer->widget_to_layout; + struct transformation failed = {0}; + g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed); + + EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); + return priv->widget_to_layout; } diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index f182345686bcfdf3cfa2a1aba0715b4f3e98c6ae..954ad171b0abdbe2625d2ab390a31ead18d9e446 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -27,34 +27,30 @@ #include "eek-types.h" #include "src/submission.h" -struct squeek_layout; +G_BEGIN_DECLS -/// Renders LevelKayboards -/// It cannot adjust styles at runtime. -typedef struct EekRenderer +#define EEK_TYPE_RENDERER (eek_renderer_get_type()) +G_DECLARE_DERIVABLE_TYPE (EekRenderer, eek_renderer, EEK, RENDERER, GObject) + +struct _EekRendererClass { - PangoContext *pcontext; // owned - GtkCssProvider *css_provider; // owned - GtkStyleContext *view_context; // owned - GtkStyleContext *button_context; // TODO: maybe move a copy to each button - /// Style class for rendering the view and button CSS. - gchar *extra_style; // owned + GObjectClass parent_class; - // Mutable state - /// Background extents - gdouble allocation_width; - gdouble allocation_height; - gint scale_factor; /* the outputs scale factor */ - /// Coords transformation - struct transformation widget_to_layout; -} EekRenderer; + cairo_surface_t *(* get_icon_surface) (EekRenderer *self, + const gchar *icon_name, + gint size, + gint scale); + /*< private >*/ + /* padding */ + gpointer pdummy[23]; +}; GType eek_renderer_get_type (void) G_GNUC_CONST; EekRenderer *eek_renderer_new (LevelKeyboard *keyboard, PangoContext *pcontext); void eek_renderer_set_allocation_size - (EekRenderer *renderer, struct squeek_layout *layout, + (EekRenderer *renderer, gdouble width, gdouble height); void eek_renderer_set_scale_factor (EekRenderer *renderer, @@ -65,9 +61,7 @@ cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name, gint scale); void eek_renderer_render_keyboard (EekRenderer *renderer, struct submission *submission, - cairo_t *cr, LevelKeyboard *keyboard); -void -eek_renderer_free (EekRenderer *self); + cairo_t *cr); struct transformation eek_renderer_get_transformation (EekRenderer *renderer); diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index a97f1231780164500e6a502b96b15ed06729b4fa..8189c88fdd1bdfbadcada41a785ce4265b3d43d2 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -47,6 +47,7 @@ static guint signals[LAST_SIGNAL] = { 0, }; struct _EekboardContextServicePrivate { LevelKeyboard *keyboard; // currently used keyboard + GHashTable *keyboard_hash; // a table of available keyboards, per layout GSettings *settings; // Owned reference // Maybe TODO: it's used only for fetching layout type. @@ -93,6 +94,13 @@ eekboard_context_service_get_property (GObject *object, static void eekboard_context_service_dispose (GObject *object) { + EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE(object); + + if (context->priv->keyboard_hash) { + g_hash_table_destroy (context->priv->keyboard_hash); + context->priv->keyboard_hash = NULL; + } + G_OBJECT_CLASS (eekboard_context_service_parent_class)-> dispose (object); } @@ -140,8 +148,7 @@ eekboard_context_service_use_layout(EekboardContextService *context, struct sque } // generic part follows - struct squeek_layout *layout = squeek_load_layout(layout_name, state->arrangement); - LevelKeyboard *keyboard = level_keyboard_new(layout); + LevelKeyboard *keyboard = level_keyboard_new(layout_name, state->arrangement); // set as current LevelKeyboard *previous_keyboard = context->priv->keyboard; context->priv->keyboard = keyboard; @@ -241,6 +248,12 @@ static void eekboard_context_service_init (EekboardContextService *self) { self->priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(self); + + self->priv->keyboard_hash = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify)g_object_unref); const char *schema_name = "org.gnome.desktop.input-sources"; GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default(); if (ssrc) { diff --git a/eekboard/eekboard-context-service.h b/eekboard/eekboard-context-service.h index 8547e3e76be0e7b8d2f095d6daf3a4a9d831aa31..b5f17988f2915a71ed62c41a839d9937aca27b50 100644 --- a/eekboard/eekboard-context-service.h +++ b/eekboard/eekboard-context-service.h @@ -72,6 +72,9 @@ struct _EekboardContextServiceClass { GObjectClass parent_class; /*< public >*/ + struct squeek_view *(*create_keyboard) (EekboardContextService *self, + const gchar *keyboard_type); + /* signals */ void (*destroyed) (EekboardContextService *self); diff --git a/src/lib.rs b/src/lib.rs index 287b5286a74eadbc804e1a73555eb5259a2e3401..ba71686b796e6a37223c4365fa1433fd84fc7ba1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,5 @@ mod style; mod submission; pub mod tests; pub mod util; -mod ui_manager; mod vkeyboard; mod xdg; diff --git a/src/outputs.h b/src/outputs.h index e018d037c39aca11541a2d2e74af4f9e130d55f1..38a207f67d10c69a3bb57fbc48f3e06d3ac36ad0 100644 --- a/src/outputs.h +++ b/src/outputs.h @@ -4,14 +4,10 @@ #include "wayland-client-protocol.h" struct squeek_outputs; -struct squeek_output_handle { - struct wl_output *output; - struct squeek_outputs *outputs; -}; struct squeek_outputs *squeek_outputs_new(); void squeek_outputs_free(struct squeek_outputs*); void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output); -struct squeek_output_handle squeek_outputs_get_current(struct squeek_outputs*); +struct wl_output *squeek_outputs_get_current(struct squeek_outputs*); int32_t squeek_outputs_get_perceptual_width(struct squeek_outputs*, struct wl_output *output); #endif diff --git a/src/outputs.rs b/src/outputs.rs index 29f4e78c002896ee698442b63720ef0ecb15ec95..08ac590d514a167cc453e28113933337ffcfb5b6 100644 --- a/src/outputs.rs +++ b/src/outputs.rs @@ -17,7 +17,7 @@ pub mod c { // Defined in C #[repr(transparent)] - #[derive(Clone, PartialEq, Copy)] + #[derive(Clone, PartialEq)] pub struct WlOutput(*const c_void); #[repr(C)] @@ -105,24 +105,6 @@ pub mod c { type COutputs = ::util::c::Wrapped; - /// A stable reference to an output. - #[derive(Clone)] - #[repr(C)] - pub struct OutputHandle { - wl_output: WlOutput, - outputs: COutputs, - } - - impl OutputHandle { - // Cannot return an Output reference - // because COutputs is too deeply wrapped - pub fn get_state(&self) -> Option { - let outputs = self.outputs.clone_ref(); - let outputs = outputs.borrow(); - find_output(&outputs, self.wl_output.clone()).map(|o| o.current.clone()) - } - } - // Defined in Rust extern fn outputs_handle_geometry( @@ -258,15 +240,46 @@ pub mod c { #[no_mangle] pub extern "C" - fn squeek_outputs_get_current(raw_collection: COutputs) -> OutputHandle { + fn squeek_outputs_get_current(raw_collection: COutputs) -> WlOutput { let collection = raw_collection.clone_ref(); let collection = collection.borrow(); - OutputHandle { - wl_output: collection.outputs[0].output.clone(), - outputs: raw_collection.clone(), - } + collection.outputs[0].output.clone() } + #[no_mangle] + pub extern "C" + fn squeek_outputs_get_perceptual_width( + raw_collection: COutputs, + wl_output: WlOutput, + ) -> i32 { + let collection = raw_collection.clone_ref(); + let collection = collection.borrow(); + + let output_state = find_output(&collection, wl_output) + .map(|o| &o.current); + match output_state { + Some(OutputState { + current_mode: Some(super::Mode { width, height } ), + transform: Some(transform), + scale, + }) => { + match transform { + Transform::Normal + | Transform::Rotated180 + | Transform::Flipped + | Transform::FlippedRotated180 => width / scale, + _ => height / scale, + } + }, + _ => { + log_print!( + logging::Level::Surprise, + "Not enough info received on output", + ); + 0 + }, + } + } // TODO: handle unregistration fn find_output( @@ -292,14 +305,6 @@ pub mod c { } } -/// Generic size -#[derive(Clone)] -pub struct Size { - pub width: u32, - pub height: u32, -} - -/// wl_output mode #[derive(Clone)] struct Mode { width: i32, @@ -310,16 +315,10 @@ struct Mode { pub struct OutputState { current_mode: Option, transform: Option, - pub scale: i32, + scale: i32, } impl OutputState { - // More properly, this would have been a builder kind of struct, - // with wl_output gradually adding properties to it - // before it reached a fully initialized state, - // when it would transform into a struct without all (some?) of the Options. - // However, it's not clear which state is fully initialized, - // and whether it would make things easier at all anyway. fn uninitialized() -> OutputState { OutputState { current_mode: None, @@ -327,32 +326,6 @@ impl OutputState { scale: 1, } } - - pub fn get_pixel_size(&self) -> Option { - use self::c::Transform; - match self { - OutputState { - current_mode: Some(Mode { width, height } ), - transform: Some(transform), - scale: _, - } => Some( - match transform { - Transform::Normal - | Transform::Rotated180 - | Transform::Flipped - | Transform::FlippedRotated180 => Size { - width: *width as u32, - height: *height as u32, - }, - _ => Size { - width: *height as u32, - height: *width as u32, - }, - } - ), - _ => None, - } - } } pub struct Output { diff --git a/src/server-context-service.c b/src/server-context-service.c index 46811ce4b8f844aa2c817e67ca32c983d4dc9af3..3e1e7f113f5a0fd2934042dfe6c64f6bfef45e43 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -43,7 +43,6 @@ struct _ServerContextService { /// Needed for instantiating the widget struct submission *submission; // unowned struct squeek_layout_state *layout; - struct ui_manager *manager; // unowned gboolean visible; PhoshLayerSurface *window; @@ -87,6 +86,18 @@ on_notify_unmap (GObject *object, g_object_set (context, "visible", FALSE, NULL); } +static uint32_t +calculate_height(int32_t width) +{ + uint32_t height = 180; + if (width < 360 && width > 0) { + height = ((unsigned)width * 7 / 12); // to match 360×210 + } else if (width < 540) { + height = 180 + (540 - (unsigned)width) * 30 / 180; // smooth transition + } + return height; +} + static void on_surface_configure(PhoshLayerSurface *surface, ServerContextService *context) { @@ -97,7 +108,7 @@ on_surface_configure(PhoshLayerSurface *surface, ServerContextService *context) "configured-height", &height, NULL); - guint desired_height = squeek_uiman_get_perceptual_height(context->manager); + guint desired_height = calculate_height(width); guint configured_height = (guint)height; // if height was already requested once but a different one was given // (for the same set of surrounding properties), @@ -120,14 +131,14 @@ make_window (ServerContextService *context) if (context->window) g_error("Window already present"); - struct squeek_output_handle output = squeek_outputs_get_current(squeek_wayland->outputs); - squeek_uiman_set_output(context->manager, output); - uint32_t height = squeek_uiman_get_perceptual_height(context->manager); + struct wl_output *output = squeek_outputs_get_current(squeek_wayland->outputs); + int32_t width = squeek_outputs_get_perceptual_width(squeek_wayland->outputs, output); + uint32_t height = calculate_height(width); context->window = g_object_new ( PHOSH_TYPE_LAYER_SURFACE, "layer-shell", squeek_wayland->layer_shell, - "wl-output", output.output, + "wl-output", output, "height", height, "anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT @@ -311,12 +322,11 @@ server_context_service_init (ServerContextService *state) { } ServerContextService * -server_context_service_new (EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman) +server_context_service_new (EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout) { ServerContextService *ui = g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL); ui->submission = submission; ui->state = state; ui->layout = layout; - ui->manager = uiman; return ui; } diff --git a/src/server-context-service.h b/src/server-context-service.h index a69f85aeedbcc82d5fbbcde099e0c2c5df86fd9c..2c88a8bc6c46ed5ac105a2679995715b09a40501 100644 --- a/src/server-context-service.h +++ b/src/server-context-service.h @@ -20,7 +20,6 @@ #include "src/layout.h" #include "src/submission.h" -#include "ui_manager.h" G_BEGIN_DECLS @@ -37,7 +36,7 @@ typedef struct _ServerContextService ServerContextService; GType server_context_service_get_type (void) G_GNUC_CONST; -ServerContextService *server_context_service_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout, struct ui_manager *uiman); +ServerContextService *server_context_service_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout); enum squeek_arrangement_kind server_context_service_get_layout_type(ServerContextService *); void server_context_service_show_keyboard (ServerContextService *context); void server_context_service_hide_keyboard (ServerContextService *context); diff --git a/src/server-main.c b/src/server-main.c index f3f5edb81fffbb471c5265191390bbe44a7a8f87..f0b9a896aac67b4c87e4109a256184e44acfafda 100644 --- a/src/server-main.c +++ b/src/server-main.c @@ -32,7 +32,6 @@ #include "outputs.h" #include "submission.h" #include "server-context-service.h" -#include "ui_manager.h" #include "wayland.h" #include @@ -46,7 +45,6 @@ struct squeekboard { ServerContextService *ui_context; // mess, includes the entire UI struct submission *submission; // Wayland text input handling. struct squeek_layout_state layout_choice; // Currently wanted layout. - struct ui_manager *ui_manager; // UI shape tracker/chooser. TODO: merge with layuot choice }; @@ -203,8 +201,6 @@ main (int argc, char **argv) g_warning("Wayland input method interface not available"); } - instance.ui_manager = squeek_uiman_new(); - instance.settings_context = eekboard_context_service_new(&instance.layout_choice); // set up dbus @@ -286,8 +282,7 @@ main (int argc, char **argv) ServerContextService *ui_context = server_context_service_new( instance.settings_context, instance.submission, - &instance.layout_choice, - instance.ui_manager); + &instance.layout_choice); if (!ui_context) { g_error("Could not initialize GUI"); exit(1); diff --git a/src/ui_manager.h b/src/ui_manager.h deleted file mode 100644 index 57d3cc70897c00c9a2d949dfc1526eed37de7724..0000000000000000000000000000000000000000 --- a/src/ui_manager.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef UI_MANAGER__ -#define UI_MANAGER__ - -#include - -#include "outputs.h" - -struct ui_manager; - -struct ui_manager *squeek_uiman_new(); -void squeek_uiman_set_output(struct ui_manager *uiman, struct squeek_output_handle output); -uint32_t squeek_uiman_get_perceptual_height(struct ui_manager *uiman); - -#endif diff --git a/src/ui_manager.rs b/src/ui_manager.rs deleted file mode 100644 index c7af6521d8cd6c9b8ab75c731500cb56ff5e013f..0000000000000000000000000000000000000000 --- a/src/ui_manager.rs +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2020 Purism SPC - * SPDX-License-Identifier: GPL-3.0+ - */ - -/*! Centrally manages the shape of the UI widgets, and the choice of layout. - * - * Coordinates this based on information collated from all possible sources. - */ - -use std::cmp::min; -use ::outputs::c::OutputHandle; - -mod c { - use super::*; - use ::util::c::Wrapped; - - #[no_mangle] - pub extern "C" - fn squeek_uiman_new() -> Wrapped { - Wrapped::new(Manager { output: None }) - } - - /// Used to size the layer surface containing all the OSK widgets. - #[no_mangle] - pub extern "C" - fn squeek_uiman_get_perceptual_height( - uiman: Wrapped, - ) -> u32 { - let uiman = uiman.clone_ref(); - let uiman = uiman.borrow(); - // TODO: what to do when there's no output? - uiman.get_perceptual_height().unwrap_or(0) - } - - #[no_mangle] - pub extern "C" - fn squeek_uiman_set_output( - uiman: Wrapped, - output: OutputHandle, - ) { - let uiman = uiman.clone_ref(); - let mut uiman = uiman.borrow_mut(); - uiman.output = Some(output); - } -} - -/// Stores current state of all things influencing what the UI should look like. -pub struct Manager { - /// Shared output handle, current state updated whenever it's needed. - // TODO: Stop assuming that the output never changes. - // (There's no way for the output manager to update the ui manager.) - // FIXME: Turn into an OutputState and apply relevant connections elsewhere. - // Otherwise testability and predictablity is low. - output: Option, - //// Pixel size of the surface. Needs explicit updating. - //surface_size: Option, -} - -impl Manager { - fn get_perceptual_height(&self) -> Option { - let output_info = (&self.output).as_ref() - .and_then(|o| o.get_state()) - .map(|os| (os.scale as u32, os.get_pixel_size())); - match output_info { - Some((scale, Some(px_size))) => Some({ - let height = if (px_size.width < 720) & (px_size.width > 0) { - px_size.width * 7 / 12 // to match 360×210 - } else if px_size.width < 1080 { - 360 + (1080 - px_size.width) * 60 / 360 // smooth transition - } else { - 360 - }; - - // Don't exceed half the display size - min(height, px_size.height / 2) / scale - }), - Some((scale, None)) => Some(360 / scale), - None => None, - } - } -} diff --git a/src/util.rs b/src/util.rs index 767c32ea199e0816cd3f200194289f8943bcc75a..9dafb34e17e0054bb04d6792f46e67582558e164 100644 --- a/src/util.rs +++ b/src/util.rs @@ -98,8 +98,7 @@ pub mod c { Rc::from_raw(self.0) } - /// Creates a new Rc reference to the same data. - /// Use for accessing the underlying data as a reference. + /// Creates a new Rc reference to the same data pub fn clone_ref(&self) -> Rc> { // A bit dangerous: the Rc may be in use elsewhere let used_rc = unsafe { Rc::from_raw(self.0) }; @@ -131,7 +130,6 @@ pub mod c { impl COpaquePtr for Wrapped {} } -/// Clones the underlying data structure, like ToOwned. pub trait CloneOwned { type Owned; fn clone_owned(&self) -> Self::Owned;