feat(wayland): initial xwayland support
This commit is contained in:
108
Cargo.lock
generated
108
Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
157
src/wayland/xwayland.rs
Normal 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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user