Skip to content

Commit ae60523

Browse files
committed
shell/workspace: Disambiguate output with edid match by connector name
If two displays have the same edid (which shouldn't happen, since edid includes a serial number, but is somewhat common in practice with identical monitors), match output stack by comparing both edid and connector name. If we get the same edid but a different connector, `set_output` truncates but also adds the new one. (Before adding edid matching, this would have just added to the output stack.) `prefers_output()` will requrire a connector name match if the edid of the current output is the same as that of the output being compared.
1 parent 6c9f42b commit ae60523

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

src/shell/workspace.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,16 @@ impl OutputMatch {
8888
}
8989
}
9090

91-
fn matches(&self, output: &Output) -> bool {
92-
self.edid.as_ref() == output.edid() && (self.edid.is_some() || self.name == output.name())
91+
// If `disambguate` is true, check that edid *and* connector name match.
92+
// Otherwise, match only edid (if it exists)
93+
fn matches(&self, output: &Output, disambiguate: bool) -> bool {
94+
if self.edid.as_ref() != output.edid() {
95+
false
96+
} else if disambiguate || self.edid.is_none() {
97+
self.name == output.name()
98+
} else {
99+
true
100+
}
93101
}
94102
}
95103

@@ -403,16 +411,36 @@ impl Workspace {
403411
if explicit {
404412
self.output_stack.clear();
405413
}
406-
if let Some(pos) = self.output_stack.iter().position(|i| i.matches(output)) {
414+
if let Some(pos) = self
415+
.output_stack
416+
.iter()
417+
.position(|i| i.matches(output, true))
418+
{
419+
// Matched edid and connector name
407420
self.output_stack.truncate(pos + 1);
421+
} else if let Some(pos) = self
422+
.output_stack
423+
.iter()
424+
.position(|i| i.matches(output, false))
425+
{
426+
// Matched edid but not connector name; truncate entries that don't match edid,
427+
// but keep old entry in case we see two outputs with the same edid.
428+
self.output_stack.truncate(pos + 1);
429+
self.output_stack.push_back(OutputMatch::for_output(output));
408430
} else {
409431
self.output_stack.push_back(OutputMatch::for_output(output));
410432
}
411433
self.output = output.clone();
412434
}
413435

414436
pub fn prefers_output(&self, output: &Output) -> bool {
415-
self.output_stack.iter().any(|i| i.matches(output))
437+
// Disambiguate match by connector name if existing output has same edid
438+
let disambiguate = output
439+
.edid()
440+
.is_some_and(|edid| self.output().edid() == Some(edid));
441+
self.output_stack
442+
.iter()
443+
.any(|i| i.matches(output, disambiguate))
416444
}
417445

418446
pub fn unmap(&mut self, mapped: &CosmicMapped) -> Option<ManagedState> {

0 commit comments

Comments
 (0)