1
0
Fork 0
forked from wry/wry

xwayland: add x-surface indirection

This commit is contained in:
Julian Orth 2022-10-16 20:53:59 +02:00
parent 8059457afb
commit 6193569596
6 changed files with 123 additions and 66 deletions

View file

@ -3,8 +3,8 @@ pub mod ext_session_lock_surface_v1;
pub mod wl_subsurface; pub mod wl_subsurface;
pub mod wp_fractional_scale_v1; pub mod wp_fractional_scale_v1;
pub mod wp_viewport; pub mod wp_viewport;
pub mod x_surface;
pub mod xdg_surface; pub mod xdg_surface;
pub mod xwindow;
pub mod zwlr_layer_surface_v1; pub mod zwlr_layer_surface_v1;
pub mod zwp_idle_inhibitor_v1; pub mod zwp_idle_inhibitor_v1;
@ -27,7 +27,8 @@ use {
wl_surface::{ wl_surface::{
cursor::CursorSurface, wl_subsurface::WlSubsurface, cursor::CursorSurface, wl_subsurface::WlSubsurface,
wp_fractional_scale_v1::WpFractionalScaleV1, wp_viewport::WpViewport, wp_fractional_scale_v1::WpFractionalScaleV1, wp_viewport::WpViewport,
xdg_surface::XdgSurfaceError, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error, x_surface::XSurface, xdg_surface::XdgSurfaceError,
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error,
}, },
wp_presentation_feedback::WpPresentationFeedback, wp_presentation_feedback::WpPresentationFeedback,
}, },
@ -291,6 +292,10 @@ trait SurfaceExt {
true true
} }
fn is_none(&self) -> bool {
!self.is_some()
}
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> { fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
if self.is_some() { if self.is_some() {
Err(WlSurfaceError::ReloObjectStillExists) Err(WlSurfaceError::ReloObjectStillExists)
@ -318,6 +323,10 @@ trait SurfaceExt {
fn focus_node(&self) -> Option<Rc<dyn Node>> { fn focus_node(&self) -> Option<Rc<dyn Node>> {
None None
} }
fn into_xsurface(self: Rc<Self>) -> Option<Rc<XSurface>> {
None
}
} }
pub struct NoneSurfaceExt; pub struct NoneSurfaceExt;
@ -394,6 +403,22 @@ impl WlSurface {
} }
} }
fn get_xsurface(self: &Rc<Self>) -> Result<Rc<XSurface>, WlSurfaceError> {
self.set_role(SurfaceRole::XSurface)?;
let mut ext = self.ext.get();
if ext.is_none() {
let xsurface = Rc::new(XSurface {
surface: self.clone(),
xwindow: Default::default(),
tracker: Default::default(),
});
track!(self.client, xsurface);
self.ext.set(xsurface.clone());
ext = xsurface;
}
Ok(ext.into_xsurface().unwrap())
}
pub fn set_output(&self, output: &Rc<OutputNode>) { pub fn set_output(&self, output: &Rc<OutputNode>) {
let old = self.output.set(output.clone()); let old = self.output.set(output.clone());
if old.id == output.id { if old.id == output.id {

View file

@ -0,0 +1,53 @@
use {
crate::{
ifs::wl_surface::{x_surface::xwindow::Xwindow, SurfaceExt, WlSurface, WlSurfaceError},
leaks::Tracker,
tree::ToplevelNode,
utils::clonecell::CloneCell,
xwayland::XWaylandEvent,
},
std::rc::Rc,
};
pub mod xwindow;
pub struct XSurface {
pub surface: Rc<WlSurface>,
pub xwindow: CloneCell<Option<Rc<Xwindow>>>,
pub tracker: Tracker<Self>,
}
impl SurfaceExt for XSurface {
fn post_commit(self: Rc<Self>) {
if let Some(xwindow) = self.xwindow.get() {
xwindow.map_status_changed();
}
}
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
self.surface.unset_ext();
if let Some(xwindow) = self.xwindow.take() {
xwindow.tl_destroy();
xwindow.data.window.set(None);
xwindow.data.surface_id.set(None);
xwindow
.data
.state
.xwayland
.queue
.push(XWaylandEvent::SurfaceDestroyed(self.surface.id));
}
Ok(())
}
fn extents_changed(&self) {
if let Some(xwindow) = self.xwindow.get() {
xwindow.toplevel_data.pos.set(self.surface.extents.get());
xwindow.tl_extents_changed();
}
}
fn into_xsurface(self: Rc<Self>) -> Option<Rc<XSurface>> {
Some(self)
}
}

View file

@ -5,7 +5,7 @@ use {
fixed::Fixed, fixed::Fixed,
ifs::{ ifs::{
wl_seat::{NodeSeatState, SeatId, WlSeatGlobal}, wl_seat::{NodeSeatState, SeatId, WlSeatGlobal},
wl_surface::{SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError}, wl_surface::{x_surface::XSurface, WlSurface, WlSurfaceError},
}, },
rect::Rect, rect::Rect,
render::Renderer, render::Renderer,
@ -132,7 +132,7 @@ pub struct Xwindow {
pub id: XwindowId, pub id: XwindowId,
pub seat_state: NodeSeatState, pub seat_state: NodeSeatState,
pub data: Rc<XwindowData>, pub data: Rc<XwindowData>,
pub surface: Rc<WlSurface>, pub x: Rc<XSurface>,
pub display_link: RefCell<Option<LinkedNode<Rc<dyn StackedNode>>>>, pub display_link: RefCell<Option<LinkedNode<Rc<dyn StackedNode>>>>,
pub toplevel_data: ToplevelData, pub toplevel_data: ToplevelData,
} }
@ -196,21 +196,31 @@ pub enum Change {
} }
impl Xwindow { impl Xwindow {
pub fn new(data: &Rc<XwindowData>, surface: &Rc<WlSurface>) -> Self { pub fn install(
data: &Rc<XwindowData>,
surface: &Rc<WlSurface>,
) -> Result<Rc<Self>, XWindowError> {
let xsurface = surface.get_xsurface()?;
if xsurface.xwindow.get().is_some() {
return Err(XWindowError::AlreadyAttached);
}
let tld = ToplevelData::new( let tld = ToplevelData::new(
&data.state, &data.state,
data.info.title.borrow_mut().clone().unwrap_or_default(), data.info.title.borrow_mut().clone().unwrap_or_default(),
Some(surface.client.clone()), Some(surface.client.clone()),
); );
tld.pos.set(surface.extents.get()); tld.pos.set(surface.extents.get());
Self { let slf = Rc::new(Self {
id: data.state.node_ids.next(), id: data.state.node_ids.next(),
seat_state: Default::default(), seat_state: Default::default(),
data: data.clone(), data: data.clone(),
surface: surface.clone(),
display_link: Default::default(), display_link: Default::default(),
toplevel_data: tld, toplevel_data: tld,
} x: xsurface,
});
slf.x.xwindow.set(Some(slf.clone()));
slf.x.surface.set_toplevel(Some(slf.clone()));
Ok(slf)
} }
pub fn destroy(&self) { pub fn destroy(&self) {
@ -220,17 +230,8 @@ impl Xwindow {
pub fn break_loops(&self) { pub fn break_loops(&self) {
self.tl_destroy(); self.tl_destroy();
self.surface.set_toplevel(None); self.x.surface.set_toplevel(None);
} self.x.xwindow.set(None);
pub fn install(self: &Rc<Self>) -> Result<(), XWindowError> {
self.surface.set_role(SurfaceRole::XSurface)?;
if self.surface.ext.get().is_some() {
return Err(XWindowError::AlreadyAttached);
}
self.surface.ext.set(self.clone());
self.surface.set_toplevel(Some(self.clone()));
Ok(())
} }
pub fn is_mapped(&self) -> bool { pub fn is_mapped(&self) -> bool {
@ -238,7 +239,7 @@ impl Xwindow {
} }
pub fn may_be_mapped(&self) -> bool { pub fn may_be_mapped(&self) -> bool {
self.surface.buffer.get().is_some() && self.data.info.mapped.get() self.x.surface.buffer.get().is_some() && self.data.info.mapped.get()
} }
fn map_change(&self) -> Change { fn map_change(&self) -> Change {
@ -289,30 +290,6 @@ impl Xwindow {
} }
} }
impl SurfaceExt for Xwindow {
fn post_commit(self: Rc<Self>) {
self.map_status_changed();
}
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
self.tl_destroy();
self.surface.unset_ext();
self.data.window.set(None);
self.data.surface_id.set(None);
self.data
.state
.xwayland
.queue
.push(XWaylandEvent::SurfaceDestroyed(self.surface.id));
Ok(())
}
fn extents_changed(&self) {
self.toplevel_data.pos.set(self.surface.extents.get());
self.tl_extents_changed();
}
}
impl Node for Xwindow { impl Node for Xwindow {
fn node_id(&self) -> NodeId { fn node_id(&self) -> NodeId {
self.id.into() self.id.into()
@ -327,11 +304,11 @@ impl Node for Xwindow {
} }
fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) {
visitor.visit_surface(&self.surface); visitor.visit_surface(&self.x.surface);
} }
fn node_visible(&self) -> bool { fn node_visible(&self) -> bool {
self.surface.visible.get() self.x.surface.visible.get()
} }
fn node_absolute_position(&self) -> Rect { fn node_absolute_position(&self) -> Rect {
@ -343,10 +320,10 @@ impl Node for Xwindow {
} }
fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult { fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
let rect = self.surface.buffer_abs_pos.get(); let rect = self.x.surface.buffer_abs_pos.get();
if x < rect.width() && y < rect.height() { if x < rect.width() && y < rect.height() {
tree.push(FoundNode { tree.push(FoundNode {
node: self.surface.clone(), node: self.x.surface.clone(),
x, x,
y, y,
}); });
@ -356,7 +333,7 @@ impl Node for Xwindow {
} }
fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_surface(&self.surface, x, y) renderer.render_surface(&self.x.surface, x, y)
} }
fn node_client(&self) -> Option<Rc<Client>> { fn node_client(&self) -> Option<Rc<Client>> {
@ -398,11 +375,11 @@ impl ToplevelNode for Xwindow {
} }
fn tl_focus_child(&self, _seat: SeatId) -> Option<Rc<dyn Node>> { fn tl_focus_child(&self, _seat: SeatId) -> Option<Rc<dyn Node>> {
Some(self.surface.clone()) Some(self.x.surface.clone())
} }
fn tl_set_workspace_ext(self: Rc<Self>, ws: &Rc<WorkspaceNode>) { fn tl_set_workspace_ext(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
self.surface.set_output(&ws.output.get()); self.x.surface.set_output(&ws.output.get());
} }
fn tl_change_extents(self: Rc<Self>, rect: &Rect) { fn tl_change_extents(self: Rc<Self>, rect: &Rect) {
@ -421,7 +398,7 @@ impl ToplevelNode for Xwindow {
.push(XWaylandEvent::Configure(self.clone())); .push(XWaylandEvent::Configure(self.clone()));
} }
if old.position() != rect.position() { if old.position() != rect.position() {
self.surface.set_absolute_position(rect.x1(), rect.y1()); self.x.surface.set_absolute_position(rect.x1(), rect.y1());
} }
} }
} }
@ -435,14 +412,14 @@ impl ToplevelNode for Xwindow {
} }
fn tl_set_visible(&self, visible: bool) { fn tl_set_visible(&self, visible: bool) {
self.surface.set_visible(visible); self.x.surface.set_visible(visible);
self.seat_state.set_visible(self, visible); self.seat_state.set_visible(self, visible);
} }
fn tl_destroy(&self) { fn tl_destroy(&self) {
self.toplevel_data.destroy_node(self); self.toplevel_data.destroy_node(self);
self.display_link.borrow_mut().take(); self.display_link.borrow_mut().take();
self.surface.destroy_node(); self.x.surface.destroy_node();
} }
} }

View file

@ -2,8 +2,8 @@ use {
crate::{ crate::{
ifs::wl_surface::{ ifs::wl_surface::{
ext_session_lock_surface_v1::ExtSessionLockSurfaceV1, ext_session_lock_surface_v1::ExtSessionLockSurfaceV1,
x_surface::xwindow::Xwindow,
xdg_surface::{xdg_popup::XdgPopup, xdg_toplevel::XdgToplevel}, xdg_surface::{xdg_popup::XdgPopup, xdg_toplevel::XdgToplevel},
xwindow::Xwindow,
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
WlSurface, WlSurface,
}, },

View file

@ -14,7 +14,7 @@ use {
}, },
wl_seat::SeatId, wl_seat::SeatId,
wl_surface::{ wl_surface::{
xwindow::{Xwindow, XwindowData}, x_surface::xwindow::{Xwindow, XwindowData},
WlSurface, WlSurface,
}, },
}, },

View file

@ -16,7 +16,7 @@ use {
}, },
wl_seat::{SeatId, WlSeatGlobal}, wl_seat::{SeatId, WlSeatGlobal},
wl_surface::{ wl_surface::{
xwindow::{XInputModel, Xwindow, XwindowData}, x_surface::xwindow::{XInputModel, Xwindow, XwindowData},
WlSurface, WlSurface,
}, },
}, },
@ -1374,14 +1374,16 @@ impl Wm {
log::error!("The xwindow has already been constructed"); log::error!("The xwindow has already been constructed");
return; return;
} }
let window = Rc::new(Xwindow::new(data, &surface)); let window = match Xwindow::install(data, &surface) {
if let Err(e) = window.install() { Ok(w) => w,
log::error!( Err(e) => {
"Could not attach the xwindow to the surface: {}", log::error!(
ErrorFmt(e) "Could not attach the xwindow to the surface: {}",
); ErrorFmt(e)
return; );
} return;
}
};
data.window.set(Some(window.clone())); data.window.set(Some(window.clone()));
{ {
self.load_window_wm_class(data).await; self.load_window_wm_class(data).await;
@ -1766,7 +1768,7 @@ impl Wm {
if prev_pid.is_some() if prev_pid.is_some()
&& prev_pid == new_pid && prev_pid == new_pid
&& revent.serial() >= self.last_input_serial && revent.serial() >= self.last_input_serial
&& w.surface.node_visible() && w.x.surface.node_visible()
{ {
// log::info!("xwm ACCEPT"); // log::info!("xwm ACCEPT");
focus_window = new_window; focus_window = new_window;