From 8ad5fc65842ba62a733440a366115b227b72041c Mon Sep 17 00:00:00 2001 From: Nova Date: Wed, 19 Jul 2023 07:53:52 -0700 Subject: [PATCH] feat(xwayland): first x window --- src/wayland/mod.rs | 3 +- src/wayland/panel_item.rs | 98 ++++++++++++++++++++++++--------------- src/wayland/xdg_shell.rs | 6 +-- src/wayland/xwayland.rs | 47 +++++++++---------- 4 files changed, 88 insertions(+), 66 deletions(-) diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 827608d..9b5de21 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -89,7 +89,8 @@ impl Wayland { let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel(); let display = Arc::new(Mutex::new(display)); 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); GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap(); diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index 75ccfc3..2616d1d 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -40,8 +40,9 @@ use smithay::{ backend::Credentials, protocol::wl_surface::WlSurface, Resource, Weak as WlWeak, }, }, + utils::Rectangle, wayland::compositor, - xwayland::X11Surface, + xwayland::{xwm::X11SurfaceError, X11Surface}, }; use stardust_xr::schemas::flex::{deserialize, serialize}; use std::sync::{Arc, Weak}; @@ -224,7 +225,7 @@ impl WaylandBackend { states .into_iter() .flat_map(|state| state.to_ne_bytes()) - .collect::>(), + .collect(), ); xdg_surface.configure(SERIAL_COUNTER.inc()); } @@ -321,6 +322,42 @@ pub struct X11Backend { pub toplevel_parent: Option, pub toplevel: X11Surface, } +impl X11Backend { + fn configure_toplevel( + &self, + size: Option>, + states: Vec, + ) -> 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> { + let toplevel_state = ( + None::, + self.toplevel.title(), + None::, + ( + 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 { + match id { + SurfaceID::Cursor => None, + SurfaceID::Toplevel => self.toplevel.wl_surface(), + SurfaceID::Popup(_) => None, + } + } +} #[derive(Debug)] pub enum Backend { @@ -350,12 +387,9 @@ impl PanelItem { .and_then(|env| startup_settings(&env)); let uid = nanoid!(); - let node = Arc::new(Node::create( - &INTERNAL_CLIENT, - "/item/panel/item", - &uid, - true, - )); + let node = Node::create(&INTERNAL_CLIENT, "/item/panel/item", &uid, true) + .add_to_scenegraph() + .unwrap(); let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap(); let panel_item = Arc::new(PanelItem { uid: uid.clone(), @@ -426,7 +460,7 @@ impl PanelItem { fn toplevel_wl_surface(&self) -> WlSurface { match &self.backend { Backend::Wayland(w) => w.toplevel_wl_surface(), - Backend::X11(_) => todo!(), + Backend::X11(x) => x.toplevel.wl_surface().unwrap(), } } fn core_surface(&self) -> Option> { @@ -442,7 +476,7 @@ impl PanelItem { fn wl_surface_from_id(&self, id: &SurfaceID) -> Option { match &self.backend { 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 { @@ -582,7 +616,7 @@ impl PanelItem { keymap, match &panel_item.backend { 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], ) -> Result<()> { 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)] struct ConfigureToplevelInfo { @@ -620,28 +653,8 @@ impl PanelItem { match &panel_item.backend { 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(()) } @@ -674,7 +687,7 @@ impl PanelItem { let Some(node) = self.node.upgrade() else { return }; let Ok(data) = (match &self.backend { Backend::Wayland(w) => w.serialize_toplevel(), - Backend::X11(_) => todo!(), + Backend::X11(x) => x.serialize_toplevel(), }) else {return}; let _ = node.send_remote_signal("commit_toplevel", &data); } @@ -724,16 +737,25 @@ impl ItemSpecialization for PanelItem { .unwrap() } Backend::X11(x) => { + let size = ( + x.toplevel.geometry().size.w as u32, + x.toplevel.geometry().size.h as u32, + ); let toplevel_state = ( None::, x.toplevel.title(), None::, - (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)), + ( + x.toplevel.geometry().size.w as u32, + 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 = ( - None::, + None::<(Vector2, Vector2)>, toplevel_state, Vec::::new(), None::, diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 6c364f0..67956bc 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -288,10 +288,9 @@ impl Dispatch, WaylandState> for WaylandState let wl_surface = xdg_surface_data.lock().wl_surface(); xdg_surface_data.lock().surface_id = SurfaceID::Toplevel; - let toplevel = toplevel_weak.upgrade().unwrap(); let (node, panel_item) = PanelItem::create( wl_surface.clone(), - Backend::Wayland(WaylandBackend::create(toplevel)), + Backend::Wayland(WaylandBackend::create(toplevel.clone())), client_credentials, seat_data.clone(), ); @@ -372,7 +371,8 @@ impl Dispatch, WaylandState> for WaylandState let popup_data = PopupData::get(&xdg_popup); let popup_data = popup_data.lock(); // 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| { if commit_count == 0 { diff --git a/src/wayland/xwayland.rs b/src/wayland/xwayland.rs index 8c5bb1e..5a758dc 100644 --- a/src/wayland/xwayland.rs +++ b/src/wayland/xwayland.rs @@ -139,32 +139,31 @@ impl XwmHandler for XWaylandHandler { &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::>() else {return}; - panel_item.commit_toplevel(); - } + { + let window = window.clone(); + move || { + let Some(wl_surface) = window.wl_surface() else {return}; + 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 + }); } }, + move |_| { + let Some(panel_item) = window.user_data().get::>() else {return}; + panel_item.commit_toplevel(); + }, ); }