diff '--color=auto' -ur a/panels/display/cc-display-config.c b/panels/display/cc-display-config.c --- a/panels/display/cc-display-config.c 2022-10-17 18:58:21.000000000 -0700 +++ b/panels/display/cc-display-config.c 2022-11-08 10:03:50.727878013 -0800 @@ -340,6 +340,26 @@ return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_privacy (self); } +gboolean +cc_display_monitor_supports_variable_refresh_rate (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->supports_variable_refresh_rate (self); +} + +gboolean +cc_display_monitor_get_variable_refresh_rate (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_variable_refresh_rate (self); +} + +void +cc_display_monitor_set_variable_refresh_rate (CcDisplayMonitor *self, + gboolean allowed) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_variable_refresh_rate (self, allowed); +} + + void cc_display_monitor_set_mode (CcDisplayMonitor *self, CcDisplayMode *m) { diff '--color=auto' -ur a/panels/display/cc-display-config-dbus.c b/panels/display/cc-display-config-dbus.c --- a/panels/display/cc-display-config-dbus.c 2022-10-17 18:58:21.000000000 -0700 +++ b/panels/display/cc-display-config-dbus.c 2022-11-08 10:05:59.787253085 -0800 @@ -325,6 +325,13 @@ UNDERSCANNING_ENABLED } CcDisplayMonitorUnderscanning; +typedef enum _CcDisplayMonitorVariableRefreshRate +{ + VRR_UNSUPPORTED = 0, + VRR_DISALLOWED, + VRR_ALLOWED +} CcDisplayMonitorVariableRefreshRate; + struct _CcDisplayMonitorDBus { CcDisplayMonitor parent_instance; @@ -340,6 +347,7 @@ int height_mm; gboolean builtin; CcDisplayMonitorUnderscanning underscanning; + CcDisplayMonitorVariableRefreshRate vrr_mode; CcDisplayMonitorPrivacy privacy_screen; int max_width; int max_height; @@ -649,6 +657,37 @@ self->underscanning = UNDERSCANNING_DISABLED; } +static gboolean +cc_display_monitor_dbus_supports_variable_refresh_rate (CcDisplayMonitor *pself) +{ + CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); + + return self->vrr_mode != VRR_UNSUPPORTED; +} + +static gboolean +cc_display_monitor_dbus_get_variable_refresh_rate (CcDisplayMonitor *pself) +{ + CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); + + return self->vrr_mode == VRR_ALLOWED; +} + +static void +cc_display_monitor_dbus_set_variable_refresh_rate (CcDisplayMonitor *pself, + gboolean allowed) +{ + CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); + + if (self->vrr_mode == VRR_UNSUPPORTED) + return; + + if (allowed) + self->vrr_mode = VRR_ALLOWED; + else + self->vrr_mode = VRR_DISALLOWED; +} + static CcDisplayMode * cc_display_monitor_dbus_get_closest_mode (CcDisplayMonitorDBus *self, CcDisplayModeDBus *mode) @@ -799,6 +838,7 @@ cc_display_monitor_dbus_init (CcDisplayMonitorDBus *self) { self->underscanning = UNDERSCANNING_UNSUPPORTED; + self->vrr_mode = VRR_UNSUPPORTED; self->max_width = G_MAXINT; self->max_height = G_MAXINT; } @@ -852,6 +892,9 @@ parent_class->supports_underscanning = cc_display_monitor_dbus_supports_underscanning; parent_class->get_underscanning = cc_display_monitor_dbus_get_underscanning; parent_class->set_underscanning = cc_display_monitor_dbus_set_underscanning; + parent_class->supports_variable_refresh_rate = cc_display_monitor_dbus_supports_variable_refresh_rate; + parent_class->get_variable_refresh_rate = cc_display_monitor_dbus_get_variable_refresh_rate; + parent_class->set_variable_refresh_rate = cc_display_monitor_dbus_set_variable_refresh_rate; parent_class->get_privacy = cc_display_monitor_dbus_get_privacy; parent_class->set_mode = cc_display_monitor_dbus_set_mode; parent_class->set_compatible_clone_mode = cc_display_monitor_dbus_set_compatible_clone_mode; @@ -930,6 +973,15 @@ else self->underscanning = UNDERSCANNING_DISABLED; } + else if (g_str_equal (s, "is-vrr-allowed")) + { + gboolean vrr_allowed = FALSE; + g_variant_get (v, "b", &vrr_allowed); + if (vrr_allowed) + self->vrr_mode = VRR_ALLOWED; + else + self->vrr_mode = VRR_DISALLOWED; + } else if (g_str_equal (s, "max-screen-size")) { g_variant_get (v, "ii", &self->max_width, &self->max_height); @@ -1042,6 +1094,10 @@ "underscanning", g_variant_new_boolean (monitor->underscanning == UNDERSCANNING_ENABLED)); + g_variant_builder_add (&props_builder, "{sv}", + "allow_vrr", + g_variant_new_boolean (monitor->vrr_mode == VRR_ALLOWED)); + mode_dbus = CC_DISPLAY_MODE_DBUS (monitor->current_mode); g_variant_builder_add (&builder, "(ss@*)", monitor->connector_name, @@ -1176,6 +1232,9 @@ if (m1->underscanning != m2->underscanning) return FALSE; + if (m1->vrr_mode != m2->vrr_mode) + return FALSE; + if (!cc_display_logical_monitor_equal (m1->logical_monitor, m2->logical_monitor)) return FALSE; diff '--color=auto' -ur a/panels/display/cc-display-config.h b/panels/display/cc-display-config.h --- a/panels/display/cc-display-config.h 2022-10-17 18:58:21.000000000 -0700 +++ b/panels/display/cc-display-config.h 2022-11-08 10:06:51.757209499 -0800 @@ -131,6 +131,10 @@ gboolean (*get_underscanning) (CcDisplayMonitor *self); void (*set_underscanning) (CcDisplayMonitor *self, gboolean u); + gboolean (*supports_variable_refresh_rate) (CcDisplayMonitor *self); + gboolean (*get_variable_refresh_rate) (CcDisplayMonitor *self); + void (*set_variable_refresh_rate) (CcDisplayMonitor *self, + gboolean u); CcDisplayMonitorPrivacy (*get_privacy) (CcDisplayMonitor *self); CcDisplayMode* (*get_mode) (CcDisplayMonitor *self); CcDisplayMode* (*get_preferred_mode) (CcDisplayMonitor *self); @@ -227,6 +231,11 @@ void cc_display_monitor_set_underscanning (CcDisplayMonitor *monitor, gboolean underscanning); +gboolean cc_display_monitor_supports_variable_refresh_rate (CcDisplayMonitor *monitor); +gboolean cc_display_monitor_get_variable_refresh_rate (CcDisplayMonitor *monitor); +void cc_display_monitor_set_variable_refresh_rate (CcDisplayMonitor *monitor, + gboolean allowed); + CcDisplayMonitorPrivacy cc_display_monitor_get_privacy (CcDisplayMonitor *self); CcDisplayMode* cc_display_monitor_get_mode (CcDisplayMonitor *monitor); diff '--color=auto' -ur a/panels/display/cc-display-settings.c b/panels/display/cc-display-settings.c --- a/panels/display/cc-display-settings.c 2022-06-30 16:12:42.000000000 -0700 +++ b/panels/display/cc-display-settings.c 2022-07-25 17:34:29.457797868 -0700 @@ -57,6 +57,8 @@ GtkWidget *scale_combo_row; GtkWidget *underscanning_row; GtkWidget *underscanning_switch; + GtkWidget *variable_refresh_rate_row; + GtkWidget *variable_refresh_rate_switch; }; typedef struct _CcDisplaySettings CcDisplaySettings; @@ -255,6 +257,7 @@ gtk_widget_set_visible (self->scale_combo_row, FALSE); gtk_widget_set_visible (self->scale_buttons_row, FALSE); gtk_widget_set_visible (self->underscanning_row, FALSE); + gtk_widget_set_visible (self->variable_refresh_rate_row, FALSE); return G_SOURCE_REMOVE; } @@ -265,6 +268,7 @@ g_object_freeze_notify ((GObject*) self->resolution_row); g_object_freeze_notify ((GObject*) self->scale_combo_row); g_object_freeze_notify ((GObject*) self->underscanning_switch); + g_object_freeze_notify ((GObject*) self->variable_refresh_rate_switch); cc_display_monitor_get_geometry (self->selected_output, NULL, NULL, &width, &height); @@ -469,6 +473,12 @@ gtk_switch_set_active (GTK_SWITCH (self->underscanning_switch), cc_display_monitor_get_underscanning (self->selected_output)); + gtk_widget_set_visible (self->variable_refresh_rate_row, + cc_display_monitor_supports_variable_refresh_rate (self->selected_output) && + !cc_display_config_is_cloning (self->config)); + gtk_switch_set_active (GTK_SWITCH (self->variable_refresh_rate_switch), + cc_display_monitor_get_variable_refresh_rate (self->selected_output)); + self->updating = TRUE; g_object_thaw_notify ((GObject*) self->enabled_switch); g_object_thaw_notify ((GObject*) self->orientation_row); @@ -476,6 +486,7 @@ g_object_thaw_notify ((GObject*) self->resolution_row); g_object_thaw_notify ((GObject*) self->scale_combo_row); g_object_thaw_notify ((GObject*) self->underscanning_switch); + g_object_thaw_notify ((GObject*) self->variable_refresh_rate_switch); self->updating = FALSE; return G_SOURCE_REMOVE; @@ -637,6 +648,21 @@ } static void +on_variable_refresh_rate_switch_active_changed_cb (GtkWidget *widget, + GParamSpec *pspec, + CcDisplaySettings *self) +{ + if (self->updating) + return; + + cc_display_monitor_set_variable_refresh_rate (self->selected_output, + gtk_switch_get_active (GTK_SWITCH (self->variable_refresh_rate_switch))); + + g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output); +} + + +static void cc_display_settings_get_property (GObject *object, guint prop_id, GValue *value, @@ -760,6 +786,8 @@ gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_combo_row); gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, underscanning_row); gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, underscanning_switch); + gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, variable_refresh_rate_row); + gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, variable_refresh_rate_switch); gtk_widget_class_bind_template_callback (widget_class, on_enabled_switch_active_changed_cb); gtk_widget_class_bind_template_callback (widget_class, on_orientation_selection_changed_cb); @@ -767,6 +795,7 @@ gtk_widget_class_bind_template_callback (widget_class, on_resolution_selection_changed_cb); gtk_widget_class_bind_template_callback (widget_class, on_scale_selection_changed_cb); gtk_widget_class_bind_template_callback (widget_class, on_underscanning_switch_active_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, on_variable_refresh_rate_switch_active_changed_cb); } static void diff '--color=auto' -ur a/panels/display/cc-display-settings.ui b/panels/display/cc-display-settings.ui --- a/panels/display/cc-display-settings.ui 2022-06-30 16:12:42.000000000 -0700 +++ b/panels/display/cc-display-settings.ui 2022-07-25 17:34:45.060088865 -0700 @@ -56,6 +56,20 @@ + + 100 + Variable Refresh Rate + + + False + end + center + + + + + + 100 Adjust for TV