Merge branch 'drop_key' into 'master'
Simplify renderer See merge request Librem5/squeekboard!272
This commit is contained in:
		
							
								
								
									
										3
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -324,6 +324,9 @@ name = "rs"
 | 
				
			|||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
					 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
					 "cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
					 "cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
					 "gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 "gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
					 "gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 "glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
					 "glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 "glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
					 "glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Cargo.toml
									
									
									
									
									
								
							@ -11,6 +11,15 @@ serde = { version = "1.0.*", features = ["derive"] }
 | 
				
			|||||||
serde_yaml = "0.8.*"
 | 
					serde_yaml = "0.8.*"
 | 
				
			||||||
xkbcommon = { version = "0.4.*", features = ["wayland"] }
 | 
					xkbcommon = { version = "0.4.*", features = ["wayland"] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.cairo-rs]
 | 
				
			||||||
 | 
					version = "0.5.*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.cairo-sys-rs]
 | 
				
			||||||
 | 
					version = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.gdk]
 | 
				
			||||||
 | 
					version = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies.gio]
 | 
					[dependencies.gio]
 | 
				
			||||||
version = ""
 | 
					version = ""
 | 
				
			||||||
features = ["v2_44"]
 | 
					features = ["v2_44"]
 | 
				
			||||||
@ -23,7 +32,6 @@ features = ["v2_44"]
 | 
				
			|||||||
version = ""
 | 
					version = ""
 | 
				
			||||||
