From 03f720c4d9bc9ff6b28b9f50ab75db371a5ed5d6 Mon Sep 17 00:00:00 2001 From: L4XB Date: Fri, 23 Oct 2026 10:12:53 +0200 Subject: [PATCH] fix(linux): keep listing resolutions after an interlaced xrandr mode resolutions() reads the mode lines below an output with (\s*\d+x\d+\s+\d+.*\n)+, which needs whitespace right after the size. A TV usually lists 1920x1080i right after 1920x1080, so the list ended there and the resolution menu offered only the current mode. Allow a suffix after the size; the per-mode pattern still skips the interlaced lines, so only the following progressive modes are added. --- src/platform/linux.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index a8b716828..1aefe1b99 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1940,8 +1940,12 @@ fn get_xrandr_conn_pat(name: &str) -> String { ) } +// The mode lines below an output. A mode name can have a suffix after its size, like the "i" of +// "1920x1080i", so a TV's interlaced mode does not end the list. +const XRANDR_MODES_PAT: &str = r"(?P(\s*\d+x\d+\S*\s+\d+.*\n)+)"; + pub fn resolutions(name: &str) -> Vec { - let resolutions_pat = r"(?P(\s*\d+x\d+\s+\d+.*\n)+)"; + let resolutions_pat = XRANDR_MODES_PAT; let connected_pat = get_xrandr_conn_pat(name); let mut v = vec![]; if let Ok(re) = Regex::new(&format!("{}{}", connected_pat, resolutions_pat)) { @@ -2035,6 +2039,28 @@ DP-1 connected 2560x1440+1920+0 (normal left inverted right x axis y axis) 597mm let caps = re.captures(xrandr_output).unwrap(); assert_eq!(get_width_height_from_captures(&caps), Some((2560, 1440))); } + + #[test] + fn interlaced_mode_does_not_end_the_mode_list() { + let xrandr_output = + "Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384 +HDMI-0 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 1600mm x 900mm + 1920x1080 60.00*+ 59.94 50.00 + 1920x1080i 60.00 59.94 50.00 + 1280x720 60.00 59.94 50.00 + 640x480 75.00 59.94 +DP-0 disconnected (normal left inverted right x axis y axis) +"; + let re = Regex::new(&format!( + "{}{}", + get_xrandr_conn_pat("HDMI-0"), + XRANDR_MODES_PAT + )) + .unwrap(); + let caps = re.captures(xrandr_output).unwrap(); + assert!(caps["resolutions"].contains(" 1280x720 ")); + assert!(caps["resolutions"].contains(" 640x480 ")); + } } pub fn change_resolution_directly(name: &str, width: usize, height: usize) -> ResultType<()> {