feat(wayland): initial xwayland support

This commit is contained in:
Nova
2023-05-11 04:58:49 -04:00
parent 945514aa31
commit 7a556439ca
6 changed files with 294 additions and 8 deletions

View File

@@ -205,6 +205,7 @@ fn main() {
std::env::var_os("WAYLAND_DISPLAY").unwrap_or_default(),
)
.env("WAYLAND_DISPLAY", &wayland.socket_name)
.env("DISPLAY", format!(":{}", wayland.xwayland_state.display))
.env(
"STARDUST_INSTANCE",
event_loop_info

View File

@@ -1,4 +1,8 @@
use crate::{core::client::Client, wayland::WAYLAND_DISPLAY, STARDUST_INSTANCE};
use crate::{
core::client::Client,
wayland::{xwayland::DISPLAY, WAYLAND_DISPLAY},
STARDUST_INSTANCE,
};
use super::{
items::{ItemAcceptor, TypeInfo},
@@ -135,6 +139,7 @@ pub fn get_connection_environment_flex(
#[cfg(feature = "wayland")]
{
var_env_insert!(env, WAYLAND_DISPLAY);
var_env_insert!(env, DISPLAY);
env.insert("GDK_BACKEND".to_string(), "wayland".to_string());
env.insert("QT_QPA_PLATFORM".to_string(), "wayland".to_string());
env.insert("MOZ_ENABLE_WAYLAND".to_string(), "1".to_string());

View File

@@ -8,7 +8,9 @@ mod state;
mod surface;
// mod xdg_activation;
mod xdg_shell;
pub mod xwayland;
use self::xwayland::XWaylandState;
use self::{state::WaylandState, surface::CORE_SURFACES};
use crate::{core::task, wayland::state::ClientState};
use color_eyre::eyre::{ensure, Result};
@@ -67,7 +69,8 @@ pub struct Wayland {
join_handle: JoinHandle<Result<()>>,
renderer: GlesRenderer,
dmabuf_rx: UnboundedReceiver<Dmabuf>,
state: Arc<Mutex<WaylandState>>,
wayland_state: Arc<Mutex<WaylandState>>,
pub xwayland_state: XWaylandState,
}
impl Wayland {
pub fn new() -> Result<Self> {
@@ -85,7 +88,8 @@ impl Wayland {
let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel();
let display = Arc::new(Mutex::new(display));
let state = WaylandState::new(display.clone(), display_handle, &renderer, dmabuf_tx);
let xwayland_state = XWaylandState::create(&display_handle).unwrap();
let wayland_state = WaylandState::new(display.clone(), display_handle, &renderer, dmabuf_tx);
let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8);
GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap();
@@ -97,8 +101,12 @@ impl Wayland {
.expect("seriously message nova this time they screwed up big time");
info!(socket_name, "Wayland active");
let join_handle =
Wayland::start_loop(display.clone(), socket, state.clone(), global_destroy_queue)?;
let join_handle = Wayland::start_loop(
display.clone(),
socket,
wayland_state.clone(),
global_destroy_queue,
)?;
Ok(Wayland {
display,
@@ -106,7 +114,8 @@ impl Wayland {
join_handle,
renderer,
dmabuf_rx,
state,
wayland_state,
xwayland_state,
})
}
@@ -167,7 +176,7 @@ impl Wayland {
}
pub fn frame_event(&self, sk: &impl StereoKitDraw) {
let state = self.state.lock();
let state = self.wayland_state.lock();
for core_surface in CORE_SURFACES.get_valid_contents() {
core_surface.frame(sk, state.output.clone());

157
src/wayland/xwayland.rs Normal file
View File

@@ -0,0 +1,157 @@
use super::seat::SeatData;
use color_eyre::eyre::Result;
use once_cell::sync::OnceCell;
use smithay::{
reexports::{
calloop::{self, EventLoop, LoopSignal},
wayland_server::DisplayHandle,
x11rb::protocol::xproto::Window,
},
utils::{Logical, Rectangle},
xwayland::{
xwm::{Reorder, ResizeEdge, XwmId},
X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler,
},
};
use std::{ffi::OsStr, iter::empty, sync::Arc, time::Duration};
use tokio::{sync::oneshot, task::JoinHandle};
use tracing::debug;
pub static DISPLAY: OnceCell<String> = OnceCell::new();
pub struct XWaylandState {
pub display: u32,
xwayland: XWayland,
event_loop_signal: LoopSignal,
event_loop_join: Option<JoinHandle<Result<(), calloop::Error>>>,
}
impl XWaylandState {
pub fn create(dh: &DisplayHandle) -> Result<Self> {
let dh = dh.clone();
let (tx, rx) = oneshot::channel();
let event_loop_join = tokio::task::spawn_blocking(move || {
let mut event_loop: EventLoop<XWaylandHandler> = EventLoop::try_new()?;
let (xwayland, connection) = XWayland::new(&dh);
let handle = event_loop.handle();
event_loop
.handle()
.insert_source(connection, move |event, _, handler| match event {
XWaylandEvent::Ready {
connection,
client,
client_fd: _,
display: _,
} => {
handler.seat = Some(SeatData::new(&dh, client.id()));
handler.wm =
X11Wm::start_wm(handle.clone(), dh.clone(), connection, client).ok();
}
XWaylandEvent::Exited => (),
})
.map_err(|e| e.error)?;
let display = xwayland.start(
event_loop.handle(),
None,
empty::<(&OsStr, &OsStr)>(),
true,
move |_| (),
)?;
let _ = tx.send(XWaylandState {
display,
xwayland,
event_loop_signal: event_loop.get_signal(),
event_loop_join: None,
});
let mut handler = XWaylandHandler::default();
event_loop.run(Duration::from_secs(60 * 60), &mut handler, |_| ())
});
let mut state = rx.blocking_recv()?;
state.event_loop_join.replace(event_loop_join);
let _ = DISPLAY.set(format!(":{}", state.display));
Ok(state)
}
}
impl Drop for XWaylandState {
fn drop(&mut self) {
self.xwayland.shutdown();
self.event_loop_signal.stop();
}
}
#[derive(Default)]
struct XWaylandHandler {
wm: Option<X11Wm>,
seat: Option<Arc<SeatData>>,
}
impl XwmHandler for XWaylandHandler {
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
self.wm.as_mut().unwrap()
}
fn new_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "New X window");
}
fn new_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "New X override redirect window");
}
fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map window request");
}
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map override redirect window");
}
fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "Unmap X window");
}
fn destroyed_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "Destroy X window");
}
fn configure_request(
&mut self,
_xwm: XwmId,
window: X11Surface,
x: Option<i32>,
y: Option<i32>,
w: Option<u32>,
h: Option<u32>,
reorder: Option<Reorder>,
) {
debug!(?window, x, y, w, h, ?reorder, "Configure X window");
}
fn configure_notify(
&mut self,
_xwm: XwmId,
window: X11Surface,
geometry: Rectangle<i32, Logical>,
above: Option<Window>,
) {
debug!(?window, ?geometry, above, "Configure X window");
}
fn resize_request(
&mut self,
_xwm: XwmId,
window: X11Surface,
button: u32,
resize_edge: ResizeEdge,
) {
debug!(?window, button, ?resize_edge, "X window requests resize");
}
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, button: u32) {
debug!(?window, button, "X window requests move");
}
}