feat(xwayland): first x window

This commit is contained in:
Nova
2023-07-19 07:53:52 -07:00
committed by Nova
parent e3b1276d77
commit 000b633767
4 changed files with 88 additions and 66 deletions

View File

@@ -89,7 +89,8 @@ 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.clone(), &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);
GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap(); GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap();

View File

@@ -40,8 +40,9 @@ use smithay::{
backend::Credentials, protocol::wl_surface::WlSurface, Resource, Weak as WlWeak, backend::Credentials, protocol::wl_surface::WlSurface, Resource, Weak as WlWeak,
}, },
}, },
utils::Rectangle,
wayland::compositor, wayland::compositor,
xwayland::X11Surface, xwayland::{xwm::X11SurfaceError, 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};
@@ -224,7 +225,7 @@ impl WaylandBackend {
states states
.into_iter() .into_iter()
.flat_map(|state| state.to_ne_bytes()) .flat_map(|state| state.to_ne_bytes())
.collect::<Vec<_>>(), .collect(),
); );
xdg_surface.configure(SERIAL_COUNTER.inc()); xdg_surface.configure(SERIAL_COUNTER.inc());
} }
@@ -321,6 +322,42 @@ pub struct X11Backend {
pub toplevel_parent: Option<X11Surface>, pub toplevel_parent: Option<X11Surface>,
pub toplevel: X11Surface, pub toplevel: X11Surface,
} }
impl X11Backend {
fn configure_toplevel(
&self,
size: Option<Vector2<u32>>,
states: Vec<u32>,
) -> Result<(), X11SurfaceError> {
self.toplevel.configure(
size.map(|s| Rectangle::from_loc_and_size((0, 0), (s.x as i32, s.y as i32))),
)?;
self.toplevel.set_maximized(states.contains(&1))?;
Ok(())
}
fn serialize_toplevel(&self) -> Result<Vec<u8>> {
let toplevel_state = (
None::<String>,
self.toplevel.title(),
None::<String>,
(
self.toplevel.geometry().size.w,
self.toplevel.geometry().size.h,
),
self.toplevel.min_size().map(|s| (s.w, s.h)),
self.toplevel.max_size().map(|s| (s.w, s.w)),
);
let data = serialize(&toplevel_state)?;
Ok(data)
}
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
match id {
SurfaceID::Cursor => None,
SurfaceID::Toplevel => self.toplevel.wl_surface(),
SurfaceID::Popup(_) => None,
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum Backend { pub enum Backend {
@@ -350,12 +387,9 @@ impl PanelItem {
.and_then(|env| startup_settings(&env)); .and_then(|env| startup_settings(&env));
let uid = nanoid!(); let uid = nanoid!();
let node = Arc::new(Node::create( let node = Node::create(&INTERNAL_CLIENT, "/item/panel/item", &uid, true)
&INTERNAL_CLIENT, .add_to_scenegraph()
"/item/panel/item", .unwrap();
&uid,
true,
));
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap(); let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
let panel_item = Arc::new(PanelItem { let panel_item = Arc::new(PanelItem {
uid: uid.clone(), uid: uid.clone(),
@@ -426,7 +460,7 @@ impl PanelItem {
fn toplevel_wl_surface(&self) -> WlSurface { fn toplevel_wl_surface(&self) -> WlSurface {
match &self.backend { match &self.backend {
Backend::Wayland(w) => w.toplevel_wl_surface(), Backend::Wayland(w) => w.toplevel_wl_surface(),
Backend::X11(_) => todo!(), Backend::X11(x) => x.toplevel.wl_surface().unwrap(),
} }
} }
fn core_surface(&self) -> Option<Arc<CoreSurface>> { fn core_surface(&self) -> Option<Arc<CoreSurface>> {
@@ -442,7 +476,7 @@ impl PanelItem {
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> { fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
match &self.backend { match &self.backend {
Backend::Wayland(w) => w.wl_surface_from_id(id), Backend::Wayland(w) => w.wl_surface_from_id(id),
Backend::X11(_) => todo!(), Backend::X11(x) => x.wl_surface_from_id(id),
} }
} }
fn wl_surface_from_id_result(&self, id: &SurfaceID) -> Result<WlSurface> { fn wl_surface_from_id_result(&self, id: &SurfaceID) -> Result<WlSurface> {
@@ -582,7 +616,7 @@ impl PanelItem {
keymap, keymap,
match &panel_item.backend { match &panel_item.backend {
Backend::Wayland(w) => w.input_surfaces(), Backend::Wayland(w) => w.input_surfaces(),
Backend::X11(_) => todo!(), Backend::X11(_) => vec![panel_item.toplevel_wl_surface()],
}, },
); );
@@ -608,7 +642,6 @@ impl PanelItem {
data: &[u8], data: &[u8],
) -> Result<()> { ) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct ConfigureToplevelInfo { struct ConfigureToplevelInfo {
@@ -620,28 +653,8 @@ impl PanelItem {
match &panel_item.backend { match &panel_item.backend {
Backend::Wayland(w) => w.configure_toplevel(info.size, info.states, info.bounds), Backend::Wayland(w) => w.configure_toplevel(info.size, info.states, info.bounds),
Backend::X11(_) => todo!(), Backend::X11(x) => x.configure_toplevel(info.size, info.states)?,
} }
let zero_size = Vector2::from([0; 2]);
let size = info.size.unwrap_or(zero_size);
// if size == zero_size && (info.states.contains(1) || info.states.contains(2)) {
// xdg_toplevel.configure(
// size.x as i32,
// size.y as i32,
// info.states
// .into_iter()
// .flat_map(|state| state.to_ne_bytes())
// .collect(),
// );
// }
xdg_toplevel.configure(
size.x as i32,
size.y as i32,
info.states.into_iter().flat_map(u32::to_ne_bytes).collect(),
);
xdg_surface.configure(SERIAL_COUNTER.inc());
core_surface.flush_clients();
Ok(()) Ok(())
} }
@@ -674,7 +687,7 @@ impl PanelItem {
let Some(node) = self.node.upgrade() else { return }; let Some(node) = self.node.upgrade() else { return };
let Ok(data) = (match &self.backend { let Ok(data) = (match &self.backend {
Backend::Wayland(w) => w.serialize_toplevel(), Backend::Wayland(w) => w.serialize_toplevel(),
Backend::X11(_) => todo!(), Backend::X11(x) => x.serialize_toplevel(),
}) else {return}; }) else {return};
let _ = node.send_remote_signal("commit_toplevel", &data); let _ = node.send_remote_signal("commit_toplevel", &data);
} }
@@ -724,16 +737,25 @@ impl ItemSpecialization for PanelItem {
.unwrap() .unwrap()
} }
Backend::X11(x) => { Backend::X11(x) => {
let size = (
x.toplevel.geometry().size.w as u32,
x.toplevel.geometry().size.h as u32,
);
let toplevel_state = ( let toplevel_state = (
None::<String>, None::<String>,
x.toplevel.title(), x.toplevel.title(),
None::<String>, None::<String>,
(x.toplevel.geometry().size.w, x.toplevel.geometry().size.h), (
x.toplevel.min_size().map(|s| (s.w, s.h)), x.toplevel.geometry().size.w as u32,
x.toplevel.max_size().map(|s| (s.w, s.w)), x.toplevel.geometry().size.h as u32,
),
x.toplevel.min_size().map(|s| (s.w as u32, s.h as u32)),
x.toplevel.max_size().map(|s| (s.w as u32, s.w as u32)),
((0_i32, 0_i32), size),
vec![0_u32; 0],
); );
let info = ( let info = (
None::<String>, None::<(Vector2<u32>, Vector2<i32>)>,
toplevel_state, toplevel_state,
Vec::<PopupData>::new(), Vec::<PopupData>::new(),
None::<SurfaceID>, None::<SurfaceID>,

View File

@@ -288,10 +288,9 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
let wl_surface = xdg_surface_data.lock().wl_surface(); let wl_surface = xdg_surface_data.lock().wl_surface();
xdg_surface_data.lock().surface_id = SurfaceID::Toplevel; xdg_surface_data.lock().surface_id = SurfaceID::Toplevel;
let toplevel = toplevel_weak.upgrade().unwrap();
let (node, panel_item) = PanelItem::create( let (node, panel_item) = PanelItem::create(
wl_surface.clone(), wl_surface.clone(),
Backend::Wayland(WaylandBackend::create(toplevel)), Backend::Wayland(WaylandBackend::create(toplevel.clone())),
client_credentials, client_credentials,
seat_data.clone(), seat_data.clone(),
); );
@@ -372,7 +371,8 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
let popup_data = PopupData::get(&xdg_popup); let popup_data = PopupData::get(&xdg_popup);
let popup_data = popup_data.lock(); let popup_data = popup_data.lock();
// panel_item.commit_popup(popup_data); // panel_item.commit_popup(popup_data);
panel_item.new_popup(&xdg_popup, &*popup_data); let Backend::Wayland(wayland_backend) = &panel_item.backend else {return};
wayland_backend.new_popup(&panel_item, &xdg_popup, &*popup_data);
}, },
move |commit_count| { move |commit_count| {
if commit_count == 0 { if commit_count == 0 {

View File

@@ -139,32 +139,31 @@ impl XwmHandler for XWaylandHandler {
&self.wayland_display, &self.wayland_display,
self.wayland_display.lock().handle(), self.wayland_display.lock().handle(),
&window.wl_surface().unwrap(), &window.wl_surface().unwrap(),
move |c| { {
let Some(wl_surface) = window.wl_surface() else {return}; let window = window.clone();
match c { move || {
0 => { let Some(wl_surface) = window.wl_surface() else {return};
let seat = seat.clone(); let seat = seat.clone();
window.user_data().insert_if_missing_threadsafe(|| { window.user_data().insert_if_missing_threadsafe(|| {
let (_node, panel_item) = PanelItem::create( let (_node, panel_item) = PanelItem::create(
wl_surface.clone(), wl_surface.clone(),
Backend::X11(X11Backend { Backend::X11(X11Backend {
toplevel_parent: None, toplevel_parent: None,
toplevel: window.clone(), toplevel: window.clone(),
}), }),
wl_surface wl_surface
.client() .client()
.and_then(|c| c.get_credentials(&dh).ok()), .and_then(|c| c.get_credentials(&dh).ok()),
seat, seat,
); );
panel_item panel_item
}); });
}
_ => {
let Some(panel_item) = window.user_data().get::<Arc<PanelItem>>() else {return};
panel_item.commit_toplevel();
}
} }
}, },
move |_| {
let Some(panel_item) = window.user_data().get::<Arc<PanelItem>>() else {return};
panel_item.commit_toplevel();
},
); );
} }