feat(xwayland): serialize start
This commit is contained in:
@@ -6,6 +6,7 @@ use smithay::{
|
||||
delegate_compositor,
|
||||
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||
wayland::compositor::{self, CompositorClientState, CompositorHandler, CompositorState},
|
||||
xwayland::XWaylandClientData,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
@@ -38,7 +39,13 @@ impl CompositorHandler for WaylandState {
|
||||
}
|
||||
|
||||
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!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ impl Wayland {
|
||||
|
||||
let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel();
|
||||
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 (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8);
|
||||
|
||||
@@ -41,6 +41,7 @@ use smithay::{
|
||||
},
|
||||
},
|
||||
wayland::compositor,
|
||||
xwayland::X11Surface,
|
||||
};
|
||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
||||
use std::sync::{Arc, Weak};
|
||||
@@ -316,7 +317,10 @@ impl WaylandBackend {
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct X11Backend;
|
||||
pub struct X11Backend {
|
||||
pub toplevel_parent: Option<X11Surface>,
|
||||
pub toplevel: X11Surface,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Backend {
|
||||
@@ -719,7 +723,24 @@ impl ItemSpecialization for PanelItem {
|
||||
))
|
||||
.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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use smithay::{
|
||||
reexports::{
|
||||
calloop::{self, EventLoop, LoopSignal},
|
||||
wayland_server::DisplayHandle,
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||
wayland_server::{Display, DisplayHandle, Resource, WEnum},
|
||||
x11rb::protocol::xproto::Window,
|
||||
},
|
||||
utils::{Logical, Rectangle},
|
||||
wayland::compositor,
|
||||
xwayland::{
|
||||
xwm::{Reorder, ResizeEdge, XwmId},
|
||||
X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler,
|
||||
@@ -26,7 +33,10 @@ pub struct XWaylandState {
|
||||
event_loop_join: Option<JoinHandle<Result<(), calloop::Error>>>,
|
||||
}
|
||||
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 (tx, rx) = oneshot::channel();
|
||||
@@ -57,7 +67,7 @@ impl XWaylandState {
|
||||
None,
|
||||
empty::<(&OsStr, &OsStr)>(),
|
||||
true,
|
||||
move |_| (),
|
||||
|_| (),
|
||||
)?;
|
||||
let _ = tx.send(XWaylandState {
|
||||
display,
|
||||
@@ -65,7 +75,13 @@ impl XWaylandState {
|
||||
event_loop_signal: event_loop.get_signal(),
|
||||
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, |_| ())
|
||||
});
|
||||
|
||||
@@ -83,11 +99,19 @@ impl Drop for XWaylandState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct XWaylandHandler {
|
||||
wayland_display: Arc<Mutex<Display<WaylandState>>>,
|
||||
wayland_display_handle: DisplayHandle,
|
||||
wm: Option<X11Wm>,
|
||||
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 {
|
||||
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) {
|
||||
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) {
|
||||
@@ -141,6 +203,11 @@ impl XwmHandler for XWaylandHandler {
|
||||
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(
|
||||
&mut self,
|
||||
_xwm: XwmId,
|
||||
@@ -148,10 +215,41 @@ impl XwmHandler for XWaylandHandler {
|
||||
button: u32,
|
||||
resize_edge: ResizeEdge,
|
||||
) {
|
||||
let Some(panel_item) = self.panel_item(&window) else {return};
|
||||
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) {
|
||||
debug!(?window, button, "X window requests move");
|
||||
fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user