diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c index 899ce00ab..d8e3a9cda 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c @@ -1261,7 +1261,7 @@ create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager) if (!mode) continue; - scale = compute_scale_for_monitor (config_manager, monitor, + scale = compute_scale_for_monitor (monitor_manager, monitor, primary_monitor); best_scale = MAX (best_scale, scale); monitor_configs = g_list_prepend (monitor_configs, create_monitor_config (monitor, mode)); diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index 46cb05a66..a3d84d440 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -1542,6 +1542,24 @@ meta_monitor_get_mode_from_id (MetaMonitor *monitor, return g_hash_table_lookup (priv->mode_ids, monitor_mode_id); } +gboolean +meta_monitor_mode_spec_has_similar_size (MetaMonitorModeSpec *monitor_mode_spec, + MetaMonitorModeSpec *other_monitor_mode_spec) +{ + const float target_ratio = 1.0; + /* The a size difference of 15% means e.g. 4K modes matches other 4K modes, + * FHD (2K) modes other FHD modes, and HD modes other HD modes, but not each + * other. + */ + const float epsilon = 0.15; + + return G_APPROX_VALUE (((float) monitor_mode_spec->width / + other_monitor_mode_spec->width) * + ((float) monitor_mode_spec->height / + other_monitor_mode_spec->height), + target_ratio, epsilon); +} + static gboolean meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec, MetaMonitorModeSpec *other_monitor_mode_spec) diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h index 066caa7f4..d8a90097f 100644 --- a/src/backends/meta-monitor.h +++ b/src/backends/meta-monitor.h @@ -182,6 +182,10 @@ META_EXPORT_TEST MetaMonitorMode * meta_monitor_get_mode_from_id (MetaMonitor *monitor, const char *monitor_mode_id); +META_EXPORT_TEST +gboolean meta_monitor_mode_spec_has_similar_size (MetaMonitorModeSpec *monitor_mode_spec, + MetaMonitorModeSpec *other_monitor_mode_spec); + META_EXPORT_TEST MetaMonitorMode * meta_monitor_get_mode_from_spec (MetaMonitor *monitor, MetaMonitorModeSpec *monitor_mode_spec); diff --git a/src/tests/meson.build b/src/tests/meson.build index 127aa52b8..4e35325e9 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -195,6 +195,11 @@ test_cases += [ 'suite': 'backend', 'sources': [ 'monitor-unit-tests.c', ], }, + { + 'name': 'monitor-utils', + 'suite': 'unit', + 'sources': [ 'monitor-util-tests.c', ], + }, { 'name': 'headless-start', 'suite': 'backend', diff --git a/src/tests/monitor-util-tests.c b/src/tests/monitor-util-tests.c new file mode 100644 index 000000000..af59d42eb --- /dev/null +++ b/src/tests/monitor-util-tests.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2022 Red Hat + * + * 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., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#include "config.h" + +#include "backends/meta-monitor.h" + +static void +assert_matches_none (MetaMonitorModeSpec *mode_spec, + MetaMonitorModeSpec *mode_specs, + int n_mode_specs) +{ + int i; + + for (i = 0; i < n_mode_specs; i++) + { + g_assert_false (meta_monitor_mode_spec_has_similar_size (mode_spec, + &mode_specs[i])); + } +} + +static void +meta_test_monitor_mode_spec_similar_size (void) +{ + MetaMonitorModeSpec matching_4k_specs[] = { + { .width = 4096, .height = 2560 }, /* 16:10 */ + { .width = 4096, .height = 2304 }, /* 16:9 */ + { .width = 3840, .height = 2400 }, /* 16:10 */ + { .width = 3840, .height = 2160 }, /* 16:9 */ + }; + MetaMonitorModeSpec matching_uhd_specs[] = { + { .width = 1920, .height = 1200 }, /* 16:10 */ + { .width = 1920, .height = 1080 }, /* 16:9 */ + { .width = 2048, .height = 1152 }, /* 16:9 */ + }; + MetaMonitorModeSpec matching_hd_specs[] = { + { .width = 1366, .height = 768 }, /* ~16:9 */ + { .width = 1280, .height = 720 }, /* 16:9 */ + }; + MetaMonitorModeSpec nonmatching_specs[] = { + { .width = 1024, .height = 768 }, + { .width = 800, .height = 600 }, + { .width = 640, .height = 480 }, + }; + int i; + + /* Test that 4K modes only matches other 4K modes */ + + for (i = 0; i < G_N_ELEMENTS (matching_4k_specs); i++) + { + MetaMonitorModeSpec *mode_spec = &matching_4k_specs[i]; + MetaMonitorModeSpec *prev_mode_spec = &matching_4k_specs[i - 1]; + + if (i != 0) + { + g_assert_true (meta_monitor_mode_spec_has_similar_size (mode_spec, + prev_mode_spec)); + } + + assert_matches_none (mode_spec, + matching_uhd_specs, G_N_ELEMENTS (matching_uhd_specs)); + assert_matches_none (mode_spec, + matching_hd_specs, G_N_ELEMENTS (matching_hd_specs)); + assert_matches_none (mode_spec, + nonmatching_specs, G_N_ELEMENTS (nonmatching_specs)); + } + + /* Test that FHD modes only matches other FHD modes */ + + for (i = 0; i < G_N_ELEMENTS (matching_uhd_specs); i++) + { + MetaMonitorModeSpec *mode_spec = &matching_uhd_specs[i]; + MetaMonitorModeSpec *prev_mode_spec = &matching_uhd_specs[i - 1]; + + if (i != 0) + { + g_assert_true (meta_monitor_mode_spec_has_similar_size (mode_spec, + prev_mode_spec)); + } + + assert_matches_none (mode_spec, + matching_hd_specs, G_N_ELEMENTS (matching_hd_specs)); + assert_matches_none (mode_spec, + nonmatching_specs, G_N_ELEMENTS (nonmatching_specs)); + } + + /* Test that HD modes only matches other HD modes */ + + for (i = 0; i < G_N_ELEMENTS (matching_hd_specs); i++) + { + MetaMonitorModeSpec *mode_spec = &matching_hd_specs[i]; + MetaMonitorModeSpec *prev_mode_spec = &matching_hd_specs[i - 1]; + + if (i != 0) + { + g_assert_true (meta_monitor_mode_spec_has_similar_size (mode_spec, + prev_mode_spec)); + } + + assert_matches_none (mode_spec, + nonmatching_specs, G_N_ELEMENTS (nonmatching_specs)); + } + + /* Test that the other modes doesn't match each other. */ + + for (i = 0; i < G_N_ELEMENTS (nonmatching_specs) - 1; i++) + { + MetaMonitorModeSpec *mode_spec = &nonmatching_specs[i]; + MetaMonitorModeSpec *next_mode_spec = &nonmatching_specs[i + 1]; + + g_assert_false (meta_monitor_mode_spec_has_similar_size (mode_spec, + next_mode_spec)); + } +} + +int +main (int argc, + char **argv) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/backends/monitor/spec/similar-size", + meta_test_monitor_mode_spec_similar_size); + + return g_test_run (); +}