Become the X11 window manager after Xwayland startup
This commits adds the necessary magic incantations to become the X11 WM after Xwayland starts. This uses the pure-Rust implementation from x11rb, but any other X11 crate could be used as well. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
2f0dadd6ca
commit
df01587459
|
@ -21,6 +21,12 @@ path = ".."
|
||||||
default-features = false
|
default-features = false
|
||||||
features = [ "renderer_glium", "backend_egl", "wayland_frontend" ]
|
features = [ "renderer_glium", "backend_egl", "wayland_frontend" ]
|
||||||
|
|
||||||
|
[dependencies.x11rb]
|
||||||
|
optional = true
|
||||||
|
version = "0.7"
|
||||||
|
default-features = false
|
||||||
|
features = [ "composite" ]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gl_generator = "0.14"
|
gl_generator = "0.14"
|
||||||
|
|
||||||
|
@ -31,5 +37,5 @@ winit = [ "smithay/backend_winit" ]
|
||||||
udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm_atomic", "smithay/backend_drm_legacy", "smithay/backend_drm_gbm", "smithay/backend_drm_eglstream", "smithay/backend_drm_egl", "smithay/backend_session", "input" ]
|
udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm_atomic", "smithay/backend_drm_legacy", "smithay/backend_drm_gbm", "smithay/backend_drm_eglstream", "smithay/backend_drm_egl", "smithay/backend_session", "input" ]
|
||||||
logind = [ "smithay/backend_session_logind" ]
|
logind = [ "smithay/backend_session_logind" ]
|
||||||
elogind = ["logind", "smithay/backend_session_elogind" ]
|
elogind = ["logind", "smithay/backend_session_elogind" ]
|
||||||
xwayland = [ "smithay/xwayland" ]
|
xwayland = [ "smithay/xwayland", "x11rb" ]
|
||||||
test_all_features = ["default"]
|
test_all_features = ["default"]
|
||||||
|
|
|
@ -5,6 +5,19 @@ use smithay:: {
|
||||||
xwayland::XWindowManager,
|
xwayland::XWindowManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use x11rb::{
|
||||||
|
connection::Connection as _,
|
||||||
|
protocol::{
|
||||||
|
composite::{ConnectionExt as _, Redirect},
|
||||||
|
xproto::{
|
||||||
|
ChangeWindowAttributesAux, ConnectionExt as _, EventMask, WindowClass,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rust_connection::{DefaultStream, RustConnection},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Implementation of [`smithay::xwayland::XWindowManager`] that is used for starting XWayland.
|
||||||
|
/// After XWayland was started, the actual state is kept in `X11State`.
|
||||||
pub struct XWm;
|
pub struct XWm;
|
||||||
|
|
||||||
impl XWm {
|
impl XWm {
|
||||||
|
@ -14,8 +27,62 @@ 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 _wm = X11State::start_wm(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xwayland_exited(&mut self) {}
|
fn xwayland_exited(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x11rb::atom_manager! {
|
||||||
|
Atoms: AtomsCookie {
|
||||||
|
WM_S0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The actual runtime state of the XWayland integration.
|
||||||
|
struct X11State {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl X11State {
|
||||||
|
fn start_wm(connection: UnixStream) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
// Create an X11 connection. XWayland only uses screen 0.
|
||||||
|
let screen = 0;
|
||||||
|
let stream = DefaultStream::from_unix_stream(connection)?;
|
||||||
|
let conn = RustConnection::connect_to_stream(stream, screen)?;
|
||||||
|
let atoms = Atoms::new(&conn)?.reply()?;
|
||||||
|
|
||||||
|
let screen = &conn.setup().roots[0];
|
||||||
|
|
||||||
|
// Actually become the WM by redirecting some operations
|
||||||
|
conn.change_window_attributes(
|
||||||
|
screen.root,
|
||||||
|
&ChangeWindowAttributesAux::default().event_mask(EventMask::SubstructureRedirect),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Tell XWayland that we are the WM by acquiring the WM_S0 selection. No X11 clients are accepted before this.
|
||||||
|
let win = conn.generate_id()?;
|
||||||
|
conn.create_window(
|
||||||
|
screen.root_depth,
|
||||||
|
win,
|
||||||
|
screen.root,
|
||||||
|
// x, y, width, height, border width
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
WindowClass::InputOutput,
|
||||||
|
x11rb::COPY_FROM_PARENT,
|
||||||
|
&Default::default(),
|
||||||
|
)?;
|
||||||
|
conn.set_selection_owner(win, atoms.WM_S0, x11rb::CURRENT_TIME)?;
|
||||||
|
|
||||||
|
// XWayland wants us to do this to function properly...?
|
||||||
|
conn.composite_redirect_subwindows(screen.root, Redirect::Manual)?;
|
||||||
|
|
||||||
|
conn.flush()?;
|
||||||
|
|
||||||
|
Ok(X11State {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue