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