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.
This commit is contained in:
		@ -45,6 +45,8 @@
 | 
				
			|||||||
typedef struct _EekGtkKeyboardPrivate
 | 
					typedef struct _EekGtkKeyboardPrivate
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    EekRenderer *renderer; // owned, nullable
 | 
					    EekRenderer *renderer; // owned, nullable
 | 
				
			||||||
 | 
					    struct render_geometry render_geometry; // mutable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekboardContextService *eekboard_context; // unowned reference
 | 
					    EekboardContextService *eekboard_context; // unowned reference
 | 
				
			||||||
    struct submission *submission; // 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);
 | 
					    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
 | 
					static gboolean
 | 
				
			||||||
eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
					eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
				
			||||||
                            cairo_t   *cr)
 | 
					                            cairo_t   *cr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self);
 | 
				
			||||||
    EekGtkKeyboardPrivate *priv =
 | 
					    EekGtkKeyboardPrivate *priv =
 | 
				
			||||||
        eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
 | 
					        eek_gtk_keyboard_get_instance_private (keyboard);
 | 
				
			||||||
    GtkAllocation allocation;
 | 
					    GtkAllocation allocation;
 | 
				
			||||||
    gtk_widget_get_allocation (self, &allocation);
 | 
					    gtk_widget_get_allocation (self, &allocation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,15 +105,14 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
				
			|||||||
                    priv->keyboard,
 | 
					                    priv->keyboard,
 | 
				
			||||||
                    pcontext);
 | 
					                    pcontext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        eek_renderer_set_allocation_size (priv->renderer,
 | 
					        set_allocation_size (keyboard, priv->keyboard->layout,
 | 
				
			||||||
                                          priv->keyboard->layout,
 | 
					            allocation.width, allocation.height);
 | 
				
			||||||
                                          allocation.width,
 | 
					 | 
				
			||||||
                                          allocation.height);
 | 
					 | 
				
			||||||
        eek_renderer_set_scale_factor (priv->renderer,
 | 
					        eek_renderer_set_scale_factor (priv->renderer,
 | 
				
			||||||
                                       gtk_widget_get_scale_factor (self));
 | 
					                                       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;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -117,8 +129,9 @@ static void
 | 
				
			|||||||
eek_gtk_keyboard_real_size_allocate (GtkWidget     *self,
 | 
					eek_gtk_keyboard_real_size_allocate (GtkWidget     *self,
 | 
				
			||||||
                                     GtkAllocation *allocation)
 | 
					                                     GtkAllocation *allocation)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self);
 | 
				
			||||||
    EekGtkKeyboardPrivate *priv =
 | 
					    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
 | 
					    // check if the change would switch types
 | 
				
			||||||
    enum squeek_arrangement_kind new_type = get_type(
 | 
					    enum squeek_arrangement_kind new_type = get_type(
 | 
				
			||||||
                (uint32_t)(allocation->width - allocation->x),
 | 
					                (uint32_t)(allocation->width - allocation->x),
 | 
				
			||||||
@ -130,10 +143,8 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget     *self,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (priv->renderer) {
 | 
					    if (priv->renderer) {
 | 
				
			||||||
        eek_renderer_set_allocation_size (priv->renderer,
 | 
					        set_allocation_size (keyboard, priv->keyboard->layout,
 | 
				
			||||||
                                          priv->keyboard->layout,
 | 
					            allocation->width, allocation->height);
 | 
				
			||||||
                                          allocation->width,
 | 
					 | 
				
			||||||
                                          allocation->height);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
 | 
					    GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->
 | 
				
			||||||
@ -162,7 +173,7 @@ static void depress(EekGtkKeyboard *self,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    squeek_layout_depress(priv->keyboard->layout,
 | 
					    squeek_layout_depress(priv->keyboard->layout,
 | 
				
			||||||
                          priv->submission,
 | 
					                          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,
 | 
					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,
 | 
					    squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
 | 
				
			||||||
                       priv->submission,
 | 
					                       priv->submission,
 | 
				
			||||||
                       x, y, eek_renderer_get_transformation(priv->renderer), time,
 | 
					                       x, y, priv->render_geometry.widget_to_layout, time,
 | 
				
			||||||
                       priv->eekboard_context, self);
 | 
					                       priv->eekboard_context, self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -185,8 +196,7 @@ static void release(EekGtkKeyboard *self, guint32 time)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
 | 
					    squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
 | 
				
			||||||
                          priv->submission,
 | 
					                          priv->submission, priv->render_geometry.widget_to_layout, time,
 | 
				
			||||||
                          eek_renderer_get_transformation(priv->renderer), time,
 | 
					 | 
				
			||||||
                          priv->eekboard_context, self);
 | 
					                          priv->eekboard_context, self);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -396,6 +406,24 @@ eek_gtk_keyboard_new (EekboardContextService *eekservice,
 | 
				
			|||||||
    priv->submission = submission;
 | 
					    priv->submission = submission;
 | 
				
			||||||
    priv->layout = layout;
 | 
					    priv->layout = layout;
 | 
				
			||||||
    priv->renderer = NULL;
 | 
					    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,
 | 
					    g_signal_connect (eekservice,
 | 
				
			||||||
                      "notify::keyboard",
 | 
					                      "notify::keyboard",
 | 
				
			||||||
                      G_CALLBACK(on_notify_keyboard),
 | 
					                      G_CALLBACK(on_notify_keyboard),
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@
 | 
				
			|||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
#include <gtk/gtk.h>
 | 
					#include <gtk/gtk.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eek/eek-renderer.h"
 | 
				
			||||||
#include "eek/eek-types.h"
 | 
					#include "eek/eek-types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct submission;
 | 
					struct submission;
 | 
				
			||||||
 | 
				
			|||||||
@ -194,23 +194,23 @@ render_button_label (cairo_t     *cr,
 | 
				
			|||||||
// FIXME: Pass just the active modifiers instead of entire submission
 | 
					// FIXME: Pass just the active modifiers instead of entire submission
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
eek_renderer_render_keyboard (EekRenderer *self,
 | 
					eek_renderer_render_keyboard (EekRenderer *self,
 | 
				
			||||||
                              struct transformation widget_to_layout,
 | 
					                              struct render_geometry geometry,
 | 
				
			||||||
                              struct submission *submission,
 | 
					                              struct submission *submission,
 | 
				
			||||||
                                   cairo_t     *cr,
 | 
					                                   cairo_t     *cr,
 | 
				
			||||||
                              LevelKeyboard *keyboard)
 | 
					                              LevelKeyboard *keyboard)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    g_return_if_fail (self->allocation_width > 0.0);
 | 
					    g_return_if_fail (geometry.allocation_width > 0.0);
 | 
				
			||||||
    g_return_if_fail (self->allocation_height > 0.0);
 | 
					    g_return_if_fail (geometry.allocation_height > 0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Paint the background covering the entire widget area */
 | 
					    /* Paint the background covering the entire widget area */
 | 
				
			||||||
    gtk_render_background (self->view_context,
 | 
					    gtk_render_background (self->view_context,
 | 
				
			||||||
                           cr,
 | 
					                           cr,
 | 
				
			||||||
                           0, 0,
 | 
					                           0, 0,
 | 
				
			||||||
                           self->allocation_width, self->allocation_height);
 | 
					                           geometry.allocation_width, geometry.allocation_height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_save(cr);
 | 
					    cairo_save(cr);
 | 
				
			||||||
    cairo_translate (cr, widget_to_layout.origin_x, widget_to_layout.origin_y);
 | 
					    cairo_translate (cr, geometry.widget_to_layout.origin_x, geometry.widget_to_layout.origin_y);
 | 
				
			||||||
    cairo_scale (cr, widget_to_layout.scale, widget_to_layout.scale);
 | 
					    cairo_scale (cr, geometry.widget_to_layout.scale, geometry.widget_to_layout.scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    squeek_draw_layout_base_view(keyboard->layout, self, cr);
 | 
					    squeek_draw_layout_base_view(keyboard->layout, self, cr);
 | 
				
			||||||
    squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission);
 | 
					    squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission);
 | 
				
			||||||
@ -262,8 +262,6 @@ static void
 | 
				
			|||||||
renderer_init (EekRenderer *self)
 | 
					renderer_init (EekRenderer *self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    self->pcontext = NULL;
 | 
					    self->pcontext = NULL;
 | 
				
			||||||
    self->allocation_width = 0.0;
 | 
					 | 
				
			||||||
    self->allocation_height = 0.0;
 | 
					 | 
				
			||||||
    self->scale_factor = 1;
 | 
					    self->scale_factor = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->css_provider = squeek_load_style();
 | 
					    self->css_provider = squeek_load_style();
 | 
				
			||||||
@ -310,22 +308,18 @@ eek_renderer_new (LevelKeyboard  *keyboard,
 | 
				
			|||||||
    return renderer;
 | 
					    return renderer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					struct render_geometry
 | 
				
			||||||
eek_renderer_set_allocation_size (EekRenderer *renderer,
 | 
					eek_render_geometry_from_allocation_size (struct squeek_layout *layout,
 | 
				
			||||||
                                  struct squeek_layout *layout,
 | 
					 | 
				
			||||||
                                  gdouble      width,
 | 
					                                  gdouble      width,
 | 
				
			||||||
                                  gdouble      height)
 | 
					                                  gdouble      height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    g_return_if_fail (width > 0.0 && height > 0.0);
 | 
					    struct render_geometry ret = {
 | 
				
			||||||
 | 
					        .allocation_width = width,
 | 
				
			||||||
    renderer->allocation_width = width;
 | 
					        .allocation_height = height,
 | 
				
			||||||
    renderer->allocation_height = height;
 | 
					        .widget_to_layout = squeek_layout_calculate_transformation(
 | 
				
			||||||
 | 
					            layout, width, height),
 | 
				
			||||||
    renderer->widget_to_layout = squeek_layout_calculate_transformation(
 | 
					    };
 | 
				
			||||||
                layout,
 | 
					    return ret;
 | 
				
			||||||
                renderer->allocation_width, renderer->allocation_height);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // This is where size-dependent surfaces would be released
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@ -357,8 +351,3 @@ eek_renderer_get_icon_surface (const gchar *icon_name,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return surface;
 | 
					    return surface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
struct transformation
 | 
					 | 
				
			||||||
eek_renderer_get_transformation (EekRenderer *renderer) {
 | 
					 | 
				
			||||||
    return renderer->widget_to_layout;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -41,22 +41,23 @@ typedef struct EekRenderer
 | 
				
			|||||||
    gchar *extra_style; // owned
 | 
					    gchar *extra_style; // owned
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Mutable state
 | 
					    // 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
 | 
					    /// Background extents
 | 
				
			||||||
    gdouble allocation_width;
 | 
					    gdouble allocation_width;
 | 
				
			||||||
    gdouble allocation_height;
 | 
					    gdouble allocation_height;
 | 
				
			||||||
    gint scale_factor; /* the outputs scale factor */
 | 
					 | 
				
			||||||
    /// Coords transformation
 | 
					    /// Coords transformation
 | 
				
			||||||
    struct transformation widget_to_layout;
 | 
					    struct transformation widget_to_layout;
 | 
				
			||||||
} EekRenderer;
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
GType            eek_renderer_get_type         (void) G_GNUC_CONST;
 | 
					GType            eek_renderer_get_type         (void) G_GNUC_CONST;
 | 
				
			||||||
EekRenderer     *eek_renderer_new              (LevelKeyboard     *keyboard,
 | 
					EekRenderer     *eek_renderer_new              (LevelKeyboard     *keyboard,
 | 
				
			||||||
                                                PangoContext    *pcontext);
 | 
					                                                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,
 | 
					void             eek_renderer_set_scale_factor (EekRenderer     *renderer,
 | 
				
			||||||
                                                gint             scale);
 | 
					                                                gint             scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,13 +65,14 @@ cairo_surface_t *eek_renderer_get_icon_surface(const gchar     *icon_name,
 | 
				
			|||||||
                                                gint             size,
 | 
					                                                gint             size,
 | 
				
			||||||
                                                gint             scale);
 | 
					                                                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);
 | 
					                                                cairo_t         *cr, LevelKeyboard *keyboard);
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
eek_renderer_free (EekRenderer        *self);
 | 
					eek_renderer_free (EekRenderer        *self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct transformation
 | 
					struct render_geometry
 | 
				
			||||||
eek_renderer_get_transformation (EekRenderer *renderer);
 | 
					eek_render_geometry_from_allocation_size (struct squeek_layout *layout,
 | 
				
			||||||
 | 
					    gdouble      width, gdouble      height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
#endif  /* EEK_RENDERER_H */
 | 
					#endif  /* EEK_RENDERER_H */
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user