diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2023-02-06 10:50:34 +0100 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2023-02-06 10:50:34 +0100 |
commit | 642cbe7d3830c7dd27230ea84e86277243ccd7b7 (patch) | |
tree | 6d4f269e0389b8f12d267cb715dc663382763c82 /src/arctica-greeter.vala | |
parent | b2fac08944adadd4b278a58a5fe363ef0df1e9c2 (diff) | |
parent | bf00dadc0584d911bf4c23cc4ab25e8a09c611ce (diff) | |
download | arctica-greeter-642cbe7d3830c7dd27230ea84e86277243ccd7b7.tar.gz arctica-greeter-642cbe7d3830c7dd27230ea84e86277243ccd7b7.tar.bz2 arctica-greeter-642cbe7d3830c7dd27230ea84e86277243ccd7b7.zip |
Merge remote-tracking branch 'gh-Ionic/feature/high-contrast-big-font'
Attributes GH PR #40: https://github.com/ArcticaProject/arctica-greeter/pull/40
Diffstat (limited to 'src/arctica-greeter.vala')
-rw-r--r-- | src/arctica-greeter.vala | 150 |
1 files changed, 141 insertions, 9 deletions
diff --git a/src/arctica-greeter.vala b/src/arctica-greeter.vala index 96a98ce..6d31a9b 100644 --- a/src/arctica-greeter.vala +++ b/src/arctica-greeter.vala @@ -21,16 +21,15 @@ public const int grid_size = 40; -public class ArcticaGreeter +[SingleInstance] +public class ArcticaGreeter : Object { - public static ArcticaGreeter singleton; - public signal void show_message (string text, LightDM.MessageType type); public signal void show_prompt (string text, LightDM.PromptType type); public signal void authentication_complete (); public signal void starting_session (); - public bool test_mode = false; + public bool test_mode { get; construct; default = false; } private string state_file; private KeyFile state; @@ -53,11 +52,8 @@ public class ArcticaGreeter public signal void xsettings_ready (); public signal void greeter_ready (); - private ArcticaGreeter (bool test_mode_) + construct { - singleton = this; - test_mode = test_mode_; - greeter = new LightDM.Greeter (); greeter.show_message.connect ((text, type) => { show_message (text, type); }); greeter.show_prompt.connect ((text, type) => { show_prompt (text, type); }); @@ -140,6 +136,22 @@ public class ArcticaGreeter xsettings_ready_cb (); } + /* + * Note that we need a way to specify a parameter for the initial instance + * creation of the singleton, but also a constructor that takes no + * parameters for later usage. + * + * Making the parameter optional is a good compromise. + * + * This this parameter is construct-only, initializing it by passing it to + * the GObject constructor is both the correct way to do it, and it will + * additionally avoid changing it in later calls of our constructor. + */ + public ArcticaGreeter (bool test_mode_ = false) + { + Object (test_mode: test_mode_); + } + public string? get_state (string key) { try @@ -294,6 +306,47 @@ public class ArcticaGreeter Canberra.PROP_EVENT_ID, "system-ready"); + /* Synchronize properties in AGSettings once. */ + var agsettings = new AGSettings (); + agsettings.high_contrast = !(!(agsettings.high_contrast)); + agsettings.big_font = !(!(agsettings.big_font)); + + /* + * Add timeouts to process the full node hierarchy to handle a11y + * changes. + * + * That's the easiest way to handle a changing node hierarchy. + * + * Alternatives would involve connecting a function for every a11y + * change to the GtkWidget::parent-set event to *every widget* we + * create, but that would make the code incredibly messy. + * + * The value has been determined by a fair dice roll and should make + * sure that changes are visible almost instantaneously to users. + */ + Timeout.add_full (GLib.Priority.HIGH_IDLE, 302, () => { + var agsettings_intimer = new AGSettings (); + /* + if (0 == GLib.Random.int_range (0, 10)) { + debug ("Syncing up high contrast value via timer: %s", agsettings_intimer.high_contrast.to_string ()); + } + */ + switch_contrast (agsettings_intimer.high_contrast); + + return true; + }); + Timeout.add_full (GLib.Priority.HIGH_IDLE, 302, () => { + var agsettings_intimer = new AGSettings (); + /* + if (0 == GLib.Random.int_range (0, 10)) { + debug ("Syncing up big font value via timer: %s", agsettings_intimer.big_font.to_string ()); + } + */ + switch_font (agsettings_intimer.big_font); + + return true; + }); + return false; } @@ -340,7 +393,7 @@ public class ArcticaGreeter { try { - ArcticaGreeter.singleton.greeter.authenticate_remote (session, userid); + greeter.authenticate_remote (session, userid); } catch (Error e) { @@ -407,6 +460,75 @@ public class ArcticaGreeter return greeter.has_guest_account_hint; } + private delegate void SwitchClassType (Gtk.Widget widget, string classname, bool enable); + + private delegate void IterateChildrenType (Gtk.Widget widget); + + private void switch_generic (Gtk.Widget widget, string classname, bool enable) + { + var style_ctx = widget.get_style_context (); + if (enable) + { + style_ctx.add_class (classname); + } + else + { + style_ctx.remove_class (classname); + } + } + + private void iterate_children_generic (Gtk.Widget widget, SwitchClassType switch_func, string classname, bool enable) + { + /* + * GTK 4 changed its API quite dramatically, got rid of GtkContainer + * and made each GtkWidget accept children, while also defining a new + * way to access those. + */ + IterateChildrenType rec_func = null; + rec_func = (widget) => { +#if HAVE_GTK_4_0 + Gtk.Widget child = widget.get_first_child (); + while (null != child) + { + rec_func (child); + child = child.get_next_sibling (); + } +#else + if (gtk_is_container (widget)) + { + ((Gtk.Container)(widget)).@foreach (rec_func); + } +#endif + + /* Common code to add or remove the CSS class. */ + switch_func (widget, classname, enable); + }; + + /* + * Actually recursively iterate through this item and all of its + * children. + */ + rec_func (widget); + } + + public void switch_contrast (bool high) + { + var time_pre = GLib.get_monotonic_time (); + iterate_children_generic (main_window, switch_generic, "high_contrast", high); + var time_post = GLib.get_monotonic_time (); + var time_diff = time_post - time_pre; + assert (0 <= time_diff); + var time_diff_sec = time_diff / 1000000; + var time_diff_msec = time_diff / 1000; + var time_diff_usec = time_diff % 1000000; + // debug ("Time passed: %" + int64.FORMAT + " s, %" + int64.FORMAT + " ms, %" + int64.FORMAT + " us", time_diff_sec, time_diff_msec, time_diff_usec); + } + + public void switch_font (bool big) + { + iterate_children_generic (main_window, switch_generic, "big_font", big); + } + private Gdk.FilterReturn focus_upon_map (Gdk.XEvent gxevent, Gdk.Event event) { var xevent = (X.Event*)gxevent; @@ -807,6 +929,16 @@ public class ArcticaGreeter if (value != "") settings.set ("gtk-xft-rgba", value, null); + /* + * Keep a reference to an AGSettings instance for the whole program + * run, so that the SingleInstance property is working the way we'd + * like it to work. + * + * We want to do this before creating the actual greeter, since the + * latter is using AGSettings quite extensively. + */ + var agsettings = new AGSettings (); + debug ("Creating Arctica Greeter"); var greeter = new ArcticaGreeter (do_test_mode); |