mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-24 18:31:22 +01:00
feat(wm): support both serial numbers and device ids
This commit makes use of both `serial_number_id` and `device_id` with the first taking priority on all monitor reconciliator code, monitor cache and on postload and reload. This allows using the serial numbers on the `display_index_preferences` config, while keeping compatibility with the use of `device_id`. Using `device_id` should be discouraged since that value can change on restart while serial number doesn't appear to do so.
This commit is contained in:
@@ -64,12 +64,12 @@ pub fn send_notification(notification: MonitorNotification) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_in_monitor_cache(device_id: &str, config: MonitorConfig) {
|
||||
pub fn insert_in_monitor_cache(serial_or_device_id: &str, config: MonitorConfig) {
|
||||
let mut monitor_cache = MONITOR_CACHE
|
||||
.get_or_init(|| Mutex::new(HashMap::new()))
|
||||
.lock();
|
||||
|
||||
monitor_cache.insert(device_id.to_string(), config);
|
||||
monitor_cache.insert(serial_or_device_id.to_string(), config);
|
||||
}
|
||||
|
||||
pub fn attached_display_devices() -> color_eyre::Result<Vec<Monitor>> {
|
||||
@@ -260,8 +260,12 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> 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.device_id().eq(monitor.device_id()) {
|
||||
if attached.serial_number_id().eq(monitor.serial_number_id())
|
||||
|| attached.device_id().eq(monitor.device_id())
|
||||
{
|
||||
monitor.set_id(attached.id());
|
||||
monitor.set_device_id(attached.device_id().clone());
|
||||
monitor.set_serial_number_id(attached.serial_number_id().clone());
|
||||
monitor.set_name(attached.name().clone());
|
||||
monitor.set_size(*attached.size());
|
||||
monitor.set_work_area_size(*attached.work_area_size());
|
||||
@@ -295,11 +299,17 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
let mut newly_removed_displays = vec![];
|
||||
|
||||
for m in wm.monitors().iter() {
|
||||
if !attached_devices
|
||||
.iter()
|
||||
.any(|attached| attached.device_id().eq(m.device_id()))
|
||||
{
|
||||
newly_removed_displays.push(m.device_id().clone());
|
||||
if !attached_devices.iter().any(|attached| {
|
||||
attached.serial_number_id().eq(m.serial_number_id())
|
||||
|| attached.device_id().eq(m.device_id())
|
||||
}) {
|
||||
let id = m
|
||||
.serial_number_id()
|
||||
.as_ref()
|
||||
.map_or(m.device_id().clone(), |sn| sn.clone());
|
||||
|
||||
newly_removed_displays.push(id.clone());
|
||||
|
||||
for workspace in m.workspaces() {
|
||||
for container in workspace.containers() {
|
||||
// Save the orphaned containers from the removed monitor
|
||||
@@ -308,7 +318,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
}
|
||||
|
||||
// Let's add their state to the cache for later
|
||||
monitor_cache.insert(m.device_id().clone(), m.into());
|
||||
monitor_cache.insert(id, m.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,8 +330,12 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
|
||||
if !newly_removed_displays.is_empty() {
|
||||
// After we have cached them, remove them from our state
|
||||
wm.monitors_mut()
|
||||
.retain(|m| !newly_removed_displays.contains(m.device_id()));
|
||||
wm.monitors_mut().retain(|m| {
|
||||
!newly_removed_displays.iter().any(|id| {
|
||||
m.serial_number_id().as_ref().is_some_and(|sn| sn == id)
|
||||
|| m.device_id() == id
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
let post_removal_monitor_count = wm.monitors().len();
|
||||
@@ -361,7 +375,11 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
|
||||
let post_removal_monitor_count = wm.monitors().len();
|
||||
|
||||
// This is the list of device ids after we have removed detached displays
|
||||
// This is the list of device ids after we have removed detached displays. We can
|
||||
// keep this with just the device_ids without the serial numbers since this is used
|
||||
// only to check which one is the newly added monitor below if there is a new
|
||||
// monitor. Everything done after with said new monitor will again consider both
|
||||
// serial number and device ids.
|
||||
let post_removal_device_ids = wm
|
||||
.monitors()
|
||||
.iter()
|
||||
@@ -382,15 +400,21 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
|
||||
// Look in the updated state for new monitors
|
||||
for m in wm.monitors_mut() {
|
||||
let device_id = m.device_id().clone();
|
||||
let device_id = m.device_id();
|
||||
// We identify a new monitor when we encounter a new device id
|
||||
if !post_removal_device_ids.contains(&device_id) {
|
||||
if !post_removal_device_ids.contains(device_id) {
|
||||
let mut cache_hit = false;
|
||||
let mut cached_id = String::new();
|
||||
// Check if that device id exists in the cache for this session
|
||||
if let Some(cached) = monitor_cache.get(&device_id) {
|
||||
if let Some((id, cached)) = monitor_cache.get_key_value(device_id).or(m
|
||||
.serial_number_id()
|
||||
.as_ref()
|
||||
.and_then(|sn| monitor_cache.get_key_value(sn)))
|
||||
{
|
||||
cache_hit = true;
|
||||
cached_id = id.clone();
|
||||
|
||||
tracing::info!("found monitor and workspace configuration for {device_id} in the monitor cache, applying");
|
||||
tracing::info!("found monitor and workspace configuration for {id} in the monitor cache, applying");
|
||||
|
||||
// If it does, load all the monitor settings from the cache entry
|
||||
m.ensure_workspace_count(cached.workspaces.len());
|
||||
@@ -411,8 +435,8 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
}
|
||||
|
||||
// Entries in the cache should only be used once; remove the entry there was a cache hit
|
||||
if cache_hit {
|
||||
monitor_cache.remove(&device_id);
|
||||
if cache_hit && !cached_id.is_empty() {
|
||||
monitor_cache.remove(&cached_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1250,9 +1250,14 @@ impl StaticConfig {
|
||||
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
|
||||
let preferred_config_idx = {
|
||||
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
|
||||
let c_idx = display_index_preferences
|
||||
.iter()
|
||||
.find_map(|(c_idx, m_id)| (monitor.device_id() == m_id).then_some(*c_idx));
|
||||
let c_idx = display_index_preferences.iter().find_map(|(c_idx, id)| {
|
||||
(monitor
|
||||
.serial_number_id()
|
||||
.as_ref()
|
||||
.is_some_and(|sn| sn == id)
|
||||
|| monitor.device_id() == id)
|
||||
.then_some(*c_idx)
|
||||
});
|
||||
c_idx
|
||||
};
|
||||
let idx = preferred_config_idx.or({
|
||||
@@ -1276,10 +1281,11 @@ impl StaticConfig {
|
||||
// Check if this monitor config is the preferred config for this monitor and store
|
||||
// a copy of the config on the monitor cache if it is.
|
||||
if idx == preferred_config_idx {
|
||||
monitor_reconciliator::insert_in_monitor_cache(
|
||||
monitor.device_id(),
|
||||
monitor_config.clone(),
|
||||
);
|
||||
let id = monitor
|
||||
.serial_number_id()
|
||||
.as_ref()
|
||||
.map_or(monitor.device_id(), |sn| sn);
|
||||
monitor_reconciliator::insert_in_monitor_cache(id, monitor_config.clone());
|
||||
}
|
||||
|
||||
if let Some(used_config_idx) = idx {
|
||||
@@ -1331,24 +1337,21 @@ impl StaticConfig {
|
||||
}
|
||||
|
||||
// Check for configs that should be tied to a specific display that isn't loaded right now
|
||||
// and cache those configs with the specific `device_id` so that when those devices are
|
||||
// connected later we can use the correct config from the cache.
|
||||
// and cache those configs with the specific `serial_number_id` or `device_id` so that when
|
||||
// those devices are connected later we can use the correct config from the cache.
|
||||
if configs_with_preference.len() > configs_used.len() {
|
||||
for i in configs_with_preference
|
||||
.iter()
|
||||
.filter(|i| !configs_used.contains(i))
|
||||
{
|
||||
let device_id = {
|
||||
let id = {
|
||||
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
|
||||
display_index_preferences.get(i).cloned()
|
||||
};
|
||||
if let (Some(device_id), Some(monitor_config)) =
|
||||
(device_id, value.monitors.as_ref().and_then(|ms| ms.get(*i)))
|
||||
if let (Some(id), Some(monitor_config)) =
|
||||
(id, value.monitors.as_ref().and_then(|ms| ms.get(*i)))
|
||||
{
|
||||
monitor_reconciliator::insert_in_monitor_cache(
|
||||
&device_id,
|
||||
monitor_config.clone(),
|
||||
);
|
||||
monitor_reconciliator::insert_in_monitor_cache(&id, monitor_config.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1378,9 +1381,14 @@ impl StaticConfig {
|
||||
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
|
||||
let preferred_config_idx = {
|
||||
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
|
||||
let c_idx = display_index_preferences
|
||||
.iter()
|
||||
.find_map(|(c_idx, m_id)| (monitor.device_id() == m_id).then_some(*c_idx));
|
||||
let c_idx = display_index_preferences.iter().find_map(|(c_idx, id)| {
|
||||
(monitor
|
||||
.serial_number_id()
|
||||
.as_ref()
|
||||
.is_some_and(|sn| sn == id)
|
||||
|| monitor.device_id() == id)
|
||||
.then_some(*c_idx)
|
||||
});
|
||||
c_idx
|
||||
};
|
||||
let idx = preferred_config_idx.or({
|
||||
@@ -1404,10 +1412,11 @@ impl StaticConfig {
|
||||
// Check if this monitor config is the preferred config for this monitor and store
|
||||
// a copy of the config on the monitor cache if it is.
|
||||
if idx == preferred_config_idx {
|
||||
monitor_reconciliator::insert_in_monitor_cache(
|
||||
monitor.device_id(),
|
||||
monitor_config.clone(),
|
||||
);
|
||||
let id = monitor
|
||||
.serial_number_id()
|
||||
.as_ref()
|
||||
.map_or(monitor.device_id(), |sn| sn);
|
||||
monitor_reconciliator::insert_in_monitor_cache(id, monitor_config.clone());
|
||||
}
|
||||
|
||||
if let Some(used_config_idx) = idx {
|
||||
@@ -1461,24 +1470,21 @@ impl StaticConfig {
|
||||
}
|
||||
|
||||
// Check for configs that should be tied to a specific display that isn't loaded right now
|
||||
// and cache those configs with the specific `device_id` so that when those devices are
|
||||
// and cache those configs with the specific `serial_number_id` so that when those devices are
|
||||
// connected later we can use the correct config from the cache.
|
||||
if configs_with_preference.len() > configs_used.len() {
|
||||
for i in configs_with_preference
|
||||
.iter()
|
||||
.filter(|i| !configs_used.contains(i))
|
||||
{
|
||||
let device_id = {
|
||||
let id = {
|
||||
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
|
||||
display_index_preferences.get(i).cloned()
|
||||
};
|
||||
if let (Some(device_id), Some(monitor_config)) =
|
||||
(device_id, value.monitors.as_ref().and_then(|ms| ms.get(*i)))
|
||||
if let (Some(id), Some(monitor_config)) =
|
||||
(id, value.monitors.as_ref().and_then(|ms| ms.get(*i)))
|
||||
{
|
||||
monitor_reconciliator::insert_in_monitor_cache(
|
||||
&device_id,
|
||||
monitor_config.clone(),
|
||||
);
|
||||
monitor_reconciliator::insert_in_monitor_cache(&id, monitor_config.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user