Map between X11 Windows and WlSurfaces
Xwayland gives us a mapping between X11 window and WlSurface IDs via special WL_SURFACE_ID messages. This commit uses these messages to find the corresponding WlSurface. For this, the new client.get_resource API from wayland-server is needed. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
a6c40a002b
commit
734b541ecd
|
@ -31,7 +31,7 @@ udev = { version = "0.5", optional = true }
|
||||||
wayland-commons = { version = "0.28", optional = true }
|
wayland-commons = { version = "0.28", optional = true }
|
||||||
wayland-egl = { version = "0.28", optional = true }
|
wayland-egl = { version = "0.28", optional = true }
|
||||||
wayland-protocols = { version = "0.28", features = ["unstable_protocols", "server"], optional = true }
|
wayland-protocols = { version = "0.28", features = ["unstable_protocols", "server"], optional = true }
|
||||||
wayland-server = { version = "0.28", optional = true }
|
wayland-server = { version = "0.28.3", optional = true }
|
||||||
wayland-sys = { version = "0.28", optional = true }
|
wayland-sys = { version = "0.28", optional = true }
|
||||||
winit = { version = "0.23.0", optional = true }
|
winit = { version = "0.23.0", optional = true }
|
||||||
xkbcommon = "0.4.0"
|
xkbcommon = "0.4.0"
|
||||||
|
|
|
@ -768,6 +768,9 @@ fn surface_commit(
|
||||||
buffer_utils: &BufferUtils,
|
buffer_utils: &BufferUtils,
|
||||||
window_map: &RefCell<MyWindowMap>,
|
window_map: &RefCell<MyWindowMap>,
|
||||||
) {
|
) {
|
||||||
|
#[cfg(feature = "xwayland")]
|
||||||
|
super::xwayland::commit_hook(surface);
|
||||||
|
|
||||||
let mut geometry = None;
|
let mut geometry = None;
|
||||||
let mut min_size = (0, 0);
|
let mut min_size = (0, 0);
|
||||||
let mut max_size = (0, 0);
|
let mut max_size = (0, 0);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::{convert::TryFrom, os::unix::net::UnixStream, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, convert::TryFrom, os::unix::net::UnixStream, rc::Rc};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::LoopHandle,
|
calloop::LoopHandle,
|
||||||
wayland_server::Client,
|
wayland_server::{protocol::wl_surface::WlSurface, Client},
|
||||||
},
|
},
|
||||||
xwayland::XWindowManager,
|
xwayland::XWindowManager,
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@ use x11rb::{
|
||||||
composite::{ConnectionExt as _, Redirect},
|
composite::{ConnectionExt as _, Redirect},
|
||||||
xproto::{
|
xproto::{
|
||||||
ChangeWindowAttributesAux, ConfigWindow, ConfigureWindowAux, ConnectionExt as _, EventMask,
|
ChangeWindowAttributesAux, ConfigWindow, ConfigureWindowAux, ConnectionExt as _, EventMask,
|
||||||
WindowClass,
|
Window, WindowClass,
|
||||||
},
|
},
|
||||||
Event,
|
Event,
|
||||||
},
|
},
|
||||||
|
@ -42,12 +42,15 @@ impl XWm {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (mut wm, source) = X11State::start_wm(connection, self.log.clone()).unwrap();
|
let (wm, source) = X11State::start_wm(connection, self.log.clone()).unwrap();
|
||||||
|
let wm = Rc::new(RefCell::new(wm));
|
||||||
|
client.data_map().insert_if_missing(|| Rc::clone(&wm));
|
||||||
self.handle
|
self.handle
|
||||||
.insert_source(source, move |events, _, _| {
|
.insert_source(source, move |events, _, _| {
|
||||||
|
let mut wm = wm.borrow_mut();
|
||||||
for event in events.into_iter() {
|
for event in events.into_iter() {
|
||||||
wm.handle_event(event)?;
|
wm.handle_event(event, &client)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -69,6 +72,7 @@ struct X11State {
|
||||||
conn: Rc<RustConnection>,
|
conn: Rc<RustConnection>,
|
||||||
atoms: Atoms,
|
atoms: Atoms,
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
|
unpaired_surfaces: HashMap<u32, Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl X11State {
|
impl X11State {
|
||||||
|
@ -114,13 +118,14 @@ impl X11State {
|
||||||
let wm = Self {
|
let wm = Self {
|
||||||
conn: Rc::clone(&conn),
|
conn: Rc::clone(&conn),
|
||||||
atoms,
|
atoms,
|
||||||
|
unpaired_surfaces: Default::default(),
|
||||||
log,
|
log,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((wm, X11Source::new(conn)))
|
Ok((wm, X11Source::new(conn)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&mut self, event: Event) -> Result<(), ReplyOrIdError> {
|
fn handle_event(&mut self, event: Event, client: &Client) -> Result<(), ReplyOrIdError> {
|
||||||
debug!(self.log, "X11: Got event {:?}", event);
|
debug!(self.log, "X11: Got event {:?}", event);
|
||||||
match event {
|
match event {
|
||||||
Event::ConfigureRequest(r) => {
|
Event::ConfigureRequest(r) => {
|
||||||
|
@ -155,15 +160,47 @@ impl X11State {
|
||||||
}
|
}
|
||||||
Event::ClientMessage(msg) => {
|
Event::ClientMessage(msg) => {
|
||||||
if msg.type_ == self.atoms.WL_SURFACE_ID {
|
if msg.type_ == self.atoms.WL_SURFACE_ID {
|
||||||
|
// We get a WL_SURFACE_ID message when Xwayland creates a WlSurface for a
|
||||||
|
// window. Both the creation of the surface and this client message happen at
|
||||||
|
// roughly the same time and are sent over different sockets (X11 socket and
|
||||||
|
// wayland socket). Thus, we could receive these two in any order. Hence, it
|
||||||
|
// can happen that we get None below when X11 was faster than Wayland.
|
||||||
|
|
||||||
let id = msg.data.as_data32()[0];
|
let id = msg.data.as_data32()[0];
|
||||||
|
let surface = client.get_resource::<WlSurface>(id);
|
||||||
info!(
|
info!(
|
||||||
self.log,
|
self.log,
|
||||||
"X11 surface {:x?} corresponds to WlSurface {:x}", msg.window, id,
|
"X11 surface {:x?} corresponds to WlSurface {:x} = {:?}", msg.window, id, surface,
|
||||||
);
|
);
|
||||||
|
match surface {
|
||||||
|
None => {
|
||||||
|
self.unpaired_surfaces.insert(id, msg.window);
|
||||||
|
}
|
||||||
|
Some(surface) => self.new_window(msg.window, surface),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_window(&mut self, window: Window, surface: WlSurface) {
|
||||||
|
debug!(self.log, "Matched X11 surface {:x?} to {:x?}", window, surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when a WlSurface commits.
|
||||||
|
pub fn commit_hook(surface: &WlSurface) {
|
||||||
|
// Is this the Xwayland client?
|
||||||
|
if let Some(client) = surface.as_ref().client() {
|
||||||
|
if let Some(x11) = client.data_map().get::<Rc<RefCell<X11State>>>() {
|
||||||
|
let mut inner = x11.borrow_mut();
|
||||||
|
// Is the surface among the unpaired surfaces (see comment next to WL_SURFACE_ID
|
||||||
|
// handling above)
|
||||||
|
if let Some(window) = inner.unpaired_surfaces.remove(&surface.as_ref().id()) {
|
||||||
|
inner.new_window(window, surface.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue