diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e994dd6..b768017 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -33,7 +33,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: doc - args: --no-deps --features "test_all_features" -p smithay -p calloop:0.8.0 -p dbus -p drm -p gbm -p input -p nix:0.20.0 -p udev -p slog -p wayland-server -p wayland-commons -p wayland-protocols -p winit + args: --no-deps --features "test_all_features" -p smithay -p calloop:0.9.0 -p dbus -p drm -p gbm -p input -p nix:0.20.0 -p udev -p slog -p wayland-server -p wayland-commons -p wayland-protocols -p winit - name: Setup index run: cp ./doc_index.html ./target/doc/index.html diff --git a/Cargo.toml b/Cargo.toml index 62f39b4..b48ca8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ members = [ "anvil" ] [dependencies] appendlist = "1.4" bitflags = "1" -calloop = "0.8.0" +calloop = "0.9.0" cgmath = "0.18.0" dbus = { version = "0.9.0", optional = true } downcast-rs = "1.2.0" @@ -33,11 +33,11 @@ slog-stdlog = { version = "4", optional = true } tempfile = { version = "3.0", optional = true } thiserror = "1" udev = { version = "0.6", optional = true } -wayland-commons = { version = "0.28", optional = true } -wayland-egl = { version = "0.28", optional = true } -wayland-protocols = { version = "0.28", features = ["unstable_protocols", "server"], optional = true } -wayland-server = { version = "0.28.3", optional = true } -wayland-sys = { version = "0.28", optional = true } +wayland-commons = { version = "0.28.6", optional = true } +wayland-egl = { version = "0.28.6", optional = true } +wayland-protocols = { version = "0.28.6", features = ["unstable_protocols", "server"], optional = true } +wayland-server = { version = "0.28.6", optional = true } +wayland-sys = { version = "0.28.6", optional = true } winit = { version = "0.25.0", optional = true } xkbcommon = "0.4.0" scan_fmt = { version = "0.2", default-features = false } diff --git a/anvil/src/state.rs b/anvil/src/state.rs index 36975be..b197677 100644 --- a/anvil/src/state.rs +++ b/anvil/src/state.rs @@ -9,7 +9,7 @@ use std::{ use smithay::{ reexports::{ - calloop::{generic::Generic, Interest, LoopHandle, Mode}, + calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction}, wayland_server::{protocol::wl_surface::WlSurface, Display}, }, wayland::{ @@ -62,7 +62,7 @@ impl AnvilState { let display = state.display.clone(); let mut display = display.borrow_mut(); match display.dispatch(std::time::Duration::from_millis(0), state) { - Ok(_) => Ok(()), + Ok(_) => Ok(PostAction::Continue), Err(e) => { error!(state.log, "I/O error on the Wayland display: {}", e); state.running.store(false, Ordering::SeqCst); diff --git a/anvil/src/xwayland/x11rb_event_source.rs b/anvil/src/xwayland/x11rb_event_source.rs index bf907ba..f3991e4 100644 --- a/anvil/src/xwayland/x11rb_event_source.rs +++ b/anvil/src/xwayland/x11rb_event_source.rs @@ -10,7 +10,7 @@ use x11rb::{ use smithay::reexports::calloop::{ generic::{Fd, Generic}, - EventSource, Interest, Mode, Poll, Readiness, Token, + EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory, }; pub struct X11Source { @@ -31,7 +31,12 @@ impl EventSource for X11Source { type Metadata = (); type Ret = Result<(), ReplyOrIdError>; - fn process_events(&mut self, _readiness: Readiness, _token: Token, callback: C) -> IOResult<()> + fn process_events( + &mut self, + readiness: Readiness, + token: Token, + mut callback: C, + ) -> IOResult where C: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { @@ -49,15 +54,19 @@ impl EventSource for X11Source { conn.flush()?; Ok(()) } - inner(&self.connection, callback).map_err(|err| IOError::new(ErrorKind::Other, err)) + let connection = &self.connection; + self.generic.process_events(readiness, token, |_, _| { + inner(connection, &mut callback).map_err(|err| IOError::new(ErrorKind::Other, err))?; + Ok(PostAction::Continue) + }) } - fn register(&mut self, poll: &mut Poll, token: Token) -> IOResult<()> { - self.generic.register(poll, token) + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> IOResult<()> { + self.generic.register(poll, factory) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> IOResult<()> { - self.generic.reregister(poll, token) + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> IOResult<()> { + self.generic.reregister(poll, factory) } fn unregister(&mut self, poll: &mut Poll) -> IOResult<()> { diff --git a/src/backend/drm/device/mod.rs b/src/backend/drm/device/mod.rs index 6242197..c776b09 100644 --- a/src/backend/drm/device/mod.rs +++ b/src/backend/drm/device/mod.rs @@ -4,7 +4,7 @@ use std::os::unix::io::{AsRawFd, RawFd}; use std::path::PathBuf; use std::sync::{atomic::AtomicBool, Arc}; -use calloop::{EventSource, Interest, Poll, Readiness, Token}; +use calloop::{EventSource, Interest, Poll, PostAction, Readiness, Token, TokenFactory}; use drm::control::{connector, crtc, Device as ControlDevice, Event, Mode, ResourceHandles}; use drm::{ClientCapability, Device as BasicDevice}; use nix::libc::dev_t; @@ -28,6 +28,7 @@ pub struct DrmDevice { has_universal_planes: bool, resources: ResourceHandles, pub(super) logger: ::slog::Logger, + token: Token, } impl AsRawFd for DrmDevice { @@ -151,6 +152,7 @@ impl DrmDevice { has_universal_planes, resources, logger: log, + token: Token::invalid(), }) } @@ -314,10 +316,18 @@ where type Metadata = (); type Ret = (); - fn process_events(&mut self, _: Readiness, _: Token, mut callback: F) -> std::io::Result<()> + fn process_events( + &mut self, + _: Readiness, + token: Token, + mut callback: F, + ) -> std::io::Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { + if token != self.token { + return Ok(PostAction::Continue); + } match self.receive_events() { Ok(events) => { for event in events { @@ -344,18 +354,21 @@ where ); } } - Ok(()) + Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - poll.register(self.as_raw_fd(), Interest::READ, calloop::Mode::Level, token) + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.register(self.as_raw_fd(), Interest::READ, calloop::Mode::Level, self.token) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - poll.reregister(self.as_raw_fd(), Interest::READ, calloop::Mode::Level, token) + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.reregister(self.as_raw_fd(), Interest::READ, calloop::Mode::Level, self.token) } fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.token = Token::invalid(); poll.unregister(self.as_raw_fd()) } } diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index 13b8e14..43a3c5a 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -16,7 +16,7 @@ use std::{ os::unix::io::{AsRawFd, RawFd}, }; -use calloop::{EventSource, Interest, Mode, Poll, Readiness, Token}; +use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; use slog::{info, o}; @@ -36,6 +36,7 @@ pub struct LibinputInputBackend { #[cfg(feature = "backend_session")] links: Vec, logger: ::slog::Logger, + token: Token, } impl LibinputInputBackend { @@ -52,6 +53,7 @@ impl LibinputInputBackend { #[cfg(feature = "backend_session")] links: Vec::new(), logger: log, + token: Token::invalid(), } } } @@ -510,22 +512,33 @@ impl EventSource for LibinputInputBackend { type Metadata = (); type Ret = (); - fn process_events(&mut self, _: Readiness, _: Token, mut callback: F) -> std::io::Result<()> + fn process_events( + &mut self, + _: Readiness, + token: Token, + mut callback: F, + ) -> std::io::Result where F: FnMut(Self::Event, &mut ()) -> Self::Ret, { - self.dispatch_new_events(|event| callback(event, &mut ())) + if token == self.token { + self.dispatch_new_events(|evt| callback(evt, &mut ()))?; + } + Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, token) + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, token) + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) } fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.token = Token::invalid(); poll.unregister(self.as_raw_fd()) } } diff --git a/src/backend/session/auto.rs b/src/backend/session/auto.rs index e799dfd..1293eb1 100644 --- a/src/backend/session/auto.rs +++ b/src/backend/session/auto.rs @@ -43,7 +43,7 @@ use crate::signaling::Signaler; use nix::fcntl::OFlag; use std::{cell::RefCell, io, os::unix::io::RawFd, path::Path, rc::Rc}; -use calloop::{EventSource, Poll, Readiness, Token}; +use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; use slog::{error, info, o, warn}; @@ -204,7 +204,7 @@ impl EventSource for AutoSessionNotifier { type Metadata = (); type Ret = (); - fn process_events(&mut self, readiness: Readiness, token: Token, callback: F) -> io::Result<()> + fn process_events(&mut self, readiness: Readiness, token: Token, callback: F) -> io::Result where F: FnMut((), &mut ()), { @@ -217,23 +217,23 @@ impl EventSource for AutoSessionNotifier { } } - fn register(&mut self, poll: &mut Poll, token: Token) -> io::Result<()> { + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> io::Result<()> { match self { #[cfg(feature = "backend_session_logind")] - AutoSessionNotifier::Logind(s) => EventSource::register(s, poll, token), - AutoSessionNotifier::Direct(s) => EventSource::register(s, poll, token), + AutoSessionNotifier::Logind(s) => EventSource::register(s, poll, factory), + AutoSessionNotifier::Direct(s) => EventSource::register(s, poll, factory), #[cfg(feature = "backend_session_libseat")] - AutoSessionNotifier::LibSeat(s) => EventSource::register(s, poll, token), + AutoSessionNotifier::LibSeat(s) => EventSource::register(s, poll, factory), } } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> io::Result<()> { + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> io::Result<()> { match self { #[cfg(feature = "backend_session_logind")] - AutoSessionNotifier::Logind(s) => EventSource::reregister(s, poll, token), - AutoSessionNotifier::Direct(s) => EventSource::reregister(s, poll, token), + AutoSessionNotifier::Logind(s) => EventSource::reregister(s, poll, factory), + AutoSessionNotifier::Direct(s) => EventSource::reregister(s, poll, factory), #[cfg(feature = "backend_session_libseat")] - AutoSessionNotifier::LibSeat(s) => EventSource::reregister(s, poll, token), + AutoSessionNotifier::LibSeat(s) => EventSource::reregister(s, poll, factory), } } diff --git a/src/backend/session/dbus/logind.rs b/src/backend/session/dbus/logind.rs index d2ccdf6..fcb119f 100644 --- a/src/backend/session/dbus/logind.rs +++ b/src/backend/session/dbus/logind.rs @@ -57,7 +57,7 @@ use std::{ sync::atomic::{AtomicBool, Ordering}, }; -use calloop::{EventSource, Poll, Readiness, Token}; +use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; use slog::{debug, error, info, o, warn}; @@ -460,7 +460,7 @@ impl EventSource for LogindSessionNotifier { type Metadata = (); type Ret = (); - fn process_events(&mut self, readiness: Readiness, token: Token, _: F) -> std::io::Result<()> + fn process_events(&mut self, readiness: Readiness, token: Token, _: F) -> std::io::Result where F: FnMut((), &mut ()), { @@ -478,15 +478,15 @@ impl EventSource for LogindSessionNotifier { } } - Ok(()) + Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - self.internal.conn.borrow_mut().register(poll, token) + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.internal.conn.borrow_mut().register(poll, factory) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - self.internal.conn.borrow_mut().reregister(poll, token) + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.internal.conn.borrow_mut().reregister(poll, factory) } fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { diff --git a/src/backend/session/dbus/mod.rs b/src/backend/session/dbus/mod.rs index 2b50d95..d833105 100644 --- a/src/backend/session/dbus/mod.rs +++ b/src/backend/session/dbus/mod.rs @@ -1,6 +1,6 @@ use std::io; -use calloop::{EventSource, Interest, Mode, Poll, Readiness, Token}; +use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; use dbus::{ blocking::LocalConnection, @@ -17,6 +17,7 @@ pub mod logind; pub(crate) struct DBusConnection { cx: LocalConnection, current_watch: Watch, + token: Token, } impl DBusConnection { @@ -25,6 +26,7 @@ impl DBusConnection { chan.set_watch_enabled(true); Ok(DBusConnection { cx: chan.into(), + token: Token::invalid(), current_watch: Watch { fd: -1, read: false, @@ -47,10 +49,13 @@ impl EventSource for DBusConnection { type Metadata = DBusConnection; type Ret = (); - fn process_events(&mut self, _: Readiness, _: Token, mut callback: F) -> io::Result<()> + fn process_events(&mut self, _: Readiness, token: Token, mut callback: F) -> io::Result where F: FnMut(Message, &mut DBusConnection), { + if token != self.token { + return Ok(PostAction::Continue); + } self.cx .channel() .read_write(Some(std::time::Duration::from_millis(0))) @@ -59,10 +64,10 @@ impl EventSource for DBusConnection { callback(message, self); } self.cx.channel().flush(); - Ok(()) + Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, token: Token) -> io::Result<()> { + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> io::Result<()> { if self.current_watch.read || self.current_watch.write { return Err(io::Error::new( io::ErrorKind::AlreadyExists, @@ -70,10 +75,10 @@ impl EventSource for DBusConnection { )); } // reregister handles all the watch logic - self.reregister(poll, token) + self.reregister(poll, factory) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> io::Result<()> { + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> io::Result<()> { let new_watch = self.cx.channel().watch(); let new_interest = match (new_watch.read, new_watch.write) { (true, true) => Some(Interest::BOTH), @@ -81,6 +86,7 @@ impl EventSource for DBusConnection { (false, true) => Some(Interest::WRITE), (false, false) => None, }; + self.token = factory.token(); if new_watch.fd != self.current_watch.fd { // remove the previous fd if self.current_watch.read || self.current_watch.write { @@ -88,12 +94,12 @@ impl EventSource for DBusConnection { } // insert the new one if let Some(interest) = new_interest { - poll.register(new_watch.fd, interest, Mode::Level, token)?; + poll.register(new_watch.fd, interest, Mode::Level, self.token)?; } } else { // update the registration if let Some(interest) = new_interest { - poll.reregister(self.current_watch.fd, interest, Mode::Level, token)?; + poll.reregister(self.current_watch.fd, interest, Mode::Level, self.token)?; } else { poll.unregister(self.current_watch.fd)?; } @@ -106,6 +112,7 @@ impl EventSource for DBusConnection { if self.current_watch.read || self.current_watch.write { poll.unregister(self.current_watch.fd)?; } + self.token = Token::invalid(); self.current_watch = Watch { fd: -1, read: false, diff --git a/src/backend/session/direct.rs b/src/backend/session/direct.rs index 34b0328..f3af0e5 100644 --- a/src/backend/session/direct.rs +++ b/src/backend/session/direct.rs @@ -453,7 +453,7 @@ impl calloop::EventSource for DirectSessionNotifier { readiness: calloop::Readiness, token: calloop::Token, _: F, - ) -> std::io::Result<()> + ) -> std::io::Result where F: FnMut((), &mut ()), { @@ -462,10 +462,14 @@ impl calloop::EventSource for DirectSessionNotifier { source.process_events(readiness, token, |_, _| self.signal_received())?; } self.source = source; - Ok(()) + Ok(calloop::PostAction::Continue) } - fn register(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> { + fn register( + &mut self, + poll: &mut calloop::Poll, + factory: &mut calloop::TokenFactory, + ) -> std::io::Result<()> { if self.source.is_some() { return Err(std::io::Error::new( std::io::ErrorKind::AlreadyExists, @@ -473,14 +477,18 @@ impl calloop::EventSource for DirectSessionNotifier { )); } let mut source = Signals::new(&[self.signal])?; - source.register(poll, token)?; + source.register(poll, factory)?; self.source = Some(source); Ok(()) } - fn reregister(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> { + fn reregister( + &mut self, + poll: &mut calloop::Poll, + factory: &mut calloop::TokenFactory, + ) -> std::io::Result<()> { if let Some(ref mut source) = self.source { - source.reregister(poll, token) + source.reregister(poll, factory) } else { Err(std::io::Error::new( std::io::ErrorKind::NotFound, diff --git a/src/backend/session/libseat.rs b/src/backend/session/libseat.rs index c7613d1..68f9a45 100644 --- a/src/backend/session/libseat.rs +++ b/src/backend/session/libseat.rs @@ -18,7 +18,7 @@ use std::{ use nix::{errno::Errno, fcntl::OFlag, unistd::close}; -use calloop::{EventSource, Poll, Readiness, Token}; +use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; use crate::{ backend::session::{AsErrno, Session, Signal as SessionSignal}, @@ -53,6 +53,7 @@ pub struct LibSeatSession { pub struct LibSeatSessionNotifier { internal: Rc, signaler: Signaler, + token: Token, } impl LibSeatSession { @@ -109,7 +110,11 @@ impl LibSeatSession { internal: Rc::downgrade(&internal), seat_name, }, - LibSeatSessionNotifier { internal, signaler }, + LibSeatSessionNotifier { + internal, + signaler, + token: Token::invalid(), + }, ) }) .map_err(|err| Error::FailedToOpenSession(Errno::from_i32(err.into()))) @@ -209,37 +214,42 @@ impl EventSource for LibSeatSessionNotifier { type Metadata = (); type Ret = (); - fn process_events(&mut self, _readiness: Readiness, _token: Token, _: F) -> std::io::Result<()> + fn process_events(&mut self, _readiness: Readiness, token: Token, _: F) -> std::io::Result where F: FnMut((), &mut ()), { - self.internal.seat.borrow_mut().dispatch(0).unwrap(); - Ok(()) + if token == self.token { + self.internal.seat.borrow_mut().dispatch(0).unwrap(); + } + Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); poll.register( self.internal.seat.borrow_mut().get_fd().unwrap(), calloop::Interest::READ, calloop::Mode::Level, - token, + self.token, ) .unwrap(); Ok(()) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); poll.reregister( self.internal.seat.borrow_mut().get_fd().unwrap(), calloop::Interest::READ, calloop::Mode::Level, - token, + self.token, ) .unwrap(); Ok(()) } fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.token = Token::invalid(); poll.unregister(self.internal.seat.borrow_mut().get_fd().unwrap()) .unwrap(); Ok(()) diff --git a/src/backend/udev.rs b/src/backend/udev.rs index 8c68530..3d0214f 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -50,7 +50,7 @@ use std::{ }; use udev::{Enumerator, EventType, MonitorBuilder, MonitorSocket}; -use calloop::{EventSource, Interest, Mode, Poll, Readiness, Token}; +use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; use slog::{debug, info, o, warn}; @@ -62,6 +62,7 @@ use slog::{debug, info, o, warn}; pub struct UdevBackend { devices: HashMap, monitor: MonitorSocket, + token: Token, logger: ::slog::Logger, } @@ -112,6 +113,7 @@ impl UdevBackend { Ok(UdevBackend { devices, monitor, + token: Token::invalid(), logger: log, }) } @@ -130,10 +132,18 @@ impl EventSource for UdevBackend { type Metadata = (); type Ret = (); - fn process_events(&mut self, _: Readiness, _: Token, mut callback: F) -> std::io::Result<()> + fn process_events( + &mut self, + _: Readiness, + token: Token, + mut callback: F, + ) -> std::io::Result where F: FnMut(UdevEvent, &mut ()), { + if token != self.token { + return Ok(PostAction::Continue); + } let monitor = self.monitor.clone(); for event in monitor { debug!( @@ -180,18 +190,21 @@ impl EventSource for UdevBackend { _ => {} } } - Ok(()) + Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, token) + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) } - fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> { - poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, token) + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) } fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.token = Token::invalid(); poll.unregister(self.as_raw_fd()) } } diff --git a/src/xwayland/xserver.rs b/src/xwayland/xserver.rs index 740bcbc..9dea03a 100644 --- a/src/xwayland/xserver.rs +++ b/src/xwayland/xserver.rs @@ -56,7 +56,7 @@ use std::{ use calloop::{ channel::{sync_channel, Channel, SyncSender}, generic::{Fd, Generic}, - Interest, LoopHandle, Mode, RegistrationToken, + Interest, LoopHandle, Mode, }; use slog::{error, info, o}; @@ -80,6 +80,7 @@ pub struct XWayland { /// Your WM code must be able handle the XWayland server connecting then /// disconnecting several time in a row, but only a single connection will /// be active at any given time. +#[derive(Debug)] pub enum XWaylandEvent { /// The XWayland server is ready Ready { @@ -145,7 +146,6 @@ impl Drop for XWayland { struct XWaylandInstance { display_lock: X11Lock, wayland_client: Option, - startup_handler: Option, wm_fd: Option, child_stdout: Option, } @@ -208,18 +208,17 @@ fn launch(inner: &Rc>>) -> std::io::Result<()> { }; let inner = inner.clone(); - let startup_handler = guard.handle.insert_source( + guard.handle.insert_source( Generic::new(Fd(child_stdout.as_raw_fd()), Interest::READ, Mode::Level), move |_, _, _| { // the closure must be called exactly one time, this cannot panic xwayland_ready(&inner); - Ok(()) + Ok(calloop::PostAction::Remove) }, )?; guard.instance = Some(XWaylandInstance { display_lock: lock, - startup_handler: Some(startup_handler), wayland_client: None, wm_fd: Some(x_wm_me), child_stdout: Some(child_stdout), @@ -242,7 +241,7 @@ impl calloop::EventSource for XWaylandSource { readiness: calloop::Readiness, token: calloop::Token, mut callback: F, - ) -> std::io::Result<()> + ) -> std::io::Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { @@ -253,12 +252,20 @@ impl calloop::EventSource for XWaylandSource { }) } - fn register(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> { - self.channel.register(poll, token) + fn register( + &mut self, + poll: &mut calloop::Poll, + factory: &mut calloop::TokenFactory, + ) -> std::io::Result<()> { + self.channel.register(poll, factory) } - fn reregister(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> { - self.channel.reregister(poll, token) + fn reregister( + &mut self, + poll: &mut calloop::Poll, + factory: &mut calloop::TokenFactory, + ) -> std::io::Result<()> { + self.channel.reregister(poll, factory) } fn unregister(&mut self, poll: &mut calloop::Poll) -> std::io::Result<()> { @@ -270,16 +277,12 @@ impl Inner { // Shutdown the XWayland server and cleanup everything fn shutdown(&mut self) { // don't do anything if not running - if let Some(mut instance) = self.instance.take() { + if let Some(instance) = self.instance.take() { info!(self.log, "Shutting down XWayland."); // kill the client if let Some(client) = instance.wayland_client { client.kill(); } - // remove the event source - if let Some(s) = instance.startup_handler.take() { - self.handle.kill(s); - } // send error occurs if the user dropped the channel... We cannot do much except ignore. let _ = self.sender.send(XWaylandEvent::Exited); @@ -345,11 +348,6 @@ fn xwayland_ready(inner: &Rc>>) { "XWayland crashed at startup, will not try to restart it." ); } - - // in all cases, cleanup - if let Some(s) = instance.startup_handler.take() { - guard.handle.kill(s); - } } /// Spawn XWayland with given sockets on given display