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},
|
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 =>
|
define_roles!(Roles =>
|
||||||
[ XdgSurface, XdgSurfaceRole ]
|
[ XdgSurface, XdgSurfaceRole ]
|
||||||
[ ShellSurface, ShellSurfaceRole]
|
[ ShellSurface, ShellSurfaceRole]
|
||||||
[ DnDIcon, DnDIconRole ]
|
[ DnDIcon, DnDIconRole ]
|
||||||
[ CursorImage, CursorImageRole ]
|
[ CursorImage, CursorImageRole ]
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "xwayland")]
|
||||||
|
define_roles!(Roles =>
|
||||||
|
[ XdgSurface, XdgSurfaceRole ]
|
||||||
|
[ ShellSurface, ShellSurfaceRole]
|
||||||
|
[ X11Surface, X11SurfaceRole ]
|
||||||
|
[ DnDIcon, DnDIconRole ]
|
||||||
|
[ CursorImage, CursorImageRole ]
|
||||||
|
);
|
||||||
|
|
||||||
pub type MyWindowMap = WindowMap<Roles>;
|
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.last_window_size.0 as u32, self.last_window_size.1 as u32),
|
||||||
self.edges.into(),
|
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")]
|
#[cfg(feature = "xwayland")]
|
||||||
let _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()
|
XWayland::init(xwm, handle.clone(), display.clone(), &mut (), log.clone()).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,14 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::shell::SurfaceData;
|
use crate::shell::SurfaceData;
|
||||||
|
#[cfg(feature = "xwayland")]
|
||||||
|
use crate::xwayland::X11Surface;
|
||||||
|
|
||||||
pub enum Kind<R> {
|
pub enum Kind<R> {
|
||||||
Xdg(ToplevelSurface<R>),
|
Xdg(ToplevelSurface<R>),
|
||||||
Wl(ShellSurface<R>),
|
Wl(ShellSurface<R>),
|
||||||
|
#[cfg(feature = "xwayland")]
|
||||||
|
X11(X11Surface),
|
||||||
}
|
}
|
||||||
|
|
||||||
// We implement Clone manually because #[derive(..)] would require R: Clone.
|
// We implement Clone manually because #[derive(..)] would require R: Clone.
|
||||||
|
@ -25,6 +29,8 @@ impl<R> Clone for Kind<R> {
|
||||||
match self {
|
match self {
|
||||||
Kind::Xdg(xdg) => Kind::Xdg(xdg.clone()),
|
Kind::Xdg(xdg) => Kind::Xdg(xdg.clone()),
|
||||||
Kind::Wl(wl) => Kind::Wl(wl.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 {
|
match *self {
|
||||||
Kind::Xdg(ref t) => t.alive(),
|
Kind::Xdg(ref t) => t.alive(),
|
||||||
Kind::Wl(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> {
|
pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
|
||||||
match *self {
|
match *self {
|
||||||
Kind::Xdg(ref t) => t.get_surface(),
|
Kind::Xdg(ref t) => t.get_surface(),
|
||||||
Kind::Wl(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) {
|
match (self, other) {
|
||||||
(Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b),
|
(Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b),
|
||||||
(Kind::Wl(a), Kind::Wl(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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use smithay::{
|
||||||
calloop::LoopHandle,
|
calloop::LoopHandle,
|
||||||
wayland_server::{protocol::wl_surface::WlSurface, Client},
|
wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||||
},
|
},
|
||||||
|
wayland::compositor::CompositorToken,
|
||||||
xwayland::XWindowManager,
|
xwayland::XWindowManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,7 +23,11 @@ use x11rb::{
|
||||||
rust_connection::{DefaultStream, RustConnection},
|
rust_connection::{DefaultStream, RustConnection},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::AnvilState;
|
use crate::{
|
||||||
|
shell::{MyWindowMap, Roles},
|
||||||
|
window_map::Kind,
|
||||||
|
AnvilState,
|
||||||
|
};
|
||||||
|
|
||||||
use x11rb_event_source::X11Source;
|
use x11rb_event_source::X11Source;
|
||||||
|
|
||||||
|
@ -32,18 +37,31 @@ mod x11rb_event_source;
|
||||||
/// After XWayland was started, the actual state is kept in `X11State`.
|
/// After XWayland was started, the actual state is kept in `X11State`.
|
||||||
pub struct XWm {
|
pub struct XWm {
|
||||||
handle: LoopHandle<AnvilState>,
|
handle: LoopHandle<AnvilState>,
|
||||||
|
token: CompositorToken<Roles>,
|
||||||
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XWm {
|
impl XWm {
|
||||||
pub fn new(handle: LoopHandle<AnvilState>, log: slog::Logger) -> Self {
|
pub fn new(
|
||||||
Self { handle, log }
|
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 {
|
impl XWindowManager for XWm {
|
||||||
fn xwayland_ready(&mut self, connection: UnixStream, client: Client) {
|
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));
|
let wm = Rc::new(RefCell::new(wm));
|
||||||
client.data_map().insert_if_missing(|| Rc::clone(&wm));
|
client.data_map().insert_if_missing(|| Rc::clone(&wm));
|
||||||
self.handle
|
self.handle
|
||||||
|
@ -73,10 +91,17 @@ struct X11State {
|
||||||
atoms: Atoms,
|
atoms: Atoms,
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
unpaired_surfaces: HashMap<u32, Window>,
|
unpaired_surfaces: HashMap<u32, Window>,
|
||||||
|
token: CompositorToken<Roles>,
|
||||||
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl X11State {
|
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.
|
// Create an X11 connection. XWayland only uses screen 0.
|
||||||
let screen = 0;
|
let screen = 0;
|
||||||
let stream = DefaultStream::from_unix_stream(connection)?;
|
let stream = DefaultStream::from_unix_stream(connection)?;
|
||||||
|
@ -119,6 +144,8 @@ impl X11State {
|
||||||
conn: Rc::clone(&conn),
|
conn: Rc::clone(&conn),
|
||||||
atoms,
|
atoms,
|
||||||
unpaired_surfaces: Default::default(),
|
unpaired_surfaces: Default::default(),
|
||||||
|
token,
|
||||||
|
window_map,
|
||||||
log,
|
log,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,6 +214,17 @@ impl X11State {
|
||||||
|
|
||||||
fn new_window(&mut self, window: Window, surface: WlSurface) {
|
fn new_window(&mut self, window: Window, surface: WlSurface) {
|
||||||
debug!(self.log, "Matched X11 surface {:x?} to {:x?}", window, surface);
|
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