diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in index 9457fac25..3a8fd2bc3 100644 --- a/data/org.gnome.mutter.gschema.xml.in +++ b/data/org.gnome.mutter.gschema.xml.in @@ -164,6 +164,19 @@ + + [] + + Per output luminance settings + + Per output and color mode luminance setting. Each entry consists of a + tuple with connector, vendor, product, serial, and a color mode, as well + as an associated floating point value representing the output luminance + in percent (%). The default when not specified is 100%. + + + diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h index d213441fd..82da6ca77 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h @@ -21,6 +21,7 @@ #include +#include "backends/meta-backend-types.h" #include "core/util-private.h" #include "meta/meta-settings.h" #include "meta/types.h" @@ -79,3 +80,11 @@ gboolean meta_settings_is_privacy_screen_enabled (MetaSettings *settings); void meta_settings_set_privacy_screen_enabled (MetaSettings *settings, gboolean enabled); + +double meta_settings_get_output_luminance (MetaSettings *settings, + const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode); + +double meta_settings_get_default_output_luminance (MetaSettings *settings, + const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode); diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c index 5f646984e..1609f2682 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c @@ -39,6 +39,7 @@ enum FONT_DPI_CHANGED, EXPERIMENTAL_FEATURES_CHANGED, PRIVACY_SCREEN_CHANGED, + OUTPUT_LUMINANCE_CHANGED, N_SIGNALS }; @@ -83,6 +84,8 @@ struct _MetaSettings /* Whether Xwayland should allow X11 clients from different endianness */ gboolean xwayland_allow_byte_swapped_clients; + + GPtrArray *output_luminance; }; G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT) @@ -341,20 +344,150 @@ update_experimental_features (MetaSettings *settings) settings)); } +typedef struct _LuminanceEntry +{ + MetaMonitorSpec *monitor_spec; + MetaColorMode color_mode; + double luminance; +} LuminanceEntry; + +static void +luminance_entry_free (LuminanceEntry *entry) +{ + g_clear_pointer (&entry->monitor_spec, meta_monitor_spec_free); + g_free (entry); +} + +static LuminanceEntry * +luminance_entry_new (const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode, + double luminance) +{ + LuminanceEntry *entry; + + entry = g_new0 (LuminanceEntry, 1); + entry->monitor_spec = meta_monitor_spec_clone (monitor_spec); + entry->color_mode = color_mode; + entry->luminance = luminance; + + return entry; +} + +static gboolean +luminance_entry_matches (LuminanceEntry *entry, + const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode) +{ + return (meta_monitor_spec_equals (entry->monitor_spec, monitor_spec) && + entry->color_mode == color_mode); +} + +static LuminanceEntry * +find_luminance_entry (MetaSettings *settings, + const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode) +{ + size_t i; + + for (i = 0; i < settings->output_luminance->len; i++) + { + LuminanceEntry *entry = + g_ptr_array_index (settings->output_luminance, i); + + if (luminance_entry_matches (entry, monitor_spec, color_mode)) + return entry; + } + + return NULL; +} + +double +meta_settings_get_output_luminance (MetaSettings *settings, + const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode) +{ + LuminanceEntry *entry; + + entry = find_luminance_entry (settings, monitor_spec, color_mode); + if (entry) + return entry->luminance; + + return meta_settings_get_default_output_luminance (settings, + monitor_spec, + color_mode); +} + +double +meta_settings_get_default_output_luminance (MetaSettings *settings, + const MetaMonitorSpec *monitor_spec, + MetaColorMode color_mode) +{ + return 100.0; +} + +static void +update_output_luminance_settings (MetaSettings *settings) +{ + g_autoptr (GVariant) output_luminance_variant = NULL; + GVariantIter iter; + char *connector; + char *vendor; + char *product; + char *serial; + uint32_t color_mode_value; + double luminance; + + output_luminance_variant = g_settings_get_value (settings->mutter_settings, + "output-luminance"); + g_variant_iter_init (&iter, output_luminance_variant); + + g_ptr_array_remove_range (settings->output_luminance, + 0, + settings->output_luminance->len); + + while (g_variant_iter_next (&iter, + "(ssssud)", + &connector, &vendor, &product, &serial, + &color_mode_value, + &luminance)) + { + g_autoptr (MetaMonitorSpec) monitor_spec = NULL; + MetaColorMode color_mode = color_mode_value; + LuminanceEntry *entry; + + monitor_spec = g_new0 (MetaMonitorSpec, 1); + *monitor_spec = (MetaMonitorSpec) { + .connector = connector, + .vendor = vendor, + .product = product, + .serial = serial + }; + + entry = luminance_entry_new (monitor_spec, color_mode, luminance); + g_ptr_array_add (settings->output_luminance, entry); + } + + g_signal_emit (settings, signals[OUTPUT_LUMINANCE_CHANGED], 0); +} + static void mutter_settings_changed (GSettings *mutter_settings, gchar *key, MetaSettings *settings) { - MetaExperimentalFeature old_experimental_features; + if (g_str_equal (key, "experimental-features")) + { + MetaExperimentalFeature old_experimental_features; - if (!g_str_equal (key, "experimental-features")) - return; - - old_experimental_features = settings->experimental_features; - if (update_experimental_features (settings)) - g_signal_emit (settings, signals[EXPERIMENTAL_FEATURES_CHANGED], 0, - (unsigned int) old_experimental_features); + old_experimental_features = settings->experimental_features; + if (update_experimental_features (settings)) + g_signal_emit (settings, signals[EXPERIMENTAL_FEATURES_CHANGED], 0, + (unsigned int) old_experimental_features); + } + else if (g_str_equal (key, "output-luminance")) + { + update_output_luminance_settings (settings); + } } static void @@ -545,6 +678,8 @@ meta_settings_dispose (GObject *object) g_clear_pointer (&settings->xwayland_grab_deny_list_patterns, g_ptr_array_unref); + g_clear_pointer (&settings->output_luminance, g_ptr_array_unref); + G_OBJECT_CLASS (meta_settings_parent_class)->dispose (object); } @@ -553,6 +688,9 @@ meta_settings_init (MetaSettings *settings) { const char *experimental_features_env; + settings->output_luminance = + g_ptr_array_new_with_free_func ((GDestroyNotify) luminance_entry_free); + settings->interface_settings = g_settings_new ("org.gnome.desktop.interface"); g_signal_connect (settings->interface_settings, "changed", G_CALLBACK (interface_settings_changed), @@ -598,6 +736,7 @@ meta_settings_init (MetaSettings *settings) update_xwayland_disable_extensions (settings); update_privacy_settings (settings); update_xwayland_allow_byte_swapped_clients (settings); + update_output_luminance_settings (settings); } static void @@ -667,4 +806,13 @@ meta_settings_class_init (MetaSettingsClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 0); + + signals[OUTPUT_LUMINANCE_CHANGED] = + g_signal_new ("output-luminance-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + }