diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index e2a99cec0..bd23d8f97 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -336,6 +336,7 @@ gboolean meta_parse_monitor_mode (const char *string,
float *out_refresh_rate,
float fallback_refresh_rate);
+META_EXPORT_TEST
gboolean meta_monitor_get_backlight_info (MetaMonitor *monitor,
int *backlight_min,
int *backlight_max);
@@ -343,5 +344,6 @@ gboolean meta_monitor_get_backlight_info (MetaMonitor *monitor,
void meta_monitor_set_backlight (MetaMonitor *monitor,
int value);
+META_EXPORT_TEST
gboolean meta_monitor_get_backlight (MetaMonitor *monitor,
int *value);
diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h
index baea0efd7..a3b4eb80d 100644
--- a/src/backends/meta-output.h
+++ b/src/backends/meta-output.h
@@ -258,9 +258,11 @@ META_EXPORT_TEST
gboolean meta_output_get_max_bpc (MetaOutput *output,
unsigned int *max_bpc);
+META_EXPORT_TEST
void meta_output_set_backlight (MetaOutput *output,
int backlight);
+META_EXPORT_TEST
int meta_output_get_backlight (MetaOutput *output);
MetaPrivacyScreenState meta_output_get_privacy_screen_state (MetaOutput *output);
diff --git a/src/tests/meson.build b/src/tests/meson.build
index ce5ec0699..5b1e9ccf9 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -271,6 +271,11 @@ test_cases += [
'suite': 'unit',
'sources': [ 'monitor-util-tests.c', ],
},
+ {
+ 'name': 'monitor-backlight',
+ 'suite': 'backend',
+ 'sources': [ 'monitor-backlight-tests.c', ]
+ },
{
'name': 'stage-views',
'suite': 'compositor',
diff --git a/src/tests/meta-monitor-test-utils.c b/src/tests/meta-monitor-test-utils.c
index 27f8219c1..a56e1f9f0 100644
--- a/src/tests/meta-monitor-test-utils.c
+++ b/src/tests/meta-monitor-test-utils.c
@@ -771,6 +771,8 @@ meta_create_monitor_test_setup (MetaBackend *backend,
output_info->suggested_x = -1;
output_info->suggested_y = -1;
}
+ output_info->backlight_min = setup->outputs[i].backlight_min;
+ output_info->backlight_max = setup->outputs[i].backlight_max;
output_info->width_mm = setup->outputs[i].width_mm;
output_info->height_mm = setup->outputs[i].height_mm;
output_info->subpixel_order = META_SUBPIXEL_ORDER_UNKNOWN;
diff --git a/src/tests/meta-monitor-test-utils.h b/src/tests/meta-monitor-test-utils.h
index 7b5e0df7e..16db0f947 100644
--- a/src/tests/meta-monitor-test-utils.h
+++ b/src/tests/meta-monitor-test-utils.h
@@ -113,6 +113,8 @@ typedef struct _MonitorTestCaseOutput
gboolean hotplug_mode;
int suggested_x;
int suggested_y;
+ int backlight_min;
+ int backlight_max;
gboolean has_edid_info;
MetaEdidInfo edid_info;
} MonitorTestCaseOutput;
diff --git a/src/tests/meta-output-test.c b/src/tests/meta-output-test.c
index c97c800f4..e788edb94 100644
--- a/src/tests/meta-output-test.c
+++ b/src/tests/meta-output-test.c
@@ -21,9 +21,50 @@
G_DEFINE_TYPE (MetaOutputTest, meta_output_test, META_TYPE_OUTPUT_NATIVE)
+static void
+on_backlight_changed (MetaOutput *output)
+{
+ const MetaOutputInfo *info = meta_output_get_info (output);
+ int value = meta_output_get_backlight (output);
+
+ g_assert_cmpint (info->backlight_min, <=, value);
+ g_assert_cmpint (info->backlight_max, >=, value);
+}
+
+static void
+meta_output_test_constructed (GObject *object)
+{
+ MetaOutput *output = META_OUTPUT (object);
+ const MetaOutputInfo *info = meta_output_get_info (output);
+
+ if (info->backlight_min != info->backlight_max)
+ {
+ int backlight_range = info->backlight_max - info->backlight_min;
+
+ meta_output_set_backlight (output,
+ info->backlight_min + backlight_range / 2);
+ g_signal_connect (output, "backlight-changed",
+ G_CALLBACK (on_backlight_changed), NULL);
+ }
+
+ G_OBJECT_CLASS (meta_output_test_parent_class)->constructed (object);
+}
+
+static GBytes *
+meta_output_test_read_edid (MetaOutputNative *output_native)
+{
+ return NULL;
+}
+
static void
meta_output_test_class_init (MetaOutputTestClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MetaOutputNativeClass *output_native_class = META_OUTPUT_NATIVE_CLASS (klass);
+
+ object_class->constructed = meta_output_test_constructed;
+
+ output_native_class->read_edid = meta_output_test_read_edid;
}
static void
diff --git a/src/tests/monitor-backlight-tests.c b/src/tests/monitor-backlight-tests.c
new file mode 100644
index 000000000..ca3cc2d50
--- /dev/null
+++ b/src/tests/monitor-backlight-tests.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2025 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, see .
+ */
+
+#include "config.h"
+
+#include
+
+#include "tests/meta-test/meta-context-test.h"
+#include "tests/meta-monitor-test-utils.h"
+
+static MonitorTestCaseSetup initial_test_case_setup = {
+ .modes = {
+ {
+ .width = 1024,
+ .height = 768,
+ .refresh_rate = 60.0
+ }
+ },
+ .n_modes = 1,
+ .outputs = {
+ {
+ .crtc = 0,
+ .modes = { 0 },
+ .n_modes = 1,
+ .preferred_mode = 0,
+ .possible_crtcs = { 0 },
+ .n_possible_crtcs = 1,
+ .width_mm = 222,
+ .height_mm = 125,
+ .is_laptop_panel = TRUE,
+ .backlight_min = 0,
+ .backlight_max = 300,
+ },
+ {
+ .crtc = 1,
+ .modes = { 0 },
+ .n_modes = 1,
+ .preferred_mode = 0,
+ .possible_crtcs = { 1 },
+ .n_possible_crtcs = 1,
+ .width_mm = 220,
+ .height_mm = 124
+ }
+ },
+ .n_outputs = 2,
+ .crtcs = {
+ {
+ .current_mode = 0
+ },
+ {
+ .current_mode = 0
+ }
+ },
+ .n_crtcs = 2
+};
+
+static MetaContext *test_context;
+
+static MetaMonitorTestSetup *
+create_test_setup (MetaBackend *backend)
+{
+ return meta_create_monitor_test_setup (backend,
+ &initial_test_case_setup,
+ MONITOR_TEST_FLAG_NO_STORED);
+}
+
+static void
+meta_test_backlight_sanity (void)
+{
+ MetaBackend *backend = meta_context_get_backend (test_context);
+ MetaMonitorManager *monitor_manager =
+ meta_backend_get_monitor_manager (backend);
+ GList *monitors;
+ MetaMonitor *first_monitor;
+ MetaMonitor *second_monitor;
+ MetaOutput *output;
+ const MetaOutputInfo *output_info;
+ int backlight_min;
+ int backlight_max;
+ int backlight;
+
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ g_assert_cmpuint (g_list_length (monitors), ==, 2);
+
+ first_monitor = g_list_nth_data (monitors, 0);
+ second_monitor = g_list_nth_data (monitors, 1);
+
+ g_assert_true (meta_monitor_get_backlight_info (first_monitor,
+ &backlight_min,
+ &backlight_max));
+ g_assert_cmpint (backlight_min, ==, 0);
+ g_assert_cmpint (backlight_max, ==, 300);
+ g_assert_true (meta_monitor_get_backlight (first_monitor, &backlight));
+ g_assert_cmpint (backlight, >=, 0);
+ g_assert_cmpuint (g_list_length (meta_monitor_get_outputs (first_monitor)),
+ ==,
+ 1);
+ output = meta_monitor_get_main_output (first_monitor);
+ output_info = meta_output_get_info (output);
+ g_assert_cmpint (meta_output_get_backlight (output), >=, 0);
+ g_assert_cmpint (output_info->backlight_min, ==, 0);
+ g_assert_cmpint (output_info->backlight_max, ==, 300);
+
+ g_assert_false (meta_monitor_get_backlight_info (second_monitor,
+ NULL,
+ NULL));
+ g_assert_false (meta_monitor_get_backlight (second_monitor, NULL));
+ g_assert_cmpuint (g_list_length (meta_monitor_get_outputs (second_monitor)),
+ ==,
+ 1);
+ output = meta_monitor_get_main_output (second_monitor);
+ output_info = meta_output_get_info (output);
+ g_assert_cmpint (meta_output_get_backlight (output), ==, -1);
+ g_assert_cmpint (output_info->backlight_min, ==, 0);
+ g_assert_cmpint (output_info->backlight_max, ==, 0);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_autoptr (MetaContext) context = NULL;
+
+ context = meta_create_test_context (META_CONTEXT_TEST_TYPE_TEST,
+ META_CONTEXT_TEST_FLAG_TEST_CLIENT);
+ g_assert (meta_context_configure (context, &argc, &argv, NULL));
+
+ test_context = context;
+
+ meta_init_monitor_test_setup (create_test_setup);
+ g_test_add_func ("/backends/backlight/sanity", meta_test_backlight_sanity);
+
+ return meta_context_test_run_tests (META_CONTEXT_TEST (context),
+ META_TEST_RUN_FLAG_NONE);
+}