xwayland: add x-surface indirection
This commit is contained in:
parent
8059457afb
commit
6193569596
6 changed files with 123 additions and 66 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
53
src/ifs/wl_surface/x_surface.rs
Normal file
53
src/ifs/wl_surface/x_surface.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use {
|
|||
},
|
||||
wl_seat::SeatId,
|
||||
wl_surface::{
|
||||
xwindow::{Xwindow, XwindowData},
|
||||
x_surface::xwindow::{Xwindow, XwindowData},
|
||||
WlSurface,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue