gnome-control-center/a11y-text-size-setting.patch
Felipe Borges dee3e3e47b a11y: Add "Text Size" setting
This allows for resizing the text of the interface to values larger
than the previously hardcoded "Large Text".

The intent of this setting is to ensure that visually rendered text,
including controls and labels using text, can be made larger so that
it can be read more easily by people with milder visual impairments,
without requiring the use of assistive technology (such as a screen
magnifier or screen reader). Users may benefit from scaling all
content on the web page, but text is most critical.

See also WCAG 2.0, criterion 1.4.4 - Resize text
https://www.w3.org/TR/WCAG22/#resize-text

Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1648

Resolves: RHEL-83848
2025-11-12 10:42:21 +01:00

339 lines
14 KiB
Diff

From 41791e1dcf3c8e81b46db13265ff48598bdc9ef3 Mon Sep 17 00:00:00 2001
From: Felipe Borges <felipeborges@gnome.org>
Date: Wed, 12 Nov 2025 10:36:16 +0100
Subject: [PATCH] a11y: Add "Text Size" setting
This allows for resizing the text of the interface to values larger
than the previously hardcoded "Large Text".
The intent of this setting is to ensure that visually rendered text,
including controls and labels using text, can be made larger so that
it can be read more easily by people with milder visual impairments,
without requiring the use of assistive technology (such as a screen
magnifier or screen reader). Users may benefit from scaling all
content on the web page, but text is most critical.
See also WCAG 2.0, criterion 1.4.4 - Resize text
https://www.w3.org/TR/WCAG22/#resize-text
Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1648
---
panels/universal-access/cc-ua-seeing-page.c | 126 +++++++++++++++----
panels/universal-access/cc-ua-seeing-page.ui | 101 ++++++++++++++-
2 files changed, 197 insertions(+), 30 deletions(-)
diff --git a/panels/universal-access/cc-ua-seeing-page.c b/panels/universal-access/cc-ua-seeing-page.c
index 7a84997b8..f14250506 100644
--- a/panels/universal-access/cc-ua-seeing-page.c
+++ b/panels/universal-access/cc-ua-seeing-page.c
@@ -36,6 +36,7 @@
# include "config.h"
#endif
+#include <math.h>
#include <glib/gi18n-lib.h>
#include "cc-list-row.h"
@@ -50,7 +51,12 @@ struct _CcUaSeeingPage
AdwSwitchRow *high_contrast_row;
AdwSwitchRow *status_shapes_row;
GtkSwitch *animation_effects_switch;
- AdwSwitchRow *large_text_row;
+ CcListRow *text_size_row;
+ GtkScale *text_size_scale;
+ AdwDialog *text_size_dialog;
+ GtkLabel *text_size_preview_label;
+ GtkLabel *text_size_label_small;
+ GtkLabel *text_size_label_large;
CcListRow *cursor_size_row;
AdwSwitchRow *sound_keys_row;
AdwSwitchRow *show_scrollbars_row;
@@ -65,32 +71,76 @@ struct _CcUaSeeingPage
G_DEFINE_TYPE (CcUaSeeingPage, cc_ua_seeing_page, ADW_TYPE_NAVIGATION_PAGE)
-static gboolean
-get_large_text_mapping (GValue *value,
- GVariant *variant,
- gpointer user_data)
+
+static void
+set_label_scale (CcUaSeeingPage *self,
+ GtkLabel *label,
+ double scale)
{
- gdouble factor;
+ PangoContext *pango_ctx;
+ PangoFontDescription *font_desc;
+ double default_font_size;
+ g_autoptr(PangoAttribute) attr = NULL;
+ g_autoptr(PangoAttrList) new_attrs = NULL;
- factor = g_variant_get_double (variant);
- g_value_set_boolean (value, factor > DPI_FACTOR_NORMAL);
+ pango_ctx = gtk_widget_get_pango_context (GTK_WIDGET (label));
+ font_desc = pango_context_get_font_description (pango_ctx);
+
+ if (font_desc)
+ {
+ default_font_size = pango_font_description_get_size (font_desc);
+
+ /* We need absolute size without text scaling applied */
+ if (pango_font_description_get_size_is_absolute (font_desc))
+ default_font_size /= g_settings_get_double (self->interface_settings,
+ KEY_TEXT_SCALING_FACTOR);
+ else
+ default_font_size *= 96.0 / 72; /* 96 dpi */
+ }
+ else
+ {
+ default_font_size = 11 * PANGO_SCALE * 96.0 / 72; /* Assuming 11 pt, 96 dpi */
+ }
- return TRUE;
+ attr = pango_attr_size_new_absolute (round (scale * default_font_size));
+ new_attrs = pango_attr_list_new ();
+ pango_attr_list_insert (new_attrs, g_steal_pointer (&attr));
+
+ gtk_label_set_attributes (label, new_attrs);
}
-static GVariant *
-set_large_text_mapping (const GValue *value,
- const GVariantType *expected_type,
- gpointer user_data)
+static void
+update_text_size_row_label (CcUaSeeingPage *self)
{
- GSettings *settings = user_data;
+ const gchar *label = NULL;
+ double text_scaling_factor;
- if (g_value_get_boolean (value))
- return g_variant_new_double (DPI_FACTOR_LARGE);
+ text_scaling_factor = g_settings_get_double (self->interface_settings,
+ KEY_TEXT_SCALING_FACTOR);
+ label = text_scaling_factor > DPI_FACTOR_NORMAL ? _("Large") : _("Default");
+ cc_list_row_set_secondary_label (self->text_size_row, label);
+}
- g_settings_reset (settings, KEY_TEXT_SCALING_FACTOR);
+static void
+apply_text_size_changes (CcUaSeeingPage *self)
+{
+ g_settings_set_double (self->interface_settings, KEY_TEXT_SCALING_FACTOR,
+ gtk_range_get_value (GTK_RANGE (self->text_size_scale)));
+ adw_dialog_close (self->text_size_dialog);
- return NULL;
+ update_text_size_row_label (self);
+}
+
+static void
+ua_text_size_value_changed (GtkRange *text_size_range,
+ gpointer user_data)
+{
+ CcUaSeeingPage *self = CC_UA_SEEING_PAGE (user_data);
+ double value = gtk_range_get_value (text_size_range);
+
+ gtk_range_set_value (text_size_range, value);
+
+ set_label_scale (self, self->text_size_preview_label, value);
}
static void
@@ -146,6 +196,16 @@ ua_cursor_row_activated_cb (CcUaSeeingPage *self)
adw_dialog_present (dialog, GTK_WIDGET (self));
}
+static void
+ua_text_size_row_activated_cb (CcUaSeeingPage *self)
+{
+ /* Intiialize scale with the current value. */
+ gtk_range_set_value (GTK_RANGE (self->text_size_scale),
+ g_settings_get_double (self->interface_settings,
+ KEY_TEXT_SCALING_FACTOR));
+ adw_dialog_present (self->text_size_dialog, GTK_WIDGET (self));
+}
+
static void
cc_ua_seeing_page_dispose (GObject *object)
{
@@ -174,19 +234,30 @@ cc_ua_seeing_page_class_init (CcUaSeeingPageClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, high_contrast_row);
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, status_shapes_row);
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, animation_effects_switch);
- gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, large_text_row);
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, cursor_size_row);
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, sound_keys_row);
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, show_scrollbars_row);
gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, screen_reader_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, text_size_dialog);
+ gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, text_size_label_small);
+ gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, text_size_label_large);
+ gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, text_size_preview_label);
+ gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, text_size_row);
+ gtk_widget_class_bind_template_child (widget_class, CcUaSeeingPage, text_size_scale);
+
gtk_widget_class_bind_template_callback (widget_class, ua_cursor_row_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, ua_text_size_row_activated_cb);
+
+ gtk_widget_class_bind_template_callback (widget_class, apply_text_size_changes);
}
static void
cc_ua_seeing_page_init (CcUaSeeingPage *self)
{
+ g_type_ensure (CC_TYPE_LIST_ROW);
+
gtk_widget_init_template (GTK_WIDGET (self));
self->kb_settings = g_settings_new (KEYBOARD_SETTINGS);
@@ -209,14 +280,15 @@ cc_ua_seeing_page_init (CcUaSeeingPage *self)
self->animation_effects_switch, "active",
G_SETTINGS_BIND_DEFAULT);
- /* Large Text */
- g_settings_bind_with_mapping (self->interface_settings, KEY_TEXT_SCALING_FACTOR,
- self->large_text_row,
- "active", G_SETTINGS_BIND_DEFAULT,
- get_large_text_mapping,
- set_large_text_mapping,
- self->interface_settings,
- NULL);
+ /* Text Size */
+ gtk_range_set_value (GTK_RANGE (self->text_size_scale),
+ g_settings_get_double (self->interface_settings,
+ KEY_TEXT_SCALING_FACTOR));
+ g_signal_connect (GTK_RANGE (self->text_size_scale), "value-changed",
+ G_CALLBACK (ua_text_size_value_changed), self);
+ update_text_size_row_label (self);
+ set_label_scale (self, self->text_size_label_small, 1.0);
+ set_label_scale (self, self->text_size_label_large, 2.0);
/* Sound Keys */
g_settings_bind (self->kb_settings, KEY_TOGGLEKEYS_ENABLED,
diff --git a/panels/universal-access/cc-ua-seeing-page.ui b/panels/universal-access/cc-ua-seeing-page.ui
index d2622d7cb..98fbd951e 100644
--- a/panels/universal-access/cc-ua-seeing-page.ui
+++ b/panels/universal-access/cc-ua-seeing-page.ui
@@ -61,10 +61,11 @@
</child>
<child>
- <object class="AdwSwitchRow" id="large_text_row">
- <property name="title" translatable="yes">_Large Text</property>
- <property name="subtitle" translatable="yes">Increase the size of all text in the user interface</property>
+ <object class="CcListRow" id="text_size_row">
+ <property name="title" translatable="yes">_Text Size</property>
+ <property name="show-arrow">True</property>
<property name="use-underline">True</property>
+ <signal name="activated" handler="ua_text_size_row_activated_cb" swapped="yes"/>
</object>
</child>
@@ -100,4 +101,98 @@
</object>
</property>
</template>
+
+ <object class="AdwDialog" id="text_size_dialog">
+ <property name="title" translatable="yes">Text Size</property>
+ <property name="content-width">500</property>
+ <property name="height-request">360</property>
+ <property name="child">
+ <object class="AdwToolbarView">
+ <child type="top">
+ <object class="AdwHeaderBar">
+ <property name="show-start-title-buttons">false</property>
+ <property name="show-end-title-buttons">false</property>
+ <child type="start">
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Cancel</property>
+ <signal name="clicked" handler="adw_dialog_close" object="text_size_dialog"/>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Apply</property>
+ <signal name="clicked" handler="apply_text_size_changes" object="CcUaSeeingPage"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <property name="content">
+ <object class="AdwPreferencesPage">
+ <property name="description" translatable="yes">Use the slider to adjust the size of user interface text</property>
+ <property name="description-centered">true</property>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwPreferencesRow">
+ <property name="activatable">false</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="text_size_label_small">
+ <property name="label" translatable="yes">A</property>
+ <property name="margin-start">20</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScale" id="text_size_scale">
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <property name="hexpand">true</property>
+ <property name="round-digits">2</property>
+ <property name="adjustment">
+ <object class="GtkAdjustment">
+ <property name="lower">1</property>
+ <property name="upper">2</property>
+ <property name="value">1</property>
+ <property name="step-increment">0.01</property>
+ <property name="page-increment">0.05</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="text_size_label_large">
+ <property name="label" translatable="yes">A</property>
+ <property name="margin-end">20</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="GtkLabel" id="text_size_preview_label">
+ <property name="vexpand">true</property>
+ <property name="wrap">true</property>
+ <property name="label" translatable="yes">Sample text</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
</interface>
--
2.51.0