diff --git a/doc/man/gdctl.rst b/doc/man/gdctl.rst index 95e3909b6..0a94ec308 100644 --- a/doc/man/gdctl.rst +++ b/doc/man/gdctl.rst @@ -77,6 +77,10 @@ SET OPTIONS Add and configure a logical monitor. See LOGICAL MONITOR OPTIONS. +``--for-lease-monitor``, ``-e`` + + Set a monitor, that is not part of any logical monitor, available for lease. + LOGICAL MONITOR OPTIONS ----------------------- @@ -157,6 +161,16 @@ of the two mirrored monitors. --right-of DP-1 --transform 270 +Set eDP-1 and DP-2 as available for lease. + +:: + + gdctl set --logical-monitor + --primary + --monitor DP-1 + --for-lease-monitor eDP-1 + --for-lease-monitor DP-2 + BUGS ---- The bug tracker can be reached by visiting the website diff --git a/src/tests/monitor-dbus-tests.c b/src/tests/monitor-dbus-tests.c index fe83df45f..d6d938a78 100644 --- a/src/tests/monitor-dbus-tests.c +++ b/src/tests/monitor-dbus-tests.c @@ -676,6 +676,32 @@ meta_test_monitor_dbus_apply_mirror (void) &expect)); } +static void +meta_test_monitor_dbus_apply_for_lease (void) +{ + MonitorTestCaseExpect expect; + + setup_apply_configuration_test (); + + check_gdctl_result ("set", + "--verbose", + "--layout-mode", "logical", + "--logical-monitor", + "--primary", + "--monitor", "DP-1", + "--for-lease-monitor", "DP-2", + NULL); + + expect = test_case_expect; + expect.n_logical_monitors = 1; + expect.screen_width = 1744; + expect.monitors[1].current_mode = -1; + expect.crtcs[1].current_mode = -1; + META_TEST_LOG_CALL ("Checking monitor configuration", + meta_check_monitor_configuration (test_context, + &expect)); +} + static void init_tests (void) { @@ -691,6 +717,8 @@ init_tests (void) meta_test_monitor_dbus_apply_mode_scale_below_transform); g_test_add_func ("/backends/native/monitor/dbus/apply/mirror", meta_test_monitor_dbus_apply_mirror); + g_test_add_func ("/backends/native/monitor/dbus/apply/for-lease", + meta_test_monitor_dbus_apply_for_lease); } int diff --git a/tools/gdctl b/tools/gdctl index 95df234e0..b231c74d2 100755 --- a/tools/gdctl +++ b/tools/gdctl @@ -260,6 +260,7 @@ class DisplayConfig: def apply_monitors_config(self, config, config_method): serial = config.monitors_state.server_serial logical_monitors = config.generate_logical_monitor_tuples() + monitors_for_lease = config.generate_monitors_for_lease_tuples() properties = {} if monitors_state.supports_changing_layout_mode: @@ -267,6 +268,11 @@ class DisplayConfig: "u", config.layout_mode.value ) + if monitors_for_lease: + properties["monitors-for-lease"] = GLib.Variant( + "a(ssss)", monitors_for_lease + ) + parameters = GLib.Variant( "(uua(iiduba(ssa{sv}))a{sv})", ( @@ -781,9 +787,15 @@ def generate_configuration(monitors_state, args): for monitor in logical_monitor.monitors: monitor_mappings[monitor.connector] = logical_monitor + monitors_for_lease = [] + for connector in args.monitors_for_lease: + monitors_for_lease.append(monitors_state.monitors[connector]) + calculate_positions(logical_monitors, layout_mode, monitor_mappings) - return Config(monitors_state, logical_monitors, layout_mode) + return Config( + monitors_state, logical_monitors, layout_mode, monitors_for_lease + ) def derive_config_method(args): @@ -812,7 +824,7 @@ def print_config(config): print_data( level=0, - is_last=True, + is_last=False, lines=lines, data=f"Logical monitors ({len(config.logical_monitors)})", ) @@ -882,6 +894,22 @@ def print_config(config): index += 1 + print_data( + level=0, + is_last=True, + lines=lines, + data=f"Monitors for lease ({len(config.monitors_for_lease)})", + ) + + for monitor in config.monitors_for_lease: + is_last = monitor == config.monitors_for_lease[-1] + print_data( + level=1, + is_last=is_last, + lines=lines, + data=f"Monitor {monitor.connector} ({monitor.display_name})", + ) + class MonitorsState: def __init__(self, display_config): @@ -1112,6 +1140,7 @@ class Config: monitors_state: MonitorsState logical_monitors: list[LogicalMonitor] layout_mode: LayoutMode + monitors_for_lease: Monitor def generate_monitor_tuples(self, monitors): tuples = [] @@ -1155,6 +1184,19 @@ class Config: ) return tuples + def generate_monitors_for_lease_tuples(self): + tuples = [] + for monitor in self.monitors_for_lease: + tuples.append( + ( + monitor.connector, + monitor.vendor, + monitor.product, + monitor.serial, + ) + ) + return tuples + class GroupAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): @@ -1358,6 +1400,14 @@ if __name__ == "__main__": nargs=0, default=[], ) + set_parser.add_argument( + "-e", + "--for-lease-monitor", + dest="monitors_for_lease", + action="append", + type=str, + default=[], + ).completer = MonitorCompleter() # type: ignore[attr-defined] logical_monitor_parser = set_parser.add_argument_group( "logical_monitor", "Logical monitor options (pass after --logical-monitor)",