Add a new surface role for Xwayland surfaces
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
734b541ecd
commit
3504182a5e
|
@ -38,12 +38,25 @@ use crate::{
|
|||
window_map::{Kind as SurfaceKind, WindowMap},
|
||||
};
|
||||
|
||||
#[cfg(feature = "xwayland")]
|
||||
use crate::xwayland::X11SurfaceRole;
|
||||
|
||||
// The xwayland feature only adds a X11Surface role, but the macro does not support #[cfg]
|
||||
#[cfg(not(feature = "xwayland"))]
|
||||
define_roles!(Roles =>
|
||||
[ XdgSurface, XdgSurfaceRole ]
|
||||
[ ShellSurface, ShellSurfaceRole]
|
||||
[ DnDIcon, DnDIconRole ]
|
||||
[ CursorImage, CursorImageRole ]
|
||||
);
|
||||
#[cfg(feature = "xwayland")]
|
||||
define_roles!(Roles =>
|
||||
[ XdgSurface, XdgSurfaceRole ]
|
||||
[ ShellSurface, ShellSurfaceRole]
|
||||
[ X11Surface, X11SurfaceRole ]
|
||||
[ DnDIcon, DnDIconRole ]
|
||||
[ CursorImage, CursorImageRole ]
|
||||
);
|
||||
|
||||
pub type MyWindowMap = WindowMap<Roles>;
|
||||
|
||||
|
@ -219,6 +232,10 @@ impl PointerGrab for ResizeSurfaceGrab {
|
|||
(self.last_window_size.0 as u32, self.last_window_size.1 as u32),
|
||||
self.edges.into(),
|
||||
),
|
||||
#[cfg(feature = "xwayland")]
|
||||
SurfaceKind::X11(_) => {
|
||||
// TODO: What to do here? Send the update via X11?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,12 @@ impl AnvilState {
|
|||
|
||||
#[cfg(feature = "xwayland")]
|
||||
let _xwayland = {
|
||||
let xwm = XWm::new(handle.clone(), log.clone());
|
||||
let xwm = XWm::new(
|
||||
handle.clone(),
|
||||
shell_handles.token,
|
||||
shell_handles.window_map.clone(),
|
||||
log.clone(),
|
||||
);
|
||||
XWayland::init(xwm, handle.clone(), display.clone(), &mut (), log.clone()).unwrap()
|
||||
};
|
||||
|
||||
|
|
|
@ -13,10 +13,14 @@ use smithay::{
|
|||
};
|
||||
|
||||
use crate::shell::SurfaceData;
|
||||
#[cfg(feature = "xwayland")]
|
||||
use crate::xwayland::X11Surface;
|
||||
|
||||
pub enum Kind<R> {
|
||||
Xdg(ToplevelSurface<R>),
|
||||
Wl(ShellSurface<R>),
|
||||
#[cfg(feature = "xwayland")]
|
||||
X11(X11Surface),
|
||||
}
|
||||
|
||||
// We implement Clone manually because #[derive(..)] would require R: Clone.
|
||||
|
@ -25,6 +29,8 @@ impl<R> Clone for Kind<R> {
|
|||
match self {
|
||||
Kind::Xdg(xdg) => Kind::Xdg(xdg.clone()),
|
||||
Kind::Wl(wl) => Kind::Wl(wl.clone()),
|
||||
#[cfg(feature = "xwayland")]
|
||||
Kind::X11(x11) => Kind::X11(x11.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,12 +43,16 @@ where
|
|||
match *self {
|
||||
Kind::Xdg(ref t) => t.alive(),
|
||||
Kind::Wl(ref t) => t.alive(),
|
||||
#[cfg(feature = "xwayland")]
|
||||
Kind::X11(ref t) => t.alive(),
|
||||
}
|
||||
}
|
||||
pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
|
||||
match *self {
|
||||
Kind::Xdg(ref t) => t.get_surface(),
|
||||
Kind::Wl(ref t) => t.get_surface(),
|
||||
#[cfg(feature = "xwayland")]
|
||||
Kind::X11(ref t) => t.get_surface(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +61,8 @@ where
|
|||
match (self, other) {
|
||||
(Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b),
|
||||
(Kind::Wl(a), Kind::Wl(b)) => a.equals(b),
|
||||
#[cfg(feature = "xwayland")]
|
||||
(Kind::X11(a), Kind::X11(b)) => a.equals(b),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use smithay::{
|
|||
calloop::LoopHandle,
|
||||
wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||
},
|
||||
wayland::compositor::CompositorToken,
|
||||
xwayland::XWindowManager,
|
||||
};
|
||||
|
||||
|
@ -22,7 +23,11 @@ use x11rb::{
|
|||
rust_connection::{DefaultStream, RustConnection},
|
||||
};
|
||||
|
||||
use crate::AnvilState;
|
||||
use crate::{
|
||||
shell::{MyWindowMap, Roles},
|
||||
window_map::Kind,
|
||||
AnvilState,
|
||||
};
|
||||
|
||||
use x11rb_event_source::X11Source;
|
||||
|
||||
|
@ -32,18 +37,31 @@ mod x11rb_event_source;
|
|||
/// After XWayland was started, the actual state is kept in `X11State`.
|
||||
pub struct XWm {
|
||||
handle: LoopHandle<AnvilState>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
}
|
||||
|
||||
impl XWm {
|
||||
pub fn new(handle: LoopHandle<AnvilState>, log: slog::Logger) -> Self {
|
||||
Self { handle, log }
|
||||
pub fn new(
|
||||
handle: LoopHandle<AnvilState>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
) -> Self {
|
||||
Self {
|
||||
handle,
|
||||
token,
|
||||
window_map,
|
||||
log,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XWindowManager for XWm {
|
||||
fn xwayland_ready(&mut self, connection: UnixStream, client: Client) {
|
||||
let (wm, source) = X11State::start_wm(connection, self.log.clone()).unwrap();
|
||||
let (wm, source) =
|
||||
X11State::start_wm(connection, self.token, self.window_map.clone(), self.log.clone()).unwrap();
|
||||
let wm = Rc::new(RefCell::new(wm));
|
||||
client.data_map().insert_if_missing(|| Rc::clone(&wm));
|
||||
self.handle
|
||||
|
@ -73,10 +91,17 @@ struct X11State {
|
|||
atoms: Atoms,
|
||||
log: slog::Logger,
|
||||
unpaired_surfaces: HashMap<u32, Window>,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
}
|
||||
|
||||
impl X11State {
|
||||
fn start_wm(connection: UnixStream, log: slog::Logger) -> Result<(Self, X11Source), Box<dyn std::error::Error>> {
|
||||
fn start_wm(
|
||||
connection: UnixStream,
|
||||
token: CompositorToken<Roles>,
|
||||
window_map: Rc<RefCell<MyWindowMap>>,
|
||||
log: slog::Logger,
|
||||
) -> Result<(Self, X11Source), Box<dyn std::error::Error>> {
|
||||
// Create an X11 connection. XWayland only uses screen 0.
|
||||
let screen = 0;
|
||||
let stream = DefaultStream::from_unix_stream(connection)?;
|
||||
|
@ -119,6 +144,8 @@ impl X11State {
|
|||
conn: Rc::clone(&conn),
|
||||
atoms,
|
||||
unpaired_surfaces: Default::default(),
|
||||
token,
|
||||
window_map,
|
||||
log,
|
||||
};
|
||||
|
||||
|
@ -187,6 +214,17 @@ impl X11State {
|
|||
|
||||
fn new_window(&mut self, window: Window, surface: WlSurface) {
|
||||
debug!(self.log, "Matched X11 surface {:x?} to {:x?}", window, surface);
|
||||
|
||||
if self.token.give_role_with(&surface, X11SurfaceRole).is_err() {
|
||||
// It makes no sense to post a protocol error here since that would only kill Xwayland
|
||||
error!(self.log, "Surface {:x?} already has a role?!", surface);
|
||||
return;
|
||||
}
|
||||
|
||||
let x11surface = X11Surface { surface };
|
||||
self.window_map
|
||||
.borrow_mut()
|
||||
.insert(Kind::X11(x11surface), (0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,3 +242,28 @@ pub fn commit_hook(surface: &WlSurface) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct X11SurfaceRole;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct X11Surface {
|
||||
surface: WlSurface,
|
||||
}
|
||||
|
||||
impl X11Surface {
|
||||
pub fn alive(&self) -> bool {
|
||||
self.surface.as_ref().is_alive()
|
||||
}
|
||||
|
||||
pub fn equals(&self, other: &Self) -> bool {
|
||||
self.alive() && other.alive() && self.surface.as_ref().equals(&other.surface.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_surface(&self) -> Option<&WlSurface> {
|
||||
if self.alive() {
|
||||
Some(&self.surface)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue