feat(xwayland): serialize start

This commit is contained in:
Nova
2023-05-24 05:35:09 -04:00
parent 1cb8e1b7a4
commit e3b1276d77
4 changed files with 138 additions and 12 deletions

View File

@@ -6,6 +6,7 @@ use smithay::{
delegate_compositor, delegate_compositor,
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client}, reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
wayland::compositor::{self, CompositorClientState, CompositorHandler, CompositorState}, wayland::compositor::{self, CompositorClientState, CompositorHandler, CompositorState},
xwayland::XWaylandClientData,
}; };
use std::sync::Arc; use std::sync::Arc;
use tracing::debug; use tracing::debug;
@@ -38,7 +39,13 @@ impl CompositorHandler for WaylandState {
} }
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState { fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
&client.get_data::<ClientState>().unwrap().compositor_state if let Some(client_state) = client.get_data::<ClientState>() {
&client_state.compositor_state
} else if let Some(xwayland_client_data) = client.get_data::<XWaylandClientData>() {
&xwayland_client_data.compositor_state
} else {
unimplemented!()
}
} }
} }

View File

@@ -88,7 +88,7 @@ impl Wayland {
let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel(); let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel();
let display = Arc::new(Mutex::new(display)); let display = Arc::new(Mutex::new(display));
let xwayland_state = XWaylandState::create(&display_handle).unwrap(); let xwayland_state = XWaylandState::create(display.clone(), &display_handle).unwrap();
let wayland_state = WaylandState::new(display.clone(), display_handle, &renderer, dmabuf_tx); let wayland_state = WaylandState::new(display.clone(), display_handle, &renderer, dmabuf_tx);
let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8); let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8);

View File

@@ -41,6 +41,7 @@ use smithay::{
}, },
}, },
wayland::compositor, wayland::compositor,
xwayland::X11Surface,
}; };
use stardust_xr::schemas::flex::{deserialize, serialize}; use stardust_xr::schemas::flex::{deserialize, serialize};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
@@ -316,7 +317,10 @@ impl WaylandBackend {
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct X11Backend; pub struct X11Backend {
pub toplevel_parent: Option<X11Surface>,
pub toplevel: X11Surface,
}
#[derive(Debug)] #[derive(Debug)]
pub enum Backend { pub enum Backend {
@@ -719,7 +723,24 @@ impl ItemSpecialization for PanelItem {
)) ))
.unwrap() .unwrap()
} }
Backend::X11(_) => todo!(), Backend::X11(x) => {
let toplevel_state = (
None::<String>,
x.toplevel.title(),
None::<String>,
(x.toplevel.geometry().size.w, x.toplevel.geometry().size.h),
x.toplevel.min_size().map(|s| (s.w, s.h)),
x.toplevel.max_size().map(|s| (s.w, s.w)),
);
let info = (
None::<String>,
toplevel_state,
Vec::<PopupData>::new(),
None::<SurfaceID>,
None::<SurfaceID>,
);
serialize((id, info)).unwrap()
}
} }
} }
} }

View File

