[dconf-editor] Add night mode.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf-editor] Add night mode.
- Date: Mon, 1 Oct 2018 13:21:33 +0000 (UTC)
commit 0069cd4679a8450e026de7113c60aa93e4fac131
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Mon Oct 1 15:19:26 2018 +0200
Add night mode.
editor/ca.desrt.dconf-editor.gschema.xml | 7 +
editor/dconf-editor.vala | 30 ++++-
editor/dconf-window.vala | 51 ++++++-
editor/meson.build | 1 +
editor/night-light-monitor.vala | 222 +++++++++++++++++++++++++++++++
5 files changed, 309 insertions(+), 2 deletions(-)
---
diff --git a/editor/ca.desrt.dconf-editor.gschema.xml b/editor/ca.desrt.dconf-editor.gschema.xml
index fbfe9ac..1f719ea 100644
--- a/editor/ca.desrt.dconf-editor.gschema.xml
+++ b/editor/ca.desrt.dconf-editor.gschema.xml
@@ -191,6 +191,13 @@
<description>When a folder only contains one subfolder and no keys, Dconf Editor can jump to that
subfolder directly. This flag enables that behaviour.</description>
</key>
</schema>
+ <schema id="ca.desrt.dconf-editor.NightLight">
+ <key name="automatic-night-mode" type="b">
+ <default>false</default>
+ <summary>Follow system night light</summary>
+ <description>Use GNOME night light setting to activate night-mode.</description>
+ </key>
+ </schema>
<schema id="ca.desrt.dconf-editor.Bookmarks">
<key name="bookmarks" type="as">
<default>[]</default>
diff --git a/editor/dconf-editor.vala b/editor/dconf-editor.vala
index bca00bd..8df0916 100644
--- a/editor/dconf-editor.vala
+++ b/editor/dconf-editor.vala
@@ -20,6 +20,9 @@ private class ConfigurationEditor : Gtk.Application
internal static string [,] internal_mappings = {
{"ca.desrt.dconf-editor.Bookmarks",
"/ca/desrt/dconf-editor/"},
+ {"ca.desrt.dconf-editor.NightLight",
+ "/ca/desrt/dconf-editor/"},
+
{"ca.desrt.dconf-editor.Demo.EmptyRelocatable",
"/ca/desrt/dconf-editor/Demo/EmptyRelocatable/"}
};
@@ -149,6 +152,7 @@ private class ConfigurationEditor : Gtk.Application
private const GLib.ActionEntry [] action_entries =
{
// generic
+ { "set-use-night-mode", set_use_night_mode, "b" },
{ "copy", copy_cb, "s" }, // TODO is that really the good way to do things? (see Taquin)
{ "about", about_cb },
@@ -320,6 +324,8 @@ private class ConfigurationEditor : Gtk.Application
set_accels_for_action ("kbd.toggle-boolean", { "<Primary>Return",
"<Primary>KP_Enter" });
+ init_night_mode ();
+
Gtk.CssProvider css_provider = new Gtk.CssProvider ();
css_provider.load_from_resource ("/ca/desrt/dconf-editor/ui/dconf-editor.css");
Gdk.Screen? screen = Gdk.Screen.get_default ();
@@ -345,6 +351,23 @@ private class ConfigurationEditor : Gtk.Application
info (_("Looks like the DConf settings backend is used, all looks good."));
} */
+ /*\
+ * * Night mode
+ \*/
+
+ NightLightMonitor night_light_monitor; // keep it here or it is unrefed
+
+ private void init_night_mode ()
+ {
+ night_light_monitor = new NightLightMonitor ("/ca/desrt/dconf-editor/");
+ }
+
+ private void set_use_night_mode (SimpleAction action, Variant? gvariant)
+ requires (gvariant != null)
+ {
+ night_light_monitor.set_use_night_mode (((!) gvariant).get_boolean ());
+ }
+
/*\
* * Window activation
\*/
@@ -480,8 +503,13 @@ private class ConfigurationEditor : Gtk.Application
private Gtk.Window get_new_window (string? schema, string? path, string? key_name)
{
- DConfWindow window = new DConfWindow (disable_warning, schema, path, key_name);
+ DConfWindow window = new DConfWindow (disable_warning, schema, path, key_name,
NightLightMonitor.NightTime.should_use_dark_theme (night_light_monitor.night_time),
night_light_monitor.dark_theme, night_light_monitor.automatic_night_mode);
add_window (window);
+
+ night_light_monitor.notify ["night-time"].connect (window.night_time_changed);
+ night_light_monitor.notify ["dark-theme"].connect (window.dark_theme_changed);
+ night_light_monitor.notify ["automatic-night-mode"].connect (window.automatic_night_mode_changed);
+
return (Gtk.Window) window;
}
diff --git a/editor/dconf-window.vala b/editor/dconf-window.vala
index c429878..3dfc853 100644
--- a/editor/dconf-window.vala
+++ b/editor/dconf-window.vala
@@ -120,8 +120,10 @@ private class DConfWindow : ApplicationWindow
private ulong use_shortpaths_changed_handler = 0;
private ulong behaviour_changed_handler = 0;
- internal DConfWindow (bool disable_warning, string? schema, string? path, string? key_name)
+ internal DConfWindow (bool disable_warning, string? schema, string? path, string? key_name, bool
_night_time, bool _dark_theme, bool _automatic_night_mode)
{
+ init_night_mode (_night_time, _dark_theme, _automatic_night_mode);
+
install_ui_action_entries ();
install_kbd_action_entries ();
@@ -357,6 +359,52 @@ private class DConfWindow : ApplicationWindow
get_style_context ().remove_class ("hc-theme");
}
+ /*\
+ * * Night mode
+ \*/
+
+ private bool night_time = false; // no need to use NightTime here (that allows an "Unknown" value)
+ private bool dark_theme = false;
+ private bool automatic_night_mode = false;
+
+ private void init_night_mode (bool _night_time, bool _dark_theme, bool _automatic_night_mode)
+ {
+ night_time = _night_time;
+ dark_theme = _dark_theme;
+ automatic_night_mode = _automatic_night_mode;
+ }
+
+ internal void night_time_changed (Object nlm, ParamSpec thing)
+ {
+ night_time = NightLightMonitor.NightTime.should_use_dark_theme (((NightLightMonitor)
nlm).night_time);
+ update_hamburger_menu ();
+ }
+
+ internal void dark_theme_changed (Object nlm, ParamSpec thing)
+ {
+ dark_theme = ((NightLightMonitor) nlm).dark_theme;
+ update_hamburger_menu ();
+ }
+
+ internal void automatic_night_mode_changed (Object nlm, ParamSpec thing)
+ {
+ automatic_night_mode = ((NightLightMonitor) nlm).automatic_night_mode;
+ // update menu not needed
+ }
+
+ private void append_or_not_night_mode_entry (ref GLib.Menu section)
+ {
+ if (!night_time)
+ return;
+
+ if (dark_theme)
+ section.append (_("Pause night mode"), "app.set-use-night-mode(false)");
+ else if (automatic_night_mode)
+ section.append (_("Reuse night mode"), "app.set-use-night-mode(true)");
+ else
+ section.append (_("Use night mode"), "app.set-use-night-mode(true)");
+ }
+
/*\
* * Window management callbacks
\*/
@@ -1062,6 +1110,7 @@ private class DConfWindow : ApplicationWindow
}
section = new GLib.Menu ();
+ append_or_not_night_mode_entry (ref section);
section.append (_("Keyboard Shortcuts"), "win.show-help-overlay");
section.append (_("About Dconf Editor"), "app.about"); // TODO move as "win."
section.freeze ();
diff --git a/editor/meson.build b/editor/meson.build
index 2a8a404..47c45c8 100644
--- a/editor/meson.build
+++ b/editor/meson.build
@@ -79,6 +79,7 @@ sources = files(
'model-utils.vala',
'modifications-handler.vala',
'modifications-revealer.vala',
+ 'night-light-monitor.vala',
'pathbar.vala',
'pathentry.vala',
'pathwidget.vala',
diff --git a/editor/night-light-monitor.vala b/editor/night-light-monitor.vala
new file mode 100644
index 0000000..565e113
--- /dev/null
+++ b/editor/night-light-monitor.vala
@@ -0,0 +1,222 @@
+/*
+ This file is part of Dconf Editor
+
+ Dconf Editor is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Dconf Editor is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Dconf Editor. If not, see <https://www.gnu.org/licenses/>.
+*/
+/*
+ This code has been inspired by the one for a similar function in Calendar
+ https://gitlab.gnome.org/GNOME/gnome-calendar commit 474ce8b9da4a3322f2fe
+ Copyright 2018 Georges Basile Stavracas Neto <georges stavracas gmail com>
+*/
+
+private class NightLightMonitor : Object
+{
+ // warnings callable during init
+ private const string warning_init_connection =
+ "Impossible to get connection for session bus, night-light mode disabled.";
+ private const string warning_init_dbus_proxy =
+ "Impossible to get dbus proxy for session bus, night-light mode disabled.";
+ private const string warning_cached_property =
+ "Impossible to get cached property from proxy, night-light mode disabled.";
+
+ // warnings callable when setting mode
+ private const string warning_check_your_logs =
+ "Something went wrong during the night mode support init, doing nothing.";
+ private const string warning_get_gtksettings =
+ "Something went wrong getting GtkSettings default object, doing nothing.";
+
+ // schema static things
+ private const string schema_name = "ca.desrt.dconf-editor.NightLight"; // TODO put in a library
+ private const string automatic_night_mode_key = "automatic-night-mode";
+
+ /*\
+ * * Public interface
+ \*/
+
+ public string schema_path { private get; internal construct; }
+
+ public enum NightTime {
+ UNKNOWN,
+ NIGHT,
+ DAY;
+
+ internal static bool should_use_dark_theme (NightTime state)
+ {
+ return state == NightTime.NIGHT;
+ }
+ }
+ public NightTime night_time { internal get; private construct set; default =
NightTime.UNKNOWN; }
+ public bool dark_theme { internal get; private construct set; default = false; }
+ public bool automatic_night_mode { internal get; private construct set; default = false; }
+
+ internal NightLightMonitor (string _schema_path)
+ {
+ Object (schema_path: _schema_path);
+ if (night_time == NightTime.UNKNOWN) // disables mode if night_time has not been set at first try
// TODO specific warning?
+ return;
+ connect_properties ();
+ }
+
+ internal void set_use_night_mode (bool night_mode_state)
+ {
+ if (night_time == NightTime.UNKNOWN) // do nothing but warn
+ warning (warning_check_your_logs);
+ else
+ {
+ paused = !night_mode_state;
+ update ();
+ }
+ }
+
+ /*\
+ * * Init proxy
+ \*/
+
+ private GLib.Settings settings;
+ private DBusProxy proxy;
+
+ construct
+ {
+ settings = new GLib.Settings.with_path (schema_name, schema_path);
+ automatic_night_mode = settings.get_boolean (automatic_night_mode_key);
+ paused = !automatic_night_mode;
+
+ DBusConnection? connection;
+ init_connection (out connection);
+ if (connection == null)
+ return;
+
+ DBusProxy? nullable_proxy;
+ init_proxy ((!) connection, out nullable_proxy);
+ if (nullable_proxy == null)
+ return;
+
+ proxy = (!) nullable_proxy;
+ night_time = get_updated_night_time (ref proxy, automatic_night_mode);
+ }
+
+ private static void init_connection (out DBusConnection? connection)
+ {
+ try
+ {
+ connection = Bus.get_sync (BusType.SESSION, null);
+ }
+ catch (Error e)
+ {
+ warning (warning_init_connection);
+ warning (e.message);
+ connection = null;
+ }
+ }
+
+ private static void init_proxy (DBusConnection connection, out DBusProxy? proxy)
+ {
+ try
+ {
+ proxy = new DBusProxy.sync (connection,
+ DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
+ null,
+ "org.gnome.SettingsDaemon.Color",
+ "/org/gnome/SettingsDaemon/Color",
+ "org.gnome.SettingsDaemon.Color",
+ null);
+ }
+ catch (Error e)
+ {
+ warning (warning_init_dbus_proxy);
+ warning (e.message);
+ proxy = null;
+ }
+ }
+
+ private static NightTime get_updated_night_time (ref DBusProxy proxy, bool automatic_night_mode)
+ {
+ Variant? variant_active = proxy.get_cached_property ("NightLightActive");
+ Variant? variant_paused = proxy.get_cached_property ("DisabledUntilTomorrow");
+ if (variant_active == null)
+ {
+ warning (warning_cached_property);
+ return NightTime.UNKNOWN;
+ }
+
+ bool night_time_is_night = ((!) variant_active).get_boolean ();
+ if (variant_paused != null)
+ night_time_is_night = night_time_is_night && !(((!) variant_paused).get_boolean () &&
automatic_night_mode);
+
+ if (night_time_is_night)
+ return NightTime.NIGHT;
+ else
+ return NightTime.DAY;
+ }
+
+ /*\
+ * * Private methods
+ \*/
+
+ private bool paused = false;
+
+ private void connect_properties ()
+ {
+ proxy.g_properties_changed.connect (() => {
+ night_time = get_updated_night_time (ref proxy, automatic_night_mode);
+ if (night_time != NightTime.NIGHT)
+ paused = !automatic_night_mode;
+ update ();
+ });
+ settings.changed [automatic_night_mode_key].connect ((_settings, _key_name) => {
+ automatic_night_mode = _settings.get_boolean (_key_name);
+ paused = !automatic_night_mode;
+ update ();
+ });
+ update ();
+ }
+
+ private void update ()
+ {
+ if (automatic_night_mode)
+ {
+ if (paused)
+ set_dark_theme_real (false);
+ else
+ set_dark_theme_real (NightTime.should_use_dark_theme (night_time));
+ }
+ else if (night_time == NightTime.NIGHT)
+ {
+ if (paused)
+ set_dark_theme_real (false);
+ else
+ set_dark_theme_real (true);
+ }
+ else
+ set_dark_theme_real (false);
+ }
+ private void set_dark_theme_real (bool night_mode)
+ {
+ if (_set_dark_theme_real (night_mode))
+ dark_theme = night_mode;
+ }
+ private static bool _set_dark_theme_real (bool night_mode)
+ {
+ Gtk.Settings? gtk_settings = Gtk.Settings.get_default ();
+ if (gtk_settings == null)
+ {
+ warning (warning_get_gtksettings);
+ return false;
+ }
+
+ if (night_mode != ((!) gtk_settings).gtk_application_prefer_dark_theme)
+ ((!) gtk_settings).@set ("gtk-application-prefer-dark-theme", night_mode);
+ return true;
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]