diff options
Diffstat (limited to 'panels/display/cc-display-config.c')
-rw-r--r-- | panels/display/cc-display-config.c | 665 |
1 files changed, 665 insertions, 0 deletions
diff --git a/panels/display/cc-display-config.c b/panels/display/cc-display-config.c new file mode 100644 index 0000000..b7532f9 --- /dev/null +++ b/panels/display/cc-display-config.c @@ -0,0 +1,665 @@ +/* + * Copyright (C) 2016 Red Hat, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <gio/gio.h> +#include <math.h> +#include "cc-display-config.h" + +static const double known_diagonals[] = { + 12.1, + 13.3, + 15.6 +}; + +static char * +diagonal_to_str (double d) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (known_diagonals); i++) + { + double delta; + + delta = fabs(known_diagonals[i] - d); + if (delta < 0.1) + return g_strdup_printf ("%0.1lf\"", known_diagonals[i]); + } + + return g_strdup_printf ("%d\"", (int) (d + 0.5)); +} + +static char * +make_display_size_string (int width_mm, + int height_mm) +{ + char *inches = NULL; + + if (width_mm > 0 && height_mm > 0) + { + double d = sqrt (width_mm * width_mm + height_mm * height_mm); + + inches = diagonal_to_str (d / 25.4); + } + + return inches; +} + +static char * +make_output_ui_name (CcDisplayMonitor *output) +{ + int width_mm, height_mm; + g_autofree char *size = NULL; + + cc_display_monitor_get_physical_size (output, &width_mm, &height_mm); + size = make_display_size_string (width_mm, height_mm); + if (size) + return g_strdup_printf ("%s (%s)", cc_display_monitor_get_display_name (output), size); + else + return g_strdup_printf ("%s", cc_display_monitor_get_display_name (output)); +} + + + +G_DEFINE_TYPE (CcDisplayMode, + cc_display_mode, + G_TYPE_OBJECT) + +static void +cc_display_mode_init (CcDisplayMode *self) +{ +} + +static void +cc_display_mode_class_init (CcDisplayModeClass *klass) +{ +} + +gboolean +cc_display_mode_is_clone_mode (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->is_clone_mode (self); +} + +void +cc_display_mode_get_resolution (CcDisplayMode *self, int *w, int *h) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->get_resolution (self, w, h); +} + +GArray * +cc_display_mode_get_supported_scales (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->get_supported_scales (self); +} + +double +cc_display_mode_get_preferred_scale (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->get_preferred_scale (self); +} + +gboolean +cc_display_mode_is_interlaced (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->is_interlaced (self); +} + +gboolean +cc_display_mode_is_preferred (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->is_preferred (self); +} + +int +cc_display_mode_get_freq (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->get_freq (self); +} + +double +cc_display_mode_get_freq_f (CcDisplayMode *self) +{ + return CC_DISPLAY_MODE_GET_CLASS (self)->get_freq_f (self); +} + + +struct _CcDisplayMonitorPrivate { + int ui_number; + gchar *ui_name; + gchar *ui_number_name; + gboolean is_usable; +}; +typedef struct _CcDisplayMonitorPrivate CcDisplayMonitorPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (CcDisplayMonitor, + cc_display_monitor, + G_TYPE_OBJECT) + +static void +cc_display_monitor_init (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + priv->ui_number = 0; + priv->ui_name = NULL; + priv->ui_number_name = NULL; + priv->is_usable = TRUE; +} + +static void +cc_display_monitor_finalize (GObject *object) +{ + CcDisplayMonitor *self = CC_DISPLAY_MONITOR (object); + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + g_clear_pointer (&priv->ui_name, g_free); + g_clear_pointer (&priv->ui_number_name, g_free); + + G_OBJECT_CLASS (cc_display_monitor_parent_class)->finalize (object); +} + +static void +cc_display_monitor_class_init (CcDisplayMonitorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = cc_display_monitor_finalize; + + g_signal_new ("rotation", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("mode", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("primary", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("active", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("scale", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("position-changed", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("is-usable", + CC_TYPE_DISPLAY_MONITOR, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); +} + +const char * +cc_display_monitor_get_display_name (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_display_name (self); +} + +const char * +cc_display_monitor_get_connector_name (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_connector_name (self); +} + +gboolean +cc_display_monitor_is_builtin (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->is_builtin (self); +} + +gboolean +cc_display_monitor_is_primary (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->is_primary (self); +} + +void +cc_display_monitor_set_primary (CcDisplayMonitor *self, gboolean primary) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_primary (self, primary); +} + +gboolean +cc_display_monitor_is_active (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->is_active (self); +} + +void +cc_display_monitor_set_active (CcDisplayMonitor *self, gboolean active) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_active (self, active); +} + +CcDisplayRotation +cc_display_monitor_get_rotation (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_rotation (self); +} + +void +cc_display_monitor_set_rotation (CcDisplayMonitor *self, + CcDisplayRotation rotation) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_rotation (self, rotation); +} + +gboolean +cc_display_monitor_supports_rotation (CcDisplayMonitor *self, CcDisplayRotation r) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->supports_rotation (self, r); +} + +void +cc_display_monitor_get_physical_size (CcDisplayMonitor *self, int *w, int *h) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_physical_size (self, w, h); +} + +void +cc_display_monitor_get_geometry (CcDisplayMonitor *self, int *x, int *y, int *w, int *h) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_geometry (self, x, y, w, h); +} + +CcDisplayMode * +cc_display_monitor_get_mode (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_mode (self); +} + +CcDisplayMode * +cc_display_monitor_get_preferred_mode (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_preferred_mode (self); +} + +guint32 +cc_display_monitor_get_id (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_id (self); +} + +GList * +cc_display_monitor_get_modes (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_modes (self); +} + +gboolean +cc_display_monitor_supports_underscanning (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->supports_underscanning (self); +} + +gboolean +cc_display_monitor_get_underscanning (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_underscanning (self); +} + +void +cc_display_monitor_set_underscanning (CcDisplayMonitor *self, + gboolean underscanning) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_underscanning (self, underscanning); +} + +CcDisplayMonitorPrivacy +cc_display_monitor_get_privacy (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_privacy (self); +} + +void +cc_display_monitor_set_mode (CcDisplayMonitor *self, CcDisplayMode *m) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_mode (self, m); +} + +void +cc_display_monitor_set_compatible_clone_mode (CcDisplayMonitor *self, CcDisplayMode *m) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_mode (self, m); +} + +void +cc_display_monitor_set_position (CcDisplayMonitor *self, int x, int y) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_position (self, x, y); +} + +double +cc_display_monitor_get_scale (CcDisplayMonitor *self) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->get_scale (self); +} + +void +cc_display_monitor_set_scale (CcDisplayMonitor *self, double s) +{ + return CC_DISPLAY_MONITOR_GET_CLASS (self)->set_scale (self, s); +} + +gboolean +cc_display_monitor_is_useful (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + return priv->is_usable && + cc_display_monitor_is_active (self); +} + +gboolean +cc_display_monitor_is_usable (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + return priv->is_usable; +} + +void +cc_display_monitor_set_usable (CcDisplayMonitor *self, gboolean is_usable) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + priv->is_usable = is_usable; + + g_signal_emit_by_name (self, "is-usable"); +} + +gint +cc_display_monitor_get_ui_number (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + return priv->ui_number; +} + +const char * +cc_display_monitor_get_ui_name (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + return priv->ui_name; +} + +const char * +cc_display_monitor_get_ui_number_name (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + return priv->ui_number_name; +} + +char * +cc_display_monitor_dup_ui_number_name (CcDisplayMonitor *self) +{ + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + return g_strdup (priv->ui_number_name); +} + +static void +cc_display_monitor_set_ui_info (CcDisplayMonitor *self, gint ui_number, gchar *ui_name) +{ + + CcDisplayMonitorPrivate *priv = cc_display_monitor_get_instance_private (self); + + priv->ui_number = ui_number; + g_free (priv->ui_name); + priv->ui_name = ui_name; + priv->ui_number_name = g_strdup_printf ("%d\u2003%s", ui_number, ui_name); +} + +struct _CcDisplayConfigPrivate { + GList *ui_sorted_monitors; +}; +typedef struct _CcDisplayConfigPrivate CcDisplayConfigPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (CcDisplayConfig, + cc_display_config, + G_TYPE_OBJECT) + +static void +cc_display_config_init (CcDisplayConfig *self) +{ + CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self); + + priv->ui_sorted_monitors = NULL; +} + +static void +cc_display_config_constructed (GObject *object) +{ + CcDisplayConfig *self = CC_DISPLAY_CONFIG (object); + CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self); + GList *monitors = cc_display_config_get_monitors (self); + GList *item; + gint ui_number = 1; + + for (item = monitors; item != NULL; item = item->next) + { + CcDisplayMonitor *monitor = item->data; + + if (cc_display_monitor_is_builtin (monitor)) + priv->ui_sorted_monitors = g_list_prepend (priv->ui_sorted_monitors, monitor); + else + priv->ui_sorted_monitors = g_list_append (priv->ui_sorted_monitors, monitor); + } + + for (item = priv->ui_sorted_monitors; item != NULL; item = item->next) + { + CcDisplayMonitor *monitor = item->data; + char *ui_name; + ui_name = make_output_ui_name (monitor); + + cc_display_monitor_set_ui_info (monitor, ui_number, ui_name); + + ui_number += 1; + } +} + +static void +cc_display_config_finalize (GObject *object) +{ + CcDisplayConfig *self = CC_DISPLAY_CONFIG (object); + CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self); + + g_list_free (priv->ui_sorted_monitors); + + G_OBJECT_CLASS (cc_display_config_parent_class)->finalize (object); +} + +static void +cc_display_config_class_init (CcDisplayConfigClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_signal_new ("primary", + CC_TYPE_DISPLAY_CONFIG, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_signal_new ("panel-orientation-managed", + CC_TYPE_DISPLAY_CONFIG, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + gobject_class->constructed = cc_display_config_constructed; + gobject_class->finalize = cc_display_config_finalize; +} + +GList * +cc_display_config_get_monitors (CcDisplayConfig *self) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), NULL); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->get_monitors (self); +} + +GList * +cc_display_config_get_ui_sorted_monitors (CcDisplayConfig *self) +{ + CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self); + + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), NULL); + return priv->ui_sorted_monitors; +} + +int +cc_display_config_count_useful_monitors (CcDisplayConfig *self) +{ + CcDisplayConfigPrivate *priv = cc_display_config_get_instance_private (self); + GList *outputs, *l; + guint count = 0; + + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), 0); + + outputs = priv->ui_sorted_monitors; + for (l = outputs; l != NULL; l = l->next) + { + CcDisplayMonitor *output = l->data; + if (!cc_display_monitor_is_useful (output)) + continue; + else + count++; + } + return count; + +} + +gboolean +cc_display_config_is_applicable (CcDisplayConfig *self) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_applicable (self); +} + +void +cc_display_config_set_mode_on_all_outputs (CcDisplayConfig *config, + CcDisplayMode *clone_mode) +{ + GList *outputs, *l; + + g_return_if_fail (CC_IS_DISPLAY_CONFIG (config)); + g_return_if_fail (cc_display_mode_is_clone_mode (clone_mode)); + + outputs = cc_display_config_get_monitors (config); + for (l = outputs; l; l = l->next) + { + CcDisplayMonitor *output = l->data; + cc_display_monitor_set_compatible_clone_mode (output, clone_mode); + cc_display_monitor_set_position (output, 0, 0); + } +} + +gboolean +cc_display_config_equal (CcDisplayConfig *self, + CcDisplayConfig *other) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE); + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (other), FALSE); + + return CC_DISPLAY_CONFIG_GET_CLASS (self)->equal (self, other); +} + +gboolean +cc_display_config_apply (CcDisplayConfig *self, + GError **error) +{ + if (!CC_IS_DISPLAY_CONFIG (self)) + { + g_warning ("Cannot apply invalid configuration"); + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Cannot apply invalid configuration"); + return FALSE; + } + + return CC_DISPLAY_CONFIG_GET_CLASS (self)->apply (self, error); +} + +gboolean +cc_display_config_is_cloning (CcDisplayConfig *self) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_cloning (self); +} + +void +cc_display_config_set_cloning (CcDisplayConfig *self, + gboolean clone) +{ + g_return_if_fail (CC_IS_DISPLAY_CONFIG (self)); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->set_cloning (self, clone); +} + +GList * +cc_display_config_generate_cloning_modes (CcDisplayConfig *self) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), NULL); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->generate_cloning_modes (self); +} + +gboolean +cc_display_config_is_layout_logical (CcDisplayConfig *self) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_layout_logical (self); +} + +void +cc_display_config_set_minimum_size (CcDisplayConfig *self, + int width, + int height) +{ + g_return_if_fail (CC_IS_DISPLAY_CONFIG (self)); + CC_DISPLAY_CONFIG_GET_CLASS (self)->set_minimum_size (self, width, height); +} + +gboolean +cc_display_config_is_scaled_mode_valid (CcDisplayConfig *self, + CcDisplayMode *mode, + double scale) +{ + g_return_val_if_fail (CC_IS_DISPLAY_CONFIG (self), FALSE); + g_return_val_if_fail (CC_IS_DISPLAY_MODE (mode), FALSE); + return CC_DISPLAY_CONFIG_GET_CLASS (self)->is_scaled_mode_valid (self, mode, scale); +} + +gboolean +cc_display_config_get_panel_orientation_managed (CcDisplayConfig *self) +{ + return CC_DISPLAY_CONFIG_GET_CLASS (self)->get_panel_orientation_managed (self); +} |