Skip to content

Commit 3149aef

Browse files
authored
Create xwayland.rs
1 parent c1212bf commit 3149aef

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use calloop::LoopHandle;
2+
use smithay::{
3+
desktop::Window,
4+
utils::{Logical, Point, Rectangle},
5+
wayland::seat::WaylandFocus,
6+
wayland::selection::SelectionTarget,
7+
xwayland::{
8+
xwm::{Reorder, ResizeEdge as X11ResizeEdge, XwmId},
9+
X11Surface, X11Wm, XWayland, XWaylandClientData, XWaylandEvent,
10+
},
11+
};
12+
use tracing::{info, warn};
13+
14+
use crate::state::BlueState;
15+
16+
pub fn init_xwayland(state: &mut BlueState, loop_handle: &LoopHandle<'static, BlueState>) {
17+
let xwayland = XWayland::new(loop_handle, &state.display_handle);
18+
19+
match xwayland {
20+
Ok((xwl, source)) => {
21+
loop_handle
22+
.insert_source(source, |event, _, state: &mut BlueState| {
23+
handle_xwayland_event(state, event);
24+
})
25+
.expect("Failed to insert XWayland source");
26+
info!("XWayland initialized");
27+
}
28+
Err(e) => {
29+
warn!("Failed to init XWayland: {} (X11 apps won't work)", e);
30+
}
31+
}
32+
}
33+
34+
fn handle_xwayland_event(state: &mut BlueState, event: XWaylandEvent) {
35+
match event {
36+
XWaylandEvent::Ready { x11_socket, display_number } => {
37+
info!("XWayland ready on DISPLAY :{}", display_number);
38+
std::env::set_var("DISPLAY", format!(":{}", display_number));
39+
state.x11_display = Some(display_number);
40+
41+
match X11Wm::start_wm(state.loop_handle.clone(), x11_socket, state.display_handle.clone()) {
42+
Ok(wm) => { state.xwm = Some(wm); }
43+
Err(e) => warn!("Failed to start X11 WM: {}", e),
44+
}
45+
}
46+
XWaylandEvent::Error => {
47+
warn!("XWayland encountered an error");
48+
state.xwm = None;
49+
}
50+
}
51+
}
52+
53+
// ── XWayland shell handler ─────────────────────────────────────────────────
54+
55+
impl smithay::xwayland::xwayland_shell::XWaylandShellHandler for BlueState {
56+
fn xwayland_shell_state(&mut self) -> &mut smithay::xwayland::xwayland_shell::XWaylandShellState {
57+
panic!("XWaylandShellState not initialized — needed by XWaylandShellHandler");
58+
}
59+
}
60+
smithay::delegate_xwayland_shell!(BlueState);
61+
62+
// ── X11 WM implementation ──────────────────────────────────────────────────
63+
64+
impl smithay::xwayland::xwm::XwmHandler for BlueState {
65+
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
66+
self.xwm.as_mut().unwrap()
67+
}
68+
69+
fn new_window(&mut self, _xwm: XwmId, _window: X11Surface) {}
70+
fn new_override_redirect_window(&mut self, _xwm: XwmId, _window: X11Surface) {}
71+
72+
fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) {
73+
window.set_mapped(true).ok();
74+
let offset = self.space.elements().count() * 30;
75+
let loc = Point::from(((offset + 150) as i32, (offset + 80) as i32));
76+
self.space.map_element(Window::new_x11_window(window), loc, true);
77+
}
78+
79+
fn map_window_notify(&mut self, _xwm: XwmId, _window: X11Surface) {}
80+
81+
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
82+
self.space.map_element(
83+
Window::new_x11_window(window),
84+
Point::from((100_i32, 100_i32)),
85+
true,
86+
);
87+
}
88+
89+
fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
90+
let found = self
91+
.space
92+
.elements()
93+
.find(|w| w.x11_surface().map(|x| x == &window).unwrap_or(false))
94+
.cloned();
95+
if let Some(w) = found {
96+
self.space.unmap_elem(&w);
97+
}
98+
}
99+
100+
fn destroyed_window(&mut self, _xwm: XwmId, _window: X11Surface) {}
101+
102+
fn configure_request(
103+
&mut self,
104+
_xwm: XwmId,
105+
window: X11Surface,
106+
_x: Option<i32>,
107+
_y: Option<i32>,
108+
w: Option<u32>,
109+
h: Option<u32>,
110+
_reorder: Option<Reorder>,
111+
) {
112+
let mut geo = window.geometry();
113+
if let Some(w) = w { geo.size.w = w as i32; }
114+
if let Some(h) = h { geo.size.h = h as i32; }
115+
let _ = window.configure(geo);
116+
}
117+
118+
fn configure_notify(
119+
&mut self,
120+
_xwm: XwmId,
121+
_window: X11Surface,
122+
_geometry: Rectangle<i32, Logical>,
123+
_above: Option<u32>,
124+
) {}
125+
126+
fn resize_request(
127+
&mut self,
128+
_xwm: XwmId,
129+
_window: X11Surface,
130+
_button: u32,
131+
_resize_edge: X11ResizeEdge,
132+
) {}
133+
134+
fn move_request(&mut self, _xwm: XwmId, _window: X11Surface, _button: u32) {}
135+
136+
fn send_selection(
137+
&mut self,
138+
_xwm: XwmId,
139+
_selection: SelectionTarget,
140+
_mime_type: String,
141+
_fd: std::os::fd::OwnedFd,
142+
) {}
143+
144+
fn allow_selection_access(&mut self, _xwm: XwmId, _selection: SelectionTarget) -> bool {
145+
true
146+
}
147+
148+
fn new_selection(
149+
&mut self,
150+
_xwm: XwmId,
151+
_selection: SelectionTarget,
152+
_mime_types: Vec<String>,
153+
) {}
154+
155+
fn cleared_selection(&mut self, _xwm: XwmId, _selection: SelectionTarget) {}
156+
}
157+
158+
smithay::delegate_xwm!(BlueState);

0 commit comments

Comments
 (0)