From 24c3fac5057f1c0e09f7acf43a9b57b2291b1736 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Wed, 17 Mar 2021 13:56:34 +0000 Subject: [PATCH] renderer: Split mutable geometry and place it directly in GtkKeyboard Geometry is now permanently married to the widget rather the renderer. While geometry is not always defined, C doesn't support sum types, so checks won't be enforced by the compiler. It's OK to pretend there's always some geometry to avoid crashes. --- eek/eek-gtk-keyboard.c | 58 +++++++++++++++++++++++++++++++----------- eek/eek-gtk-keyboard.h | 1 + eek/eek-renderer.c | 41 +++++++++++------------------ eek/eek-renderer.h | 22 ++++++++-------- 4 files changed, 71 insertions(+), 51 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index a574d6c6..17f16e11 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -45,6 +45,8 @@ typedef struct _EekGtkKeyboardPrivate { EekRenderer *renderer; // owned, nullable + struct render_geometry render_geometry; // mutable + EekboardContextService *eekboard_context; // unowned reference struct submission *submission; // unowned reference @@ -72,12 +74,23 @@ eek_gtk_keyboard_real_realize (GtkWidget *self) GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->realize (self); } +static void set_allocation_size(EekGtkKeyboard *gtk_keyboard, + struct squeek_layout *layout, gdouble width, gdouble height) +{ + // This is where size-dependent surfaces would be released + EekGtkKeyboardPrivate *priv = + eek_gtk_keyboard_get_instance_private (gtk_keyboard); + priv->render_geometry = eek_render_geometry_from_allocation_size( + layout, width, height); +} + static gboolean eek_gtk_keyboard_real_draw (GtkWidget *self, cairo_t *cr) { + EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self); EekGtkKeyboardPrivate *priv = - eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + eek_gtk_keyboard_get_instance_private (keyboard); GtkAllocation allocation; gtk_widget_get_allocation (self, &allocation); @@ -92,15 +105,14 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, priv->keyboard, pcontext); - eek_renderer_set_allocation_size (priv->renderer, - priv->keyboard->layout, - allocation.width, - allocation.height); + set_allocation_size (keyboard, 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->renderer->widget_to_layout, priv->submission, cr, priv->keyboard); + eek_renderer_render_keyboard (priv->renderer, priv->render_geometry, + priv->submission, cr, priv->keyboard); return FALSE; } @@ -117,8 +129,9 @@ static void eek_gtk_keyboard_real_size_allocate (GtkWidget *self, GtkAllocation *allocation) { + EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self); EekGtkKeyboardPrivate *priv = - eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + eek_gtk_keyboard_get_instance_private (keyboard); // check if the change would switch types enum squeek_arrangement_kind new_type = get_type( (uint32_t)(allocation->width - allocation->x), @@ -130,10 +143,8 @@ 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); + set_allocation_size (keyboard, priv->keyboard->layout, + allocation->width, allocation->height); } GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)-> @@ -162,7 +173,7 @@ static void depress(EekGtkKeyboard *self, } squeek_layout_depress(priv->keyboard->layout, priv->submission, - x, y, eek_renderer_get_transformation(priv->renderer), time, self); + x, y, priv->render_geometry.widget_to_layout, time, self); } static void drag(EekGtkKeyboard *self, @@ -174,7 +185,7 @@ static void drag(EekGtkKeyboard *self, } squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, priv->submission, - x, y, eek_renderer_get_transformation(priv->renderer), time, + x, y, priv->render_geometry.widget_to_layout, time, priv->eekboard_context, self); } @@ -185,8 +196,7 @@ static void release(EekGtkKeyboard *self, guint32 time) return; } squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, - priv->submission, - eek_renderer_get_transformation(priv->renderer), time, + priv->submission, priv->render_geometry.widget_to_layout, time, priv->eekboard_context, self); } @@ -396,6 +406,24 @@ eek_gtk_keyboard_new (EekboardContextService *eekservice, priv->submission = submission; priv->layout = layout; priv->renderer = NULL; + // This should really be done on initialization. + // Before the widget is allocated, + // we don't really know what geometry it takes. + // When it's off the screen, we also kinda don't. + struct render_geometry initial_geometry = { + // Set to 100 just to make sure if there's any attempt to use it, + // it actually gives plausible results instead of blowing up, + // e.g. on zero division. + .allocation_width = 100, + .allocation_height = 100, + .widget_to_layout = { + .origin_x = 0, + .origin_y = 0, + .scale = 1, + }, + }; + priv->render_geometry = initial_geometry; + g_signal_connect (eekservice, "notify::keyboard", G_CALLBACK(on_notify_keyboard), diff --git a/eek/eek-gtk-keyboard.h b/eek/eek-gtk-keyboard.h index e9df72b3..faccd1fa 100644 --- a/eek/eek-gtk-keyboard.h +++ b/eek/eek-gtk-keyboard.h @@ -28,6 +28,7 @@ #include #include +#include "eek/eek-renderer.h" #include "eek/eek-types.h" struct submission; diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 84556f35..1ae3540f 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -194,23 +194,23 @@ render_button_label (cairo_t *cr, // FIXME: Pass just the active modifiers instead of entire submission void eek_renderer_render_keyboard (EekRenderer *self, - struct transformation widget_to_layout, + struct render_geometry geometry, struct submission *submission, cairo_t *cr, LevelKeyboard *keyboard) { - g_return_if_fail (self->allocation_width > 0.0); - g_return_if_fail (self->allocation_height > 0.0); + g_return_if_fail (geometry.allocation_width > 0.0); + g_return_if_fail (geometry.allocation_height > 0.0); /* Paint the background covering the entire widget area */ gtk_render_background (self->view_context, cr, 0, 0, - self->allocation_width, self->allocation_height); + geometry.allocation_width, geometry.allocation_height); cairo_save(cr); - cairo_translate (cr, widget_to_layout.origin_x, widget_to_layout.origin_y); - cairo_scale (cr, widget_to_layout.scale, widget_to_layout.scale); + cairo_translate (cr, geometry.widget_to_layout.origin_x, geometry.widget_to_layout.origin_y); + cairo_scale (cr, geometry.widget_to_layout.scale, geometry.widget_to_layout.scale); squeek_draw_layout_base_view(keyboard->layout, self, cr); squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission); @@ -262,8 +262,6 @@ static void renderer_init (EekRenderer *self) { self->pcontext = NULL; - self->allocation_width = 0.0; - self->allocation_height = 0.0; self->scale_factor = 1; self->css_provider = squeek_load_style(); @@ -310,22 +308,18 @@ eek_renderer_new (LevelKeyboard *keyboard, return renderer; } -void -eek_renderer_set_allocation_size (EekRenderer *renderer, - struct squeek_layout *layout, +struct render_geometry +eek_render_geometry_from_allocation_size (struct squeek_layout *layout, gdouble width, gdouble height) { - g_return_if_fail (width > 0.0 && height > 0.0); - - renderer->allocation_width = width; - renderer->allocation_height = height; - - renderer->widget_to_layout = squeek_layout_calculate_transformation( - layout, - renderer->allocation_width, renderer->allocation_height); - - // This is where size-dependent surfaces would be released + struct render_geometry ret = { + .allocation_width = width, + .allocation_height = height, + .widget_to_layout = squeek_layout_calculate_transformation( + layout, width, height), + }; + return ret; } void @@ -357,8 +351,3 @@ eek_renderer_get_icon_surface (const gchar *icon_name, } return surface; } - -struct transformation -eek_renderer_get_transformation (EekRenderer *renderer) { - return renderer->widget_to_layout; -} diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index bc8bfc7a..a339b2ad 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -41,22 +41,23 @@ typedef struct EekRenderer gchar *extra_style; // owned // Mutable state + gint scale_factor; /* the outputs scale factor */ +} EekRenderer; + + +/// Mutable part of the renderer state. +/// TODO: Possibly should include scale factor. +struct render_geometry { /// Background extents gdouble allocation_width; gdouble allocation_height; - gint scale_factor; /* the outputs scale factor */ /// Coords transformation struct transformation widget_to_layout; -} EekRenderer; - +}; 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, - gdouble width, - gdouble height); void eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale); @@ -64,13 +65,14 @@ cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name, gint size, gint scale); -void eek_renderer_render_keyboard (EekRenderer *renderer, struct transformation widget_to_layout, struct submission *submission, +void eek_renderer_render_keyboard (EekRenderer *renderer, struct render_geometry geometry, struct submission *submission, cairo_t *cr, LevelKeyboard *keyboard); void eek_renderer_free (EekRenderer *self); -struct transformation -eek_renderer_get_transformation (EekRenderer *renderer); +struct render_geometry +eek_render_geometry_from_allocation_size (struct squeek_layout *layout, + gdouble width, gdouble height); G_END_DECLS #endif /* EEK_RENDERER_H */