refactor: trait away panel item backends

This commit is contained in:
Nova
2023-07-23 19:59:35 -04:00
parent eedf5446e8
commit 1047f5242b
10 changed files with 1037 additions and 950 deletions

View File

@@ -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 },
},
)
}
}