aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-08-21 11:52:52 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-08-21 11:52:52 +0400
commit07d92e7c41c430abb1cf7721d80ac4d6da0b139a (patch)
tree3df8318bf23b2b1713646c721aadd3d7a17aa06d /src
parent78090e1140b99d245c6932d10e084e7f11d34083 (diff)
downloadniri-07d92e7c41c430abb1cf7721d80ac4d6da0b139a.tar.gz
niri-07d92e7c41c430abb1cf7721d80ac4d6da0b139a.tar.bz2
niri-07d92e7c41c430abb1cf7721d80ac4d6da0b139a.zip
Fix monitor un/replugging while session is paused
Diffstat (limited to 'src')
-rw-r--r--src/tty.rs105
1 files changed, 77 insertions, 28 deletions
diff --git a/src/tty.rs b/src/tty.rs
index 3fcebe06..9991856f 100644
--- a/src/tty.rs
+++ b/src/tty.rs
@@ -18,7 +18,7 @@ use smithay::backend::session::{Event as SessionEvent, Session};
use smithay::backend::udev::{self, UdevBackend, UdevEvent};
use smithay::desktop::utils::OutputPresentationFeedback;
use smithay::output::{Mode, Output, OutputModeSource, PhysicalProperties, Subpixel};
-use smithay::reexports::calloop::{LoopHandle, RegistrationToken};
+use smithay::reexports::calloop::{Dispatcher, LoopHandle, RegistrationToken};
use smithay::reexports::drm::control::{
connector, crtc, Mode as DrmMode, ModeFlags, ModeTypeFlags,
};
@@ -40,6 +40,7 @@ const SUPPORTED_COLOR_FORMATS: &[Fourcc] = &[Fourcc::Argb8888, Fourcc::Abgr8888]
pub struct Tty {
session: LibSeatSession,
+ udev_dispatcher: Dispatcher<'static, UdevBackend, LoopData>,
primary_gpu_path: PathBuf,
output_device: Option<OutputDevice>,
}
@@ -122,10 +123,49 @@ impl Backend for Tty {
}
impl Tty {
- pub fn new(event_loop: LoopHandle<LoopData>) -> Self {
+ pub fn new(event_loop: LoopHandle<'static, LoopData>) -> Self {
let (session, notifier) = LibSeatSession::new().unwrap();
let seat_name = session.seat();
+ let udev_backend = UdevBackend::new(session.seat()).unwrap();
+ let udev_dispatcher =
+ Dispatcher::new(udev_backend, move |event, _, data: &mut LoopData| {
+ let tty = data.tty.as_mut().unwrap();
+ let niri = &mut data.niri;
+
+ match event {
+ UdevEvent::Added { device_id, path } => {
+ if !tty.session.is_active() {
+ debug!("skipping UdevEvent::Added as session is inactive");
+ return;
+ }
+
+ if let Err(err) = tty.device_added(device_id, &path, niri) {
+ warn!("error adding device: {err:?}");
+ }
+ }
+ UdevEvent::Changed { device_id } => {
+ if !tty.session.is_active() {
+ debug!("skipping UdevEvent::Changed as session is inactive");
+ return;
+ }
+
+ tty.device_changed(device_id, niri)
+ }
+ UdevEvent::Removed { device_id } => {
+ if !tty.session.is_active() {
+ debug!("skipping UdevEvent::Removed as session is inactive");
+ return;
+ }
+
+ tty.device_removed(device_id, niri)
+ }
+ }
+ });
+ event_loop
+ .register_dispatcher(udev_dispatcher.clone())
+ .unwrap();
+
let mut libinput = Libinput::new_with_udev(LibinputSessionInterface::from(session.clone()));
libinput.udev_assign_seat(&seat_name).unwrap();
@@ -140,6 +180,7 @@ impl Tty {
})
.unwrap();
+ let udev_dispatcher_c = udev_dispatcher.clone();
event_loop
.insert_source(notifier, move |event, _, data| {
let tty = data.tty.as_mut().unwrap();
@@ -163,17 +204,42 @@ impl Tty {
}
if let Some(output_device) = &mut tty.output_device {
- output_device.drm.activate();
+ // We had an output device, check if it's been removed.
+ let output_device_id = output_device.id;
+ if !udev_dispatcher_c
+ .as_source_ref()
+ .device_list()
+ .any(|(device_id, _)| device_id == output_device_id)
+ {
+ // The output device, if we had any, has been removed.
+ tty.device_removed(output_device_id, niri);
+ } else {
+ // It hasn't been removed, update its state as usual.
+ output_device.drm.activate();
+
+ // Refresh the connectors.
+ tty.device_changed(output_device_id, niri);
+
+ // Refresh the state on unchanged connectors.
+ let output_device = tty.output_device.as_mut().unwrap();
+ for drm_compositor in output_device.surfaces.values_mut() {
+ if let Err(err) = drm_compositor.surface().reset_state() {
+ warn!("error resetting DRM surface state: {err}");
+ }
+ drm_compositor.reset_buffers();
+ }
- for drm_compositor in output_device.surfaces.values_mut() {
- if let Err(err) = drm_compositor.surface().reset_state() {
- warn!("error resetting DRM surface state: {err}");
+ niri.queue_redraw_all();
+ }
+ } else {
+ // We didn't have an output device, check if it's been added.
+ for (device_id, path) in udev_dispatcher_c.as_source_ref().device_list()
+ {
+ if let Err(err) = tty.device_added(device_id, path, niri) {
+ warn!("error adding device: {err:?}");
}
- drm_compositor.reset_buffers();
}
}
-
- niri.queue_redraw_all();
}
}
})
@@ -183,35 +249,18 @@ impl Tty {
Self {
session,
+ udev_dispatcher,
primary_gpu_path,
output_device: None,
}
}
pub fn init(&mut self, niri: &mut Niri) {
- let backend = UdevBackend::new(&self.session.seat()).unwrap();
- for (device_id, path) in backend.device_list() {
+ for (device_id, path) in self.udev_dispatcher.clone().as_source_ref().device_list() {
if let Err(err) = self.device_added(device_id, path, niri) {
warn!("error adding device: {err:?}");
}
}
-
- niri.event_loop
- .insert_source(backend, move |event, _, data| {
- let tty = data.tty.as_mut().unwrap();
- let niri = &mut data.niri;
-
- match event {
- UdevEvent::Added { device_id, path } => {
- if let Err(err) = tty.device_added(device_id, &path, niri) {
- warn!("error adding device: {err:?}");
- }
- }
- UdevEvent::Changed { device_id } => tty.device_changed(device_id, niri),
- UdevEvent::Removed { device_id } => tty.device_removed(device_id, niri),
- }
- })
- .unwrap();
}
fn device_added(