summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2023-03-07 22:36:57 +0100
committerMarge Bot <marge-bot@gnome.org>2023-04-18 18:38:03 +0000
commit2fd9834d94b19df019131d588910b47c1be8d18d (patch)
tree1c7bc9d7c5787353295d6035cb093c7df5a5e222
parent550a1dadf1dd667ce95a1b0cbb5b0cc186a4e467 (diff)
downloadmutter-2fd9834d94b19df019131d588910b47c1be8d18d.tar.gz
monitor: Add helper to parse simple mode strings
This will be used to extract the resolution and refresh rate from strings like "1920x1080@60.0" or "1280x720". This aims to replace the use of the locale dependent sscanf() function. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2902>
-rw-r--r--src/backends/meta-monitor.c47
-rw-r--r--src/backends/meta-monitor.h7
-rw-r--r--src/tests/monitor-util-tests.c81
3 files changed, 135 insertions, 0 deletions
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index 72bae35b3..00502bb35 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -2305,3 +2305,50 @@ meta_monitor_set_hdr_metadata (MetaMonitor *monitor,
return TRUE;
}
+
+gboolean
+meta_parse_monitor_mode (const char *string,
+ int *out_width,
+ int *out_height,
+ float *out_refresh_rate,
+ float fallback_refresh_rate)
+{
+ char *ptr = (char *) string;
+ int width, height;
+ float refresh_rate;
+
+ width = g_ascii_strtoull (ptr, &ptr, 10);
+ if (width == 0)
+ return FALSE;
+
+ if (ptr[0] != 'x')
+ return FALSE;
+ ptr++;
+
+ height = g_ascii_strtoull (ptr, &ptr, 10);
+ if (height == 0)
+ return FALSE;
+
+ if (ptr[0] == '\0')
+ {
+ refresh_rate = fallback_refresh_rate;
+ goto out;
+ }
+
+ if (ptr[0] != '@')
+ return FALSE;
+ ptr++;
+
+ refresh_rate = g_ascii_strtod (ptr, &ptr);
+ if (refresh_rate == 0.0)
+ return FALSE;
+
+ if (ptr[0] != '\0')
+ return FALSE;
+
+out:
+ *out_width = width;
+ *out_height = height;
+ *out_refresh_rate = refresh_rate;
+ return TRUE;
+}
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index bccfccbfa..c679f5368 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -318,4 +318,11 @@ gboolean meta_monitor_set_hdr_metadata (MetaMonitor *monitor,
MetaOutputHdrMetadata *metadata,
GError **error);
+META_EXPORT_TEST
+gboolean meta_parse_monitor_mode (const char *string,
+ int *out_width,
+ int *out_height,
+ float *out_refresh_rate,
+ float fallback_refresh_rate);
+
#endif /* META_MONITOR_H */
diff --git a/src/tests/monitor-util-tests.c b/src/tests/monitor-util-tests.c
index af59d42eb..f7386b5bc 100644
--- a/src/tests/monitor-util-tests.c
+++ b/src/tests/monitor-util-tests.c
@@ -130,6 +130,85 @@ meta_test_monitor_mode_spec_similar_size (void)
}
}
+static void
+meta_test_monitor_parse_mode (void)
+{
+ const float fallback_refresh_rate = 60.0;
+ struct {
+ const char *string;
+
+ gboolean expected_pass;
+ int expected_width;
+ int expected_height;
+ float expected_refresh_rate;
+ } test_cases[] = {
+ {
+ .string = "800x600",
+ .expected_pass = TRUE,
+ .expected_width = 800,
+ .expected_height = 600,
+ .expected_refresh_rate = fallback_refresh_rate,
+ },
+ {
+ .string = "1280x720@30",
+ .expected_pass = TRUE,
+ .expected_width = 1280,
+ .expected_height = 720,
+ .expected_refresh_rate = 30.0,
+ },
+ {
+ .string = "1920x1080@120.50",
+ .expected_pass = TRUE,
+ .expected_width = 1920,
+ .expected_height = 1080,
+ .expected_refresh_rate = 120.5,
+ },
+ {
+ .string = "800X600",
+ .expected_pass = FALSE,
+ },
+ {
+ .string = "800x",
+ .expected_pass = FALSE,
+ },
+ {
+ .string = "800x600@",
+ .expected_pass = FALSE,
+ },
+ {
+ .string = "800x600@notanumber",
+ .expected_pass = FALSE,
+ },
+ {
+ .string = "nonsense",
+ .expected_pass = FALSE,
+ },
+ };
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
+ {
+ int width, height;
+ float refresh_rate;
+
+ if (meta_parse_monitor_mode (test_cases[i].string,
+ &width, &height, &refresh_rate,
+ fallback_refresh_rate))
+ {
+ g_assert_true (test_cases[i].expected_pass);
+ g_assert_cmpint (width, ==, test_cases[i].expected_width);
+ g_assert_cmpint (height, ==, test_cases[i].expected_height);
+ g_assert_cmpfloat_with_epsilon (refresh_rate,
+ test_cases[i].expected_refresh_rate,
+ FLT_EPSILON);
+ }
+ else
+ {
+ g_assert_false (test_cases[i].expected_pass);
+ }
+ }
+}
+
int
main (int argc,
char **argv)
@@ -138,6 +217,8 @@ main (int argc,
g_test_add_func ("/backends/monitor/spec/similar-size",
meta_test_monitor_mode_spec_similar_size);
+ g_test_add_func ("/backends/monitor/parse-mode",
+ meta_test_monitor_parse_mode);
return g_test_run ();
}