From 83fea8cd313b2824e72fee299431941504bb5b45 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 1 Dec 2019 15:01:08 +0000 Subject: [PATCH 01/15] Drop squeek_key --- eek/eek-gtk-keyboard.c | 4 ++-- eek/eek-keyboard.c | 2 -- eek/eek-renderer.c | 36 ++++++++++++------------------------ eek/eek-renderer.h | 9 +-------- eek/eek-xml-layout.c | 1 - src/keyboard.h | 12 ------------ src/keyboard.rs | 24 ------------------------ src/layout.h | 4 ---- src/layout.rs | 10 ---------- 9 files changed, 15 insertions(+), 87 deletions(-) delete mode 100644 src/keyboard.h diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 67f354df..c9590db5 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -334,7 +334,7 @@ render_pressed_button (GtkWidget *widget, 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_button (priv->renderer, cr, place, 1.0, TRUE, FALSE); /* eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE); */ @@ -353,7 +353,7 @@ eek_gtk_render_locked_button (EekGtkKeyboard *self, struct button_place place) 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_button (priv->renderer, cr, &place, 1.0, FALSE, TRUE); gdk_window_end_draw_frame (window, context); diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index ee750abb..82c45be7 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -34,8 +34,6 @@ #include "eekboard/eekboard-context-service.h" #include "eekboard/key-emitter.h" #include "keymap.h" -#include "src/keyboard.h" - #include "eek-keyboard.h" void level_keyboard_deinit(LevelKeyboard *self) { diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 1bfaf672..88d2f843 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -426,18 +426,23 @@ eek_renderer_render_button_label (EekRenderer *self, * * Renders a key separately from the normal keyboard rendering. */ -static void -eek_renderer_real_render_button (EekRenderer *self, +void +eek_renderer_render_button (EekRenderer *self, cairo_t *cr, struct button_place *place, gdouble scale, - gboolean rotate) + gboolean is_pressed, + gboolean is_locked) { + g_return_if_fail (EEK_IS_RENDERER(self)); + g_return_if_fail (place); + g_return_if_fail (scale >= 0.0); + 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); + eek_renderer_get_button_bounds (view_bounds, place, &bounds, TRUE); cairo_save (cr); /* Because this function is called separately from the keyboard rendering @@ -446,12 +451,11 @@ eek_renderer_real_render_button (EekRenderer *self, 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); + eek_renderer_apply_transformation_for_button (cr, view_bounds, place, scale, TRUE); render_button ( self, cr, view_bounds, place, - squeek_key_is_pressed(key) != 0, - squeek_key_is_locked (key) != 0 + is_pressed, + is_locked ); cairo_restore (cr); } @@ -560,7 +564,6 @@ eek_renderer_class_init (EekRendererClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 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; @@ -823,21 +826,6 @@ eek_renderer_get_icon_surface (const gchar *icon_name, 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) diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index ced11c15..2288b01e 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -36,12 +36,6 @@ struct _EekRendererClass { 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); @@ -77,8 +71,7 @@ void eek_renderer_set_scale_factor (EekRenderer *renderer, void eek_renderer_render_button (EekRenderer *renderer, cairo_t *cr, struct button_place *place, - gdouble scale, - gboolean rotate); + gdouble scale, gboolean is_pressed, gboolean is_locked); cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name, gint size, diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index fe95e10c..300d463b 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -24,7 +24,6 @@ #include "config.h" #include "eek-keyboard.h" -#include "src/keyboard.h" #include "src/layout.h" #include "eek-xml-layout.h" diff --git a/src/keyboard.h b/src/keyboard.h deleted file mode 100644 index 554fb382..00000000 --- a/src/keyboard.h +++ /dev/null @@ -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 diff --git a/src/keyboard.rs b/src/keyboard.rs index 0ae163e6..0aa4dcfb 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -10,30 +10,6 @@ use ::action::Action; use std::io::Write; use std::iter::{ FromIterator, IntoIterator }; -use ::util::CloneOwned; - -/// Gathers stuff defined in C or called by C -pub mod c { - use super::*; - use ::util::c; - - pub type CKeyState = c::Wrapped; - - // 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 { diff --git a/src/layout.h b/src/layout.h index c88bea30..eefae7fe 100644 --- a/src/layout.h +++ b/src/layout.h @@ -6,7 +6,6 @@ #include "eek/eek-element.h" #include "eek/eek-gtk-keyboard.h" #include "eek/eek-types.h" -#include "src/keyboard.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" enum squeek_arrangement_kind { @@ -40,9 +39,6 @@ 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_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); diff --git a/src/layout.rs b/src/layout.rs index 27e32cd5..9a2264f3 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -129,16 +129,6 @@ pub mod c { 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] pub extern "C" fn squeek_button_get_label( From 4ee832c59436b58ab6a1a1bcbd9ff2667c49e0bf Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 1 Dec 2019 15:22:00 +0000 Subject: [PATCH 02/15] renderer: Remove some unneeded vars --- eek/eek-renderer.c | 29 +++++++++++------------------ eek/eek-renderer.h | 1 - 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 88d2f843..78d962f8 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -64,7 +64,7 @@ static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, Gt static void invalidate (EekRenderer *renderer); static void render_button (EekRenderer *self, - cairo_t *cr, EekBounds view_bounds, struct button_place *place, + cairo_t *cr, struct button_place *place, gboolean pressed, gboolean locked); struct _CreateKeyboardSurfaceCallbackData { @@ -95,7 +95,7 @@ create_keyboard_surface_button_callback (struct squeek_button *button, .row = data->row, .button = button, }; - render_button (data->renderer, data->cr, squeek_view_get_bounds(data->view), &place, FALSE, FALSE); + render_button (data->renderer, data->cr, &place, FALSE, FALSE); cairo_restore (data->cr); } @@ -125,11 +125,6 @@ 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, @@ -148,8 +143,12 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) cairo_save (data.cr); cairo_scale (data.cr, priv->scale, priv->scale); + + EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard)); cairo_translate (data.cr, bounds.x, bounds.y); + GdkRGBA color = {0}; + gtk_style_context_get_color (priv->view_context, GTK_STATE_FLAG_NORMAL, &color); cairo_set_source_rgba (data.cr, color.red, color.green, @@ -194,7 +193,6 @@ static void render_button_in_context(EekRenderer *self, gint scale_factor, cairo_t *cr, GtkStyleContext *ctx, - EekBounds view_bounds, struct button_place *place, gboolean active) { cairo_surface_t *outline_surface = NULL; @@ -218,7 +216,7 @@ static void render_button_in_context(EekRenderer *self, cairo_paint (cr); cairo_save (cr); - eek_renderer_apply_transformation_for_button (cr, view_bounds, place, 1.0, FALSE); + eek_renderer_apply_transformation_for_button (cr, place, 1.0, FALSE); render_outline (cr, ctx, bounds); cairo_restore (cr); @@ -265,7 +263,6 @@ static void render_button_in_context(EekRenderer *self, static void render_button (EekRenderer *self, cairo_t *cr, - EekBounds view_bounds, struct button_place *place, gboolean pressed, gboolean locked) @@ -292,7 +289,7 @@ render_button (EekRenderer *self, } 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, priv->scale_factor, cr, ctx, place, pressed); // Save and restore functions don't work if gtk_render_* was used in between gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL); @@ -319,17 +316,13 @@ render_button (EekRenderer *self, */ 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; + EekBounds bounds = squeek_button_get_bounds(place->button); 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); @@ -451,9 +444,9 @@ eek_renderer_render_button (EekRenderer *self, 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, TRUE); + eek_renderer_apply_transformation_for_button (cr, place, scale, TRUE); render_button ( - self, cr, view_bounds, place, + self, cr, place, is_pressed, is_locked ); diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index 2288b01e..fce70b41 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -83,7 +83,6 @@ 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); From 5266c621fd45ecc3663f82da0c579e7c6bf73fb1 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 1 Dec 2019 15:27:14 +0000 Subject: [PATCH 03/15] renderer: Simplified outline rendering --- eek/eek-renderer.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 78d962f8..c422d2b0 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -195,35 +195,12 @@ static void render_button_in_context(EekRenderer *self, GtkStyleContext *ctx, struct button_place *place, gboolean active) { - cairo_surface_t *outline_surface = NULL; + /* blank background */ + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); + cairo_paint (cr); - /* 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 */ - cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); - cairo_paint (cr); - - cairo_save (cr); - eek_renderer_apply_transformation_for_button (cr, place, 1.0, FALSE); - 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); + render_outline (cr, ctx, bounds); cairo_paint (cr); /* render icon (if any) */ From d415ecf5d0c9cc29ab69629ac771766115c9f2dc Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 1 Dec 2019 15:31:16 +0000 Subject: [PATCH 04/15] renderer: Drop row from button rendering --- eek/eek-renderer.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index c422d2b0..a7233e4a 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -64,7 +64,7 @@ static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, Gt static void invalidate (EekRenderer *renderer); static void render_button (EekRenderer *self, - cairo_t *cr, struct button_place *place, + cairo_t *cr, const struct squeek_button *button, gboolean pressed, gboolean locked); struct _CreateKeyboardSurfaceCallbackData { @@ -91,11 +91,8 @@ create_keyboard_surface_button_callback (struct squeek_button *button, 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, &place, FALSE, FALSE); + + render_button (data->renderer, data->cr, button, FALSE, FALSE); cairo_restore (data->cr); } @@ -193,18 +190,18 @@ static void render_button_in_context(EekRenderer *self, gint scale_factor, cairo_t *cr, GtkStyleContext *ctx, - struct button_place *place, + const struct squeek_button *button, gboolean active) { /* blank background */ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); cairo_paint (cr); - EekBounds bounds = squeek_button_get_bounds(place->button); + EekBounds bounds = squeek_button_get_bounds(button); render_outline (cr, ctx, bounds); cairo_paint (cr); /* 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) { cairo_surface_t *icon_surface = @@ -234,13 +231,13 @@ static void render_button_in_context(EekRenderer *self, return; } } - eek_renderer_render_button_label (self, cr, ctx, place->button); + eek_renderer_render_button_label (self, cr, ctx, button); } static void render_button (EekRenderer *self, cairo_t *cr, - struct button_place *place, + const struct squeek_button *button, gboolean pressed, gboolean locked) { @@ -251,7 +248,7 @@ render_button (EekRenderer *self, from the button's symbol. */ g_autoptr (GtkWidgetPath) path = NULL; 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); /* Update the style context with the updated widget path. */ @@ -260,13 +257,13 @@ render_button (EekRenderer *self, (pressed) or normal. */ gtk_style_context_set_state(ctx, 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) { gtk_style_context_add_class(ctx, "locked"); } gtk_style_context_add_class(ctx, outline_name); - render_button_in_context(self, priv->scale, priv->scale_factor, cr, ctx, place, pressed); + render_button_in_context(self, priv->scale, priv->scale_factor, cr, ctx, button, pressed); // Save and restore functions don't work if gtk_render_* was used in between gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL); @@ -423,7 +420,7 @@ eek_renderer_render_button (EekRenderer *self, eek_renderer_apply_transformation_for_button (cr, place, scale, TRUE); render_button ( - self, cr, place, + self, cr, place->button, is_pressed, is_locked ); From 34fce7395d08440851142a0931d4c538cb3c5eaa Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 1 Dec 2019 15:36:01 +0000 Subject: [PATCH 05/15] renderer: Drop unused params --- eek/eek-renderer.c | 36 +++++++++++++----------------------- eek/eek-renderer.h | 6 ++---- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index a7233e4a..08ccbe30 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -291,8 +291,7 @@ render_button (EekRenderer *self, void eek_renderer_apply_transformation_for_button (cairo_t *cr, struct button_place *place, - gdouble scale, - gboolean rotate) + gdouble scale) { EekBounds bounds = squeek_button_get_bounds(place->button); gdouble s; @@ -300,14 +299,13 @@ eek_renderer_apply_transformation_for_button (cairo_t *cr, 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); - } + + 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 @@ -409,7 +407,7 @@ eek_renderer_render_button (EekRenderer *self, EekBounds bounds; EekBounds view_bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard)); - eek_renderer_get_button_bounds (view_bounds, place, &bounds, TRUE); + eek_renderer_get_button_bounds (view_bounds, place, &bounds); cairo_save (cr); /* Because this function is called separately from the keyboard rendering @@ -418,7 +416,7 @@ eek_renderer_render_button (EekRenderer *self, cairo_scale (cr, priv->scale, priv->scale); cairo_translate (cr, bounds.x, bounds.y); - eek_renderer_apply_transformation_for_button (cr, place, scale, TRUE); + eek_renderer_apply_transformation_for_button (cr, place, scale); render_button ( self, cr, place->button, is_pressed, @@ -700,8 +698,7 @@ eek_renderer_get_size (EekRenderer *renderer, void eek_renderer_get_button_bounds (EekBounds view_bounds, struct button_place *place, - EekBounds *bounds, - gboolean rotate) + EekBounds *bounds) { gint angle = 0; EekPoint points[4], min, max; @@ -712,12 +709,6 @@ eek_renderer_get_button_bounds (EekBounds view_bounds, 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; @@ -727,9 +718,8 @@ eek_renderer_get_button_bounds (EekBounds view_bounds, points[3].x = points[0].x; points[3].y = points[2].y; - if (rotate) { - angle = squeek_row_get_angle (place->row); - } + + angle = squeek_row_get_angle (place->row); min = points[2]; max = points[0]; diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index fce70b41..ec52e809 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -61,8 +61,7 @@ void eek_renderer_get_size (EekRenderer *renderer, gdouble *height); void eek_renderer_get_button_bounds (EekBounds view_bounds, struct button_place *button, - EekBounds *bounds, - gboolean rotate); + EekBounds *bounds); gdouble eek_renderer_get_scale (EekRenderer *renderer); void eek_renderer_set_scale_factor (EekRenderer *renderer, @@ -84,8 +83,7 @@ void eek_renderer_set_border_width (EekRenderer *renderer, void eek_renderer_apply_transformation_for_button (cairo_t *cr, struct button_place *place, - gdouble scale, - gboolean rotate); + gdouble scale); struct transformation eek_renderer_get_transformation (EekRenderer *renderer); From 6e32a2ef412f79419a6879bc4d2a205a18d5f0f9 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sun, 1 Dec 2019 16:00:40 +0000 Subject: [PATCH 06/15] renderer: Simplify surface rendering --- eek/eek-renderer.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 08ccbe30..ce9499ee 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -88,8 +88,8 @@ create_keyboard_surface_button_callback (struct squeek_button *button, cairo_rectangle (data->cr, 0.0, 0.0, - bounds.width + 100, - bounds.height + 100); + bounds.width, + bounds.height); cairo_clip (data->cr); render_button (data->renderer, data->cr, button, FALSE, FALSE); @@ -125,7 +125,6 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) CreateKeyboardSurfaceCallbackData data = { .cr = cairo_create (priv->keyboard_surface), .renderer = renderer, - .view = view, }; /* Paint the background covering the entire widget area */ @@ -138,12 +137,6 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) 0, 0, priv->allocation_width, priv->allocation_height); - cairo_save (data.cr); - cairo_scale (data.cr, priv->scale, priv->scale); - - EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard)); - cairo_translate (data.cr, bounds.x, bounds.y); - GdkRGBA color = {0}; gtk_style_context_get_color (priv->view_context, GTK_STATE_FLAG_NORMAL, &color); cairo_set_source_rgba (data.cr, @@ -152,8 +145,15 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) color.blue, color.alpha); + cairo_save (data.cr); + + cairo_scale (data.cr, priv->scale, priv->scale); + + EekBounds bounds = squeek_view_get_bounds (view); + cairo_translate (data.cr, bounds.x, bounds.y); + /* draw rows */ - squeek_view_foreach(level_keyboard_current(priv->keyboard), + squeek_view_foreach(view, create_keyboard_surface_row_callback, &data); From f9fbd3fb2d1b91f025fae925228509f241309007 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Mon, 2 Dec 2019 16:45:25 +0000 Subject: [PATCH 07/15] rendering: Simplify Cairo context usage, remove unneeded calls. Moved Cairo context usage to Rust, and rearranged ctx setup (position) to happen in one place. Removed render calls that were overwritten on each draw call anyway. --- Cargo.lock | 3 + Cargo.toml | 10 +- eek/eek-gtk-keyboard.c | 54 +--------- eek/eek-renderer.c | 41 +++----- eek/eek-renderer.h | 4 - eek/eek-types.h | 9 ++ src/drawing.rs | 154 ++++++++++++++++++++++++++++ src/keyboard.rs | 2 +- src/layout.h | 11 +- src/layout.rs | 222 ++++++++++++++++++++--------------------- src/lib.rs | 4 + 11 files changed, 310 insertions(+), 204 deletions(-) create mode 100644 src/drawing.rs diff --git a/Cargo.lock b/Cargo.lock index bb1d07ef..cb1be684 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,6 +324,9 @@ name = "rs" version = "0.1.0" dependencies = [ "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)", "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)", diff --git a/Cargo.toml b/Cargo.toml index b7fbd203..c8a2d632 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,15 @@ serde = { version = "1.0.*", features = ["derive"] } serde_yaml = "0.8.*" xkbcommon = { version = "0.4.*", features = ["wayland"] } +[dependencies.cairo-rs] +version = "0.5.*" + +[dependencies.cairo-sys-rs] +version = "" + +[dependencies.gdk] +version = "" + [dependencies.gio] version = "" features = ["v2_44"] @@ -22,7 +31,6 @@ features = ["v2_44"] version = "" features = ["v2_44"] - [dependencies.gtk] version = "0.5.*" features = ["v3_22"] diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index c9590db5..9f092fd1 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -85,7 +85,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, cairo_t *cr) { EekGtkKeyboardPrivate *priv = - eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); GtkAllocation allocation; gtk_widget_get_allocation (self, &allocation); @@ -101,10 +101,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *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); - // render only a few remaining changes - squeek_layout_draw_all_changed(priv->keyboard->layout, EEK_GTK_KEYBOARD(self)); return FALSE; } @@ -113,7 +110,7 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, GtkAllocation *allocation) { EekGtkKeyboardPrivate *priv = - eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); if (priv->renderer) eek_renderer_set_allocation_size (priv->renderer, @@ -231,7 +228,7 @@ static void eek_gtk_keyboard_real_unmap (GtkWidget *self) { EekGtkKeyboardPrivate *priv = - eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); + eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); if (priv->keyboard) { squeek_layout_release_all_only( @@ -322,25 +319,9 @@ eek_gtk_keyboard_new (LevelKeyboard *keyboard) return GTK_WIDGET(ret); } -static void -render_pressed_button (GtkWidget *widget, - struct button_place *place) -{ - EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); +EekRenderer *eek_gtk_keyboard_get_renderer(EekGtkKeyboard *self) { 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_button (priv->renderer, cr, place, 1.0, TRUE, FALSE); -/* - eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE); -*/ - gdk_window_end_draw_frame (window, context); - - cairo_region_destroy (region); + return priv->renderer; } void @@ -381,31 +362,6 @@ render_released_button (GtkWidget *widget, 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, diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index ce9499ee..2d687b38 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -63,7 +63,7 @@ static void eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, Gt const struct squeek_button *button); static void invalidate (EekRenderer *renderer); -static void render_button (EekRenderer *self, +void eek_render_button (EekRenderer *self, cairo_t *cr, const struct squeek_button *button, gboolean pressed, gboolean locked); @@ -92,7 +92,7 @@ create_keyboard_surface_button_callback (struct squeek_button *button, bounds.height); cairo_clip (data->cr); - render_button (data->renderer, data->cr, button, FALSE, FALSE); + eek_render_button (data->renderer, data->cr, button, FALSE, FALSE); cairo_restore (data->cr); } @@ -147,8 +147,6 @@ render_keyboard_surface (EekRenderer *renderer, struct squeek_view *view) cairo_save (data.cr); - cairo_scale (data.cr, priv->scale, priv->scale); - EekBounds bounds = squeek_view_get_bounds (view); cairo_translate (data.cr, bounds.x, bounds.y); @@ -186,12 +184,10 @@ render_outline (cairo_t *cr, } static void render_button_in_context(EekRenderer *self, - gdouble scale, gint scale_factor, cairo_t *cr, GtkStyleContext *ctx, - const struct squeek_button *button, - gboolean active) { + const struct squeek_button *button) { /* blank background */ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); cairo_paint (cr); @@ -234,8 +230,8 @@ static void render_button_in_context(EekRenderer *self, eek_renderer_render_button_label (self, cr, ctx, button); } -static void -render_button (EekRenderer *self, +void +eek_render_button (EekRenderer *self, cairo_t *cr, const struct squeek_button *button, gboolean pressed, @@ -263,7 +259,7 @@ render_button (EekRenderer *self, } gtk_style_context_add_class(ctx, outline_name); - render_button_in_context(self, priv->scale, priv->scale_factor, cr, ctx, button, 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 gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL); @@ -417,7 +413,7 @@ eek_renderer_render_button (EekRenderer *self, cairo_translate (cr, bounds.x, bounds.y); eek_renderer_apply_transformation_for_button (cr, place, scale); - render_button ( + eek_render_button ( self, cr, place->button, is_pressed, is_locked @@ -425,21 +421,19 @@ eek_renderer_render_button (EekRenderer *self, cairo_restore (cr); } -static void -eek_renderer_real_render_keyboard (EekRenderer *self, +void +eek_renderer_render_keyboard (EekRenderer *self, cairo_t *cr) { EekRendererPrivate *priv = eek_renderer_get_instance_private (self); - cairo_pattern_t *source; g_return_if_fail (priv->keyboard); g_return_if_fail (priv->allocation_width > 0.0); g_return_if_fail (priv->allocation_height > 0.0); - cairo_save (cr); - + cairo_save(cr); cairo_translate (cr, priv->origin_x, priv->origin_y); - + cairo_scale (cr, priv->scale, priv->scale); if (priv->keyboard_surface) cairo_surface_destroy (priv->keyboard_surface); @@ -450,10 +444,11 @@ eek_renderer_real_render_keyboard (EekRenderer *self, render_keyboard_surface (self, squeek_layout_get_current_view(priv->keyboard->layout)); cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0); - source = cairo_get_source (cr); + cairo_pattern_t *source = cairo_get_source (cr); cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD); cairo_paint (cr); + squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr); cairo_restore (cr); } @@ -529,8 +524,6 @@ eek_renderer_class_init (EekRendererClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; - klass->render_keyboard = eek_renderer_real_render_keyboard; - gobject_class->set_property = eek_renderer_set_property; gobject_class->get_property = eek_renderer_get_property; gobject_class->dispose = eek_renderer_dispose; @@ -783,14 +776,6 @@ eek_renderer_get_icon_surface (const gchar *icon_name, return surface; } -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 sign (EekPoint *p1, EekPoint *p2, EekPoint *p3) { diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index ec52e809..c5b3d4d8 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -25,7 +25,6 @@ #include #include "eek-types.h" -#include "src/layout.h" G_BEGIN_DECLS @@ -36,9 +35,6 @@ struct _EekRendererClass { GObjectClass parent_class; - void (* render_keyboard) (EekRenderer *self, - cairo_t *cr); - cairo_surface_t *(* get_icon_surface) (EekRenderer *self, const gchar *icon_name, gint size, diff --git a/eek/eek-types.h b/eek/eek-types.h index db187250..6324094b 100644 --- a/eek/eek-types.h +++ b/eek/eek-types.h @@ -88,5 +88,14 @@ struct transformation { gdouble origin_y; 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 #endif /* EEK_TYPES_H */ diff --git a/src/drawing.rs b/src/drawing.rs new file mode 100644 index 00000000..71ef59fe --- /dev/null +++ b/src/drawing.rs @@ -0,0 +1,154 @@ +/*! Drawing the UI */ + +use cairo; +use std::cell::RefCell; + +use ::keyboard; +use ::layout; +use ::layout::{ Button, Layout }; +use ::layout::c::{ EekGtkKeyboard, Point }; + +use gdk::{ WindowExt, DrawingContextExt }; +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, + ); + + pub fn eek_gtk_keyboard_get_renderer( + keyboard: EekGtkKeyboard, + ) -> EekRenderer; + + pub fn eek_renderer_get_transformation( + renderer: EekRenderer, + ) -> layout::c::Transformation; + } + + #[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, + ); + } + } + } + } +} + +/// 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(); +} + +/// Renders a single frame +/// Opens a frame on `keyboard`'s `GdkWindow`, attempt to get a drawing context, +/// calls `f`, closes the frame. +/// If the drawing context was successfully retrieved, returns `f` call result. +pub fn render_as_frame(keyboard: EekGtkKeyboard, mut f: F) -> Option + where F: FnMut(c::EekRenderer, &cairo::Context) -> T +{ + let renderer = unsafe { c::eek_gtk_keyboard_get_renderer(keyboard) }; + + let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) }; + widget.get_window() + .and_then(|window| { + // Need to split the `.and_then` chain here + // because `window` needs to be in scope + // for the references deeper inside. + window.get_clip_region() + // contrary to the docs, `Region` gets destroyed automatically + .and_then(|region| window.begin_draw_frame(®ion)) + .and_then(|drawctx| { + let ret: Option = drawctx.get_cairo_context() + .map(|cr| { + let transformation = unsafe { + c::eek_renderer_get_transformation(renderer) + }; + cr.translate( + transformation.origin_x, + transformation.origin_y, + ); + cr.scale( + transformation.scale, + transformation.scale, + ); + queue_redraw(keyboard); + f(renderer, &cr) // finally! + }); + // This must always happen after `begin_draw_frame`, + // enven if `get_cairo_context` fails. + window.end_draw_frame(&drawctx); + ret + }) + }) +} diff --git a/src/keyboard.rs b/src/keyboard.rs index 0aa4dcfb..c81c7450 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -11,7 +11,7 @@ use ::action::Action; use std::io::Write; use std::iter::{ FromIterator, IntoIterator }; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum PressType { Released = 0, Pressed = 1, diff --git a/src/layout.h b/src/layout.h index eefae7fe..6c6455f3 100644 --- a/src/layout.h +++ b/src/layout.h @@ -5,6 +5,7 @@ #include #include "eek/eek-element.h" #include "eek/eek-gtk-keyboard.h" +#include "eek/eek-renderer.h" #include "eek/eek-types.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" @@ -13,17 +14,9 @@ enum squeek_arrangement_kind { ARRANGEMENT_KIND_WIDE = 1, }; -struct squeek_button; -struct squeek_row; struct squeek_view; 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*); @@ -71,5 +64,5 @@ void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboar double x_widget, double y_widget, struct transformation widget_to_layout, 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); #endif diff --git a/src/layout.rs b/src/layout.rs index 9a2264f3..03a04c5f 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -24,6 +24,7 @@ use std::rc::Rc; use std::vec::Vec; use ::action::Action; +use ::drawing; use ::float_ord::FloatOrd; use ::keyboard::{ KeyState, PressType }; use ::submission::{ Timestamp, VirtualKeyboard }; @@ -34,10 +35,12 @@ use std::borrow::Borrow; pub mod c { use super::*; + use gtk_sys; use std::ffi::CStr; use std::os::raw::{ c_char, c_void }; use std::ptr; - use gtk_sys; + + use std::ops::Add; // The following defined in C @@ -55,6 +58,23 @@ pub mod c { pub x: f64, pub y: f64, } + + impl Add for Point { + type Output = Self; + fn add(self, other: Self) -> Self { + &self + other + } + } + + impl Add 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 #[repr(C)] @@ -66,6 +86,51 @@ pub mod c { pub height: f64 } + impl Bounds { + pub fn get_position(&self) -> Point { + Point { + x: self.x, + y: self.y, + } + } + } + + /// Scale + translate + #[repr(C)] + pub struct Transformation { + pub origin_x: f64, + pub origin_y: f64, + pub 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, + } + } + } + type ButtonCallback = unsafe extern "C" fn(button: *mut ::layout::Button, data: *mut UserData); type RowCallback = unsafe extern "C" fn(row: *mut ::layout::Row, data: *mut UserData); @@ -212,7 +277,7 @@ pub mod c { use super::*; use ::submission::c::ZwpVirtualKeyboardV1; - + #[repr(C)] #[derive(PartialEq, Debug)] pub struct CButtonPlace { @@ -228,42 +293,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 #[allow(dead_code)] @@ -289,24 +318,6 @@ pub mod c { 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, @@ -346,15 +357,16 @@ pub mod c { // because it will be mutated in the loop for key in layout.pressed_keys.clone() { let key: &Rc> = key.borrow(); - ui::release_key( + seat::handle_release_key( layout, &virtual_keyboard, &widget_to_layout, time, ui_keyboard, - key + key, ); } + drawing::queue_redraw(ui_keyboard); } /// Release all buittons but don't redraw @@ -393,27 +405,16 @@ pub mod c { let point = widget_to_layout.forward( Point { x: x_widget, y: y_widget } ); - - // the immutable reference to `layout` through `view` - // must be dropped - // 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 { + + if let Some(position) = layout.get_button_at_point(point) { + let mut state = position.button.state.clone(); layout.press_key( &VirtualKeyboard(virtual_keyboard), &mut state, Timestamp(time), ); - - unsafe { eek_gtk_on_button_pressed(c_place, ui_keyboard) }; + // maybe TODO: draw on the display buffer here + drawing::queue_redraw(ui_keyboard); } } @@ -439,23 +440,26 @@ pub mod c { ); let pressed = layout.pressed_keys.clone(); - let state_place = { + let button_info = { let view = layout.get_current_view(); let place = view.find_button_by_position(point); place.map(|place| {( 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; for wrapped_key in pressed { let key: &Rc> = wrapped_key.borrow(); if Rc::ptr_eq(&state, &wrapped_key.0) { found = true; } else { - ui::release_key( + seat::handle_release_key( layout, &virtual_keyboard, &widget_to_layout, @@ -467,12 +471,12 @@ pub mod c { } if !found { 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 { for wrapped_key in pressed { let key: &Rc> = wrapped_key.borrow(); - ui::release_key( + seat::handle_release_key( layout, &virtual_keyboard, &widget_to_layout, @@ -482,33 +486,7 @@ pub mod c { ); } } - } - - #[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) - }, - } - } - } + drawing::queue_redraw(ui_keyboard); } #[cfg(test)] @@ -535,6 +513,12 @@ pub mod c { } } +/// Relative to `View` +struct ButtonPosition { + view_position: c::Point, + button: Button, +} + pub struct ButtonPlace<'a> { button: &'a Button, row: &'a Row, @@ -779,7 +763,8 @@ impl Layout { locked_keys: HashSet::new(), } } - fn get_current_view(&self) -> &Box { + + pub fn get_current_view(&self) -> &Box { self.views.get(&self.current_view).expect("Selected nonexistent view") } @@ -871,6 +856,18 @@ impl Layout { }; }; } + + fn get_button_at_point(&self, point: c::Point) -> Option { + 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 { @@ -1002,15 +999,15 @@ mod procedures { } } -/// Top level UI procedures -mod ui { +/// Top level procedures, dispatching to everything +mod seat { use super::*; // TODO: turn into release_button - pub fn release_key( + pub fn handle_release_key( layout: &mut Layout, virtual_keyboard: &VirtualKeyboard, - widget_to_layout: &c::procedures::Transformation, + widget_to_layout: &c::Transformation, time: Timestamp, ui_keyboard: c::EekGtkKeyboard, key: &Rc>, @@ -1040,6 +1037,7 @@ mod ui { } } + // TODO: move one level up; multiple buttons might have been released procedures::release_ui_buttons(view, key, ui_keyboard); } } diff --git a/src/lib.rs b/src/lib.rs index 3795b257..d7bf622d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ #[macro_use] extern crate bitflags; +extern crate cairo; +extern crate cairo_sys; +extern crate gdk; extern crate gio; extern crate glib; extern crate glib_sys; @@ -14,6 +17,7 @@ extern crate xkbcommon; mod action; pub mod data; +mod drawing; pub mod float_ord; pub mod imservice; mod keyboard; From e6da2a3b5b03d23b66e507137058285b58163f2d Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 13:58:50 +0000 Subject: [PATCH 08/15] rendering: Remove unneeded redraw after button release --- eek/eek-gtk-keyboard.c | 48 ------------------------------------------ src/layout.rs | 31 --------------------------- 2 files changed, 79 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 9f092fd1..53086f5b 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -61,10 +61,6 @@ typedef struct _EekGtkKeyboardPrivate 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 eek_gtk_keyboard_real_realize (GtkWidget *self) { @@ -341,47 +337,3 @@ eek_gtk_render_locked_button (EekGtkKeyboard *self, struct button_place place) 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_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 -} diff --git a/src/layout.rs b/src/layout.rs index 03a04c5f..d06b098e 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -308,16 +308,6 @@ pub mod c { origin: Point, angle: i32 ) -> 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, - ); } /// Places each button in order, starting from 0 on the left, @@ -904,24 +894,6 @@ mod procedures { c::procedures::eek_are_bounds_inside(bounds, point, origin, angle) }) == 1 } - - /// Switch off all UI buttons associated with the (state) key - pub fn release_ui_buttons( - view: &Box, - key: &Rc>, - 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)] mod test { @@ -1036,9 +1008,6 @@ mod seat { ); } } - - // TODO: move one level up; multiple buttons might have been released - procedures::release_ui_buttons(view, key, ui_keyboard); } } From 804aa5335148a0948cc4c7f1bcc3f044f7d771db Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 14:01:03 +0000 Subject: [PATCH 09/15] renderer: Remove unused locked key render function --- eek/eek-gtk-keyboard.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 53086f5b..c0a35633 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -151,8 +151,6 @@ eek_gtk_keyboard_real_button_press_event (GtkWidget *self, return TRUE; } - - // TODO: this belongs more in gtk_keyboard, with a way to find out which key to re-render static gboolean eek_gtk_keyboard_real_button_release_event (GtkWidget *self, @@ -319,21 +317,3 @@ EekRenderer *eek_gtk_keyboard_get_renderer(EekGtkKeyboard *self) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); return priv->renderer; } - -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, FALSE, TRUE); - - gdk_window_end_draw_frame (window, context); - - cairo_region_destroy (region); -} - From 581c86809ab1dafb3c7808ffe2fdfbc0cf8988e6 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 14:03:51 +0000 Subject: [PATCH 10/15] renderer: Simply cut off when painting outside bounds --- eek/eek-renderer.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 2d687b38..b82401df 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -444,8 +444,6 @@ eek_renderer_render_keyboard (EekRenderer *self, render_keyboard_surface (self, squeek_layout_get_current_view(priv->keyboard->layout)); cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0); - cairo_pattern_t *source = cairo_get_source (cr); - cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD); cairo_paint (cr); squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr); From f77db1bb7366ed41779696969921d038d549593f Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 14:30:51 +0000 Subject: [PATCH 11/15] renderer: Render whole keyboard the same way as pressed buttons Removed window size dependent surface. --- eek/eek-renderer.c | 124 ++++----------------------------------------- src/drawing.rs | 25 +++++++++ src/layout.h | 11 +--- src/layout.rs | 35 ------------- 4 files changed, 37 insertions(+), 158 deletions(-) diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index b82401df..29089659 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -52,7 +52,6 @@ typedef struct _EekRendererPrivate gint origin_y; PangoFontDescription *font; // owned reference - cairo_surface_t *keyboard_surface; } EekRendererPrivate; @@ -62,7 +61,6 @@ 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, const struct squeek_button *button); -static void invalidate (EekRenderer *renderer); void eek_render_button (EekRenderer *self, cairo_t *cr, const struct squeek_button *button, gboolean pressed, gboolean locked); @@ -75,91 +73,6 @@ struct _CreateKeyboardSurfaceCallbackData { }; 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, - bounds.height); - cairo_clip (data->cr); - - eek_render_button (data->renderer, data->cr, button, 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); - - CreateKeyboardSurfaceCallbackData data = { - .cr = cairo_create (priv->keyboard_surface), - .renderer = renderer, - }; - - /* 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); - - GdkRGBA color = {0}; - gtk_style_context_get_color (priv->view_context, GTK_STATE_FLAG_NORMAL, &color); - cairo_set_source_rgba (data.cr, - color.red, - color.green, - color.blue, - color.alpha); - - cairo_save (data.cr); - - EekBounds bounds = squeek_view_get_bounds (view); - cairo_translate (data.cr, bounds.x, bounds.y); - - /* draw rows */ - squeek_view_foreach(view, - create_keyboard_surface_row_callback, - &data); - - cairo_restore (data.cr); - - cairo_destroy (data.cr); -} - static void render_outline (cairo_t *cr, GtkStyleContext *ctx, @@ -431,21 +344,17 @@ eek_renderer_render_keyboard (EekRenderer *self, g_return_if_fail (priv->allocation_width > 0.0); g_return_if_fail (priv->allocation_height > 0.0); + /* Paint the background covering the entire widget area */ + gtk_render_background (priv->view_context, + cr, + 0, 0, + priv->allocation_width, priv->allocation_height); + cairo_save(cr); cairo_translate (cr, priv->origin_x, priv->origin_y); cairo_scale (cr, priv->scale, priv->scale); - 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); - - render_keyboard_surface (self, squeek_layout_get_current_view(priv->keyboard->layout)); - - cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0); - 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); } @@ -476,6 +385,7 @@ eek_renderer_get_property (GObject *object, GValue *value, GParamSpec *pspec) { + (void)value; switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -497,8 +407,7 @@ eek_renderer_dispose (GObject *object) priv->pcontext = NULL; } - /* this will release all allocated surfaces and font if any */ - invalidate (EEK_RENDERER(object)); + // this is where renderer-specific surfaces would be released G_OBJECT_CLASS (eek_renderer_parent_class)->dispose (object); } @@ -577,7 +486,6 @@ eek_renderer_init (EekRenderer *self) priv->scale = 1.0; priv->scale_factor = 1; priv->font = NULL; - priv->keyboard_surface = NULL; GtkIconTheme *theme = gtk_icon_theme_get_default (); @@ -586,17 +494,6 @@ eek_renderer_init (EekRenderer *self) 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 * eek_renderer_new (LevelKeyboard *keyboard, PangoContext *pcontext) @@ -667,7 +564,8 @@ eek_renderer_set_allocation_size (EekRenderer *renderer, /* 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); + + // This is where size-dependent surfaces would be released } void diff --git a/src/drawing.rs b/src/drawing.rs index 71ef59fe..0389d8a8 100644 --- a/src/drawing.rs +++ b/src/drawing.rs @@ -75,6 +75,31 @@ mod c { } } } + + #[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) diff --git a/src/layout.h b/src/layout.h index 6c6455f3..602ebf83 100644 --- a/src/layout.h +++ b/src/layout.h @@ -21,11 +21,6 @@ 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*); const char *squeek_button_get_label(const struct squeek_button*); const char *squeek_button_get_icon_name(const struct squeek_button*); @@ -37,11 +32,6 @@ void squeek_button_print(const struct squeek_button* button); EekBounds squeek_view_get_bounds(const struct squeek_view*); -typedef void (*RowCallback) (struct squeek_row *row, gpointer user_data); -void squeek_view_foreach(struct squeek_view*, - RowCallback callback, - gpointer user_data); - void squeek_layout_place_contents(struct squeek_layout*); struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*); @@ -65,4 +55,5 @@ void squeek_layout_drag(struct squeek_layout *layout, struct zwp_virtual_keyboar struct transformation widget_to_layout, uint32_t timestamp, 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 diff --git a/src/layout.rs b/src/layout.rs index d06b098e..1a40d824 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -43,10 +43,6 @@ pub mod c { use std::ops::Add; // The following defined in C - - #[repr(transparent)] - pub struct UserData(*const c_void); - #[repr(transparent)] #[derive(Copy, Clone)] pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget); @@ -130,9 +126,6 @@ pub mod c { } } } - - type ButtonCallback = unsafe extern "C" fn(button: *mut ::layout::Button, data: *mut UserData); - type RowCallback = unsafe extern "C" fn(row: *mut ::layout::Row, data: *mut UserData); // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers @@ -142,20 +135,6 @@ pub mod c { unsafe { &*view }.bounds.clone() } - #[no_mangle] - pub extern "C" - fn squeek_view_foreach( - view: *mut ::layout::View, - callback: RowCallback, - data: *mut UserData, - ) { - let view = unsafe { &mut *view }; - for row in view.rows.iter_mut() { - let row = row.as_mut() as *mut ::layout::Row; - unsafe { callback(row, data) }; - } - } - #[no_mangle] pub extern "C" fn squeek_row_get_angle(row: *const ::layout::Row) -> i32 { @@ -172,20 +151,6 @@ pub mod c { 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] pub extern "C" From 51a77c41c3f91af978661e7399b0c177e05f2f10 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 15:19:53 +0000 Subject: [PATCH 12/15] renderer: Remove unused functions --- eek/eek-gtk-keyboard.c | 5 +- eek/eek-renderer.c | 151 ----------------------------------------- eek/eek-renderer.h | 19 ------ 3 files changed, 4 insertions(+), 171 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index c0a35633..96d899b6 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -239,6 +239,7 @@ eek_gtk_keyboard_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { + (void)value; switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -295,7 +296,9 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass) static void eek_gtk_keyboard_init (EekGtkKeyboard *self) -{} +{ + (void)self; +} /** * eek_gtk_keyboard_new: diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 29089659..c5c0a0a3 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -182,41 +182,6 @@ eek_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, - struct button_place *place, - gdouble scale) -{ - EekBounds bounds = squeek_button_get_bounds(place->button); - gdouble s; - - gint angle = squeek_row_get_angle (place->row); - - cairo_scale (cr, scale, scale); - - 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 eek_renderer_render_button_label (EekRenderer *self, cairo_t *cr, @@ -289,51 +254,6 @@ eek_renderer_render_button_label (EekRenderer *self, g_object_unref (layout); } -/* - * eek_renderer_real_render_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 - * - * Renders a key separately from the normal keyboard rendering. -*/ -void -eek_renderer_render_button (EekRenderer *self, - cairo_t *cr, - struct button_place *place, - gdouble scale, - gboolean is_pressed, - gboolean is_locked) -{ - g_return_if_fail (EEK_IS_RENDERER(self)); - g_return_if_fail (place); - g_return_if_fail (scale >= 0.0); - - 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); - - 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, place, scale); - eek_render_button ( - self, cr, place->button, - is_pressed, - is_locked - ); - cairo_restore (cr); -} - void eek_renderer_render_keyboard (EekRenderer *self, cairo_t *cr) @@ -568,77 +488,6 @@ eek_renderer_set_allocation_size (EekRenderer *renderer, // This is where size-dependent surfaces would be released } -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) -{ - 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); - - 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; - - - 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 eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale) { diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index c5b3d4d8..0d46237e 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -52,34 +52,15 @@ void eek_renderer_set_allocation_size (EekRenderer *renderer, gdouble width, 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); - -gdouble eek_renderer_get_scale (EekRenderer *renderer); void eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale); -void eek_renderer_render_button (EekRenderer *renderer, - cairo_t *cr, - struct button_place *place, - gdouble scale, gboolean is_pressed, gboolean is_locked); - cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name, gint size, gint scale); void eek_renderer_render_keyboard (EekRenderer *renderer, cairo_t *cr); -void eek_renderer_set_border_width (EekRenderer *renderer, - gdouble border_width); -void eek_renderer_apply_transformation_for_button - (cairo_t *cr, - struct button_place *place, - gdouble scale); struct transformation eek_renderer_get_transformation (EekRenderer *renderer); From 1c4d027af52d675d661106a0d8b3cd98011a4789 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 15:42:54 +0000 Subject: [PATCH 13/15] cleanup: Remove references to squeek_view --- eek/eek-keyboard.c | 5 ----- eek/eek-keyboard.h | 1 - eek/eek-renderer.c | 44 ++++++++------------------------------------ src/layout.h | 11 +++-------- src/layout.rs | 45 ++++++++++++++++----------------------------- 5 files changed, 27 insertions(+), 79 deletions(-) diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 82c45be7..07790245 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -57,8 +57,3 @@ LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek keyboard->manager = manager; return keyboard; } - -struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard) -{ - return squeek_layout_get_current_view(keyboard->layout); -} diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index 05bf5330..ebf63351 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -49,7 +49,6 @@ typedef struct _LevelKeyboard LevelKeyboard; gchar * eek_keyboard_get_keymap (LevelKeyboard *keyboard); -struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard); LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_layout *layout); void level_keyboard_deinit(LevelKeyboard *self); void level_keyboard_free(LevelKeyboard *self); diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index c5c0a0a3..2c30a062 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -42,14 +42,12 @@ typedef struct _EekRendererPrivate GtkStyleContext *view_context; // owned 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_height; - gdouble scale; gint scale_factor; /* the outputs scale factor */ - gint origin_x; - gint origin_y; + struct transformation widget_to_layout; PangoFontDescription *font; // owned reference @@ -65,14 +63,6 @@ void eek_render_button (EekRenderer *self, cairo_t *cr, const struct squeek_button *button, 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 render_outline (cairo_t *cr, GtkStyleContext *ctx, @@ -271,8 +261,8 @@ eek_renderer_render_keyboard (EekRenderer *self, priv->allocation_width, priv->allocation_height); cairo_save(cr); - cairo_translate (cr, priv->origin_x, priv->origin_y); - cairo_scale (cr, priv->scale, priv->scale); + cairo_translate (cr, priv->widget_to_layout.origin_x, priv->widget_to_layout.origin_y); + cairo_scale (cr, priv->widget_to_layout.scale, priv->widget_to_layout.scale); squeek_draw_layout_base_view(priv->keyboard->layout, self, cr); squeek_layout_draw_all_changed(priv->keyboard->layout, self, cr); @@ -403,7 +393,6 @@ eek_renderer_init (EekRenderer *self) priv->border_width = 1.0; priv->allocation_width = 0.0; priv->allocation_height = 0.0; - priv->scale = 1.0; priv->scale_factor = 1; priv->font = NULL; @@ -461,8 +450,6 @@ eek_renderer_set_allocation_size (EekRenderer *renderer, gdouble width, gdouble height) { - gdouble scale; - g_return_if_fail (EEK_IS_RENDERER(renderer)); g_return_if_fail (width > 0.0 && height > 0.0); @@ -471,19 +458,9 @@ eek_renderer_set_allocation_size (EekRenderer *renderer, priv->allocation_width = width; priv->allocation_height = height; - /* Calculate a scale factor to use when rendering the keyboard into the - available space. */ - EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(priv->keyboard)); - - gdouble w = (bounds.x * 2) + bounds.width; - 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); + priv->widget_to_layout = squeek_layout_calculate_transformation( + priv->keyboard->layout, + priv->allocation_width, priv->allocation_height); // This is where size-dependent surfaces would be released } @@ -574,10 +551,5 @@ eek_renderer_get_transformation (EekRenderer *renderer) { g_return_val_if_fail (EEK_IS_RENDERER(renderer), failed); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); - struct transformation ret = { - .origin_x = priv->origin_x, - .origin_y = priv->origin_y, - .scale = priv->scale, - }; - return ret; + return priv->widget_to_layout; } diff --git a/src/layout.h b/src/layout.h index 602ebf83..45748ecc 100644 --- a/src/layout.h +++ b/src/layout.h @@ -14,13 +14,8 @@ enum squeek_arrangement_kind { ARRANGEMENT_KIND_WIDE = 1, }; -struct squeek_view; struct squeek_layout; -int32_t squeek_row_get_angle(const struct squeek_row*); - -EekBounds squeek_row_get_bounds(const struct squeek_row*); - EekBounds squeek_button_get_bounds(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*); @@ -29,12 +24,12 @@ const char *squeek_button_get_outline_name(const struct squeek_button*); void squeek_button_print(const struct squeek_button* button); - -EekBounds squeek_view_get_bounds(const struct squeek_view*); +struct transformation squeek_layout_calculate_transformation( + const struct squeek_layout *layout, + double allocation_width, double allocation_size); void 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); const char *squeek_layout_get_keymap(const struct squeek_layout*); diff --git a/src/layout.rs b/src/layout.rs index 1a40d824..d9b43235 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -129,29 +129,6 @@ pub mod c { // 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_view_get_bounds(view: *const ::layout::View) -> Bounds { - unsafe { &*view }.bounds.clone() - } - - #[no_mangle] - 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_button_get_bounds(button: *const ::layout::Button) -> Bounds { @@ -207,16 +184,26 @@ pub mod c { println!("{:?}", button); } + /// Positions the layout within the available space #[no_mangle] 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 view_name = layout.current_view.clone(); - layout.views.get(&view_name) - .expect("Current view doesn't exist") - .as_ref() as *const View + let bounds = &layout.get_current_view().bounds; + let h_scale = allocation_width / bounds.width; + let v_scale = allocation_height / bounds.height; + 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] pub extern "C" fn squeek_layout_get_keymap(layout: *const Layout) -> *const c_char { From 36362291ef317205ca940b52e1f1ce25368d0861 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 7 Dec 2019 15:50:21 +0000 Subject: [PATCH 14/15] cleanup: Unbox View and Row They are no longer referenced anywhere in C, so it's safe to let Rust memory management deal with them. --- src/data.rs | 8 ++++---- src/layout.rs | 27 +++++++++++++++------------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/data.rs b/src/data.rs index 503716ca..cc02948d 100644 --- a/src/data.rs +++ b/src/data.rs @@ -405,7 +405,7 @@ impl Layout { let views = HashMap::from_iter( self.views.iter().map(|(name, view)| {( name.clone(), - Box::new(::layout::View { + ::layout::View { bounds: ::layout::c::Bounds { x: self.bounds.x, y: self.bounds.y, @@ -413,7 +413,7 @@ impl Layout { height: self.bounds.height, }, rows: view.iter().map(|row| { - Box::new(::layout::Row { + ::layout::Row { angle: 0, bounds: None, buttons: row.split_ascii_whitespace().map(|name| { @@ -427,9 +427,9 @@ impl Layout { &mut warning_handler, )) }).collect(), - }) + } }).collect(), - }) + } )}) ); diff --git a/src/layout.rs b/src/layout.rs index d9b43235..80dcb52c 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -74,7 +74,7 @@ pub mod c { /// Defined in eek-types.h #[repr(C)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, PartialEq)] pub struct Bounds { pub x: f64, pub y: f64, @@ -570,7 +570,7 @@ pub struct Spacing { pub struct View { /// Position relative to keyboard origin pub bounds: c::Bounds, - pub rows: Vec>, + pub rows: Vec, } impl View { @@ -665,7 +665,7 @@ pub struct Layout { // Views own the actual buttons which have state // Maybe they should own UI only, // and keys should be owned by a dedicated non-UI-State? - pub views: HashMap>, + pub views: HashMap, // Non-UI stuff /// xkb keymap applicable to the contained keys. Unchangeable @@ -684,7 +684,7 @@ pub struct Layout { /// A builder structure for picking up layout data from storage pub struct LayoutData { - pub views: HashMap>, + pub views: HashMap, pub keymap_str: CString, } @@ -706,7 +706,7 @@ impl Layout { } } - pub fn get_current_view(&self) -> &Box { + pub fn get_current_view(&self) -> &View { self.views.get(&self.current_view).expect("Selected nonexistent view") } @@ -815,7 +815,7 @@ impl Layout { mod procedures { use super::*; - type Path<'v> = (&'v Box, &'v Box