diff options
-rw-r--r-- | docs/reference/endless/endless-sections.txt | 8 | ||||
-rw-r--r-- | endless/eoswindow.c | 298 | ||||
-rw-r--r-- | endless/eoswindow.h | 38 | ||||
-rw-r--r-- | test/smoke-tests/app-window.js | 24 | ||||
-rw-r--r-- | test/test-window.c | 65 |
5 files changed, 427 insertions, 6 deletions
diff --git a/docs/reference/endless/endless-sections.txt b/docs/reference/endless/endless-sections.txt index 8752058..4e4887a 100644 --- a/docs/reference/endless/endless-sections.txt +++ b/docs/reference/endless/endless-sections.txt @@ -32,6 +32,14 @@ EosWindow eos_window_new eos_window_get_page_manager eos_window_set_page_manager +eos_window_get_font_scaling_active +eos_window_set_font_scaling_active +eos_window_get_font_scaling_default_size +eos_window_set_font_scaling_default_size +eos_window_get_font_scaling_default_window_size +eos_window_set_font_scaling_default_window_size +eos_window_get_font_scaling_min_font_size +eos_window_set_font_scaling_min_font_size <SUBSECTION Standard> EosWindowClass EOS_IS_WINDOW diff --git a/endless/eoswindow.c b/endless/eoswindow.c index 8fda631..c06b1a7 100644 --- a/endless/eoswindow.c +++ b/endless/eoswindow.c @@ -33,6 +33,31 @@ * }, * }); * ]| + * + * We will use an application-configurable base font size for application- + * configurable resolution and scale up/down from there for different screen sizes. + * + * Font scaling can be enabled by setting #EosWindow:font-scaling-active to + * true. Font scaling is turned off and the property is false by default. + * + * The default font size by which font scaling will occur can be set by + * #EosWindow:font-scaling-default-size. + * + * The default window resolution height by which font scaling will occur can be + * set by #EosWindow:font-scaling-default-window-size. + * + * The default minimum font size under which a font will never scale can be set + * by #EosWindow:font-scaling-min-font-size. + * + * For instance, supose we have a default font size of 12px, a default window size + * of 720px, and a window allocation of 360px. The calculated base pixel size + * will be 12px * (360px / 720px) = 6px. A corresponding CSS font-size of 1em will + * be equivalent to 6 px. A CSS font-size of 0.5em will be equivalent to 3px. If the + * window is resized to a height of 720px, then the calculated base pixel size will + * be 12px, and the CSS font-size of 1em will be equivalent to 12px. A CSS + * font-size of 0.5em will be equivalent to 6px. If the minimum font size is set + * to 12px, then the font-size will be forced to 12px, ignoring the calculated font + * size of 6px. */ #define DEFAULT_WINDOW_WIDTH 800 @@ -40,6 +65,8 @@ #define BACKGROUND_FRAME_NAME_TEMPLATE "_eos-window-background-%d" +#define FONT_SIZE_TEMPLATE "EosWindow { font-size: %fpx; }" + #define TRANSPARENT_FRAME_CSS_PROPERTIES "{ background-image: none;\n" \ " background-color: transparent\n;" \ " border-width: 0px; }\n" @@ -68,6 +95,13 @@ typedef struct { EosPageManager *page_manager; + /* For scaling base font-size */ + GtkCssProvider *font_size_provider; + gboolean font_scaling_active; + gint font_scaling_default_size; + gint font_scaling_default_window_size; + gint font_scaling_min_font_size; + /* For keeping track of what to display alongside the current page */ GtkWidget *current_page; gulong visible_page_property_handler; @@ -82,6 +116,10 @@ enum PROP_0, PROP_APPLICATION, PROP_PAGE_MANAGER, + PROP_FONT_SCALING_ACTIVE, + PROP_FONT_SCALING_DEFAULT_SIZE, + PROP_FONT_SCALING_DEFAULT_WINDOW_SIZE, + PROP_FONT_SCALING_MIN_FONT_SIZE, NPROPS }; @@ -373,6 +411,22 @@ eos_window_get_property (GObject *object, g_value_set_object (value, eos_window_get_page_manager (self)); break; + case PROP_FONT_SCALING_ACTIVE: + g_value_set_boolean (value, priv->font_scaling_active); + break; + + case PROP_FONT_SCALING_DEFAULT_SIZE: + g_value_set_int (value, priv->font_scaling_default_size); + break; + + case PROP_FONT_SCALING_DEFAULT_WINDOW_SIZE: + g_value_set_int (value, priv->font_scaling_default_window_size); + break; + + case PROP_FONT_SCALING_MIN_FONT_SIZE: + g_value_set_int (value, priv->font_scaling_min_font_size); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -412,6 +466,22 @@ eos_window_set_property (GObject *object, eos_window_set_page_manager (self, g_value_get_object (value)); break; + case PROP_FONT_SCALING_ACTIVE: + eos_window_set_font_scaling_active (self, g_value_get_boolean (value)); + break; + + case PROP_FONT_SCALING_DEFAULT_SIZE: + eos_window_set_font_scaling_default_size (self, g_value_get_int (value)); + break; + + case PROP_FONT_SCALING_DEFAULT_WINDOW_SIZE: + eos_window_set_font_scaling_default_window_size (self, g_value_get_int (value)); + break; + + case PROP_FONT_SCALING_MIN_FONT_SIZE: + eos_window_set_font_scaling_min_font_size (self, g_value_get_int (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -424,6 +494,7 @@ eos_window_finalize (GObject *object) EosWindowPrivate *priv = eos_window_get_instance_private (self); g_object_unref (priv->background_provider); + g_object_unref (priv->font_size_provider); g_free (priv->current_background_css_props); G_OBJECT_CLASS (eos_window_parent_class)->finalize (object); @@ -498,6 +569,38 @@ eos_window_get_preferred_height (GtkWidget *widget, natural_height); } +/* Updates the base font size depending on the window size. */ +static void +eos_window_size_allocate (GtkWidget *window, GtkAllocation *allocation) +{ + EosWindow *self = EOS_WINDOW (window); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + + if (priv->font_scaling_active) + { + GtkStyleProvider *provider = GTK_STYLE_PROVIDER (priv->font_size_provider); + gdouble base_pixel_size = (gdouble) priv->font_scaling_default_size * + ((gdouble) allocation->height / (gdouble) priv->font_scaling_default_window_size); + + if (base_pixel_size < priv->font_scaling_min_font_size) + base_pixel_size = priv->font_scaling_min_font_size; + + GError *error = NULL; + + gchar *font_size_css = g_strdup_printf (FONT_SIZE_TEMPLATE, base_pixel_size); + GdkScreen *screen = gdk_screen_get_default (); + + gtk_style_context_remove_provider_for_screen (screen, provider); + gtk_css_provider_load_from_data (provider, font_size_css, -1, &error); + gtk_style_context_add_provider_for_screen (screen, provider, + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + g_free(font_size_css); + } + + GTK_WIDGET_CLASS (eos_window_parent_class)->size_allocate (window, allocation); +} + /* Our default delete event handler destroys the window. */ static gboolean eos_window_default_delete (GtkWidget* window, @@ -518,6 +621,7 @@ eos_window_class_init (EosWindowClass *klass) object_class->finalize = eos_window_finalize; widget_class->get_preferred_height = eos_window_get_preferred_height; widget_class->get_preferred_width = eos_window_get_preferred_width; + widget_class->size_allocate = eos_window_size_allocate; /** * EosWindow:application: @@ -543,6 +647,56 @@ eos_window_class_init (EosWindowClass *klass) EOS_TYPE_PAGE_MANAGER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + /** + * EosWindow:font-scaling-active: + * + * The scaling flag that determines if the windows scale or not. + */ + eos_window_props[PROP_FONT_SCALING_ACTIVE] = + g_param_spec_boolean ("font-scaling-active", "Font scaling active", + "Whether or not EosWindow objects scale font size", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + /** + * EosWindow:font-scaling-default-size: + * + * The default font-size by which font scaling will occur. Units are in pixels. + */ + eos_window_props[PROP_FONT_SCALING_DEFAULT_SIZE] = + g_param_spec_int ("font-scaling-default-size", "Font scaling default size", + "This is the default font-size by which font-size for children widgets will scale", + 1, + G_MAXINT, + 12, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + /** + * EosWindow:font-scaling-default-window-size: + * + * The base resolution by which font scaling will occur. Units are in pixels. + */ + eos_window_props[PROP_FONT_SCALING_DEFAULT_WINDOW_SIZE] = + g_param_spec_int ("font-scaling-default-window-size", "Font scaling default window size", + "This is the base resolution by which font-size for children widgets will scale", + 1, + G_MAXINT, + 1080, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + /** + * EosWindow:font-scaling-min-font-size: + * + * The minimum font-size under which font scaling won't occur. Units are in pixels. + */ + eos_window_props[PROP_FONT_SCALING_MIN_FONT_SIZE] = + g_param_spec_int ("font-scaling-min-font-size", "Font scaling default size", + "This is the minimum font-size under which font-size for children widgets won't scale", + 1, + G_MAXINT, + 8, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, NPROPS, eos_window_props); } @@ -622,6 +776,9 @@ eos_window_init (EosWindow *self) gtk_container_add (GTK_CONTAINER (priv->background_stack), priv->current_background); g_free (background_name0); + /* Dynamically set the base font-size based on the given window allocation. */ + priv->font_size_provider = gtk_css_provider_new (); + priv->background_provider = gtk_css_provider_new (); // We start all the background frames transparent with no styling priv->current_background_css_props = g_strdup (TRANSPARENT_FRAME_CSS_PROPERTIES); @@ -731,3 +888,144 @@ eos_window_set_page_manager (EosWindow *self, g_signal_connect_swapped (priv->page_manager, "notify::visible-page", G_CALLBACK (update_page), self); } + +/** + * eos_window_get_font_scaling_active: + * @self: the window + * + * See #EosWindow:font-scaling-active for details. + * + * Returns: whether or not the font will automatically scale. + */ +gboolean +eos_window_get_font_scaling_active (EosWindow *self) +{ + g_return_val_if_fail (self != NULL && EOS_IS_WINDOW (self), FALSE); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + + return priv->font_scaling_active; +} + +/** + * eos_window_set_font_scaling_active: + * @self: the window + * @is_scaling: true for enabling font scaling and + * false for disabling font scaling + * + * Sets whether or not the font will automatically scale. + * See #EosWindow:font-scaling-active for details. + */ +void +eos_window_set_font_scaling_active (EosWindow *self, + gboolean is_scaling) +{ + g_return_if_fail (self != NULL && EOS_IS_WINDOW (self)); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + priv->font_scaling_active = is_scaling; +} + +/** + * eos_window_get_font_scaling_default_size: + * @self: the window + * + * See #EosWindow:font-scaling-default-size for details. + * + * Returns: the default font size by which the font size of children widgets + * will scale. + */ +gint +eos_window_get_font_scaling_default_size (EosWindow *self) +{ + g_return_val_if_fail (self != NULL && EOS_IS_WINDOW (self), -1); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + + return priv->font_scaling_default_size; +} + +/** + * eos_window_set_font_scaling_default_size: + * @self: the window + * @new_default_font_size: the new default font size + * + * Sets the default font size by which the font size of children widgets + * will scale. See #EosWindow:font-scaling-default-size for details. + */ +void +eos_window_set_font_scaling_default_size (EosWindow *self, + gint new_default_font_size) +{ + g_return_if_fail (self != NULL && EOS_IS_WINDOW (self)); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + priv->font_scaling_default_size = new_default_font_size; +} + +/** + * eos_window_get_font_scaling_default_window_size: + * @self: the window + * + * See #EosWindow:font-scaling-default-window-size for details. + * + * Returns: the default window size by which font scaling + * will occur. + */ +gint +eos_window_get_font_scaling_default_window_size (EosWindow *self) +{ + g_return_val_if_fail (self != NULL && EOS_IS_WINDOW (self), -1); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + + return priv->font_scaling_default_window_size; +} + +/** + * eos_window_set_font_scaling_default_window_size: + * @self: the window + * @new_default_window_size: the new default window size + * + * Sets the default window size by which the font size of children widgets + * will scale. See #EosWindow:font-scaling-default-window-size for details. + */ +void +eos_window_set_font_scaling_default_window_size (EosWindow *self, + gint new_default_window_size) +{ + g_return_if_fail (self != NULL && EOS_IS_WINDOW (self)); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + priv->font_scaling_default_window_size = new_default_window_size; +} + +/** + * eos_window_get_font_scaling_min_font_size: + * @self: the window + * + * See #EosWindow:font-scaling-min-font-size for details. + * + * Returns: the minimum font size below which font scaling + * won't occur. + */ +gint +eos_window_get_font_scaling_min_font_size (EosWindow *self) +{ + g_return_val_if_fail (self != NULL && EOS_IS_WINDOW (self), -1); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + + return priv->font_scaling_min_font_size; +} + +/** + * eos_window_set_font_scaling_min_font_size: + * @self: the window + * @new_min_font_size: the new min font size + * + * Sets the min font size by which the font size of children widgets + * will scale. See #EosWindow:font-scaling-min-font-size for + * details. + */ +void +eos_window_set_font_scaling_min_font_size (EosWindow *self, + gint new_min_font_size) +{ + g_return_if_fail (self != NULL && EOS_IS_WINDOW (self)); + EosWindowPrivate *priv = eos_window_get_instance_private (self); + priv->font_scaling_min_font_size = new_min_font_size; +} diff --git a/endless/eoswindow.h b/endless/eoswindow.h index 820aa09..317f0c5 100644 --- a/endless/eoswindow.h +++ b/endless/eoswindow.h @@ -59,17 +59,45 @@ struct _EosWindowClass }; EOS_SDK_ALL_API_VERSIONS -GType eos_window_get_type (void) G_GNUC_CONST; +GType eos_window_get_type (void) G_GNUC_CONST; EOS_SDK_ALL_API_VERSIONS -GtkWidget *eos_window_new (EosApplication *application); +GtkWidget *eos_window_new (EosApplication *application); EOS_SDK_ALL_API_VERSIONS -EosPageManager *eos_window_get_page_manager (EosWindow *self); +EosPageManager *eos_window_get_page_manager (EosWindow *self); EOS_SDK_ALL_API_VERSIONS -void eos_window_set_page_manager (EosWindow *self, - EosPageManager *page_manager); +void eos_window_set_page_manager (EosWindow *self, + EosPageManager *page_manager); + +EOS_SDK_ALL_API_VERSIONS +gboolean eos_window_get_font_scaling_active (EosWindow *self); + +EOS_SDK_ALL_API_VERSIONS +void eos_window_set_font_scaling_active (EosWindow *self, + gboolean is_scaling); + +EOS_SDK_ALL_API_VERSIONS +gint eos_window_get_font_scaling_default_size (EosWindow *self); + +EOS_SDK_ALL_API_VERSIONS +void eos_window_set_font_scaling_default_size (EosWindow *self, + gint new_default_font_size); + +EOS_SDK_ALL_API_VERSIONS +gint eos_window_get_font_scaling_default_window_size (EosWindow *self); + +EOS_SDK_ALL_API_VERSIONS +void eos_window_set_font_scaling_default_window_size (EosWindow *self, + gint new_default_window_size); + +EOS_SDK_ALL_API_VERSIONS +gint eos_window_get_font_scaling_min_font_size (EosWindow *self); + +EOS_SDK_ALL_API_VERSIONS +void eos_window_set_font_scaling_min_font_size (EosWindow *self, + gint new_min_font_size); G_END_DECLS diff --git a/test/smoke-tests/app-window.js b/test/smoke-tests/app-window.js index 6821358..d7554b9 100644 --- a/test/smoke-tests/app-window.js +++ b/test/smoke-tests/app-window.js @@ -3,6 +3,7 @@ const Lang = imports.lang; const Endless = imports.gi.Endless; const Gtk = imports.gi.Gtk; +const Gdk = imports.gi.Gdk; const GObject = imports.gi.GObject; const TEST_APPLICATION_ID = 'com.endlessm.example.test'; @@ -103,12 +104,16 @@ const Toolbox = new Lang.Class ({ this._label2 = new Gtk.Label({ label: 'Actions on page 1' }); this.switch1 = new Gtk.Switch({ active: false }); this.switch2 = new Gtk.Switch({ active: true }); + this.button1 = new Gtk.Button({ label: 'Scale font down' }); + this.button2 = new Gtk.Button({ label: 'Scale font up' }); this.add(this._label); this.add(this._label1); this.add(this.switch1); this.add(this._label2); this.add(this.switch2); + this.add(this.button1); + this.add(this.button2); } }); @@ -214,8 +219,25 @@ const TestApplication = new Lang.Class ({ this._window = new Endless.Window({ application: this, - page_manager: this._pm + page_manager: this._pm, + 'font-scaling-active': true, + 'font-scaling-default-size': 16 }); + + this._toolbox.button1.connect('clicked', Lang.bind(this, function () { + let current_font_size = this._window.get_font_scaling_default_size(); + this._window.set_font_scaling_default_size(current_font_size - 1); + })); + this._toolbox.button2.connect('clicked', Lang.bind(this, function () { + let current_font_size = this._window.get_font_scaling_default_size(); + this._window.set_font_scaling_default_size(current_font_size + 1); + })); + + let provider = new Gtk.CssProvider(); + provider.load_from_data("EosWindow { font-size: 1em; }"); + Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + this._window.show_all(); }, diff --git a/test/test-window.c b/test/test-window.c index 0b47ac6..32639be 100644 --- a/test/test-window.c +++ b/test/test-window.c @@ -94,6 +94,63 @@ test_get_set_page_manager (GApplication *app) } static void +test_get_set_font_scaling_active (GApplication *app) +{ + GtkWidget *win = eos_window_new (EOS_APPLICATION (app)); + + gboolean is_scaling_default = eos_window_get_font_scaling_active (EOS_WINDOW (win)); + g_assert (!is_scaling_default); + + eos_window_set_font_scaling_active (EOS_WINDOW (win), TRUE); + gboolean is_scaling = eos_window_get_font_scaling_active (EOS_WINDOW (win)); + g_assert (is_scaling); + + gtk_widget_destroy (win); +} + +static void +test_get_set_font_scaling_default_size (GApplication *app) +{ + GtkWidget *win = eos_window_new (EOS_APPLICATION (app)); + gint new_font_size = 10; + + eos_window_set_font_scaling_default_size (EOS_WINDOW (win), new_font_size); + gint returned_font_size = eos_window_get_font_scaling_default_size (EOS_WINDOW (win)); + + g_assert (new_font_size == returned_font_size); + + gtk_widget_destroy (win); +} + +static void +test_get_set_font_scaling_default_window_size (GApplication *app) +{ + GtkWidget *win = eos_window_new (EOS_APPLICATION (app)); + gint new_window_size = 720; + + eos_window_set_font_scaling_default_window_size (EOS_WINDOW (win), new_window_size); + gint returned_window_size = eos_window_get_font_scaling_default_window_size (EOS_WINDOW (win)); + + g_assert (new_window_size == returned_window_size); + + gtk_widget_destroy (win); +} + +static void +test_get_set_font_scaling_min_font_size (GApplication *app) +{ + GtkWidget *win = eos_window_new (EOS_APPLICATION (app)); + gint new_min_font_size = 10; + + eos_window_set_font_scaling_min_font_size (EOS_WINDOW (win), new_min_font_size); + gint returned_min_font_size = eos_window_get_font_scaling_min_font_size (EOS_WINDOW (win)); + + g_assert (new_min_font_size == returned_min_font_size); + + gtk_widget_destroy (win); +} + +static void test_prop_page_manager (GApplication *app) { GtkWidget *win = eos_window_new (EOS_APPLICATION (app)); @@ -181,6 +238,14 @@ add_window_tests (void) test_has_default_page_manager); ADD_APP_WINDOW_TEST ("/window/get-set-page-manager", test_get_set_page_manager); + ADD_APP_WINDOW_TEST ("/window/get-set-font-scaling-active", + test_get_set_font_scaling_active); + ADD_APP_WINDOW_TEST ("/window/get-set-font-scaling-default-size", + test_get_set_font_scaling_default_size); + ADD_APP_WINDOW_TEST ("/window/get-set-font-scaling-default-window-size", + test_get_set_font_scaling_default_window_size); + ADD_APP_WINDOW_TEST ("/window/get-set-font-scaling-min-font-size", + test_get_set_font_scaling_min_font_size); ADD_APP_WINDOW_TEST ("/window/prop-page-manager", test_prop_page_manager); ADD_APP_WINDOW_TEST ("/window/main-area-widgets-visibility", test_main_area_widgets_visibility); |