diff --git a/data/cosmic-comp.service b/data/cosmic-comp.service index 5778da1d6..1d628ddac 100644 --- a/data/cosmic-comp.service +++ b/data/cosmic-comp.service @@ -8,5 +8,6 @@ Before=cosmic-session.target [Service] Type=notify ExecStart=/usr/bin/cosmic-comp -Restart=never -ExecStopPost=/usr/bin/systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY \ No newline at end of file +Restart=on-failure +RestartSec=1s +ExecStopPost=/usr/bin/systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY diff --git a/src/backend/kms/device.rs b/src/backend/kms/device.rs index 44682dc51..773abe5c2 100644 --- a/src/backend/kms/device.rs +++ b/src/backend/kms/device.rs @@ -34,6 +34,7 @@ use smithay::{ output::{Mode as OutputMode, Output, PhysicalProperties, Scale, Subpixel}, reexports::{ calloop::{LoopHandle, RegistrationToken}, + drm::Device as _, drm::control::{Device as ControlDevice, ModeTypeFlags, connector, crtc}, gbm::BufferObjectFlags as GbmBufferFlags, rustix::fs::{Dev as dev_t, OFlags}, @@ -685,6 +686,14 @@ pub struct OutputChanges { } impl Device { + pub(super) fn has_drm_master(&self) -> bool { + self.drm + .device() + .device_fd() + .authenticated() + .unwrap_or(false) + } + fn new( dev: dev_t, path: impl AsRef, diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 16559e4e2..3781ad8c1 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -59,8 +59,32 @@ use device::*; pub(crate) use surface::Surface; pub use surface::Timings; +fn primary_master_failure_requires_retry(is_primary: bool, acquired: bool) -> bool { + is_primary && !acquired +} + use super::render::{CLEAR_COLOR, CursorMode, output_elements}; +#[cfg(test)] +mod tests { + use super::primary_master_failure_requires_retry; + + #[test] + fn primary_master_failure_is_retryable() { + assert!(primary_master_failure_requires_retry(true, false)); + } + + #[test] + fn secondary_master_failure_does_not_block_startup() { + assert!(!primary_master_failure_requires_retry(false, false)); + } + + #[test] + fn acquired_primary_master_does_not_require_retry() { + assert!(!primary_master_failure_requires_retry(true, true)); + } +} + #[derive(Debug)] pub struct KmsState { pub drm_devices: IndexMap, @@ -146,6 +170,24 @@ pub fn init_backend( warn!("Failed to determine primary gpu: {}", err); } + let primary_node = *state.backend.kms().primary_node.read().unwrap(); + if let Some(primary_node) = primary_node { + let primary_device = state + .backend + .kms() + .drm_devices + .values() + .find(|device| device.inner.render_node == primary_node) + .context("Primary render device is not available")?; + + if primary_master_failure_requires_retry(true, primary_device.has_drm_master()) { + anyhow::bail!( + "Unable to acquire DRM master for primary device {}; retrying compositor startup", + primary_device.inner.dev_node + ); + } + } + if let Err(err) = state.refresh_output_config() { info!( ?err, diff --git a/src/input/mod.rs b/src/input/mod.rs index 0cb26a9da..81a7f8af6 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -2529,7 +2529,7 @@ pub fn update_output_image_copy_cursor_position( position: Point, ) { let output_geometry = output.geometry(); - for session in cursor_sessions_for_output(&shell, &output) { + for session in cursor_sessions_for_output(shell, output) { if let Some(cursor_geometry) = seat.cursor_geometry( (position - output_geometry.loc.to_f64()) .as_logical() diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index b8288019b..b4f16c4c2 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -333,17 +333,15 @@ impl XdgShellHandler for State { if let Some(ref grab) = grab { if grab.has_ended() { should_ungrab = true; - } else if let Some(target) = grab.current_grab() { - if let Some(wl_surface) = target.wl_surface() { - if wl_surface.as_ref() == surface.wl_surface() - || smithay::desktop::PopupManager::popups_for_surface( - surface.wl_surface(), - ) - .any(|(p, _)| p.wl_surface() == wl_surface.as_ref()) - { - should_ungrab = true; - } - } + } else if let Some(target) = grab.current_grab() + && let Some(wl_surface) = target.wl_surface() + && (wl_surface.as_ref() == surface.wl_surface() + || smithay::desktop::PopupManager::popups_for_surface( + surface.wl_surface(), + ) + .any(|(p, _)| p.wl_surface() == wl_surface.as_ref())) + { + should_ungrab = true; } } if should_ungrab {