diff --git a/komorebi/src/monitor_reconciliator/mod.rs b/komorebi/src/monitor_reconciliator/mod.rs index b9d57816..282ed8cc 100644 --- a/komorebi/src/monitor_reconciliator/mod.rs +++ b/komorebi/src/monitor_reconciliator/mod.rs @@ -258,6 +258,26 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result | MonitorNotification::SessionUnlocked | MonitorNotification::DisplayConnectionChange => { tracing::debug!("handling display connection change notification"); + let mut has_duplicate_serial_ids = false; + + { + let mut serial_id_tracker = vec![]; + + for m in wm.monitors() { + if let Some(id) = m.serial_number_id() { + serial_id_tracker.push(id); + } + } + + serial_id_tracker.sort(); + let before_dedup = serial_id_tracker.len(); + serial_id_tracker.dedup(); + let after_dedup = serial_id_tracker.len(); + if before_dedup != after_dedup { + has_duplicate_serial_ids = true; + } + } + let mut monitor_cache = MONITOR_CACHE .get_or_init(|| Mutex::new(HashMap::new())) .lock(); @@ -270,8 +290,9 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result // Make sure that in our state any attached displays have the latest Win32 data for monitor in wm.monitors_mut() { for attached in &attached_devices { - if attached.serial_number_id().eq(monitor.serial_number_id()) - || attached.device_id().eq(monitor.device_id()) + // Acer monitors are dumb and can have the same serial ID, so check by device ID first + if attached.device_id().eq(monitor.device_id()) + || attached.serial_number_id().eq(monitor.serial_number_id()) { monitor.set_id(attached.id()); monitor.set_device(attached.device().clone()); @@ -313,13 +334,17 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result for (m_idx, m) in wm.monitors().iter().enumerate() { if !attached_devices.iter().any(|attached| { - attached.serial_number_id().eq(m.serial_number_id()) - || attached.device_id().eq(m.device_id()) + // Acer monitors are dumb and can have the same serial ID, so check by device ID first + attached.device_id().eq(m.device_id()) + || attached.serial_number_id().eq(m.serial_number_id()) }) { - let id = m - .serial_number_id() - .as_ref() - .map_or(m.device_id().clone(), |sn| sn.clone()); + let id = if has_duplicate_serial_ids { + m.device_id().clone() + } else { + m.serial_number_id() + .as_ref() + .map_or(m.device_id().clone(), |sn| sn.clone()) + }; newly_removed_displays.push(id.clone()); diff --git a/komorebi/src/static_config.rs b/komorebi/src/static_config.rs index 06c674c7..ca52ea55 100644 --- a/komorebi/src/static_config.rs +++ b/komorebi/src/static_config.rs @@ -1199,6 +1199,8 @@ impl StaticConfig { let offset = wm.work_area_offset; for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() { + let mut prefers_device_id = false; + let preferred_config_idx = { let display_index_preferences = DISPLAY_INDEX_PREFERENCES.read(); let c_idx = display_index_preferences.iter().find_map(|(c_idx, id)| { @@ -1209,6 +1211,15 @@ impl StaticConfig { || monitor.device_id() == id) .then_some(*c_idx) }); + + if let Some(c_idx) = c_idx { + if let Some(id) = display_index_preferences.get(&c_idx) { + if id.contains("UID") { + prefers_device_id = true; + } + } + } + c_idx }; let idx = preferred_config_idx.or({ @@ -1256,10 +1267,16 @@ impl StaticConfig { // Check if this monitor config is the preferred config for this monitor and store // a copy of the monitor itself on the monitor cache if it is. if idx == preferred_config_idx { - let id = monitor - .serial_number_id() - .as_ref() - .map_or(monitor.device_id(), |sn| sn); + // Don't even consider the serial ID if the user prefers the device ID + let id = if prefers_device_id { + monitor.device_id() + } else { + monitor + .serial_number_id() + .as_ref() + .map_or(monitor.device_id(), |sn| sn) + }; + monitor_reconciliator::insert_in_monitor_cache(id, monitor.clone()); } @@ -1368,6 +1385,8 @@ impl StaticConfig { let offset = wm.work_area_offset; for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() { + let mut prefers_device_id = false; + let preferred_config_idx = { let display_index_preferences = DISPLAY_INDEX_PREFERENCES.read(); let c_idx = display_index_preferences.iter().find_map(|(c_idx, id)| { @@ -1378,6 +1397,15 @@ impl StaticConfig { || monitor.device_id() == id) .then_some(*c_idx) }); + + if let Some(c_idx) = c_idx { + if let Some(id) = display_index_preferences.get(&c_idx) { + if id.contains("UID") { + prefers_device_id = true; + } + } + } + c_idx }; let idx = preferred_config_idx.or({ @@ -1428,10 +1456,16 @@ impl StaticConfig { // Check if this monitor config is the preferred config for this monitor and store // a copy of the monitor itself on the monitor cache if it is. if idx == preferred_config_idx { - let id = monitor - .serial_number_id() - .as_ref() - .map_or(monitor.device_id(), |sn| sn); + // Don't even consider the serial ID if the user prefers the device ID + let id = if prefers_device_id { + monitor.device_id() + } else { + monitor + .serial_number_id() + .as_ref() + .map_or(monitor.device_id(), |sn| sn) + }; + monitor_reconciliator::insert_in_monitor_cache(id, monitor.clone()); }