feat(xwayland): first x window
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user