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 wp_fractional_scale_v1;
pub mod wp_viewport;
pub mod x_surface;
pub mod xdg_surface;
pub mod xwindow;
pub mod zwlr_layer_surface_v1;
pub mod zwp_idle_inhibitor_v1;
@ -27,7 +27,8 @@ use {
wl_surface::{
cursor::CursorSurface, wl_subsurface::WlSubsurface,
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,
},
@ -291,6 +292,10 @@ trait SurfaceExt {
true
}
fn is_none(&self) -> bool {
!self.is_some()
}
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
if self.is_some() {
Err(WlSurfaceError::ReloObjectStillExists)
@ -318,6 +323,10 @@ trait SurfaceExt {
fn focus_node(&self) -> Option<Rc<dyn Node>> {
None
}
fn into_xsurface(self: Rc<Self>) -> Option<Rc<XSurface>> {
None
}
}
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>) {
let old = self.output.set(output.clone());
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,
ifs::{
wl_seat::{NodeSeatState, SeatId, WlSeatGlobal},
wl_surface::{SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError},
wl_surface::{x_surface::XSurface, WlSurface, WlSurfaceError},
},
rect::Rect,
render::Renderer,
@ -132,7 +132,7 @@ pub struct Xwindow {
pub id: XwindowId,
pub seat_state: NodeSeatState,
pub data: Rc<XwindowData>,
pub surface: Rc<WlSurface>,
pub x: Rc<XSurface>,
pub display_link: RefCell<Option<LinkedNode<Rc<dyn StackedNode>>>>,
pub toplevel_data: ToplevelData,
}
@ -196,21 +196,31 @@ pub enum Change {
}
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(
&data.state,
data.info.title.borrow_mut().clone().unwrap_or_default(),
Some(surface.client.clone()),
);
tld.pos.set(surface.extents.get());
Self {
let slf = Rc::new(Self {
id: data.state.node_ids.next(),
seat_state: Default::default(),
data: data.clone(),
surface: surface.clone(),
display_link: Default::default(),
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) {
@ -220,17 +230,8 @@ impl Xwindow {
pub fn break_loops(&self) {
self.tl_destroy();
self.surface.set_toplevel(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(())
self.x.surface.set_toplevel(None);
self.x.xwindow.set(None);
}
pub fn is_mapped(&self) -> bool {
@ -238,7 +239,7 @@ impl Xwindow {
}
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 {
@ -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 {
fn node_id(&self) -> NodeId {
self.id.into()
@ -327,11 +304,11 @@ impl Node for Xwindow {
}
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 {
self.surface.visible.get()
self.x.surface.visible.get()
}
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 {
let rect = self.surface.buffer_abs_pos.get();
let rect = self.x.surface.buffer_abs_pos.get();
if x < rect.width() && y < rect.height() {
tree.push(FoundNode {
node: self.surface.clone(),
node: self.x.surface.clone(),
x,
y,
});
@ -356,7 +333,7 @@ impl Node for Xwindow {
}
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>> {
@ -398,11 +375,11 @@ impl ToplevelNode for Xwindow {
}
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>) {
self.surface.set_output(&ws.output.get());
self.x.surface.set_output(&ws.output.get());
}
fn tl_change_extents(self: Rc<Self>, rect: &Rect) {
@ -421,7 +398,7 @@ impl ToplevelNode for Xwindow {
.push(XWaylandEvent::Configure(self.clone()));
}
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) {
self.surface.set_visible(visible);
self.x.surface.set_visible(visible);
self.seat_state.set_visible(self, visible);
}
fn tl_destroy(&self) {
self.toplevel_data.destroy_node(self);
self.display_link.borrow_mut().take();
self.surface.destroy_node();
self.x.surface.destroy_node();
}
}

View file

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

View file

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

View file

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