@@ -1,13 +1,20 @@
use super::seat::SeatData; use super::{panel_item::RecommendedState, seat::SeatData, state::WaylandState};
use crate::wayland::{
panel_item::{Backend, PanelItem, X11Backend},
surface::CoreSurface,
};
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use smithay::{ use smithay::{
reexports::{ reexports::{
calloop::{self, EventLoop, LoopSignal}, calloop::{self, EventLoop, LoopSignal},
wayland_server::DisplayHandle, wayland_protocols::xdg::shell::server::xdg_toplevel,
wayland_server::{Display, DisplayHandle, Resource, WEnum},
x11rb::protocol::xproto::Window, x11rb::protocol::xproto::Window,
}, },
utils::{Logical, Rectangle}, utils::{Logical, Rectangle},
wayland::compositor,
xwayland::{ xwayland::{
xwm::{Reorder, ResizeEdge, XwmId}, xwm::{Reorder, ResizeEdge, XwmId},
X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler, X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler,
@@ -26,7 +33,10 @@ pub struct XWaylandState {
event_loop_join: Option<JoinHandle<Result<(), calloop::Error>>>, event_loop_join: Option<JoinHandle<Result<(), calloop::Error>>>,
} }
impl XWaylandState { impl XWaylandState {
pub fn create(dh: &DisplayHandle) -> Result<Self> { pub fn create(
wayland_display: Arc<Mutex<Display<WaylandState>>>,
dh: &DisplayHandle,
) -> Result<Self> {
let dh = dh.clone(); let dh = dh.clone();
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
@@ -57,7 +67,7 @@ impl XWaylandState {
None, None,
empty::<(&OsStr, &OsStr)>(), empty::<(&OsStr, &OsStr)>(),
true, true,
move |_| (), |_| (),
)?; )?;
let _ = tx.send(XWaylandState { let _ = tx.send(XWaylandState {
display, display,
@@ -65,7 +75,13 @@ impl XWaylandState {
event_loop_signal: event_loop.get_signal(), event_loop_signal: event_loop.get_signal(),
event_loop_join: None, event_loop_join: None,
}); });
let mut handler = XWaylandHandler::default(); let wayland_display_handle = wayland_display.lock().handle();
let mut handler = XWaylandHandler {
wayland_display,
wayland_display_handle,
wm: None,
seat: None,
};
event_loop.run(Duration::from_secs(60 * 60), &mut handler, |_| ()) event_loop.run(Duration::from_secs(60 * 60), &mut handler, |_| ())
}); });
@@ -83,11 +99,19 @@ impl Drop for XWaylandState {
} }
} }
#[derive(Default)]
struct XWaylandHandler { struct XWaylandHandler {
wayland_display: Arc<Mutex<Display<WaylandState>>>,
wayland_display_handle: DisplayHandle,
wm: Option<X11Wm>, wm: Option<X11Wm>,
seat: Option<Arc<SeatData>>, seat: Option<Arc<SeatData>>,
} }
impl XWaylandHandler {
fn panel_item(&self, window: &X11Surface) -> Option<Arc<PanelItem>> {
compositor::with_states(&window.wl_surface()?, |s| {
s.data_map.get::<Arc<PanelItem>>().cloned()
})
}
}
impl XwmHandler for XWaylandHandler { impl XwmHandler for XWaylandHandler {
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm { fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
@@ -104,6 +128,44 @@ impl XwmHandler for XWaylandHandler {
fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) { fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map window request"); debug!(?window, "X map window request");
window.set_mapped(true).unwrap();
}
fn map_window_notify(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map window notify");
let dh = self.wayland_display_handle.clone();
let seat = self.seat.clone().unwrap();
CoreSurface::add_to(
&self.wayland_display,
self.wayland_display.lock().handle(),
&window.wl_surface().unwrap(),
move |c| {
let Some(wl_surface) = window.wl_surface() else {return};
match c {
0 => {
let seat = seat.clone();
window.user_data().insert_if_missing_threadsafe(|| {
let (_node, panel_item) = PanelItem::create(
wl_surface.clone(),
Backend::X11(X11Backend {
toplevel_parent: None,
toplevel: window.clone(),
}),
wl_surface
.client()
.and_then(|c| c.get_credentials(&dh).ok()),
seat,
);
panel_item
});
}
_ => {
let Some(panel_item) = window.user_data().get::<Arc<PanelItem>>() else {return};
panel_item.commit_toplevel();
}
}
},
);
} }
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) { fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
@@ -141,6 +203,11 @@ impl XwmHandler for XWaylandHandler {
debug!(?window, ?geometry, above, "Configure X window"); debug!(?window, ?geometry, above, "Configure X window");
} }
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, button: u32) {
let Some(panel_item) = self.panel_item(&window) else {return};
debug!(?window, button, "X window requests move");
panel_item.recommend_toplevel_state(RecommendedState::Move);
}
fn resize_request( fn resize_request(
&mut self, &mut self,
_xwm: XwmId, _xwm: XwmId,
@@ -148,10 +215,41 @@ impl XwmHandler for XWaylandHandler {
button: u32, button: u32,
resize_edge: ResizeEdge, resize_edge: ResizeEdge,
) { ) {
let Some(panel_item) = self.panel_item(&window) else {return};
debug!(?window, button, ?resize_edge, "X window requests resize"); debug!(?window, button, ?resize_edge, "X window requests resize");
panel_item.recommend_toplevel_state(RecommendedState::Resize(
WEnum::Value(match resize_edge {
ResizeEdge::Top => xdg_toplevel::ResizeEdge::Top,
ResizeEdge::Bottom => xdg_toplevel::ResizeEdge::Bottom,
ResizeEdge::Left => xdg_toplevel::ResizeEdge::Left,
ResizeEdge::TopLeft => xdg_toplevel::ResizeEdge::TopLeft,
ResizeEdge::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft,
ResizeEdge::Right => xdg_toplevel::ResizeEdge::Right,
ResizeEdge::TopRight => xdg_toplevel::ResizeEdge::TopRight,
ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight,
})
.into(),
));
} }
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, button: u32) { fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, button, "X window requests move"); let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Maximize(true));
}
fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Maximize(false));
}
fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true));
}
fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true));
}
fn minimize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Minimize);
} }
} }