From c3df7734630046891c8689a71ab8a6a1efee68a7 Mon Sep 17 00:00:00 2001 From: Dor Askayo Date: Sat, 28 Mar 2020 19:29:59 +0300 Subject: [PATCH] display: Add a switch for variable refresh rate This can be used to allow or disallow variable refresh rate on monitors that support it. --- panels/display/cc-display-config-dbus.c | 63 ++++++++++++++++++++++++- panels/display/cc-display-config.c | 19 ++++++++ panels/display/cc-display-config.h | 9 ++++ panels/display/cc-display-settings.c | 29 ++++++++++++ panels/display/cc-display-settings.ui | 15 ++++++ 5 files changed, 134 insertions(+), 1 deletion(-) diff --git a/panels/display/cc-display-config-dbus.c b/panels/display/cc-display-config-dbus.c index d94f5417bf..ba6f74caf7 100644 --- a/panels/display/cc-display-config-dbus.c +++ b/panels/display/cc-display-config-dbus.c @@ -317,7 +317,6 @@ cc_display_logical_monitor_class_init (CcDisplayLogicalMonitorClass *klass) gobject_class->finalize = cc_display_logical_monitor_finalize; } - typedef enum _CcDisplayMonitorUnderscanning { UNDERSCANNING_UNSUPPORTED = 0, @@ -325,6 +324,13 @@ typedef enum _CcDisplayMonitorUnderscanning UNDERSCANNING_ENABLED } CcDisplayMonitorUnderscanning; +typedef enum _CcDisplayMonitorVariableRefreshRate +{ + VRR_UNSUPPORTED = 0, + VRR_DISALLOWED, + VRR_ALLOWED +} CcDisplayMonitorVariableRefreshRate; + struct _CcDisplayMonitorDBus { CcDisplayMonitor parent_instance; @@ -341,6 +347,7 @@ struct _CcDisplayMonitorDBus gboolean builtin; CcDisplayMonitorUnderscanning underscanning; CcDisplayMonitorPrivacy privacy_screen; + CcDisplayMonitorVariableRefreshRate vrr_mode; int max_width; int max_height; @@ -649,6 +656,37 @@ cc_display_monitor_dbus_set_underscanning (CcDisplayMonitor *pself, 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 +837,7 @@ static void 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; } @@ -853,6 +892,9 @@ cc_display_monitor_dbus_class_init (CcDisplayMonitorDBusClass *klass) parent_class->get_underscanning = cc_display_monitor_dbus_get_underscanning; parent_class->set_underscanning = cc_display_monitor_dbus_set_underscanning; parent_class->get_privacy = cc_display_monitor_dbus_get_privacy; + 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->set_mode = cc_display_monitor_dbus_set_mode; parent_class->set_compatible_clone_mode = cc_display_monitor_dbus_set_compatible_clone_mode; parent_class->set_position = cc_display_monitor_dbus_set_position; @@ -930,6 +972,15 @@ cc_display_monitor_dbus_new (GVariant *variant, 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 +1093,13 @@ build_monitors_variant (GHashTable *monitors) "underscanning", g_variant_new_boolean (monitor->underscanning == UNDERSCANNING_ENABLED)); + if (monitor->vrr_mode != VRR_UNSUPPORTED) + { + 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 +1234,9 @@ cc_display_config_dbus_equal (CcDisplayConfig *pself, 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 --git a/panels/display/cc-display-config.c b/panels/display/cc-display-config.c index f2ccda5221..687aa85c54 100644 --- a/panels/display/cc-display-config.c +++ b/panels/display/cc-display-config.c @@ -340,6 +340,25 @@ cc_display_monitor_get_privacy (CcDisplayMonitor *self) 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 --git a/panels/display/cc-display-config.h b/panels/display/cc-display-config.h index ea52c2d599..70aa9ebbee 100644 --- a/panels/display/cc-display-config.h +++ b/panels/display/cc-display-config.h @@ -132,6 +132,10 @@ struct _CcDisplayMonitorClass void (*set_underscanning) (CcDisplayMonitor *self, gboolean u); CcDisplayMonitorPrivacy (*get_privacy) (CcDisplayMonitor *self); + gboolean (*supports_variable_refresh_rate) (CcDisplayMonitor *self); + gboolean (*get_variable_refresh_rate) (CcDisplayMonitor *self); + void (*set_variable_refresh_rate) (CcDisplayMonitor *self, + gboolean u); CcDisplayMode* (*get_mode) (CcDisplayMonitor *self); CcDisplayMode* (*get_preferred_mode) (CcDisplayMonitor *self); GList* (*get_modes) (CcDisplayMonitor *self); @@ -230,6 +234,11 @@ void cc_display_monitor_set_underscanning (CcDisplayMonitor * CcDisplayMonitorPrivacy cc_display_monitor_get_privacy (CcDisplayMonitor *self); +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); + CcDisplayMode* cc_display_monitor_get_mode (CcDisplayMonitor *monitor); void cc_display_monitor_get_geometry (CcDisplayMonitor *monitor, int *x, diff --git a/panels/display/cc-display-settings.c b/panels/display/cc-display-settings.c index 79de8b657a..39d2c7eff5 100644 --- a/panels/display/cc-display-settings.c +++ b/panels/display/cc-display-settings.c @@ -57,6 +57,8 @@ struct _CcDisplaySettings GtkWidget *scale_combo_row; GtkWidget *underscanning_row; GtkWidget *underscanning_switch; + GtkWidget *variable_refresh_rate_row; + GtkWidget *variable_refresh_rate_switch; }; typedef struct _CcDisplaySettings CcDisplaySettings; @@ -257,6 +259,7 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self) 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; } @@ -267,6 +270,7 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self) 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); @@ -470,6 +474,12 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self) 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); @@ -477,6 +487,7 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self) 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; @@ -625,6 +636,21 @@ on_underscanning_switch_active_changed_cb (CcDisplaySettings *self) g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output); } +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, @@ -749,6 +775,8 @@ cc_display_settings_class_init (CcDisplaySettingsClass *klass) 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); @@ -756,6 +784,7 @@ cc_display_settings_class_init (CcDisplaySettingsClass *klass) 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 --git a/panels/display/cc-display-settings.ui b/panels/display/cc-display-settings.ui index 6de2ba6ee1..f0c9fa10bc 100644 --- a/panels/display/cc-display-settings.ui +++ b/panels/display/cc-display-settings.ui @@ -58,6 +58,21 @@ + + + 100 + Variable Refresh Rate + variable_refresh_rate_switch + + + False + end + center + + + + + 100 -- GitLab