feat: add nested Phase 0 compositor
This commit is contained in:
1 parent
aab447ef25
commit
475d433ec4
8 files changed
+2710
-2
No files matched your search
@@ -0,0 +1,122 @@
|
||||
use std::{error::Error, ffi::OsString, sync::Arc, time::Instant};
|
||||
|
||||
use smithay::{
|
||||
desktop::{PopupManager, Space, Window, WindowSurfaceType},
|
||||
input::{Seat, SeatState},
|
||||
reexports::{
|
||||
calloop::{EventLoop, Interest, LoopSignal, Mode, PostAction, generic::Generic},
|
||||
wayland_server::{
|
||||
Display, DisplayHandle,
|
||||
backend::{ClientData, ClientId, DisconnectReason},
|
||||
protocol::wl_surface::WlSurface,
|
||||
},
|
||||
},
|
||||
utils::{Logical, Point},
|
||||
wayland::{
|
||||
compositor::{CompositorClientState, CompositorState},
|
||||
output::OutputManagerState,
|
||||
shell::xdg::XdgShellState,
|
||||
shm::ShmState,
|
||||
socket::ListeningSocketSource,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Ferese {
|
||||
pub start_time: Instant,
|
||||
pub socket_name: OsString,
|
||||
pub display_handle: DisplayHandle,
|
||||
pub loop_signal: LoopSignal,
|
||||
pub space: Space<Window>,
|
||||
pub popups: PopupManager,
|
||||
pub seat: Seat<Self>,
|
||||
pub compositor_state: CompositorState,
|
||||
pub output_manager_state: OutputManagerState,
|
||||
pub seat_state: SeatState<Self>,
|
||||
pub shm_state: ShmState,
|
||||
pub xdg_shell_state: XdgShellState,
|
||||
}
|
||||
|
||||
impl Ferese {
|
||||
pub fn new(
|
||||
event_loop: &mut EventLoop<Self>,
|
||||
display: Display<Self>,
|
||||
) -> Result<Self, Box<dyn Error>> {
|
||||
let display_handle = display.handle();
|
||||
let compositor_state = CompositorState::new::<Self>(&display_handle);
|
||||
let xdg_shell_state = XdgShellState::new::<Self>(&display_handle);
|
||||
let shm_state = ShmState::new::<Self>(&display_handle, Vec::new());
|
||||
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
|
||||
let mut seat_state = SeatState::new();
|
||||
let mut seat = seat_state.new_wl_seat(&display_handle, "ferese-winit");
|
||||
seat.add_keyboard(Default::default(), 200, 25)?;
|
||||
seat.add_pointer();
|
||||
let socket_name = Self::init_wayland_listener(display, event_loop)?;
|
||||
|
||||
Ok(Self {
|
||||
start_time: Instant::now(),
|
||||
socket_name,
|
||||
display_handle,
|
||||
loop_signal: event_loop.get_signal(),
|
||||
space: Space::default(),
|
||||
popups: PopupManager::default(),
|
||||
seat,
|
||||
compositor_state,
|
||||
output_manager_state,
|
||||
seat_state,
|
||||
shm_state,
|
||||
xdg_shell_state,
|
||||
})
|
||||
}
|
||||
|
||||
fn init_wayland_listener(
|
||||
display: Display<Self>,
|
||||
event_loop: &mut EventLoop<Self>,
|
||||
) -> Result<OsString, Box<dyn Error>> {
|
||||
let listening_socket = ListeningSocketSource::new_auto()?;
|
||||
let socket_name = listening_socket.socket_name().to_os_string();
|
||||
let loop_handle = event_loop.handle();
|
||||
|
||||
loop_handle.insert_source(listening_socket, |client_stream, _, state| {
|
||||
if let Err(error) = state
|
||||
.display_handle
|
||||
.insert_client(client_stream, Arc::new(ClientState::default()))
|
||||
{
|
||||
tracing::warn!(%error, "failed to register Wayland client");
|
||||
}
|
||||
})?;
|
||||
loop_handle.insert_source(
|
||||
Generic::new(display, Interest::READ, Mode::Level),
|
||||
|_, display, state| {
|
||||
// SAFETY: this event source owns the display for the loop lifetime.
|
||||
unsafe { display.get_mut().dispatch_clients(state)? };
|
||||
Ok(PostAction::Continue)
|
||||
},
|
||||
)?;
|
||||
Ok(socket_name)
|
||||
}
|
||||
|
||||
pub fn surface_under(
|
||||
&self,
|
||||
position: Point<f64, Logical>,
|
||||
) -> Option<(WlSurface, Point<f64, Logical>)> {
|
||||
self.space
|
||||
.element_under(position)
|
||||
.and_then(|(window, location)| {
|
||||
window
|
||||
.surface_under(position - location.to_f64(), WindowSurfaceType::ALL)
|
||||
.map(|(surface, surface_location)| {
|
||||
(surface, (surface_location + location).to_f64())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ClientState {
|
||||
pub compositor_state: CompositorClientState,
|
||||
}
|
||||
|
||||
impl ClientData for ClientState {
|
||||
fn initialized(&self, _client_id: ClientId) {}
|
||||
fn disconnected(&self, _client_id: ClientId, _reason: DisconnectReason) {}
|
||||
}
|
||||
Reference in new issue
Block a user