refactor: trait away panel item backends
This commit is contained in:
@@ -1,16 +1,23 @@
|
||||
use super::{panel_item::RecommendedState, seat::SeatData, state::WaylandState};
|
||||
use crate::wayland::{
|
||||
panel_item::{Backend, PanelItem, X11Backend},
|
||||
surface::CoreSurface,
|
||||
use super::{
|
||||
seat::{KeyboardEvent, PointerEvent, SeatData},
|
||||
xdg_shell::PopupData,
|
||||
};
|
||||
use crate::{
|
||||
nodes::{
|
||||
drawable::model::ModelPart,
|
||||
items::panel::{Backend, PanelItem, RecommendedState, SurfaceID},
|
||||
},
|
||||
wayland::surface::CoreSurface,
|
||||
};
|
||||
use color_eyre::eyre::Result;
|
||||
use mint::Vector2;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use smithay::{
|
||||
reexports::{
|
||||
calloop::{EventLoop, LoopSignal},
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||
wayland_server::{Display, DisplayHandle, Resource, WEnum},
|
||||
wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle, Resource, WEnum},
|
||||
x11rb::protocol::xproto::Window,
|
||||
},
|
||||
utils::{Logical, Rectangle},
|
||||
@@ -20,6 +27,7 @@ use smithay::{
|
||||
X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler,
|
||||
},
|
||||
};
|
||||
use stardust_xr::schemas::flex::serialize;
|
||||
use std::{ffi::OsStr, iter::empty, sync::Arc, time::Duration};
|
||||
use tokio::sync::oneshot;
|
||||
use tracing::debug;
|
||||
@@ -31,10 +39,7 @@ pub struct XWaylandState {
|
||||
event_loop_signal: LoopSignal,
|
||||
}
|
||||
impl XWaylandState {
|
||||
pub fn create(
|
||||
wayland_display: Arc<Mutex<Display<WaylandState>>>,
|
||||
dh: &DisplayHandle,
|
||||
) -> Result<Self> {
|
||||
pub fn create(dh: &DisplayHandle) -> Result<Self> {
|
||||
let dh = dh.clone();
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
@@ -45,18 +50,22 @@ impl XWaylandState {
|
||||
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();
|
||||
.insert_source(connection, {
|
||||
let dh = dh.clone();
|
||||
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 => (),
|
||||
}
|
||||
XWaylandEvent::Exited => (),
|
||||
})
|
||||
.map_err(|e| e.error)?;
|
||||
|
||||
@@ -71,10 +80,8 @@ impl XWaylandState {
|
||||
display,
|
||||
event_loop_signal: event_loop.get_signal(),
|
||||
});
|
||||
let wayland_display_handle = wayland_display.lock().handle();
|
||||
let mut handler = XWaylandHandler {
|
||||
wayland_display,
|
||||
wayland_display_handle,
|
||||
wayland_display_handle: dh,
|
||||
wm: None,
|
||||
seat: None,
|
||||
};
|
||||
@@ -94,15 +101,14 @@ impl Drop for XWaylandState {
|
||||
}
|
||||
|
||||
struct XWaylandHandler {
|
||||
wayland_display: Arc<Mutex<Display<WaylandState>>>,
|
||||
wayland_display_handle: DisplayHandle,
|
||||
wm: Option<X11Wm>,
|
||||
seat: Option<Arc<SeatData>>,
|
||||
}
|
||||
impl XWaylandHandler {
|
||||
fn panel_item(&self, window: &X11Surface) -> Option<Arc<PanelItem>> {
|
||||
fn panel_item(&self, window: &X11Surface) -> Option<Arc<PanelItem<X11Backend>>> {
|
||||
compositor::with_states(&window.wl_surface()?, |s| {
|
||||
s.data_map.get::<Arc<PanelItem>>().cloned()
|
||||
s.data_map.get::<Arc<PanelItem<X11Backend>>>().cloned()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -130,8 +136,7 @@ impl XwmHandler for XWaylandHandler {
|
||||
let dh = self.wayland_display_handle.clone();
|
||||
let seat = self.seat.clone().unwrap();
|
||||
CoreSurface::add_to(
|
||||
&self.wayland_display,
|
||||
self.wayland_display.lock().handle(),
|
||||
self.wayland_display_handle.clone(),
|
||||
&window.wl_surface().unwrap(),
|
||||
{
|
||||
let window = window.clone();
|
||||
@@ -140,22 +145,24 @@ impl XwmHandler for XWaylandHandler {
|
||||
let seat = seat.clone();
|
||||
window.user_data().insert_if_missing_threadsafe(|| {
|
||||
let (_node, panel_item) = PanelItem::create(
|
||||
wl_surface.clone(),
|
||||
Backend::X11(X11Backend {
|
||||
Box::new(X11Backend {
|
||||
toplevel_parent: None,
|
||||
toplevel: window.clone(),
|
||||
seat,
|
||||
_pointer_grab: Mutex::new(None),
|
||||
_keyboard_grab: Mutex::new(None),
|
||||
}),
|
||||
wl_surface
|
||||
.client()
|
||||
.and_then(|c| c.get_credentials(&dh).ok()),
|
||||
seat,
|
||||
.and_then(|c| c.get_credentials(&dh).ok())
|
||||
.map(|c| c.pid),
|
||||
);
|
||||
panel_item
|
||||
});
|
||||
}
|
||||
},
|
||||
move |_| {
|
||||
let Some(panel_item) = window.user_data().get::<Arc<PanelItem>>() else {return};
|
||||
let Some(panel_item) = window.user_data().get::<Arc<PanelItem<X11Backend>>>() else {return};
|
||||
panel_item.commit_toplevel();
|
||||
},
|
||||
);
|
||||
@@ -246,3 +253,144 @@ impl XwmHandler for XWaylandHandler {
|
||||
panel_item.recommend_toplevel_state(RecommendedState::Minimize);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct X11Backend {
|
||||
pub toplevel_parent: Option<X11Surface>,
|
||||
pub toplevel: X11Surface,
|
||||
pub seat: Arc<SeatData>,
|
||||
_pointer_grab: Mutex<Option<SurfaceID>>,
|
||||
_keyboard_grab: Mutex<Option<SurfaceID>>,
|
||||
}
|
||||
impl X11Backend {
|
||||
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
|
||||
match id {
|
||||
SurfaceID::Cursor => None,
|
||||
SurfaceID::Toplevel => self.toplevel.wl_surface(),
|
||||
SurfaceID::Popup(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
// fn flush_client(&self) {
|
||||
// let Some(client) = self.toplevel.wl_surface().and_then(|s| s.client()) else {return};
|
||||
// if let Some(client_state) = client.get_data::<ClientState>() {
|
||||
// client_state.flush();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
impl Backend for X11Backend {
|
||||
fn serialize_start_data(&self, id: &str) -> Result<Vec<u8>> {
|
||||
let size = (
|
||||
self.toplevel.geometry().size.w as u32,
|
||||
self.toplevel.geometry().size.h as u32,
|
||||
);
|
||||
let toplevel_state = (
|
||||
None::<String>,
|
||||
self.toplevel.title(),
|
||||
None::<String>,
|
||||
(
|
||||
self.toplevel.geometry().size.w as u32,
|
||||
self.toplevel.geometry().size.h as u32,
|
||||
),
|
||||
self.toplevel.min_size().map(|s| (s.w as u32, s.h as u32)),
|
||||
self.toplevel.max_size().map(|s| (s.w as u32, s.w as u32)),
|
||||
((0_i32, 0_i32), size),
|
||||
vec![0_u32; 0],
|
||||
);
|
||||
let info = (
|
||||
None::<(Vector2<u32>, Vector2<i32>)>,
|
||||
toplevel_state,
|
||||
Vec::<PopupData>::new(),
|
||||
None::<SurfaceID>,
|
||||
None::<SurfaceID>,
|
||||
);
|
||||
serialize((id, info)).map_err(|e| e.into())
|
||||
}
|
||||
fn serialize_toplevel(&self) -> Result<Vec<u8>> {
|
||||
let toplevel_state = (
|
||||
None::<String>,
|
||||
self.toplevel.title(),
|
||||
None::<String>,
|
||||
(
|
||||
self.toplevel.geometry().size.w,
|
||||
self.toplevel.geometry().size.h,
|
||||
),
|
||||
self.toplevel.min_size().map(|s| (s.w, s.h)),
|
||||
self.toplevel.max_size().map(|s| (s.w, s.w)),
|
||||
);
|
||||
let data = serialize(&toplevel_state)?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
fn set_toplevel_capabilities(&self, _capabilities: Vec<u8>) {}
|
||||
|
||||
fn configure_toplevel(
|
||||
&self,
|
||||
size: Option<Vector2<u32>>,
|
||||
states: Vec<u32>,
|
||||
_bounds: Option<Vector2<u32>>,
|
||||
) {
|
||||
let _ = self.toplevel.configure(
|
||||
size.map(|s| Rectangle::from_loc_and_size((0, 0), (s.x as i32, s.y as i32))),
|
||||
);
|
||||
let _ = self.toplevel.set_maximized(states.contains(&1));
|
||||
}
|
||||
|
||||
fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc<ModelPart>) {
|
||||
let Some(wl_surface) = self.wl_surface_from_id(&surface) else {return};
|
||||
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return};
|
||||
|
||||
core_surface.apply_material(model_part);
|
||||
}
|
||||
|
||||
fn pointer_motion(&self, surface: &SurfaceID, position: Vector2<f32>) {
|
||||
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
||||
self.seat
|
||||
.pointer_event(&surface, PointerEvent::Motion(position));
|
||||
}
|
||||
fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool) {
|
||||
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
||||
self.seat.pointer_event(
|
||||
&surface,
|
||||
PointerEvent::Button {
|
||||
button,
|
||||
state: if pressed { 1 } else { 0 },
|
||||
},
|
||||
)
|
||||
}
|
||||
fn pointer_scroll(
|
||||
&self,
|
||||
surface: &SurfaceID,
|
||||
scroll_distance: Option<Vector2<f32>>,
|
||||
scroll_steps: Option<Vector2<f32>>,
|
||||
) {
|
||||
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
||||
self.seat.pointer_event(
|
||||
&surface,
|
||||
PointerEvent::Scroll {
|
||||
axis_continuous: scroll_distance,
|
||||
axis_discrete: scroll_steps,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn keyboard_set_keymap(&self, keymap: &str) -> Result<()> {
|
||||
self.seat.set_keymap_str(
|
||||
&keymap,
|
||||
if let Some(toplevel) = self.toplevel.wl_surface() {
|
||||
vec![toplevel]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
)
|
||||
}
|
||||
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
|
||||
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
||||
self.seat.keyboard_event(
|
||||
&surface,
|
||||
KeyboardEvent::Key {
|
||||
key,
|
||||
state: if state { 1 } else { 0 },
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user