features = ["v2_44"]
 | 
					features = ["v2_44"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
[dependencies.gtk]
 | 
					[dependencies.gtk]
 | 
				
			||||||
version = "0.5.*"
 | 
					version = "0.5.*"
 | 
				
			||||||
features = ["v3_22"]
 | 
					features = ["v3_22"]
 | 
				
			||||||
 | 
				
			|||||||
@ -61,10 +61,6 @@ typedef struct _EekGtkKeyboardPrivate
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
 | 
					G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void       render_pressed_button      (GtkWidget *widget, struct button_place *place);
 | 
					 | 
				
			||||||
static void       render_released_button     (GtkWidget *widget,
 | 
					 | 
				
			||||||
                                              const struct squeek_button *button);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
eek_gtk_keyboard_real_realize (GtkWidget      *self)
 | 
					eek_gtk_keyboard_real_realize (GtkWidget      *self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -101,10 +97,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
				
			|||||||
                                       gtk_widget_get_scale_factor (self));
 | 
					                                       gtk_widget_get_scale_factor (self));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // render the keyboard without any key activity (TODO: from a cached buffer)
 | 
					 | 
				
			||||||
    eek_renderer_render_keyboard (priv->renderer, cr);
 | 
					    eek_renderer_render_keyboard (priv->renderer, cr);
 | 
				
			||||||
    // render only a few remaining changes
 | 
					 | 
				
			||||||
    squeek_layout_draw_all_changed(priv->keyboard->layout, EEK_GTK_KEYBOARD(self));
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -158,8 +151,6 @@ eek_gtk_keyboard_real_button_press_event (GtkWidget      *self,
 | 
				
			|||||||
    return TRUE;
 | 
					    return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO: this belongs more in gtk_keyboard, with a way to find out which key to re-render
 | 
					// TODO: this belongs more in gtk_keyboard, with a way to find out which key to re-render
 | 
				
			||||||
static gboolean
 | 
					static gboolean
 | 
				
			||||||
eek_gtk_keyboard_real_button_release_event (GtkWidget      *self,
 | 
					eek_gtk_keyboard_real_button_release_event (GtkWidget      *self,
 | 
				
			||||||
@ -248,6 +239,7 @@ eek_gtk_keyboard_set_property (GObject      *object,
 | 
				
			|||||||
                               const GValue *value,
 | 
					                               const GValue *value,
 | 
				
			||||||
                               GParamSpec   *pspec)
 | 
					                               GParamSpec   *pspec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    (void)value;
 | 
				
			||||||
    switch (prop_id) {
 | 
					    switch (prop_id) {
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
					        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
				
			||||||
@ -304,7 +296,9 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
eek_gtk_keyboard_init (EekGtkKeyboard *self)
 | 
					eek_gtk_keyboard_init (EekGtkKeyboard *self)
 | 
				
			||||||
{}
 | 
					{
 | 
				
			||||||
 | 
					    (void)self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * eek_gtk_keyboard_new:
 | 
					 * eek_gtk_keyboard_new:
 | 
				
			||||||
@ -322,110 +316,7 @@ eek_gtk_keyboard_new (LevelKeyboard *keyboard)
 | 
				
			|||||||
    return GTK_WIDGET(ret);
 | 
					    return GTK_WIDGET(ret);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					EekRenderer *eek_gtk_keyboard_get_renderer(EekGtkKeyboard *self) {
 | 
				
			||||||
render_pressed_button (GtkWidget *widget,
 | 
					 | 
				
			||||||
                       struct button_place *place)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekGtkKeyboard        *self = EEK_GTK_KEYBOARD (widget);
 | 
					 | 
				
			||||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
					    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
				
			||||||
 | 
					    return priv->renderer;
 | 
				
			||||||
    GdkWindow         *window  = gtk_widget_get_window (widget);
 | 
					 | 
				
			||||||
    cairo_region_t    *region  = gdk_window_get_clip_region (window);
 | 
					 | 
				
			||||||
    GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
 | 
					 | 
				
			||||||
    cairo_t           *cr      = gdk_drawing_context_get_cairo_context (context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
    eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
    gdk_window_end_draw_frame (window, context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_region_destroy (region);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_gtk_render_locked_button (EekGtkKeyboard *self, struct button_place place)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    GdkWindow         *window  = gtk_widget_get_window (GTK_WIDGET(self));
 | 
					 | 
				
			||||||
    cairo_region_t    *region  = gdk_window_get_clip_region (window);
 | 
					 | 
				
			||||||
    GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
 | 
					 | 
				
			||||||
    cairo_t           *cr      = gdk_drawing_context_get_cairo_context (context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_renderer_render_button (priv->renderer, cr, &place, 1.0, TRUE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gdk_window_end_draw_frame (window, context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_region_destroy (region);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO: does it really redraw the entire keyboard?
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
render_released_button (GtkWidget *widget,
 | 
					 | 
				
			||||||
                        const struct squeek_button *button)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    (void)button;
 | 
					 | 
				
			||||||
    EekGtkKeyboard        *self = EEK_GTK_KEYBOARD (widget);
 | 
					 | 
				
			||||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    GdkWindow         *window  = gtk_widget_get_window (widget);
 | 
					 | 
				
			||||||
    cairo_region_t    *region  = gdk_window_get_clip_region (window);
 | 
					 | 
				
			||||||
    GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
 | 
					 | 
				
			||||||
    cairo_t           *cr      = gdk_drawing_context_get_cairo_context (context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_renderer_render_keyboard (priv->renderer, cr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gdk_window_end_draw_frame (window, context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_region_destroy (region);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_gtk_on_button_pressed (struct button_place place,
 | 
					 | 
				
			||||||
                   EekGtkKeyboard *self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* renderer may have not been set yet if the widget is a popup */
 | 
					 | 
				
			||||||
    if (!priv->renderer)
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!place.row) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    render_pressed_button (GTK_WIDGET(self), &place);
 | 
					 | 
				
			||||||
    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if HAVE_LIBCANBERRA
 | 
					 | 
				
			||||||
    ca_gtk_play_for_widget (widget, 0,
 | 
					 | 
				
			||||||
                            CA_PROP_EVENT_ID, "button-pressed",
 | 
					 | 
				
			||||||
                            CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
 | 
					 | 
				
			||||||
                            CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
 | 
					 | 
				
			||||||
                            NULL);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_gtk_on_button_released (const struct squeek_button *button,
 | 
					 | 
				
			||||||
                    struct squeek_view *view,
 | 
					 | 
				
			||||||
                    EekGtkKeyboard *self)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    (void)view;
 | 
					 | 
				
			||||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* renderer may have not been set yet if the widget is a popup */
 | 
					 | 
				
			||||||
    if (!priv->renderer)
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render_released_button (GTK_WIDGET(self), button);
 | 
					 | 
				
			||||||
    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if HAVE_LIBCANBERRA
 | 
					 | 
				
			||||||
    ca_gtk_play_for_widget (widget, 0,
 | 
					 | 
				
			||||||
                            CA_PROP_EVENT_ID, "button-released",
 | 
					 | 
				
			||||||
                            CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
 | 
					 | 
				
			||||||
                            CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
 | 
					 | 
				
			||||||
                            NULL);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -34,8 +34,6 @@
 | 
				
			|||||||
#include "eekboard/eekboard-context-service.h"
 | 
					#include "eekboard/eekboard-context-service.h"
 | 
				
			||||||
#include "eekboard/key-emitter.h"
 | 
					#include "eekboard/key-emitter.h"
 | 
				
			||||||
#include "keymap.h"
 | 
					#include "keymap.h"
 | 
				
			||||||
#include "src/keyboard.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "eek-keyboard.h"
 | 
					#include "eek-keyboard.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void level_keyboard_deinit(LevelKeyboard *self) {
 | 
					void level_keyboard_deinit(LevelKeyboard *self) {
 | 
				
			||||||
@ -59,8 +57,3 @@ LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek
 | 
				
			|||||||
    keyboard->manager = manager;
 | 
					    keyboard->manager = manager;
 | 
				
			||||||
    return keyboard;
 | 
					    return keyboard;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return squeek_layout_get_current_view(keyboard->layout);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,6 @@ typedef struct _LevelKeyboard LevelKeyboard;
 | 
				
			|||||||
gchar *             eek_keyboard_get_keymap
 | 
					gchar *             eek_keyboard_get_keymap
 | 
				
			||||||
                                     (LevelKeyboard *keyboard);
 | 
					                                     (LevelKeyboard *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard);
 | 
					 | 
				
			||||||
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout);
 | 
					LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout);
 | 
				
			||||||
void level_keyboard_deinit(LevelKeyboard *self);
 | 
					void level_keyboard_deinit(LevelKeyboard *self);
 | 
				
			||||||
void level_keyboard_free(LevelKeyboard *self);
 | 
					void level_keyboard_free(LevelKeyboard *self);
 | 
				
			||||||
 | 
				
			|||||||
@ -42,17 +42,14 @@ typedef struct _EekRendererPrivate
 | 
				
			|||||||
    GtkStyleContext *view_context; // owned
 | 
					    GtkStyleContext *view_context; // owned
 | 
				
			||||||
    GtkStyleContext *button_context; // TODO: maybe move a copy to each button
 | 
					    GtkStyleContext *button_context; // TODO: maybe move a copy to each button
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdouble border_width;
 | 
					    gdouble border_width; // FIXME: border of what?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdouble allocation_width;
 | 
					    gdouble allocation_width;
 | 
				
			||||||
    gdouble allocation_height;
 | 
					    gdouble allocation_height;
 | 
				
			||||||
    gdouble scale;
 | 
					 | 
				
			||||||
    gint scale_factor; /* the outputs scale factor */
 | 
					    gint scale_factor; /* the outputs scale factor */
 | 
				
			||||||
    gint origin_x;
 | 
					    struct transformation widget_to_layout;
 | 
				
			||||||
    gint origin_y;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PangoFontDescription *font; // owned reference
 | 
					    PangoFontDescription *font; // owned reference
 | 
				
			||||||
    cairo_surface_t *keyboard_surface;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
} EekRendererPrivate;
 | 
					} EekRendererPrivate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,110 +59,10 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
 | 
				
			|||||||
static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, GtkStyleContext *ctx,
 | 
					static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, GtkStyleContext *ctx,
 | 
				
			||||||
                                                const struct squeek_button *button);
 | 
					                                                const struct squeek_button *button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void invalidate                         (EekRenderer *renderer);
 | 
					void eek_render_button                         (EekRenderer *self,
 | 
				
			||||||
static void render_button                         (EekRenderer *self,
 | 
					                                                cairo_t     *cr, const struct squeek_button *button,
 | 
				
			||||||
                                                cairo_t     *cr, EekBounds view_bounds, struct button_place *place,
 | 
					 | 
				
			||||||
                                                gboolean     pressed, gboolean locked);
 | 
					                                                gboolean     pressed, gboolean locked);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct _CreateKeyboardSurfaceCallbackData {
 | 
					 | 
				
			||||||
    cairo_t *cr;
 | 
					 | 
				
			||||||
    EekRenderer *renderer;
 | 
					 | 
				
			||||||
    struct squeek_view *view;
 | 
					 | 
				
			||||||
    struct squeek_row *row;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
typedef struct _CreateKeyboardSurfaceCallbackData CreateKeyboardSurfaceCallbackData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
create_keyboard_surface_button_callback (struct squeek_button *button,
 | 
					 | 
				
			||||||
                                      gpointer    user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    CreateKeyboardSurfaceCallbackData *data = user_data;
 | 
					 | 
				
			||||||
    EekBounds bounds = squeek_button_get_bounds(button);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_save (data->cr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_translate (data->cr, bounds.x, bounds.y);
 | 
					 | 
				
			||||||
    cairo_rectangle (data->cr,
 | 
					 | 
				
			||||||
                     0.0,
 | 
					 | 
				
			||||||
                     0.0,
 | 
					 | 
				
			||||||
                     bounds.width + 100,
 | 
					 | 
				
			||||||
                     bounds.height + 100);
 | 
					 | 
				
			||||||
    cairo_clip (data->cr);
 | 
					 | 
				
			||||||
    struct button_place place = {
 | 
					 | 
				
			||||||
        .row = data->row,
 | 
					 | 
				
			||||||
        .button = button,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    render_button (data->renderer, data->cr, squeek_view_get_bounds(data->view), &place, FALSE, FALSE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_restore (data->cr);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
create_keyboard_surface_row_callback (struct squeek_row *row,
 | 
					 | 
				
			||||||
                                          gpointer    user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    CreateKeyboardSurfaceCallbackData *data = user_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekBounds bounds = squeek_row_get_bounds(row);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_save (data->cr);
 | 
					 | 
				
			||||||
    cairo_translate (data->cr, bounds.x, bounds.y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gint angle = squeek_row_get_angle (row);
 | 
					 | 
				
			||||||
    cairo_rotate (data->cr, angle * G_PI / 180);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data->row = row;
 | 
					 | 
				
			||||||
    squeek_row_foreach(row, create_keyboard_surface_button_callback, data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_restore (data->cr);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    GdkRGBA color = {0};
 | 
					 | 
				
			||||||
    gtk_style_context_get_color (priv->view_context, GTK_STATE_FLAG_NORMAL, &color);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    CreateKeyboardSurfaceCallbackData data = {
 | 
					 | 
				
			||||||
        .cr = cairo_create (priv->keyboard_surface),
 | 
					 | 
				
			||||||
        .renderer = renderer,
 | 
					 | 
				
			||||||
        .view = view,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Paint the background covering the entire widget area */
 | 
					 | 
				
			||||||
    gtk_render_background (priv->view_context,
 | 
					 | 
				
			||||||
                           data.cr,
 | 
					 | 
				
			||||||
                           0, 0,
 | 
					 | 
				
			||||||
                           priv->allocation_width, priv->allocation_height);
 | 
					 | 
				
			||||||
    gtk_render_frame (priv->view_context,
 | 
					 | 
				
			||||||
                      data.cr,
 | 
					 | 
				
			||||||
                      0, 0,
 | 
					 | 
				
			||||||
                      priv->allocation_width, priv->allocation_height);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_save (data.cr);
 | 
					 | 
				
			||||||
    cairo_scale (data.cr, priv->scale, priv->scale);
 | 
					 | 
				
			||||||
    cairo_translate (data.cr, bounds.x, bounds.y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_set_source_rgba (data.cr,
 | 
					 | 
				
			||||||
                           color.red,
 | 
					 | 
				
			||||||
                           color.green,
 | 
					 | 
				
			||||||
                           color.blue,
 | 
					 | 
				
			||||||
                           color.alpha);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* draw rows */
 | 
					 | 
				
			||||||
    squeek_view_foreach(level_keyboard_current(priv->keyboard),
 | 
					 | 
				
			||||||
                        create_keyboard_surface_row_callback,
 | 
					 | 
				
			||||||
                        &data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_restore (data.cr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_destroy (data.cr);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
render_outline (cairo_t     *cr,
 | 
					render_outline (cairo_t     *cr,
 | 
				
			||||||
                GtkStyleContext *ctx,
 | 
					                GtkStyleContext *ctx,
 | 
				
			||||||
@ -190,46 +87,20 @@ render_outline (cairo_t     *cr,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void render_button_in_context(EekRenderer *self,
 | 
					static void render_button_in_context(EekRenderer *self,
 | 
				
			||||||
                                     gdouble scale,
 | 
					 | 
				
			||||||
                                     gint scale_factor,
 | 
					                                     gint scale_factor,
 | 
				
			||||||
                                     cairo_t     *cr,
 | 
					                                     cairo_t     *cr,
 | 
				
			||||||
                                     GtkStyleContext *ctx,
 | 
					                                     GtkStyleContext *ctx,
 | 
				
			||||||
                                     EekBounds view_bounds,
 | 
					                                     const struct squeek_button *button) {
 | 
				
			||||||
                                     struct button_place *place,
 | 
					 | 
				
			||||||
                                     gboolean active) {
 | 
					 | 
				
			||||||
    cairo_surface_t *outline_surface = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* render outline */
 | 
					 | 
				
			||||||
    EekBounds bounds = squeek_button_get_bounds(place->button);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cairo_t *cr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Outline will be drawn on the outside of the button, so the
 | 
					 | 
				
			||||||
        // surface needs to be bigger than the button
 | 
					 | 
				
			||||||
        outline_surface =
 | 
					 | 
				
			||||||
            cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 | 
					 | 
				
			||||||
                                        (int)ceil(bounds.width) + 10,
 | 
					 | 
				
			||||||
                                        (int)ceil(bounds.height) + 10);
 | 
					 | 
				
			||||||
        cr = cairo_create (outline_surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* blank background */
 | 
					    /* blank background */
 | 
				
			||||||
    cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
 | 
					    cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
 | 
				
			||||||
    cairo_paint (cr);
 | 
					    cairo_paint (cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cairo_save (cr);
 | 
					    EekBounds bounds = squeek_button_get_bounds(button);
 | 
				
			||||||
        eek_renderer_apply_transformation_for_button (cr, view_bounds, place, 1.0, FALSE);
 | 
					 | 
				
			||||||
    render_outline (cr, ctx, bounds);
 | 
					    render_outline (cr, ctx, bounds);
 | 
				
			||||||
        cairo_restore (cr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        cairo_destroy (cr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
 | 
					 | 
				
			||||||
    cairo_surface_destroy(outline_surface);
 | 
					 | 
				
			||||||
    cairo_paint (cr);
 | 
					    cairo_paint (cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* render icon (if any) */
 | 
					    /* render icon (if any) */
 | 
				
			||||||
    const char *icon_name = squeek_button_get_icon_name(place->button);
 | 
					    const char *icon_name = squeek_button_get_icon_name(button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (icon_name) {
 | 
					    if (icon_name) {
 | 
				
			||||||
        cairo_surface_t *icon_surface =
 | 
					        cairo_surface_t *icon_surface =
 | 
				
			||||||
@ -259,14 +130,13 @@ static void render_button_in_context(EekRenderer *self,
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    eek_renderer_render_button_label (self, cr, ctx, place->button);
 | 
					    eek_renderer_render_button_label (self, cr, ctx, button);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					void
 | 
				
			||||||
render_button (EekRenderer *self,
 | 
					eek_render_button (EekRenderer *self,
 | 
				
			||||||
            cairo_t     *cr,
 | 
					            cairo_t     *cr,
 | 
				
			||||||
               EekBounds view_bounds,
 | 
					            const struct squeek_button *button,
 | 
				
			||||||
            struct button_place *place,
 | 
					 | 
				
			||||||
               gboolean     pressed,
 | 
					               gboolean     pressed,
 | 
				
			||||||
               gboolean     locked)
 | 
					               gboolean     locked)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -277,7 +147,7 @@ render_button (EekRenderer *self,
 | 
				
			|||||||
       from the button's symbol. */
 | 
					       from the button's symbol. */
 | 
				
			||||||
    g_autoptr (GtkWidgetPath) path = NULL;
 | 
					    g_autoptr (GtkWidgetPath) path = NULL;
 | 
				
			||||||
    path = gtk_widget_path_copy (gtk_style_context_get_path (ctx));
 | 
					    path = gtk_widget_path_copy (gtk_style_context_get_path (ctx));
 | 
				
			||||||
    const char *name = squeek_button_get_name(place->button);
 | 
					    const char *name = squeek_button_get_name(button);
 | 
				
			||||||
    gtk_widget_path_iter_set_name (path, -1, name);
 | 
					    gtk_widget_path_iter_set_name (path, -1, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Update the style context with the updated widget path. */
 | 
					    /* Update the style context with the updated widget path. */
 | 
				
			||||||
@ -286,13 +156,13 @@ render_button (EekRenderer *self,
 | 
				
			|||||||
       (pressed) or normal. */
 | 
					       (pressed) or normal. */
 | 
				
			||||||
    gtk_style_context_set_state(ctx,
 | 
					    gtk_style_context_set_state(ctx,
 | 
				
			||||||
        pressed ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
 | 
					        pressed ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
 | 
				
			||||||
    const char *outline_name = squeek_button_get_outline_name(place->button);
 | 
					    const char *outline_name = squeek_button_get_outline_name(button);
 | 
				
			||||||
    if (locked) {
 | 
					    if (locked) {
 | 
				
			||||||
        gtk_style_context_add_class(ctx, "locked");
 | 
					        gtk_style_context_add_class(ctx, "locked");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    gtk_style_context_add_class(ctx, outline_name);
 | 
					    gtk_style_context_add_class(ctx, outline_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render_button_in_context(self, priv->scale, priv->scale_factor, cr, ctx, view_bounds, place, pressed);
 | 
					    render_button_in_context(self, priv->scale_factor, cr, ctx, button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Save and restore functions don't work if gtk_render_* was used in between
 | 
					    // Save and restore functions don't work if gtk_render_* was used in between
 | 
				
			||||||
    gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL);
 | 
					    gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL);
 | 
				
			||||||
@ -302,47 +172,6 @@ render_button (EekRenderer *self,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * eek_renderer_apply_transformation_for_key:
 | 
					 | 
				
			||||||
 * @self: The renderer used to render the key
 | 
					 | 
				
			||||||
 * @cr: The Cairo rendering context used for rendering
 | 
					 | 
				
			||||||
 * @key: The key to be transformed
 | 
					 | 
				
			||||||
 * @scale: The factor used to scale the key bounds before rendering
 | 
					 | 
				
			||||||
 * @rotate: Whether to rotate the key by the angle defined for the key's
 | 
					 | 
				
			||||||
 *   in its section definition
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  Applies a transformation, consisting of scaling and rotation, to the
 | 
					 | 
				
			||||||
 *  current rendering context using the bounds for the given key. The scale
 | 
					 | 
				
			||||||
 *  factor is separate to the normal scale factor for the keyboard as a whole
 | 
					 | 
				
			||||||
 *  and is applied cumulatively. It is typically used to render larger than
 | 
					 | 
				
			||||||
 *  normal keys for popups.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_renderer_apply_transformation_for_button (cairo_t     *cr,
 | 
					 | 
				
			||||||
                                              EekBounds view_bounds,
 | 
					 | 
				
			||||||
                                           struct button_place *place,
 | 
					 | 
				
			||||||
                                           gdouble      scale,
 | 
					 | 
				
			||||||
                                           gboolean     rotate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekBounds bounds, rotated_bounds;
 | 
					 | 
				
			||||||
    gdouble s;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_renderer_get_button_bounds (view_bounds, place, &bounds, FALSE);
 | 
					 | 
				
			||||||
    eek_renderer_get_button_bounds (view_bounds, place, &rotated_bounds, TRUE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gint angle = squeek_row_get_angle (place->row);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_scale (cr, scale, scale);
 | 
					 | 
				
			||||||
    if (rotate) {
 | 
					 | 
				
			||||||
        s = sin (angle * G_PI / 180);
 | 
					 | 
				
			||||||
        if (s < 0)
 | 
					 | 
				
			||||||
            cairo_translate (cr, 0, - bounds.width * s);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            cairo_translate (cr, bounds.height * s, 0);
 | 
					 | 
				
			||||||
        cairo_rotate (cr, angle * G_PI / 180);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
eek_renderer_render_button_label (EekRenderer *self,
 | 
					eek_renderer_render_button_label (EekRenderer *self,
 | 
				
			||||||
                                  cairo_t     *cr,
 | 
					                                  cairo_t     *cr,
 | 
				
			||||||
@ -415,76 +244,28 @@ eek_renderer_render_button_label (EekRenderer *self,
 | 
				
			|||||||
    g_object_unref (layout);
 | 
					    g_object_unref (layout);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					void
 | 
				
			||||||
 * eek_renderer_real_render_key:
 | 
					eek_renderer_render_keyboard (EekRenderer *self,
 | 
				
			||||||
 * @self: The renderer used to render the key
 | 
					 | 
				
			||||||
 * @cr: The Cairo rendering context used for rendering
 | 
					 | 
				
			||||||
 * @key: The key to be transformed
 | 
					 | 
				
			||||||
 * @scale: The factor used to scale the key bounds before rendering
 | 
					 | 
				
			||||||
 * @rotate: Whether to rotate the key by the angle defined for the key's
 | 
					 | 
				
			||||||
 *   in its section definition
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   Renders a key separately from the normal keyboard rendering.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
eek_renderer_real_render_button (EekRenderer *self,
 | 
					 | 
				
			||||||
                              cairo_t     *cr,
 | 
					 | 
				
			||||||
                              struct button_place *place,
 | 
					 | 
				
			||||||
                              gdouble      scale,
 | 
					 | 
				
			||||||
                              gboolean     rotate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
 | 
					 | 
				
			||||||
    EekBounds bounds;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekBounds view_bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
 | 
					 | 
				
			||||||
    eek_renderer_get_button_bounds (view_bounds, place, &bounds, rotate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_save (cr);
 | 
					 | 
				
			||||||
    /* Because this function is called separately from the keyboard rendering
 | 
					 | 
				
			||||||
       function, the transformation for the context needs to be set up */
 | 
					 | 
				
			||||||
    cairo_translate (cr, priv->origin_x, priv->origin_y);
 | 
					 | 
				
			||||||
    cairo_scale (cr, priv->scale, priv->scale);
 | 
					 | 
				
			||||||
    cairo_translate (cr, bounds.x, bounds.y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    eek_renderer_apply_transformation_for_button (cr, view_bounds, place, scale, rotate);
 | 
					 | 
				
			||||||
    struct squeek_key *key = squeek_button_get_key(place->button);
 | 
					 | 
				
			||||||
    render_button (
 | 
					 | 
				
			||||||
                self, cr, view_bounds, place,
 | 
					 | 
				
			||||||
                squeek_key_is_pressed(key) != 0,
 | 
					 | 
				
			||||||
                squeek_key_is_locked (key) != 0
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    cairo_restore (cr);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
eek_renderer_real_render_keyboard (EekRenderer *self,
 | 
					 | 
				
			||||||
                                   cairo_t     *cr)
 | 
					                                   cairo_t     *cr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
 | 
					    EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
 | 
				
			||||||
    cairo_pattern_t *source;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_return_if_fail (priv->keyboard);
 | 
					    g_return_if_fail (priv->keyboard);
 | 
				
			||||||
    g_return_if_fail (priv->allocation_width > 0.0);
 | 
					    g_return_if_fail (priv->allocation_width > 0.0);
 | 
				
			||||||
    g_return_if_fail (priv->allocation_height > 0.0);
 | 
					    g_return_if_fail (priv->allocation_height > 0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cairo_save (cr);
 | 
					    /* Paint the background covering the entire widget area */
 | 
				
			||||||
 | 
					    gtk_render_background (priv->view_context,
 | 
				
			||||||
    cairo_translate (cr, priv->origin_x, priv->origin_y);
 | 
					                           cr,
 | 
				
			||||||
 | 
					                           0, 0,
 | 
				
			||||||
    if (priv->keyboard_surface)
 | 
					 | 
				
			||||||
        cairo_surface_destroy (priv->keyboard_surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    priv->keyboard_surface = cairo_surface_create_for_rectangle (
 | 
					 | 
				
			||||||
        cairo_get_target (cr), 0, 0,
 | 
					 | 
				
			||||||
                           priv->allocation_width, priv->allocation_height);
 | 
					                           priv->allocation_width, priv->allocation_height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render_keyboard_surface (self, squeek_layout_get_current_view(priv->keyboard->layout));
 | 
					    cairo_save(cr);
 | 
				
			||||||
 | 
					    cairo_translate (cr, priv->widget_to_layout.origin_x, priv->widget_to_layout.origin_y);
 | 
				
			||||||
    cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0);
 | 
					    cairo_scale (cr, priv->widget_to_layout.scale, priv->widget_to_layout.scale);
 | 
				
			||||||
    source = cairo_get_source (cr);
 | 
					 | 
				
			||||||
    cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD);
 | 
					 | 
				
			||||||
    cairo_paint (cr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    squeek_draw_layout_base_view(priv->keyboard->layout, self, cr);
 | 
				
			||||||
 | 
					    squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr);
 | 
				
			||||||
    cairo_restore (cr);
 | 
					    cairo_restore (cr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -514,6 +295,7 @@ eek_renderer_get_property (GObject    *object,
 | 
				
			|||||||
                           GValue     *value,
 | 
					                           GValue     *value,
 | 
				
			||||||
                           GParamSpec *pspec)
 | 
					                           GParamSpec *pspec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    (void)value;
 | 
				
			||||||
    switch (prop_id) {
 | 
					    switch (prop_id) {
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
					        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
				
			||||||
@ -535,8 +317,7 @@ eek_renderer_dispose (GObject *object)
 | 
				
			|||||||
        priv->pcontext = NULL;
 | 
					        priv->pcontext = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* this will release all allocated surfaces and font if any */
 | 
					    // this is where renderer-specific surfaces would be released
 | 
				
			||||||
    invalidate (EEK_RENDERER(object));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    G_OBJECT_CLASS (eek_renderer_parent_class)->dispose (object);
 | 
					    G_OBJECT_CLASS (eek_renderer_parent_class)->dispose (object);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -560,9 +341,6 @@ eek_renderer_class_init (EekRendererClass *klass)
 | 
				
			|||||||
    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
 | 
					    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
 | 
				
			||||||
    GParamSpec        *pspec;
 | 
					    GParamSpec        *pspec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    klass->render_button = eek_renderer_real_render_button;
 | 
					 | 
				
			||||||
    klass->render_keyboard = eek_renderer_real_render_keyboard;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gobject_class->set_property = eek_renderer_set_property;
 | 
					    gobject_class->set_property = eek_renderer_set_property;
 | 
				
			||||||
    gobject_class->get_property = eek_renderer_get_property;
 | 
					    gobject_class->get_property = eek_renderer_get_property;
 | 
				
			||||||
    gobject_class->dispose = eek_renderer_dispose;
 | 
					    gobject_class->dispose = eek_renderer_dispose;
 | 
				
			||||||
@ -615,10 +393,8 @@ eek_renderer_init (EekRenderer *self)
 | 
				
			|||||||
    priv->border_width = 1.0;
 | 
					    priv->border_width = 1.0;
 | 
				
			||||||
    priv->allocation_width = 0.0;
 | 
					    priv->allocation_width = 0.0;
 | 
				
			||||||
    priv->allocation_height = 0.0;
 | 
					    priv->allocation_height = 0.0;
 | 
				
			||||||
    priv->scale = 1.0;
 | 
					 | 
				
			||||||
    priv->scale_factor = 1;
 | 
					    priv->scale_factor = 1;
 | 
				
			||||||
    priv->font = NULL;
 | 
					    priv->font = NULL;
 | 
				
			||||||
    priv->keyboard_surface = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GtkIconTheme *theme = gtk_icon_theme_get_default ();
 | 
					    GtkIconTheme *theme = gtk_icon_theme_get_default ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -627,17 +403,6 @@ eek_renderer_init (EekRenderer *self)
 | 
				
			|||||||
    priv->css_provider = squeek_load_style();
 | 
					    priv->css_provider = squeek_load_style();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
invalidate (EekRenderer *renderer)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (priv->keyboard_surface) {
 | 
					 | 
				
			||||||
        cairo_surface_destroy (priv->keyboard_surface);
 | 
					 | 
				
			||||||
        priv->keyboard_surface = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EekRenderer *
 | 
					EekRenderer *
 | 
				
			||||||
eek_renderer_new (LevelKeyboard  *keyboard,
 | 
					eek_renderer_new (LevelKeyboard  *keyboard,
 | 
				
			||||||
                  PangoContext *pcontext)
 | 
					                  PangoContext *pcontext)
 | 
				
			||||||
@ -685,8 +450,6 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
 | 
				
			|||||||
                                  gdouble      width,
 | 
					                                  gdouble      width,
 | 
				
			||||||
                                  gdouble      height)
 | 
					                                  gdouble      height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gdouble scale;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
					    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
				
			||||||
    g_return_if_fail (width > 0.0 && height > 0.0);
 | 
					    g_return_if_fail (width > 0.0 && height > 0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -695,99 +458,11 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
 | 
				
			|||||||
    priv->allocation_width = width;
 | 
					    priv->allocation_width = width;
 | 
				
			||||||
    priv->allocation_height = height;
 | 
					    priv->allocation_height = height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Calculate a scale factor to use when rendering the keyboard into the
 | 
					    priv->widget_to_layout = squeek_layout_calculate_transformation(
 | 
				
			||||||
       available space. */
 | 
					                priv->keyboard->layout,
 | 
				
			||||||
    EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
 | 
					                priv->allocation_width, priv->allocation_height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gdouble w = (bounds.x * 2) + bounds.width;
 | 
					    // This is where size-dependent surfaces would be released
 | 
				
			||||||
    gdouble h = (bounds.y * 2) + bounds.height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    scale = MIN(width / w, height / h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    priv->scale = scale;
 | 
					 | 
				
			||||||
    /* Set the rendering offset in widget coordinates to center the keyboard */
 | 
					 | 
				
			||||||
    priv->origin_x = (gint)floor((width - (scale * w)) / 2);
 | 
					 | 
				
			||||||
    priv->origin_y = (gint)floor((height - (scale * h)) / 2);
 | 
					 | 
				
			||||||
    invalidate (renderer);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_renderer_get_size (EekRenderer *renderer,
 | 
					 | 
				
			||||||
                       gdouble     *width,
 | 
					 | 
				
			||||||
                       gdouble     *height)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard));
 | 
					 | 
				
			||||||
    if (width)
 | 
					 | 
				
			||||||
        *width = bounds.width;
 | 
					 | 
				
			||||||
    if (height)
 | 
					 | 
				
			||||||
        *height = bounds.height;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_renderer_get_button_bounds (EekBounds view_bounds,
 | 
					 | 
				
			||||||
                                struct button_place *place,
 | 
					 | 
				
			||||||
                             EekBounds   *bounds,
 | 
					 | 
				
			||||||
                             gboolean     rotate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    gint angle = 0;
 | 
					 | 
				
			||||||
    EekPoint points[4], min, max;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_return_if_fail (place);
 | 
					 | 
				
			||||||
    g_return_if_fail (bounds != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekBounds button_bounds = squeek_button_get_bounds(place->button);
 | 
					 | 
				
			||||||
    EekBounds row_bounds = squeek_row_get_bounds (place->row);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!rotate) {
 | 
					 | 
				
			||||||
        button_bounds.x += view_bounds.x + row_bounds.x;
 | 
					 | 
				
			||||||
        button_bounds.y += view_bounds.y + row_bounds.y;
 | 
					 | 
				
			||||||
        *bounds = button_bounds;
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    points[0].x = button_bounds.x;
 | 
					 | 
				
			||||||
    points[0].y = button_bounds.y;
 | 
					 | 
				
			||||||
    points[1].x = points[0].x + button_bounds.width;
 | 
					 | 
				
			||||||
    points[1].y = points[0].y;
 | 
					 | 
				
			||||||
    points[2].x = points[1].x;
 | 
					 | 
				
			||||||
    points[2].y = points[1].y + button_bounds.height;
 | 
					 | 
				
			||||||
    points[3].x = points[0].x;
 | 
					 | 
				
			||||||
    points[3].y = points[2].y;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (rotate) {
 | 
					 | 
				
			||||||
        angle = squeek_row_get_angle (place->row);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    min = points[2];
 | 
					 | 
				
			||||||
    max = points[0];
 | 
					 | 
				
			||||||
    for (unsigned i = 0; i < G_N_ELEMENTS(points); i++) {
 | 
					 | 
				
			||||||
        eek_point_rotate (&points[i], angle);
 | 
					 | 
				
			||||||
        if (points[i].x < min.x)
 | 
					 | 
				
			||||||
            min.x = points[i].x;
 | 
					 | 
				
			||||||
        if (points[i].x > max.x)
 | 
					 | 
				
			||||||
            max.x = points[i].x;
 | 
					 | 
				
			||||||
        if (points[i].y < min.y)
 | 
					 | 
				
			||||||
            min.y = points[i].y;
 | 
					 | 
				
			||||||
        if (points[i].y > max.y)
 | 
					 | 
				
			||||||
            max.y = points[i].y;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    bounds->x = view_bounds.x + row_bounds.x + min.x;
 | 
					 | 
				
			||||||
    bounds->y = view_bounds.y + row_bounds.y + min.y;
 | 
					 | 
				
			||||||
    bounds->width = (max.x - min.x);
 | 
					 | 
				
			||||||
    bounds->height = (max.y - min.y);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
gdouble
 | 
					 | 
				
			||||||
eek_renderer_get_scale (EekRenderer *renderer)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    g_return_val_if_fail (EEK_IS_RENDERER(renderer), 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return priv->scale;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@ -823,29 +498,6 @@ eek_renderer_get_icon_surface (const gchar *icon_name,
 | 
				
			|||||||
    return surface;
 | 
					    return surface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_renderer_render_button (EekRenderer *renderer,
 | 
					 | 
				
			||||||
                         cairo_t     *cr,
 | 
					 | 
				
			||||||
                         struct button_place *place,
 | 
					 | 
				
			||||||
                         gdouble      scale,
 | 
					 | 
				
			||||||
                         gboolean     rotate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
					 | 
				
			||||||
    g_return_if_fail (place);
 | 
					 | 
				
			||||||
    g_return_if_fail (scale >= 0.0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EEK_RENDERER_GET_CLASS(renderer)->
 | 
					 | 
				
			||||||
        render_button (renderer, cr, place, scale, rotate);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
eek_renderer_render_keyboard (EekRenderer *renderer,
 | 
					 | 
				
			||||||
                              cairo_t     *cr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    g_return_if_fail (EEK_IS_RENDERER(renderer));
 | 
					 | 
				
			||||||
    EEK_RENDERER_GET_CLASS(renderer)->render_keyboard (renderer, cr);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					static gboolean
 | 
				
			||||||
sign (EekPoint *p1, EekPoint *p2, EekPoint *p3)
 | 
					sign (EekPoint *p1, EekPoint *p2, EekPoint *p3)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -899,10 +551,5 @@ eek_renderer_get_transformation (EekRenderer *renderer) {
 | 
				
			|||||||
    g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed);
 | 
					    g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
					    EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
 | 
				
			||||||
    struct transformation ret = {
 | 
					    return priv->widget_to_layout;
 | 
				
			||||||
        .origin_x = priv->origin_x,
 | 
					 | 
				
			||||||
        .origin_y = priv->origin_y,
 | 
					 | 
				
			||||||
        .scale = priv->scale,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,6 @@
 | 
				
			|||||||
#include <pango/pangocairo.h>
 | 
					#include <pango/pangocairo.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-types.h"
 | 
					#include "eek-types.h"
 | 
				
			||||||
#include "src/layout.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
G_BEGIN_DECLS
 | 
					G_BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,15 +35,6 @@ struct _EekRendererClass
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    GObjectClass parent_class;
 | 
					    GObjectClass parent_class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void             (* render_button)         (EekRenderer *self,
 | 
					 | 
				
			||||||
                                             cairo_t     *cr,
 | 
					 | 
				
			||||||
                                             struct button_place *place,
 | 
					 | 
				
			||||||
                                             gdouble      scale,
 | 
					 | 
				
			||||||
                                             gboolean     rotate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void             (* render_keyboard)    (EekRenderer *self,
 | 
					 | 
				
			||||||
                                             cairo_t     *cr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cairo_surface_t *(* get_icon_surface)   (EekRenderer *self,
 | 
					    cairo_surface_t *(* get_icon_surface)   (EekRenderer *self,
 | 
				
			||||||
                                             const gchar *icon_name,
 | 
					                                             const gchar *icon_name,
 | 
				
			||||||
                                             gint         size,
 | 
					                                             gint         size,
 | 
				
			||||||
@ -62,38 +52,15 @@ void             eek_renderer_set_allocation_size
 | 
				
			|||||||
                                               (EekRenderer     *renderer,
 | 
					                                               (EekRenderer     *renderer,
 | 
				
			||||||
                                                gdouble          width,
 | 
					                                                gdouble          width,
 | 
				
			||||||
                                                gdouble          height);
 | 
					                                                gdouble          height);
 | 
				
			||||||
void             eek_renderer_get_size         (EekRenderer     *renderer,
 | 
					 | 
				
			||||||
                                                gdouble         *width,
 | 
					 | 
				
			||||||
                                                gdouble         *height);
 | 
					 | 
				
			||||||
void             eek_renderer_get_button_bounds   (EekBounds view_bounds,
 | 
					 | 
				
			||||||
                                                struct button_place *button,
 | 
					 | 
				
			||||||
                                                EekBounds       *bounds,
 | 
					 | 
				
			||||||
                                                gboolean         rotate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
gdouble          eek_renderer_get_scale        (EekRenderer     *renderer);
 | 
					 | 
				
			||||||
void             eek_renderer_set_scale_factor (EekRenderer     *renderer,
 | 
					void             eek_renderer_set_scale_factor (EekRenderer     *renderer,
 | 
				
			||||||
                                                gint             scale);
 | 
					                                                gint             scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void             eek_renderer_render_button       (EekRenderer     *renderer,
 | 
					 | 
				
			||||||
                                                cairo_t         *cr,
 | 
					 | 
				
			||||||
                                                struct button_place *place,
 | 
					 | 
				
			||||||
                                                gdouble          scale,
 | 
					 | 
				
			||||||
                                                gboolean         rotate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cairo_surface_t *eek_renderer_get_icon_surface(const gchar     *icon_name,
 | 
					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,
 | 
					void             eek_renderer_render_keyboard  (EekRenderer     *renderer,
 | 
				
			||||||
                                                cairo_t         *cr);
 | 
					                                                cairo_t         *cr);
 | 
				
			||||||
void             eek_renderer_set_border_width (EekRenderer     *renderer,
 | 
					 | 
				
			||||||
                                                gdouble          border_width);
 | 
					 | 
				
			||||||
void             eek_renderer_apply_transformation_for_button
 | 
					 | 
				
			||||||
                                               (cairo_t         *cr,
 | 
					 | 
				
			||||||
                                                EekBounds view_bounds,
 | 
					 | 
				
			||||||
                                                struct button_place *place,
 | 
					 | 
				
			||||||
                                                gdouble          scale,
 | 
					 | 
				
			||||||
                                                gboolean         rotate);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct transformation
 | 
					struct transformation
 | 
				
			||||||
eek_renderer_get_transformation (EekRenderer *renderer);
 | 
					eek_renderer_get_transformation (EekRenderer *renderer);
 | 
				
			||||||
 | 
				
			|||||||
@ -88,5 +88,14 @@ struct transformation {
 | 
				
			|||||||
    gdouble origin_y;
 | 
					    gdouble origin_y;
 | 
				
			||||||
    gdouble scale;
 | 
					    gdouble scale;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct squeek_button;
 | 
				
			||||||
 | 
					struct squeek_row;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Represents the path to the button within a view
 | 
				
			||||||
 | 
					struct button_place {
 | 
				
			||||||
 | 
					    const struct squeek_row *row;
 | 
				
			||||||
 | 
					    const struct squeek_button *button;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
G_END_DECLS
 | 
					G_END_DECLS
 | 
				
			||||||
#endif  /* EEK_TYPES_H */
 | 
					#endif  /* EEK_TYPES_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,6 @@
 | 
				
			|||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-keyboard.h"
 | 
					#include "eek-keyboard.h"
 | 
				
			||||||
#include "src/keyboard.h"
 | 
					 | 
				
			||||||
#include "src/layout.h"
 | 
					#include "src/layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "eek-xml-layout.h"
 | 
					#include "eek-xml-layout.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -405,7 +405,7 @@ impl Layout {
 | 
				
			|||||||
        let views = HashMap::from_iter(
 | 
					        let views = HashMap::from_iter(
 | 
				
			||||||
            self.views.iter().map(|(name, view)| {(
 | 
					            self.views.iter().map(|(name, view)| {(
 | 
				
			||||||
                name.clone(),
 | 
					                name.clone(),
 | 
				
			||||||
                Box::new(::layout::View {
 | 
					                ::layout::View {
 | 
				
			||||||
                    bounds: ::layout::c::Bounds {
 | 
					                    bounds: ::layout::c::Bounds {
 | 
				
			||||||
                        x: self.bounds.x,
 | 
					                        x: self.bounds.x,
 | 
				
			||||||
                        y: self.bounds.y,
 | 
					                        y: self.bounds.y,
 | 
				
			||||||
@ -413,7 +413,7 @@ impl Layout {
 | 
				
			|||||||
                        height: self.bounds.height,
 | 
					                        height: self.bounds.height,
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    rows: view.iter().map(|row| {
 | 
					                    rows: view.iter().map(|row| {
 | 
				
			||||||
                        Box::new(::layout::Row {
 | 
					                        ::layout::Row {
 | 
				
			||||||
                            angle: 0,
 | 
					                            angle: 0,
 | 
				
			||||||
                            bounds: None,
 | 
					                            bounds: None,
 | 
				
			||||||
                            buttons: row.split_ascii_whitespace().map(|name| {
 | 
					                            buttons: row.split_ascii_whitespace().map(|name| {
 | 
				
			||||||
@ -427,9 +427,9 @@ impl Layout {
 | 
				
			|||||||
                                    &mut warning_handler,
 | 
					                                    &mut warning_handler,
 | 
				
			||||||
                                ))
 | 
					                                ))
 | 
				
			||||||
                            }).collect(),
 | 
					                            }).collect(),
 | 
				
			||||||
                        })
 | 
					                        }
 | 
				
			||||||
                    }).collect(),
 | 
					                    }).collect(),
 | 
				
			||||||
                })
 | 
					                }
 | 
				
			||||||
            )})
 | 
					            )})
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										126
									
								
								src/drawing.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/drawing.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,126 @@
 | 
				
			|||||||
 | 
					/*! Drawing the UI */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use cairo;
 | 
				
			||||||
 | 
					use std::cell::RefCell;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use ::keyboard;
 | 
				
			||||||
 | 
					use ::layout::{ Button, Layout };
 | 
				
			||||||
 | 
					use ::layout::c::{ EekGtkKeyboard, Point };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use glib::translate::FromGlibPtrNone;
 | 
				
			||||||
 | 
					use gtk::WidgetExt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod c {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use cairo_sys;
 | 
				
			||||||
 | 
					    use std::os::raw::c_void;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // This is constructed only in C, no need for warnings
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    #[repr(transparent)]
 | 
				
			||||||
 | 
					    #[derive(Clone, Copy)]
 | 
				
			||||||
 | 
					    pub struct EekRenderer(*const c_void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    extern "C" {
 | 
				
			||||||
 | 
					        // Button and View inside CButtonPlace are safe to pass to C
 | 
				
			||||||
 | 
					        // as long as they don't outlive the call
 | 
				
			||||||
 | 
					        // and nothing dereferences them
 | 
				
			||||||
 | 
					        #[allow(improper_ctypes)]
 | 
				
			||||||
 | 
					        pub fn eek_render_button(
 | 
				
			||||||
 | 
					            renderer: EekRenderer,
 | 
				
			||||||
 | 
					            cr: *mut cairo_sys::cairo_t,
 | 
				
			||||||
 | 
					            button: *const Button,
 | 
				
			||||||
 | 
					            pressed: u64,
 | 
				
			||||||
 | 
					            locked: u64,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub extern "C"
 | 
				
			||||||
 | 
					    fn squeek_layout_draw_all_changed(
 | 
				
			||||||
 | 
					        layout: *mut Layout,
 | 
				
			||||||
 | 
					        renderer: EekRenderer,
 | 
				
			||||||
 | 
					        cr: *mut cairo_sys::cairo_t,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        let layout = unsafe { &mut *layout };
 | 
				
			||||||
 | 
					        let cr = unsafe { cairo::Context::from_raw_none(cr) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let view = layout.get_current_view();
 | 
				
			||||||
 | 
					        let view_position = view.bounds.get_position();
 | 
				
			||||||
 | 
					        for row in &view.rows {
 | 
				
			||||||
 | 
					            for button in &row.buttons {
 | 
				
			||||||
 | 
					                let state = RefCell::borrow(&button.state).clone();
 | 
				
			||||||
 | 
					                if state.pressed == keyboard::PressType::Pressed || state.locked {
 | 
				
			||||||
 | 
					                    let position = &view_position
 | 
				
			||||||
 | 
					                        + row.bounds.clone().unwrap().get_position()
 | 
				
			||||||
 | 
					                        + button.bounds.get_position();
 | 
				
			||||||
 | 
					                    render_button_at_position(
 | 
				
			||||||
 | 
					                        renderer, &cr,
 | 
				
			||||||
 | 
					                        position, button.as_ref(),
 | 
				
			||||||
 | 
					                        state.pressed, state.locked,
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub extern "C"
 | 
				
			||||||
 | 
					    fn squeek_draw_layout_base_view(
 | 
				
			||||||
 | 
					        layout: *mut Layout,
 | 
				
			||||||
 | 
					        renderer: EekRenderer,
 | 
				
			||||||
 | 
					        cr: *mut cairo_sys::cairo_t,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        let layout = unsafe { &mut *layout };
 | 
				
			||||||
 | 
					        let cr = unsafe { cairo::Context::from_raw_none(cr) };
 | 
				
			||||||
 | 
					        let view = layout.get_current_view();
 | 
				
			||||||
 | 
					        let view_position = view.bounds.get_position();
 | 
				
			||||||
 | 
					        for row in &view.rows {
 | 
				
			||||||
 | 
					            for button in &row.buttons {
 | 
				
			||||||
 | 
					                let position = &view_position
 | 
				
			||||||
 | 
					                    + row.bounds.clone().unwrap().get_position()
 | 
				
			||||||
 | 
					                    + button.bounds.get_position();
 | 
				
			||||||
 | 
					                render_button_at_position(
 | 
				
			||||||
 | 
					                    renderer, &cr,
 | 
				
			||||||
 | 
					                    position, button.as_ref(),
 | 
				
			||||||
 | 
					                    keyboard::PressType::Released, false,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Renders a button at a position (button's own bounds ignored)
 | 
				
			||||||
 | 
					pub fn render_button_at_position(
 | 
				
			||||||
 | 
					    renderer: c::EekRenderer,
 | 
				
			||||||
 | 
					    cr: &cairo::Context,
 | 
				
			||||||
 | 
					    position: Point,
 | 
				
			||||||
 | 
					    button: &Button,
 | 
				
			||||||
 | 
					    pressed: keyboard::PressType,
 | 
				
			||||||
 | 
					    locked: bool,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    cr.save();
 | 
				
			||||||
 | 
					    cr.translate(position.x, position.y);
 | 
				
			||||||
 | 
					    cr.rectangle(
 | 
				
			||||||
 | 
					        0.0, 0.0,
 | 
				
			||||||
 | 
					        button.bounds.width, button.bounds.height
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    cr.clip();
 | 
				
			||||||
 | 
					    unsafe {
 | 
				
			||||||
 | 
					        c::eek_render_button(
 | 
				
			||||||
 | 
					            renderer,
 | 
				
			||||||
 | 
					            cairo::Context::to_raw_none(&cr),
 | 
				
			||||||
 | 
					            button as *const Button,
 | 
				
			||||||
 | 
					            pressed as u64,
 | 
				
			||||||
 | 
					            locked as u64,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    cr.restore();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn queue_redraw(keyboard: EekGtkKeyboard) {
 | 
				
			||||||
 | 
					    let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) };
 | 
				
			||||||
 | 
					    widget.queue_draw();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,12 +0,0 @@
 | 
				
			|||||||
#ifndef __KEYBOARD_H
 | 
					 | 
				
			||||||
#define __KEYBOARD_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "inttypes.h"
 | 
					 | 
				
			||||||
#include "stdbool.h"
 | 
					 | 
				
			||||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct squeek_key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t squeek_key_is_pressed(struct squeek_key *key);
 | 
					 | 
				
			||||||
uint32_t squeek_key_is_locked(struct squeek_key *key);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@ -10,32 +10,8 @@ use ::action::Action;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use std::io::Write;
 | 
					use std::io::Write;
 | 
				
			||||||
use std::iter::{ FromIterator, IntoIterator };
 | 
					use std::iter::{ FromIterator, IntoIterator };
 | 
				
			||||||
use ::util::CloneOwned;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Gathers stuff defined in C or called by C
 | 
					#[derive(Debug, Clone, Copy, PartialEq)]
 | 
				
			||||||
pub mod c {
 | 
					 | 
				
			||||||
    use super::*;
 | 
					 | 
				
			||||||
    use ::util::c;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub type CKeyState = c::Wrapped<KeyState>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[no_mangle]
 | 
					 | 
				
			||||||
    pub extern "C"
 | 
					 | 
				
			||||||
    fn squeek_key_is_pressed(key: CKeyState) -> u32 {
 | 
					 | 
				
			||||||
        //let key = unsafe { Rc::from_raw(key.0) };
 | 
					 | 
				
			||||||
        return key.clone_owned().pressed as u32;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[no_mangle]
 | 
					 | 
				
			||||||
    pub extern "C"
 | 
					 | 
				
			||||||
    fn squeek_key_is_locked(key: CKeyState) -> u32 {
 | 
					 | 
				
			||||||
        return key.clone_owned().locked as u32;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, Clone, Copy)]
 | 
					 | 
				
			||||||
pub enum PressType {
 | 
					pub enum PressType {
 | 
				
			||||||
    Released = 0,
 | 
					    Released = 0,
 | 
				
			||||||
    Pressed = 1,
 | 
					    Pressed = 1,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										37
									
								
								src/layout.h
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/layout.h
									
									
									
									
									
								
							@ -5,8 +5,8 @@
 | 
				
			|||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
#include "eek/eek-element.h"
 | 
					#include "eek/eek-element.h"
 | 
				
			||||||
#include "eek/eek-gtk-keyboard.h"
 | 
					#include "eek/eek-gtk-keyboard.h"
 | 
				
			||||||
 | 
					#include "eek/eek-renderer.h"
 | 
				
			||||||
#include "eek/eek-types.h"
 | 
					#include "eek/eek-types.h"
 | 
				
			||||||
#include "src/keyboard.h"
 | 
					 | 
				
			||||||
#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
					#include "virtual-keyboard-unstable-v1-client-protocol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum squeek_arrangement_kind {
 | 
					enum squeek_arrangement_kind {
 | 
				
			||||||
@ -14,48 +14,22 @@ enum squeek_arrangement_kind {
 | 
				
			|||||||
    ARRANGEMENT_KIND_WIDE = 1,
 | 
					    ARRANGEMENT_KIND_WIDE = 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct squeek_button;
 | 
					 | 
				
			||||||
struct squeek_row;
 | 
					 | 
				
			||||||
struct squeek_view;
 | 
					 | 
				
			||||||
struct squeek_layout;
 | 
					struct squeek_layout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Represents the path to the button within a view
 | 
					 | 
				
			||||||
struct button_place {
 | 
					 | 
				
			||||||
    const struct squeek_row *row;
 | 
					 | 
				
			||||||
    const struct squeek_button *button;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int32_t squeek_row_get_angle(const struct squeek_row*);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EekBounds squeek_row_get_bounds(const struct squeek_row*);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data);
 | 
					 | 
				
			||||||
void squeek_row_foreach(struct squeek_row*,
 | 
					 | 
				
			||||||
                            ButtonCallback   callback,
 | 
					 | 
				
			||||||
                            gpointer      user_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EekBounds squeek_button_get_bounds(const struct squeek_button*);
 | 
					EekBounds squeek_button_get_bounds(const struct squeek_button*);
 | 
				
			||||||
const char *squeek_button_get_label(const struct squeek_button*);
 | 
					const char *squeek_button_get_label(const struct squeek_button*);
 | 
				
			||||||
const char *squeek_button_get_icon_name(const struct squeek_button*);
 | 
					const char *squeek_button_get_icon_name(const struct squeek_button*);
 | 
				
			||||||
const char *squeek_button_get_name(const struct squeek_button*);
 | 
					const char *squeek_button_get_name(const struct squeek_button*);
 | 
				
			||||||
const char *squeek_button_get_outline_name(const struct squeek_button*);
 | 
					const char *squeek_button_get_outline_name(const struct squeek_button*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct squeek_key *squeek_button_get_key(const struct squeek_button*);
 | 
					 | 
				
			||||||
uint32_t *squeek_button_has_key(const struct squeek_button* button,
 | 
					 | 
				
			||||||
                                const struct squeek_key *key);
 | 
					 | 
				
			||||||
void squeek_button_print(const struct squeek_button* button);
 | 
					void squeek_button_print(const struct squeek_button* button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct transformation squeek_layout_calculate_transformation(
 | 
				
			||||||
EekBounds squeek_view_get_bounds(const struct squeek_view*);
 | 
					        const struct squeek_layout *layout,
 | 
				
			||||||
 | 
					        double allocation_width, double allocation_size);
 | 
				
			||||||
typedef void (*RowCallback) (struct squeek_row *row, gpointer user_data);
 | 
					 | 
				
			||||||
void squeek_view_foreach(struct squeek_view*,
 | 
					 | 
				
			||||||
                            RowCallback   callback,
 | 
					 | 
				
			||||||
                            gpointer      user_data);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
squeek_layout_place_contents(struct squeek_layout*);
 | 
					squeek_layout_place_contents(struct squeek_layout*);
 | 
				
			||||||
struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
 | 
					struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
 | 
				
			||||||
const char *squeek_layout_get_keymap(const struct squeek_layout*);
 | 
					const char *squeek_layout_get_keymap(const struct squeek_layout*);
 | 
				
			||||||
@ -75,5 +49,6 @@ void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboar
 | 
				
			|||||||
                        double x_widget, double y_widget,
 | 
					                        double x_widget, double y_widget,
 | 
				
			||||||
                        struct transformation widget_to_layout,
 | 
					                        struct transformation widget_to_layout,
 | 
				
			||||||
                        uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
 | 
					                        uint32_t timestamp, EekGtkKeyboard *ui_keyboard);
 | 
				
			||||||
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekGtkKeyboard *ui_keyboard);
 | 
					void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t     *cr);
 | 
				
			||||||
 | 
					void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t     *cr);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										352
									
								
								src/layout.rs
									
									
									
									
									
								
							
							
						
						
									
										352
									
								
								src/layout.rs
									
									
									
									
									
								
							@ -24,6 +24,7 @@ use std::rc::Rc;
 | 
				
			|||||||
use std::vec::Vec;
 | 
					use std::vec::Vec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use ::action::Action;
 | 
					use ::action::Action;
 | 
				
			||||||
 | 
					use ::drawing;
 | 
				
			||||||
use ::float_ord::FloatOrd;
 | 
					use ::float_ord::FloatOrd;
 | 
				
			||||||
use ::keyboard::{ KeyState, PressType };
 | 
					use ::keyboard::{ KeyState, PressType };
 | 
				
			||||||
use ::submission::{ Timestamp, VirtualKeyboard };
 | 
					use ::submission::{ Timestamp, VirtualKeyboard };
 | 
				
			||||||
@ -34,16 +35,14 @@ use std::borrow::Borrow;
 | 
				
			|||||||
pub mod c {
 | 
					pub mod c {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use gtk_sys;
 | 
				
			||||||
    use std::ffi::CStr;
 | 
					    use std::ffi::CStr;
 | 
				
			||||||
    use std::os::raw::{ c_char, c_void };
 | 
					    use std::os::raw::{ c_char, c_void };
 | 
				
			||||||
    use std::ptr;
 | 
					    use std::ptr;
 | 
				
			||||||
    use gtk_sys;
 | 
					
 | 
				
			||||||
 | 
					    use std::ops::Add;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The following defined in C
 | 
					    // The following defined in C
 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[repr(transparent)]
 | 
					 | 
				
			||||||
    pub struct UserData(*const c_void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[repr(transparent)]
 | 
					    #[repr(transparent)]
 | 
				
			||||||
    #[derive(Copy, Clone)]
 | 
					    #[derive(Copy, Clone)]
 | 
				
			||||||
    pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget);
 | 
					    pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget);
 | 
				
			||||||
@ -56,9 +55,26 @@ pub mod c {
 | 
				
			|||||||
        pub y: f64,
 | 
					        pub y: f64,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    impl Add for Point {
 | 
				
			||||||
 | 
					        type Output = Self;
 | 
				
			||||||
 | 
					        fn add(self, other: Self) -> Self {
 | 
				
			||||||
 | 
					            &self + other
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl Add<Point> for &Point {
 | 
				
			||||||
 | 
					        type Output = Point;
 | 
				
			||||||
 | 
					        fn add(self, other: Point) -> Point {
 | 
				
			||||||
 | 
					            Point {
 | 
				
			||||||
 | 
					                x: self.x + other.x,
 | 
				
			||||||
 | 
					                y: self.y + other.y,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Defined in eek-types.h
 | 
					    /// Defined in eek-types.h
 | 
				
			||||||
    #[repr(C)]
 | 
					    #[repr(C)]
 | 
				
			||||||
    #[derive(Clone, Debug)]
 | 
					    #[derive(Clone, Debug, PartialEq)]
 | 
				
			||||||
    pub struct Bounds {
 | 
					    pub struct Bounds {
 | 
				
			||||||
        pub x: f64,
 | 
					        pub x: f64,
 | 
				
			||||||
        pub y: f64,
 | 
					        pub y: f64,
 | 
				
			||||||
@ -66,61 +82,52 @@ pub mod c {
 | 
				
			|||||||
        pub height: f64
 | 
					        pub height: f64
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    type ButtonCallback = unsafe extern "C" fn(button: *mut ::layout::Button, data: *mut UserData);
 | 
					    impl Bounds {
 | 
				
			||||||
    type RowCallback = unsafe extern "C" fn(row: *mut ::layout::Row, data: *mut UserData);
 | 
					        pub fn get_position(&self) -> Point {
 | 
				
			||||||
 | 
					            Point {
 | 
				
			||||||
    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
					                x: self.x,
 | 
				
			||||||
 | 
					                y: self.y,
 | 
				
			||||||
    #[no_mangle]
 | 
					            }
 | 
				
			||||||
    pub extern "C"
 | 
					        }
 | 
				
			||||||
    fn squeek_view_get_bounds(view: *const ::layout::View) -> Bounds {
 | 
					 | 
				
			||||||
        unsafe { &*view }.bounds.clone()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[no_mangle]
 | 
					    /// Scale + translate
 | 
				
			||||||
    pub extern "C"
 | 
					    #[repr(C)]
 | 
				
			||||||
    fn squeek_view_foreach(
 | 
					    pub struct Transformation {
 | 
				
			||||||
        view: *mut ::layout::View,
 | 
					        pub origin_x: f64,
 | 
				
			||||||
        callback: RowCallback,
 | 
					        pub origin_y: f64,
 | 
				
			||||||
        data: *mut UserData,
 | 
					        pub scale: f64,
 | 
				
			||||||
    ) {
 | 
					    }
 | 
				
			||||||
        let view = unsafe { &mut *view };
 | 
					
 | 
				
			||||||
        for row in view.rows.iter_mut() {
 | 
					    impl Transformation {
 | 
				
			||||||
            let row = row.as_mut() as *mut ::layout::Row;
 | 
					        fn forward(&self, p: Point) -> Point {
 | 
				
			||||||
            unsafe { callback(row, data) };
 | 
					            Point {
 | 
				
			||||||
 | 
					                x: (p.x - self.origin_x) / self.scale,
 | 
				
			||||||
 | 
					                y: (p.y - self.origin_y) / self.scale,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        fn reverse(&self, p: Point) -> Point {
 | 
				
			||||||
 | 
					            Point {
 | 
				
			||||||
 | 
					                x: p.x * self.scale + self.origin_x,
 | 
				
			||||||
 | 
					                y: p.y * self.scale + self.origin_y,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        pub fn reverse_bounds(&self, b: Bounds) -> Bounds {
 | 
				
			||||||
 | 
					            let start = self.reverse(Point { x: b.x, y: b.y });
 | 
				
			||||||
 | 
					            let end = self.reverse(Point {
 | 
				
			||||||
 | 
					                x: b.x + b.width,
 | 
				
			||||||
 | 
					                y: b.y + b.height,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            Bounds {
 | 
				
			||||||
 | 
					                x: start.x,
 | 
				
			||||||
 | 
					                y: start.y,
 | 
				
			||||||
 | 
					                width: end.x - start.x,
 | 
				
			||||||
 | 
					                height: end.y - start.y,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[no_mangle]
 | 
					    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
				
			||||||
    pub extern "C"
 | 
					 | 
				
			||||||
    fn squeek_row_get_angle(row: *const ::layout::Row) -> i32 {
 | 
					 | 
				
			||||||
        let row = unsafe { &*row };
 | 
					 | 
				
			||||||
        row.angle
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    #[no_mangle]
 | 
					 | 
				
			||||||
    pub extern "C"
 | 
					 | 
				
			||||||
    fn squeek_row_get_bounds(row: *const ::layout::Row) -> Bounds {
 | 
					 | 
				
			||||||
        let row = unsafe { &*row };
 | 
					 | 
				
			||||||
        match &row.bounds {
 | 
					 | 
				
			||||||
            Some(bounds) => bounds.clone(),
 | 
					 | 
				
			||||||
            None => panic!("Row doesn't have any bounds yet"),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    #[no_mangle]
 | 
					 | 
				
			||||||
    pub extern "C"
 | 
					 | 
				
			||||||
    fn squeek_row_foreach(
 | 
					 | 
				
			||||||
        row: *mut ::layout::Row,
 | 
					 | 
				
			||||||
        callback: ButtonCallback,
 | 
					 | 
				
			||||||
        data: *mut UserData,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        let row = unsafe { &mut *row };
 | 
					 | 
				
			||||||
        for button in row.buttons.iter_mut() {
 | 
					 | 
				
			||||||
            let button = button.as_mut() as *mut ::layout::Button;
 | 
					 | 
				
			||||||
            unsafe { callback(button, data) };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub extern "C"
 | 
					    pub extern "C"
 | 
				
			||||||
@ -129,16 +136,6 @@ pub mod c {
 | 
				
			|||||||
        button.bounds.clone()
 | 
					        button.bounds.clone()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Borrow a new reference to key state. Doesn't need freeing
 | 
					 | 
				
			||||||
    #[no_mangle]
 | 
					 | 
				
			||||||
    pub extern "C"
 | 
					 | 
				
			||||||
    fn squeek_button_get_key(
 | 
					 | 
				
			||||||
        button: *const ::layout::Button
 | 
					 | 
				
			||||||
    ) -> ::keyboard::c::CKeyState {
 | 
					 | 
				
			||||||
        let button = unsafe { &*button };
 | 
					 | 
				
			||||||
        ::keyboard::c::CKeyState::wrap(button.state.clone())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub extern "C"
 | 
					    pub extern "C"
 | 
				
			||||||
    fn squeek_button_get_label(
 | 
					    fn squeek_button_get_label(
 | 
				
			||||||
@ -187,14 +184,24 @@ pub mod c {
 | 
				
			|||||||
        println!("{:?}", button);
 | 
					        println!("{:?}", button);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    /// Positions the layout within the available space
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub extern "C"
 | 
					    pub extern "C"
 | 
				
			||||||
    fn squeek_layout_get_current_view(layout: *const Layout) -> *const View {
 | 
					    fn squeek_layout_calculate_transformation(
 | 
				
			||||||
 | 
					        layout: *const Layout,
 | 
				
			||||||
 | 
					        allocation_width: f64,
 | 
				
			||||||
 | 
					        allocation_height: f64,
 | 
				
			||||||
 | 
					    ) -> Transformation {
 | 
				
			||||||
        let layout = unsafe { &*layout };
 | 
					        let layout = unsafe { &*layout };
 | 
				
			||||||
        let view_name = layout.current_view.clone();
 | 
					        let bounds = &layout.get_current_view().bounds;
 | 
				
			||||||
        layout.views.get(&view_name)
 | 
					        let h_scale = allocation_width / bounds.width;
 | 
				
			||||||
            .expect("Current view doesn't exist")
 | 
					        let v_scale = allocation_height / bounds.height;
 | 
				
			||||||
            .as_ref() as *const View
 | 
					        let scale = if h_scale > v_scale { h_scale } else { v_scale };
 | 
				
			||||||
 | 
					        Transformation {
 | 
				
			||||||
 | 
					            origin_x: allocation_width - (scale * bounds.width) / 2.0,
 | 
				
			||||||
 | 
					            origin_y: allocation_height - (scale * bounds.height) / 2.0,
 | 
				
			||||||
 | 
					            scale: scale,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
@ -239,42 +246,6 @@ pub mod c {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Scale + translate
 | 
					 | 
				
			||||||
        #[repr(C)]
 | 
					 | 
				
			||||||
        pub struct Transformation {
 | 
					 | 
				
			||||||
            origin_x: f64,
 | 
					 | 
				
			||||||
            origin_y: f64,
 | 
					 | 
				
			||||||
            scale: f64,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        impl Transformation {
 | 
					 | 
				
			||||||
            fn forward(&self, p: Point) -> Point {
 | 
					 | 
				
			||||||
                Point {
 | 
					 | 
				
			||||||
                    x: (p.x - self.origin_x) / self.scale,
 | 
					 | 
				
			||||||
                    y: (p.y - self.origin_y) / self.scale,
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            fn reverse(&self, p: Point) -> Point {
 | 
					 | 
				
			||||||
                Point {
 | 
					 | 
				
			||||||
                    x: p.x * self.scale + self.origin_x,
 | 
					 | 
				
			||||||
                    y: p.y * self.scale + self.origin_y,
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            pub fn reverse_bounds(&self, b: Bounds) -> Bounds {
 | 
					 | 
				
			||||||
                let start = self.reverse(Point { x: b.x, y: b.y });
 | 
					 | 
				
			||||||
                let end = self.reverse(Point {
 | 
					 | 
				
			||||||
                    x: b.x + b.width,
 | 
					 | 
				
			||||||
                    y: b.y + b.height,
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                Bounds {
 | 
					 | 
				
			||||||
                    x: start.x,
 | 
					 | 
				
			||||||
                    y: start.y,
 | 
					 | 
				
			||||||
                    width: end.x - start.x,
 | 
					 | 
				
			||||||
                    height: end.y - start.y,
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // This is constructed only in C, no need for warnings
 | 
					        // This is constructed only in C, no need for warnings
 | 
				
			||||||
        #[allow(dead_code)]
 | 
					        #[allow(dead_code)]
 | 
				
			||||||
        #[repr(transparent)]
 | 
					        #[repr(transparent)]
 | 
				
			||||||
@ -289,34 +260,6 @@ pub mod c {
 | 
				
			|||||||
                origin: Point,
 | 
					                origin: Point,
 | 
				
			||||||
                angle: i32
 | 
					                angle: i32
 | 
				
			||||||
            ) -> u32;
 | 
					            ) -> u32;
 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Button and View are safe to pass to C
 | 
					 | 
				
			||||||
            // as long as they don't outlive the call
 | 
					 | 
				
			||||||
            // and nothing dereferences them
 | 
					 | 
				
			||||||
            #[allow(improper_ctypes)]
 | 
					 | 
				
			||||||
            pub fn eek_gtk_on_button_released(
 | 
					 | 
				
			||||||
                button: *const Button,
 | 
					 | 
				
			||||||
                view: *const View,
 | 
					 | 
				
			||||||
                keyboard: EekGtkKeyboard,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Button and View inside CButtonPlace are safe to pass to C
 | 
					 | 
				
			||||||
            // as long as they don't outlive the call
 | 
					 | 
				
			||||||
            // and nothing dereferences them
 | 
					 | 
				
			||||||
            #[allow(improper_ctypes)]
 | 
					 | 
				
			||||||
            pub fn eek_gtk_on_button_pressed(
 | 
					 | 
				
			||||||
                place: CButtonPlace,
 | 
					 | 
				
			||||||
                keyboard: EekGtkKeyboard,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // Button and View inside CButtonPlace are safe to pass to C
 | 
					 | 
				
			||||||
            // as long as they don't outlive the call
 | 
					 | 
				
			||||||
            // and nothing dereferences them
 | 
					 | 
				
			||||||
            #[allow(improper_ctypes)]
 | 
					 | 
				
			||||||
            pub fn eek_gtk_render_locked_button(
 | 
					 | 
				
			||||||
                keyboard: EekGtkKeyboard,
 | 
					 | 
				
			||||||
                place: CButtonPlace,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Places each button in order, starting from 0 on the left,
 | 
					        /// Places each button in order, starting from 0 on the left,
 | 
				
			||||||
@ -356,15 +299,16 @@ pub mod c {
 | 
				
			|||||||
            // because it will be mutated in the loop
 | 
					            // because it will be mutated in the loop
 | 
				
			||||||
            for key in layout.pressed_keys.clone() {
 | 
					            for key in layout.pressed_keys.clone() {
 | 
				
			||||||
                let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
					                let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
				
			||||||
                ui::release_key(
 | 
					                seat::handle_release_key(
 | 
				
			||||||
                    layout,
 | 
					                    layout,
 | 
				
			||||||
                    &virtual_keyboard,
 | 
					                    &virtual_keyboard,
 | 
				
			||||||
                    &widget_to_layout,
 | 
					                    &widget_to_layout,
 | 
				
			||||||
                    time,
 | 
					                    time,
 | 
				
			||||||
                    ui_keyboard,
 | 
					                    ui_keyboard,
 | 
				
			||||||
                    key
 | 
					                    key,
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            drawing::queue_redraw(ui_keyboard);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Release all buittons but don't redraw
 | 
					        /// Release all buittons but don't redraw
 | 
				
			||||||
@ -404,26 +348,15 @@ pub mod c {
 | 
				
			|||||||
                Point { x: x_widget, y: y_widget }
 | 
					                Point { x: x_widget, y: y_widget }
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // the immutable reference to `layout` through `view`
 | 
					            if let Some(position) = layout.get_button_at_point(point) {
 | 
				
			||||||
            // must be dropped
 | 
					                let mut state = position.button.state.clone();
 | 
				
			||||||
            // before `layout.press_key` borrows it mutably again
 | 
					 | 
				
			||||||
            let state_place = {
 | 
					 | 
				
			||||||
                let view = layout.get_current_view();
 | 
					 | 
				
			||||||
                let place = view.find_button_by_position(point);
 | 
					 | 
				
			||||||
                place.map(|place| {(
 | 
					 | 
				
			||||||
                    place.button.state.clone(),
 | 
					 | 
				
			||||||
                    place.into(),
 | 
					 | 
				
			||||||
                )})
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if let Some((mut state, c_place)) = state_place {
 | 
					 | 
				
			||||||
                layout.press_key(
 | 
					                layout.press_key(
 | 
				
			||||||
                    &VirtualKeyboard(virtual_keyboard),
 | 
					                    &VirtualKeyboard(virtual_keyboard),
 | 
				
			||||||
                    &mut state,
 | 
					                    &mut state,
 | 
				
			||||||
                    Timestamp(time),
 | 
					                    Timestamp(time),
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					                // maybe TODO: draw on the display buffer here
 | 
				
			||||||
                unsafe { eek_gtk_on_button_pressed(c_place, ui_keyboard) };
 | 
					                drawing::queue_redraw(ui_keyboard);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -449,23 +382,26 @@ pub mod c {
 | 
				
			|||||||
            );
 | 
					            );
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            let pressed = layout.pressed_keys.clone();
 | 
					            let pressed = layout.pressed_keys.clone();
 | 
				
			||||||
            let state_place = {
 | 
					            let button_info = {
 | 
				
			||||||
                let view = layout.get_current_view();
 | 
					                let view = layout.get_current_view();
 | 
				
			||||||
                let place = view.find_button_by_position(point);
 | 
					                let place = view.find_button_by_position(point);
 | 
				
			||||||
                place.map(|place| {(
 | 
					                place.map(|place| {(
 | 
				
			||||||
                    place.button.state.clone(),
 | 
					                    place.button.state.clone(),
 | 
				
			||||||
                    place.into(),
 | 
					                    place.button.clone(),
 | 
				
			||||||
 | 
					                    view.bounds.get_position()
 | 
				
			||||||
 | 
					                        + place.row.bounds.clone().unwrap().get_position()
 | 
				
			||||||
 | 
					                        + place.button.bounds.get_position(),
 | 
				
			||||||
                )})
 | 
					                )})
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if let Some((mut state, c_place)) = state_place {
 | 
					            if let Some((mut state, _button, _view_position)) = button_info {
 | 
				
			||||||
                let mut found = false;
 | 
					                let mut found = false;
 | 
				
			||||||
                for wrapped_key in pressed {
 | 
					                for wrapped_key in pressed {
 | 
				
			||||||
                    let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
 | 
					                    let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
 | 
				
			||||||
                    if Rc::ptr_eq(&state, &wrapped_key.0) {
 | 
					                    if Rc::ptr_eq(&state, &wrapped_key.0) {
 | 
				
			||||||
                        found = true;
 | 
					                        found = true;
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        ui::release_key(
 | 
					                        seat::handle_release_key(
 | 
				
			||||||
                            layout,
 | 
					                            layout,
 | 
				
			||||||
                            &virtual_keyboard,
 | 
					                            &virtual_keyboard,
 | 
				
			||||||
                            &widget_to_layout,
 | 
					                            &widget_to_layout,
 | 
				
			||||||
@ -477,12 +413,12 @@ pub mod c {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                if !found {
 | 
					                if !found {
 | 
				
			||||||
                    layout.press_key(&virtual_keyboard, &mut state, time);
 | 
					                    layout.press_key(&virtual_keyboard, &mut state, time);
 | 
				
			||||||
                    unsafe { eek_gtk_on_button_pressed(c_place, ui_keyboard) };
 | 
					                    // maybe TODO: draw on the display buffer here
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                for wrapped_key in pressed {
 | 
					                for wrapped_key in pressed {
 | 
				
			||||||
                    let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
 | 
					                    let key: &Rc<RefCell<KeyState>> = wrapped_key.borrow();
 | 
				
			||||||
                    ui::release_key(
 | 
					                    seat::handle_release_key(
 | 
				
			||||||
                        layout,
 | 
					                        layout,
 | 
				
			||||||
                        &virtual_keyboard,
 | 
					                        &virtual_keyboard,
 | 
				
			||||||
                        &widget_to_layout,
 | 
					                        &widget_to_layout,
 | 
				
			||||||
@ -492,33 +428,7 @@ pub mod c {
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					            drawing::queue_redraw(ui_keyboard);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        #[no_mangle]
 | 
					 | 
				
			||||||
        pub extern "C"
 | 
					 | 
				
			||||||
        fn squeek_layout_draw_all_changed(
 | 
					 | 
				
			||||||
            layout: *mut Layout,
 | 
					 | 
				
			||||||
            ui_keyboard: EekGtkKeyboard,
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            let layout = unsafe { &mut *layout };
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            for row in &layout.get_current_view().rows {
 | 
					 | 
				
			||||||
                for button in &row.buttons {
 | 
					 | 
				
			||||||
                    let c_place = CButtonPlace::from(
 | 
					 | 
				
			||||||
                        ButtonPlace { row, button }
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
                    let state = RefCell::borrow(&button.state);
 | 
					 | 
				
			||||||
                    match (state.pressed, state.locked) {
 | 
					 | 
				
			||||||
                        (PressType::Released, false) => {}
 | 
					 | 
				
			||||||
                        (PressType::Pressed, _) => unsafe {
 | 
					 | 
				
			||||||
                            eek_gtk_on_button_pressed(c_place, ui_keyboard)
 | 
					 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                        (_, true) => unsafe {
 | 
					 | 
				
			||||||
                            eek_gtk_render_locked_button(ui_keyboard, c_place)
 | 
					 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #[cfg(test)]
 | 
					        #[cfg(test)]
 | 
				
			||||||
@ -545,6 +455,12 @@ pub mod c {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Relative to `View`
 | 
				
			||||||
 | 
					struct ButtonPosition {
 | 
				
			||||||
 | 
					    view_position: c::Point,
 | 
				
			||||||
 | 
					    button: Button,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ButtonPlace<'a> {
 | 
					pub struct ButtonPlace<'a> {
 | 
				
			||||||
    button: &'a Button,
 | 
					    button: &'a Button,
 | 
				
			||||||
    row: &'a Row,
 | 
					    row: &'a Row,
 | 
				
			||||||
@ -654,7 +570,7 @@ pub struct Spacing {
 | 
				
			|||||||
pub struct View {
 | 
					pub struct View {
 | 
				
			||||||
    /// Position relative to keyboard origin
 | 
					    /// Position relative to keyboard origin
 | 
				
			||||||
    pub bounds: c::Bounds,
 | 
					    pub bounds: c::Bounds,
 | 
				
			||||||
    pub rows: Vec<Box<Row>>,
 | 
					    pub rows: Vec<Row>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl View {
 | 
					impl View {
 | 
				
			||||||
@ -749,7 +665,7 @@ pub struct Layout {
 | 
				
			|||||||
    // Views own the actual buttons which have state
 | 
					    // Views own the actual buttons which have state
 | 
				
			||||||
    // Maybe they should own UI only,
 | 
					    // Maybe they should own UI only,
 | 
				
			||||||
    // and keys should be owned by a dedicated non-UI-State?
 | 
					    // and keys should be owned by a dedicated non-UI-State?
 | 
				
			||||||
    pub views: HashMap<String, Box<View>>,
 | 
					    pub views: HashMap<String, View>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Non-UI stuff
 | 
					    // Non-UI stuff
 | 
				
			||||||
    /// xkb keymap applicable to the contained keys. Unchangeable
 | 
					    /// xkb keymap applicable to the contained keys. Unchangeable
 | 
				
			||||||
@ -768,7 +684,7 @@ pub struct Layout {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// A builder structure for picking up layout data from storage
 | 
					/// A builder structure for picking up layout data from storage
 | 
				
			||||||
pub struct LayoutData {
 | 
					pub struct LayoutData {
 | 
				
			||||||
    pub views: HashMap<String, Box<View>>,
 | 
					    pub views: HashMap<String, View>,
 | 
				
			||||||
    pub keymap_str: CString,
 | 
					    pub keymap_str: CString,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -789,7 +705,8 @@ impl Layout {
 | 
				
			|||||||
            locked_keys: HashSet::new(),
 | 
					            locked_keys: HashSet::new(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn get_current_view(&self) -> &Box<View> {
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_current_view(&self) -> &View {
 | 
				
			||||||
        self.views.get(&self.current_view).expect("Selected nonexistent view")
 | 
					        self.views.get(&self.current_view).expect("Selected nonexistent view")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -881,12 +798,24 @@ impl Layout {
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn get_button_at_point(&self, point: c::Point) -> Option<ButtonPosition> {
 | 
				
			||||||
 | 
					        let view = self.get_current_view();
 | 
				
			||||||
 | 
					        let place = view.find_button_by_position(point);
 | 
				
			||||||
 | 
					        place.map(|place| ButtonPosition {
 | 
				
			||||||
 | 
					            button: place.button.clone(),
 | 
				
			||||||
 | 
					            // Rows have no business being inside a view
 | 
				
			||||||
 | 
					            // if they have no valid bounds.
 | 
				
			||||||
 | 
					            view_position: place.row.bounds.clone().unwrap().get_position()
 | 
				
			||||||
 | 
					                + place.button.bounds.get_position(),
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod procedures {
 | 
					mod procedures {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    type Path<'v> = (&'v Box<Row>, &'v Box<Button>);
 | 
					    type Path<'v> = (&'v Row, &'v Box<Button>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Finds all `(row, button)` paths that refer to the specified key `state`
 | 
					    /// Finds all `(row, button)` paths that refer to the specified key `state`
 | 
				
			||||||
    pub fn find_key_paths<'v, 's>(
 | 
					    pub fn find_key_paths<'v, 's>(
 | 
				
			||||||
@ -918,24 +847,6 @@ mod procedures {
 | 
				
			|||||||
        }) == 1
 | 
					        }) == 1
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Switch off all UI buttons associated with the (state) key
 | 
					 | 
				
			||||||
    pub fn release_ui_buttons(
 | 
					 | 
				
			||||||
        view: &Box<View>,
 | 
					 | 
				
			||||||
        key: &Rc<RefCell<KeyState>>,
 | 
					 | 
				
			||||||
        ui_keyboard: c::EekGtkKeyboard,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        let paths = ::layout::procedures::find_key_paths(&view, key);
 | 
					 | 
				
			||||||
        for (_row, button) in paths {
 | 
					 | 
				
			||||||
            unsafe {
 | 
					 | 
				
			||||||
                c::procedures::eek_gtk_on_button_released(
 | 
					 | 
				
			||||||
                    button.as_ref() as *const Button,
 | 
					 | 
				
			||||||
                    view.as_ref() as *const View,
 | 
					 | 
				
			||||||
                    ui_keyboard,
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    #[cfg(test)]
 | 
					    #[cfg(test)]
 | 
				
			||||||
    mod test {
 | 
					    mod test {
 | 
				
			||||||
        use super::*;
 | 
					        use super::*;
 | 
				
			||||||
@ -957,12 +868,15 @@ mod procedures {
 | 
				
			|||||||
            let button = make_button_with_state("1".into(), state);
 | 
					            let button = make_button_with_state("1".into(), state);
 | 
				
			||||||
            let button_ptr = as_ptr(&button);
 | 
					            let button_ptr = as_ptr(&button);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            let row = Box::new(Row {
 | 
					            let row_bounds = Some(c::Bounds {
 | 
				
			||||||
 | 
					                x: 0.1, y: 2.3,
 | 
				
			||||||
 | 
					                width: 4.5, height: 6.7,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            let row = Row {
 | 
				
			||||||
                buttons: vec!(button),
 | 
					                buttons: vec!(button),
 | 
				
			||||||
                angle: 0,
 | 
					                angle: 0,
 | 
				
			||||||
                bounds: None
 | 
					                bounds: row_bounds.clone(),
 | 
				
			||||||
            });
 | 
					            };
 | 
				
			||||||
            let row_ptr = as_ptr(&row);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let view = View {
 | 
					            let view = View {
 | 
				
			||||||
                bounds: c::Bounds {
 | 
					                bounds: c::Bounds {
 | 
				
			||||||
@ -974,10 +888,10 @@ mod procedures {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            assert_eq!(
 | 
					            assert_eq!(
 | 
				
			||||||
                find_key_paths(&view, &state_clone.clone()).iter()
 | 
					                find_key_paths(&view, &state_clone.clone()).iter()
 | 
				
			||||||
                    .map(|(row, button)| { (as_ptr(row), as_ptr(button)) })
 | 
					                    .map(|(row, button)| { (row.bounds.clone(), as_ptr(button)) })
 | 
				
			||||||
                    .collect::<Vec<_>>(),
 | 
					                    .collect::<Vec<_>>(),
 | 
				
			||||||
                vec!(
 | 
					                vec!(
 | 
				
			||||||
                    (row_ptr, button_ptr)
 | 
					                    (row_bounds, button_ptr)
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1012,15 +926,15 @@ mod procedures {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Top level UI procedures
 | 
					/// Top level procedures, dispatching to everything
 | 
				
			||||||
mod ui {
 | 
					mod seat {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: turn into release_button
 | 
					    // TODO: turn into release_button
 | 
				
			||||||
    pub fn release_key(
 | 
					    pub fn handle_release_key(
 | 
				
			||||||
        layout: &mut Layout,
 | 
					        layout: &mut Layout,
 | 
				
			||||||
        virtual_keyboard: &VirtualKeyboard,
 | 
					        virtual_keyboard: &VirtualKeyboard,
 | 
				
			||||||
        widget_to_layout: &c::procedures::Transformation,
 | 
					        widget_to_layout: &c::Transformation,
 | 
				
			||||||
        time: Timestamp,
 | 
					        time: Timestamp,
 | 
				
			||||||
        ui_keyboard: c::EekGtkKeyboard,
 | 
					        ui_keyboard: c::EekGtkKeyboard,
 | 
				
			||||||
        key: &Rc<RefCell<KeyState>>,
 | 
					        key: &Rc<RefCell<KeyState>>,
 | 
				
			||||||
@ -1049,8 +963,6 @@ mod ui {
 | 
				
			|||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        procedures::release_ui_buttons(view, key, ui_keyboard);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,8 @@
 | 
				
			|||||||
#[macro_use]
 | 
					#[macro_use]
 | 
				
			||||||
extern crate bitflags;
 | 
					extern crate bitflags;
 | 
				
			||||||
 | 
					extern crate cairo;
 | 
				
			||||||
 | 
					extern crate cairo_sys;
 | 
				
			||||||
 | 
					extern crate gdk;
 | 
				
			||||||
extern crate gio;
 | 
					extern crate gio;
 | 
				
			||||||
extern crate glib;
 | 
					extern crate glib;
 | 
				
			||||||
extern crate glib_sys;
 | 
					extern crate glib_sys;
 | 
				
			||||||
@ -14,6 +17,7 @@ extern crate xkbcommon;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
mod action;
 | 
					mod action;
 | 
				
			||||||
pub mod data;
 | 
					pub mod data;
 | 
				
			||||||
 | 
					mod drawing;
 | 
				
			||||||
pub mod float_ord;
 | 
					pub mod float_ord;
 | 
				
			||||||
pub mod imservice;
 | 
					pub mod imservice;
 | 
				
			||||||
mod keyboard;
 | 
					mod keyboard;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user