xwayland: rework as an EventSource
Reorganize the XWayland abstraction into a calloop EventLoop. Fixes #245 Fixes #203
This commit is contained in:
parent
01b5c1a183
commit
671e2053e9
|
@ -23,11 +23,9 @@ use smithay::{
|
|||
#[cfg(feature = "egl")]
|
||||
use smithay::backend::egl::display::EGLBufferReader;
|
||||
#[cfg(feature = "xwayland")]
|
||||
use smithay::xwayland::XWayland;
|
||||
use smithay::xwayland::{XWayland, XWaylandEvent};
|
||||
|
||||
use crate::shell::init_shell;
|
||||
#[cfg(feature = "xwayland")]
|
||||
use crate::xwayland::XWm;
|
||||
|
||||
pub struct AnvilState<BackendData> {
|
||||
pub backend_data: BackendData,
|
||||
|
@ -48,9 +46,8 @@ pub struct AnvilState<BackendData> {
|
|||
pub start_time: std::time::Instant,
|
||||
#[cfg(feature = "egl")]
|
||||
pub egl_reader: Option<EGLBufferReader>,
|
||||
// things we must keep alive
|
||||
#[cfg(feature = "xwayland")]
|
||||
_xwayland: XWayland<XWm<BackendData>>,
|
||||
pub xwayland: XWayland<AnvilState<BackendData>>,
|
||||
}
|
||||
|
||||
impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
||||
|
@ -141,14 +138,19 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
|||
.expect("Failed to initialize the keyboard");
|
||||
|
||||
#[cfg(feature = "xwayland")]
|
||||
let _xwayland = {
|
||||
let xwm = XWm::new(
|
||||
handle.clone(),
|
||||
shell_handles.token,
|
||||
shell_handles.window_map.clone(),
|
||||
log.clone(),
|
||||
let xwayland = {
|
||||
let (xwayland, channel) = XWayland::new(handle.clone(), display.clone(), log.clone());
|
||||
let ret = handle.insert_source(channel, |event, _, anvil_state| match event {
|
||||
XWaylandEvent::Ready { connection, client } => anvil_state.xwayland_ready(connection, client),
|
||||
XWaylandEvent::Exited => anvil_state.xwayland_exited(),
|
||||
});
|
||||
if let Err(e) = ret {
|
||||
error!(
|
||||
log,
|
||||
"Failed to insert the XWaylandSource into the event loop: {}", e
|
||||
);
|
||||
XWayland::init(xwm, handle.clone(), display.clone(), &mut (), log.clone()).unwrap()
|
||||
}
|
||||
xwayland
|
||||
};
|
||||
|
||||
AnvilState {
|
||||
|
@ -170,7 +172,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
|||
egl_reader,
|
||||
start_time: std::time::Instant::now(),
|
||||
#[cfg(feature = "xwayland")]
|
||||
_xwayland,
|
||||
xwayland,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,6 +219,12 @@ pub fn run_udev(
|
|||
.map_err(|e| -> IoError { e.into() })
|
||||
.unwrap();
|
||||
|
||||
/*
|
||||
* Start XWayland if supported
|
||||
*/
|
||||
#[cfg(feature = "xwayland")]
|
||||
state.start_xwayland();
|
||||
|
||||
/*
|
||||
* And run our loop
|
||||
*/
|
||||
|
|
|
@ -98,6 +98,9 @@ pub fn run_winit(
|
|||
let start_time = std::time::Instant::now();
|
||||
let mut cursor_visible = true;
|
||||
|
||||
#[cfg(feature = "xwayland")]
|
||||
state.start_xwayland();
|
||||
|
||||
info!(log, "Initialization completed, starting the main loop.");
|
||||
|
||||
while state.running.load(Ordering::SeqCst) {
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
use std::{cell::RefCell, collections::HashMap, convert::TryFrom, os::unix::net::UnixStream, rc::Rc};
|
||||
|
||||
use smithay::{
|
||||
reexports::{
|
||||
calloop::LoopHandle,
|
||||
wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||
},
|
||||
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||
wayland::compositor::CompositorToken,
|
||||
xwayland::XWindowManager,
|
||||
};
|
||||
|
||||
use x11rb::{
|
||||
|
@ -33,35 +29,16 @@ use x11rb_event_source::X11Source;
|
|||
|
||||
mod x11rb_event_source;
|
||||
|
||||
/// Implementation of [`smithay::xwayland::XWindowManager`] that is used for starting XWayland.
|
||||
/// After XWayland was started, the actual state is kept in `X11State`.
|
||||
pub struct XWm<Backend> {
|
||||
handle: LoopHandle<'static, AnvilState<Backend>>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
}
|
||||
|
||||
impl<Backend> XWm<Backend> {
|
||||
pub fn new(
|
||||
handle: LoopHandle<'static, AnvilState<Backend>>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
) -> Self {
|
||||
Self {
|
||||
handle,
|
||||
token,
|
||||
window_map,
|
||||
log,
|
||||
impl<BackendData: 'static> AnvilState<BackendData> {
|
||||
pub fn start_xwayland(&mut self) {
|
||||
if let Err(e) = self.xwayland.start() {
|
||||
error!(self.log, "Failed to start XWayland: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Backend> XWindowManager for XWm<Backend> {
|
||||
fn xwayland_ready(&mut self, connection: UnixStream, client: Client) {
|
||||
pub fn xwayland_ready(&mut self, connection: UnixStream, client: Client) {
|
||||
let (wm, source) =
|
||||
X11State::start_wm(connection, self.token, self.window_map.clone(), self.log.clone()).unwrap();
|
||||
X11State::start_wm(connection, self.ctoken, self.window_map.clone(), self.log.clone()).unwrap();
|
||||
let wm = Rc::new(RefCell::new(wm));
|
||||
client.data_map().insert_if_missing(|| Rc::clone(&wm));
|
||||
self.handle
|
||||
|
@ -75,7 +52,9 @@ impl<Backend> XWindowManager for XWm<Backend> {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
fn xwayland_exited(&mut self) {}
|
||||
pub fn xwayland_exited(&mut self) {
|
||||
error!(self.log, "Xwayland crashed");
|
||||
}
|
||||
}
|
||||
|
||||
x11rb::atom_manager! {
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
//! The starting point is the [`XWayland`](struct.XWayland.html) struct, which represents the
|
||||
//! running `XWayland` instance. Dropping it will shutdown XWayland.
|
||||
//!
|
||||
//! You need to provide an implementation of the `XWindowManager` trait which gives you
|
||||
//! access to the X11 WM connection and the `Client` associated with XWayland. You'll need
|
||||
//! to treat XWayland (and all its X11 apps) as one special client, and play the role of
|
||||
//! an X11 Window Manager.
|
||||
//! You need to provide an implementation of a X11 Window Manager for XWayland to
|
||||
//! function properly. You'll need to treat XWayland (and all its X11 apps) as one
|
||||
//! special client, and play the role of an X11 Window Manager.
|
||||
//!
|
||||
//! Smithay does not provide any helper for doing that yet, but it is planned.
|
||||
|
||||
mod x11_sockets;
|
||||
mod xserver;
|
||||
|
||||
pub use self::xserver::{XWayland, XWindowManager};
|
||||
pub use self::xserver::{XWayland, XWaylandEvent};
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
use nix::{errno::Errno, sys::socket, Error as NixError, Result as NixResult};
|
||||
|
||||
/// Find a free X11 display slot and setup
|
||||
pub(crate) fn prepare_x11_sockets(log: ::slog::Logger) -> Result<(X11Lock, [UnixStream; 2]), ()> {
|
||||
pub(crate) fn prepare_x11_sockets(log: ::slog::Logger) -> Result<(X11Lock, [UnixStream; 2]), std::io::Error> {
|
||||
for d in 0..33 {
|
||||
// if fails, try the next one
|
||||
if let Ok(lock) = X11Lock::grab(d, log.clone()) {
|
||||
|
@ -18,7 +18,10 @@ pub(crate) fn prepare_x11_sockets(log: ::slog::Logger) -> Result<(X11Lock, [Unix
|
|||
}
|
||||
// If we reach here, all values from 0 to 32 failed
|
||||
// we need to stop trying at some point
|
||||
Err(())
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::AddrInUse,
|
||||
"Could not find a free socket for the XServer.",
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) struct X11Lock {
|
||||
|
|
|
@ -54,6 +54,7 @@ use std::{
|
|||
};
|
||||
|
||||
use calloop::{
|
||||
channel::{sync_channel, Channel, SyncSender},
|
||||
generic::{Fd, Generic},
|
||||
Interest, LoopHandle, Mode, RegistrationToken,
|
||||
};
|
||||
|
@ -65,69 +66,75 @@ use wayland_server::{Client, Display, Filter};
|
|||
use super::x11_sockets::{prepare_x11_sockets, X11Lock};
|
||||
|
||||
/// The XWayland handle
|
||||
pub struct XWayland<WM: XWindowManager> {
|
||||
inner: Rc<RefCell<Inner<WM>>>,
|
||||
pub struct XWayland<Data> {
|
||||
inner: Rc<RefCell<Inner<Data>>>,
|
||||
}
|
||||
|
||||
/// Trait to be implemented by you WM for XWayland
|
||||
/// Events generated by the XWayland manager
|
||||
///
|
||||
/// This is a very low-level trait, only notifying you
|
||||
/// when the connection with XWayland is up, or when
|
||||
/// it terminates.
|
||||
/// This is a very low-level interface, only notifying you when the connection
|
||||
/// with XWayland is up, or when it terminates.
|
||||
///
|
||||
/// You WM 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.
|
||||
pub trait XWindowManager {
|
||||
/// 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.
|
||||
pub enum XWaylandEvent {
|
||||
/// The XWayland server is ready
|
||||
///
|
||||
/// Your privileged connection to it is this `UnixStream`
|
||||
fn xwayland_ready(&mut self, connection: UnixStream, client: Client);
|
||||
/// The XWayland server has exited
|
||||
fn xwayland_exited(&mut self);
|
||||
Ready {
|
||||
/// Privileged X11 connection to XWayland
|
||||
connection: UnixStream,
|
||||
/// Wayland client representing XWayland
|
||||
client: Client,
|
||||
},
|
||||
/// The XWayland server exited
|
||||
Exited,
|
||||
}
|
||||
|
||||
impl<WM: XWindowManager + 'static> XWayland<WM> {
|
||||
/// Start the XWayland server
|
||||
pub fn init<L, T: Any, Data: 'static>(
|
||||
wm: WM,
|
||||
impl<Data: Any + 'static> XWayland<Data> {
|
||||
/// Create a new XWayland manager
|
||||
pub fn new<L>(
|
||||
handle: LoopHandle<'static, Data>,
|
||||
display: Rc<RefCell<Display>>,
|
||||
data: &mut T,
|
||||
logger: L,
|
||||
) -> Result<XWayland<WM>, ()>
|
||||
) -> (XWayland<Data>, XWaylandSource)
|
||||
where
|
||||
L: Into<Option<::slog::Logger>>,
|
||||
{
|
||||
let log = crate::slog_or_fallback(logger);
|
||||
// We don't expect to ever have more than 2 messages in flight, if XWayland got ready and then died right away
|
||||
let (sender, channel) = sync_channel(2);
|
||||
let inner = Rc::new(RefCell::new(Inner {
|
||||
wm,
|
||||
kill_source: {
|
||||
let handle = handle.clone();
|
||||
Box::new(move |source| handle.kill(source))
|
||||
},
|
||||
source_maker: Box::new(move |inner, fd| {
|
||||
handle
|
||||
.insert_source(
|
||||
Generic::new(Fd(fd), Interest::READ, Mode::Level),
|
||||
move |evt, _, _| {
|
||||
debug_assert!(evt.readable);
|
||||
xwayland_ready(&inner);
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.map_err(|_| ())
|
||||
}),
|
||||
handle,
|
||||
wayland_display: display,
|
||||
instance: None,
|
||||
sender,
|
||||
log: log.new(o!("smithay_module" => "XWayland")),
|
||||
}));
|
||||
launch(&inner, data)?;
|
||||
Ok(XWayland { inner })
|
||||
(XWayland { inner }, XWaylandSource { channel })
|
||||
}
|
||||
|
||||
/// Attempt to start the XWayland instance
|
||||
///
|
||||
/// If it succeeds, you'll eventually receive an `XWaylandEvent::Ready`
|
||||
/// through the source provided by `XWayland::new()` containing an
|
||||
/// `UnixStream` representing your WM connection to XWayland, and the
|
||||
/// wayland `Client` for XWayland.
|
||||
///
|
||||
/// Does nothing if XWayland is already started or starting.
|
||||
pub fn start(&self) -> std::io::Result<()> {
|
||||
launch(&self.inner)
|
||||
}
|
||||
|
||||
/// Shutdown XWayland
|
||||
///
|
||||
/// Does nothing if it was not already running, otherwise kills it and you will
|
||||
/// later receive a `XWaylandEvent::Exited` event.
|
||||
pub fn shutdown(&self) {
|
||||
self.inner.borrow_mut().shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
impl<WM: XWindowManager> Drop for XWayland<WM> {
|
||||
impl<Data> Drop for XWayland<Data> {
|
||||
fn drop(&mut self) {
|
||||
self.inner.borrow_mut().shutdown();
|
||||
}
|
||||
|
@ -135,32 +142,25 @@ impl<WM: XWindowManager> Drop for XWayland<WM> {
|
|||
|
||||
struct XWaylandInstance {
|
||||
display_lock: X11Lock,
|
||||
wayland_client: Client,
|
||||
wayland_client: Option<Client>,
|
||||
startup_handler: Option<RegistrationToken>,
|
||||
wm_fd: Option<UnixStream>,
|
||||
started_at: ::std::time::Instant,
|
||||
child_stdout: Option<ChildStdout>,
|
||||
}
|
||||
|
||||
type SourceMaker<WM> = dyn FnMut(Rc<RefCell<Inner<WM>>>, RawFd) -> Result<RegistrationToken, ()>;
|
||||
|
||||
// Inner implementation of the XWayland manager
|
||||
struct Inner<WM: XWindowManager> {
|
||||
wm: WM,
|
||||
source_maker: Box<SourceMaker<WM>>,
|
||||
struct Inner<Data> {
|
||||
sender: SyncSender<XWaylandEvent>,
|
||||
handle: LoopHandle<'static, Data>,
|
||||
wayland_display: Rc<RefCell<Display>>,
|
||||
instance: Option<XWaylandInstance>,
|
||||
kill_source: Box<dyn Fn(RegistrationToken)>,
|
||||
log: ::slog::Logger,
|
||||
}
|
||||
|
||||
// Launch an XWayland server
|
||||
//
|
||||
// Does nothing if there is already a launched instance
|
||||
fn launch<WM: XWindowManager + 'static, T: Any>(
|
||||
inner: &Rc<RefCell<Inner<WM>>>,
|
||||
data: &mut T,
|
||||
) -> Result<(), ()> {
|
||||
fn launch<Data: Any>(inner: &Rc<RefCell<Inner<Data>>>) -> std::io::Result<()> {
|
||||
let mut guard = inner.borrow_mut();
|
||||
if guard.instance.is_some() {
|
||||
return Ok(());
|
||||
|
@ -168,16 +168,20 @@ fn launch<WM: XWindowManager + 'static, T: Any>(
|
|||
|
||||
info!(guard.log, "Starting XWayland");
|
||||
|
||||
let (x_wm_x11, x_wm_me) = UnixStream::pair().map_err(|_| ())?;
|
||||
let (wl_x11, wl_me) = UnixStream::pair().map_err(|_| ())?;
|
||||
let (x_wm_x11, x_wm_me) = UnixStream::pair()?;
|
||||
let (wl_x11, wl_me) = UnixStream::pair()?;
|
||||
|
||||
let (lock, x_fds) = prepare_x11_sockets(guard.log.clone())?;
|
||||
|
||||
// we have now created all the required sockets
|
||||
|
||||
// record launch time
|
||||
let creation_time = ::std::time::Instant::now();
|
||||
|
||||
// Setup the associated wayland client to be created in an idle callback, so that we don't need
|
||||
// to access the dispatch_data *right now*
|
||||
let idle_inner = inner.clone();
|
||||
guard.handle.insert_idle(move |data| {
|
||||
let mut guard = idle_inner.borrow_mut();
|
||||
let guard = &mut *guard;
|
||||
if let Some(ref mut instance) = guard.instance {
|
||||
// create the wayland client for XWayland
|
||||
let client = unsafe {
|
||||
guard
|
||||
|
@ -185,47 +189,98 @@ fn launch<WM: XWindowManager + 'static, T: Any>(
|
|||
.borrow_mut()
|
||||
.create_client(wl_me.into_raw_fd(), data)
|
||||
};
|
||||
client.data_map().insert_if_missing(|| inner.clone());
|
||||
client.add_destructor(Filter::new(|e: Arc<_>, _, mut data| {
|
||||
client_destroy::<WM, T>(&e, data.get().unwrap())
|
||||
}));
|
||||
client.data_map().insert_if_missing(|| idle_inner.clone());
|
||||
client.add_destructor(Filter::new(|e: Arc<_>, _, _| client_destroy::<Data>(&e)));
|
||||
|
||||
instance.wayland_client = Some(client.clone());
|
||||
}
|
||||
});
|
||||
|
||||
// all is ready, we can do the fork dance
|
||||
let child_stdout = match spawn_xwayland(lock.display(), wl_x11, x_wm_x11, &x_fds) {
|
||||
Ok(child_stdout) => child_stdout,
|
||||
Err(e) => {
|
||||
error!(guard.log, "XWayland failed to spawn"; "err" => format!("{:?}", e));
|
||||
return Err(());
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
let startup_handler = (&mut *guard.source_maker)(inner.clone(), child_stdout.as_raw_fd())?;
|
||||
let inner = inner.clone();
|
||||
let startup_handler = 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(())
|
||||
},
|
||||
)?;
|
||||
|
||||
guard.instance = Some(XWaylandInstance {
|
||||
display_lock: lock,
|
||||
wayland_client: client,
|
||||
startup_handler: Some(startup_handler),
|
||||
wayland_client: None,
|
||||
wm_fd: Some(x_wm_me),
|
||||
started_at: creation_time,
|
||||
child_stdout: Some(child_stdout),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<WM: XWindowManager> Inner<WM> {
|
||||
pub struct XWaylandSource {
|
||||
channel: Channel<XWaylandEvent>,
|
||||
}
|
||||
|
||||
impl calloop::EventSource for XWaylandSource {
|
||||
type Event = XWaylandEvent;
|
||||
type Metadata = ();
|
||||
type Ret = ();
|
||||
|
||||
fn process_events<F>(
|
||||
&mut self,
|
||||
readiness: calloop::Readiness,
|
||||
token: calloop::Token,
|
||||
mut callback: F,
|
||||
) -> std::io::Result<()>
|
||||
where
|
||||
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
||||
{
|
||||
self.channel
|
||||
.process_events(readiness, token, |event, &mut ()| match event {
|
||||
calloop::channel::Event::Msg(msg) => callback(msg, &mut ()),
|
||||
calloop::channel::Event::Closed => {}
|
||||
})
|
||||
}
|
||||
|
||||
fn register(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> {
|
||||
self.channel.register(poll, token)
|
||||
}
|
||||
|
||||
fn reregister(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> {
|
||||
self.channel.reregister(poll, token)
|
||||
}
|
||||
|
||||
fn unregister(&mut self, poll: &mut calloop::Poll) -> std::io::Result<()> {
|
||||
self.channel.unregister(poll)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Data> Inner<Data> {
|
||||
// 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() {
|
||||
info!(self.log, "Shutting down XWayland.");
|
||||
self.wm.xwayland_exited();
|
||||
// kill the client
|
||||
instance.wayland_client.kill();
|
||||
if let Some(client) = instance.wayland_client {
|
||||
client.kill();
|
||||
}
|
||||
// remove the event source
|
||||
if let Some(s) = instance.startup_handler.take() {
|
||||
(self.kill_source)(s);
|
||||
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);
|
||||
|
||||
// All connections and lockfiles are cleaned by their destructors
|
||||
|
||||
// Remove DISPLAY from the env
|
||||
|
@ -238,32 +293,17 @@ impl<WM: XWindowManager> Inner<WM> {
|
|||
}
|
||||
}
|
||||
|
||||
fn client_destroy<WM: XWindowManager + 'static, T: Any>(map: &::wayland_server::UserDataMap, data: &mut T) {
|
||||
let inner = map.get::<Rc<RefCell<Inner<WM>>>>().unwrap();
|
||||
|
||||
// shutdown the server
|
||||
let started_at = inner.borrow().instance.as_ref().map(|i| i.started_at);
|
||||
fn client_destroy<Data: 'static>(map: &::wayland_server::UserDataMap) {
|
||||
let inner = map.get::<Rc<RefCell<Inner<Data>>>>().unwrap();
|
||||
inner.borrow_mut().shutdown();
|
||||
|
||||
// restart it, unless we really just started it, if it crashes right
|
||||
// at startup there is no point
|
||||
if started_at.map(|t| t.elapsed().as_secs()).unwrap_or(10) > 5 {
|
||||
warn!(inner.borrow().log, "XWayland crashed, restarting.");
|
||||
let _ = launch(&inner, data);
|
||||
} else {
|
||||
warn!(
|
||||
inner.borrow().log,
|
||||
"XWayland crashed less than 5 seconds after its startup, not restarting."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
|
||||
fn xwayland_ready<Data: 'static>(inner: &Rc<RefCell<Inner<Data>>>) {
|
||||
// Lots of re-borrowing to please the borrow-checker
|
||||
let mut guard = inner.borrow_mut();
|
||||
let inner = &mut *guard;
|
||||
let guard = &mut *guard;
|
||||
// instance should never be None at this point
|
||||
let instance = inner.instance.as_mut().unwrap();
|
||||
let wm = &mut inner.wm;
|
||||
let instance = guard.instance.as_mut().unwrap();
|
||||
// neither the child_stdout
|
||||
let child_stdout = instance.child_stdout.as_mut().unwrap();
|
||||
|
||||
|
@ -272,7 +312,7 @@ fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
|
|||
let success = match child_stdout.read(&mut buffer) {
|
||||
Ok(len) => len > 0 && buffer[0] == b'S',
|
||||
Err(e) => {
|
||||
error!(inner.log, "Checking launch status failed"; "err" => format!("{:?}", e));
|
||||
error!(guard.log, "Checking launch status failed"; "err" => format!("{:?}", e));
|
||||
false
|
||||
}
|
||||
};
|
||||
|
@ -282,21 +322,22 @@ fn xwayland_ready<WM: XWindowManager>(inner: &Rc<RefCell<Inner<WM>>>) {
|
|||
::std::env::set_var("DISPLAY", format!(":{}", instance.display_lock.display()));
|
||||
|
||||
// signal the WM
|
||||
info!(inner.log, "XWayland is ready, signaling the WM.");
|
||||
wm.xwayland_ready(
|
||||
instance.wm_fd.take().unwrap(), // This is a bug if None
|
||||
instance.wayland_client.clone(),
|
||||
);
|
||||
info!(guard.log, "XWayland is ready, signaling the WM.");
|
||||
// send error occurs if the user dropped the channel... We cannot do much except ignore.
|
||||
let _ = guard.sender.send(XWaylandEvent::Ready {
|
||||
connection: instance.wm_fd.take().unwrap(), // This is a bug if None
|
||||
client: instance.wayland_client.clone().unwrap(),
|
||||
});
|
||||
} else {
|
||||
error!(
|
||||
inner.log,
|
||||
guard.log,
|
||||
"XWayland crashed at startup, will not try to restart it."
|
||||
);
|
||||
}
|
||||
|
||||
// in all cases, cleanup
|
||||
if let Some(s) = instance.startup_handler.take() {
|
||||
(inner.kill_source)(s);
|
||||
guard.handle.kill(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue