feat(wayland): initial xwayland support

This commit is contained in:
Nova
2023-05-11 04:58:49 -04:00
parent 08010efa46
commit e879b724ec
6 changed files with 294 additions and 8 deletions

108
Cargo.lock generated
View File

@@ -670,6 +670,70 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "encoding"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
dependencies = [
"encoding-index-japanese",
"encoding-index-korean",
"encoding-index-simpchinese",
"encoding-index-singlebyte",
"encoding-index-tradchinese",
]
[[package]]
name = "encoding-index-japanese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-korean"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-simpchinese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-singlebyte"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-tradchinese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding_index_tests"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
[[package]]
name = "equivalent"
version = "1.0.1"
@@ -813,6 +877,16 @@ dependencies = [
"pin-utils",
]
[[package]]
name = "gethostname"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "getrandom"
version = "0.2.10"
@@ -1988,6 +2062,7 @@ dependencies = [
"drm",
"drm-ffi",
"drm-fourcc",
"encoding",
"gl_generator",
"indexmap 1.9.3",
"lazy_static",
@@ -1998,6 +2073,7 @@ dependencies = [
"profiling",
"rand",
"scan_fmt",
"scopeguard",
"tempfile",
"thiserror",
"tracing",
@@ -2005,6 +2081,7 @@ dependencies = [
"wayland-protocols-misc",
"wayland-protocols-wlr",
"wayland-server",
"x11rb",
"xkbcommon",
]
@@ -2654,6 +2731,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-wsapoll"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -2744,6 +2830,28 @@ dependencies = [
"memchr",
]
[[package]]
name = "x11rb"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617"
dependencies = [
"gethostname",
"nix 0.25.1",
"winapi",
"winapi-wsapoll",
"x11rb-protocol",
]
[[package]]
name = "x11rb-protocol"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0b1513b141123073ce54d5bb1d33f801f17508fbd61e02060b1214e96d39c56"
dependencies = [
"nix 0.25.1",
]
[[package]]
name = "xkbcommon"
version = "0.5.1"

View File

@@ -70,7 +70,13 @@ version = "0.16.7"
git = "https://github.com/smithay/smithay.git" # Until we get stereokit to understand OES samplers and external textures
# path = "../smithay"
default-features = false
features = ["desktop", "backend_drm", "renderer_gl", "wayland_frontend"]
features = [
"desktop",
"backend_drm",
"renderer_gl",
"wayland_frontend",
"xwayland",
]
version = "*"
optional = true

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");
}
}