+ if not new_configuration[output].edid or "off" in new_configuration[output].options:
+ disable_outputs.append(new_configuration[output].option_vector)
+ else:
+ if "off" not in current_configuration[output].options:
+ remain_active_count += 1
+ enable_outputs.append(new_configuration[output].option_vector)
+ if xrandr_version() >= Version("1.3.0") and "transform" in current_configuration[output].options:
+ auxiliary_changes_pre.append(["--output", output, "--transform", "none"])
+
+ # Perform pe-change auxiliary changes
+ if auxiliary_changes_pre:
+ argv = base_argv + list(chain.from_iterable(auxiliary_changes_pre))
+ if subprocess.call(argv) != 0:
+ raise RuntimeError("Command failed: %s" % " ".join(argv))
+
+ # Disable unused outputs, but make sure that there always is at least one active screen
+ disable_keep = 0 if remain_active_count else 1
+ if len(disable_outputs) > disable_keep:
+ if subprocess.call(base_argv + list(chain.from_iterable(disable_outputs[:-1] if disable_keep else disable_outputs))) != 0:
+ # Disabling the outputs failed. Retry with the next command:
+ # Sometimes disabling of outputs fails due to an invalid RRSetScreenSize.
+ # This does not occur if simultaneously the primary screen is reset.
+ pass
+ else:
+ disable_outputs = disable_outputs[-1:] if disable_keep else []
+
+ # If disable_outputs still has more than one output in it, one of the xrandr-calls below would
+ # disable the last two screens. This is a problem, so if this would happen, instead disable only
+ # one screen in the first call below.
+ if len(disable_outputs) > 0 and len(disable_outputs) % 2 == 0:
+ # In the context of a xrandr call that changes the display state, `--query' should do nothing
+ disable_outputs.insert(0, ['--query'])
+
+ # Enable the remaining outputs in pairs of two operations
+ operations = disable_outputs + enable_outputs
+ for index in range(0, len(operations), 2):
+ argv = base_argv + list(chain.from_iterable(operations[index:index+2]))
+ if subprocess.call(argv) != 0:
+ raise RuntimeError("Command failed: %s" % " ".join(argv))
+
+def add_unused_outputs(source_configuration, target_configuration):
+ "Add outputs that are missing in target to target, in 'off' state"
+ for output_name, output in source_configuration.items():
+ if output_name not in target_configuration:
+ target_configuration[output_name] = XrandrOutput(output_name, output.edid, { "off": None })
+
+def remove_irrelevant_outputs(source_configuration, target_configuration):
+ "Remove outputs from target that ought to be 'off' and already are"
+ for output_name, output in source_configuration.items():
+ if "off" in output.options and output_name in target_configuration and "off" in target_configuration[output_name].options:
+ del target_configuration[output_name]