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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
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]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -813,6 +877,16 @@ dependencies = [
|
|||||||
"pin-utils",
|
"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]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
@@ -1988,6 +2062,7 @@ dependencies = [
|
|||||||
"drm",
|
"drm",
|
||||||
"drm-ffi",
|
"drm-ffi",
|
||||||
"drm-fourcc",
|
"drm-fourcc",
|
||||||
|
"encoding",
|
||||||
"gl_generator",
|
"gl_generator",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -1998,6 +2073,7 @@ dependencies = [
|
|||||||
"profiling",
|
"profiling",
|
||||||
"rand",
|
"rand",
|
||||||
"scan_fmt",
|
"scan_fmt",
|
||||||
|
"scopeguard",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -2005,6 +2081,7 @@ dependencies = [
|
|||||||
"wayland-protocols-misc",
|
"wayland-protocols-misc",
|
||||||
"wayland-protocols-wlr",
|
"wayland-protocols-wlr",
|
||||||
"wayland-server",
|
"wayland-server",
|
||||||
|
"x11rb",
|
||||||
"xkbcommon",
|
"xkbcommon",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2654,6 +2731,15 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
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]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -2744,6 +2830,28 @@ dependencies = [
|
|||||||
"memchr",
|
"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]]
|
[[package]]
|
||||||
name = "xkbcommon"
|
name = "xkbcommon"
|
||||||
version = "0.5.1"
|
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
|
git = "https://github.com/smithay/smithay.git" # Until we get stereokit to understand OES samplers and external textures
|
||||||
# path = "../smithay"
|
# path = "../smithay"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["desktop", "backend_drm", "renderer_gl", "wayland_frontend"]
|
features = [
|
||||||
|
"desktop",
|
||||||
|
"backend_drm",
|
||||||
|
"renderer_gl",
|
||||||
|
"wayland_frontend",
|
||||||
|
"xwayland",
|
||||||
|
]
|
||||||
version = "*"
|
version = "*"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ fn main() {
|
|||||||
std::env::var_os("WAYLAND_DISPLAY").unwrap_or_default(),
|
std::env::var_os("WAYLAND_DISPLAY").unwrap_or_default(),
|
||||||
)
|
)
|
||||||
.env("WAYLAND_DISPLAY", &wayland.socket_name)
|
.env("WAYLAND_DISPLAY", &wayland.socket_name)
|
||||||
|
.env("DISPLAY", format!(":{}", wayland.xwayland_state.display))
|
||||||
.env(
|
.env(
|
||||||
"STARDUST_INSTANCE",
|
"STARDUST_INSTANCE",
|
||||||
event_loop_info
|
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::{
|
use super::{
|
||||||
items::{ItemAcceptor, TypeInfo},
|
items::{ItemAcceptor, TypeInfo},
|
||||||
@@ -135,6 +139,7 @@ pub fn get_connection_environment_flex(
|
|||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
{
|
{
|
||||||
var_env_insert!(env, WAYLAND_DISPLAY);
|
var_env_insert!(env, WAYLAND_DISPLAY);
|
||||||
|
var_env_insert!(env, DISPLAY);
|
||||||
env.insert("GDK_BACKEND".to_string(), "wayland".to_string());
|
env.insert("GDK_BACKEND".to_string(), "wayland".to_string());
|
||||||
env.insert("QT_QPA_PLATFORM".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());
|
env.insert("MOZ_ENABLE_WAYLAND".to_string(), "1".to_string());
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ mod state;
|
|||||||
mod surface;
|
mod surface;
|
||||||
// mod xdg_activation;
|
// mod xdg_activation;
|
||||||
mod xdg_shell;
|
mod xdg_shell;
|
||||||
|
pub mod xwayland;
|
||||||
|
|
||||||
|
use self::xwayland::XWaylandState;
|
||||||
use self::{state::WaylandState, surface::CORE_SURFACES};
|
use self::{state::WaylandState, surface::CORE_SURFACES};
|
||||||
use crate::{core::task, wayland::state::ClientState};
|
use crate::{core::task, wayland::state::ClientState};
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::{ensure, Result};
|
||||||
@@ -67,7 +69,8 @@ pub struct Wayland {
|
|||||||
join_handle: JoinHandle<Result<()>>,
|
join_handle: JoinHandle<Result<()>>,
|
||||||
renderer: GlesRenderer,
|
renderer: GlesRenderer,
|
||||||
dmabuf_rx: UnboundedReceiver<Dmabuf>,
|
dmabuf_rx: UnboundedReceiver<Dmabuf>,
|
||||||
state: Arc<Mutex<WaylandState>>,
|
wayland_state: Arc<Mutex<WaylandState>>,
|
||||||
|
pub xwayland_state: XWaylandState,
|
||||||
}
|
}
|
||||||
impl Wayland {
|
impl Wayland {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
@@ -85,7 +88,8 @@ impl Wayland {
|
|||||||
|
|
||||||
let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel();
|
let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel();
|
||||||
let display = Arc::new(Mutex::new(display));
|
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);
|
let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8);
|
||||||
GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap();
|
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");
|
.expect("seriously message nova this time they screwed up big time");
|
||||||
info!(socket_name, "Wayland active");
|
info!(socket_name, "Wayland active");
|
||||||
|
|
||||||
let join_handle =
|
let join_handle = Wayland::start_loop(
|
||||||
Wayland::start_loop(display.clone(), socket, state.clone(), global_destroy_queue)?;
|
display.clone(),
|
||||||
|
socket,
|
||||||
|
wayland_state.clone(),
|
||||||
|
global_destroy_queue,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(Wayland {
|
Ok(Wayland {
|
||||||
display,
|
display,
|
||||||
@@ -106,7 +114,8 @@ impl Wayland {
|
|||||||
join_handle,
|
join_handle,
|
||||||
renderer,
|
renderer,
|
||||||
dmabuf_rx,
|
dmabuf_rx,
|
||||||
state,
|
wayland_state,
|
||||||
|
xwayland_state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +176,7 @@ impl Wayland {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame_event(&self, sk: &impl StereoKitDraw) {
|
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() {
|
for core_surface in CORE_SURFACES.get_valid_contents() {
|
||||||
core_surface.frame(sk, state.output.clone());
|
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