mirror of
https://github.com/CloudNebulaProject/wayray.git
synced 2026-04-10 13:10:41 +00:00
Wire up Winit backend and calloop event loop for wrsrvd
Initialize WinitGraphicsBackend with GlesRenderer, create a virtual Output matching the window size, set up a Wayland listening socket via ListeningSocketSource, and run the main event loop through calloop with WinitEventLoop as an event source. The compositor now opens a window and accepts Wayland client connections.
This commit is contained in:
parent
383e91addf
commit
50c8f68906
2 changed files with 150 additions and 4 deletions
|
|
@ -2,11 +2,31 @@ mod errors;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::handlers::ClientState;
|
||||||
use crate::state::WayRay;
|
use crate::state::WayRay;
|
||||||
use miette::Result;
|
use miette::Result;
|
||||||
use smithay::reexports::wayland_server::Display;
|
use smithay::{
|
||||||
|
backend::{
|
||||||
|
renderer::gles::GlesRenderer,
|
||||||
|
winit::{self, WinitEvent},
|
||||||
|
},
|
||||||
|
output::{Mode, Output, PhysicalProperties, Subpixel},
|
||||||
|
reexports::wayland_server::Display,
|
||||||
|
utils::Transform,
|
||||||
|
wayland::{compositor::CompositorClientState, socket::ListeningSocketSource},
|
||||||
|
};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
/// Data accessible from calloop event callbacks.
|
||||||
|
struct CalloopData {
|
||||||
|
state: WayRay,
|
||||||
|
display: Display<WayRay>,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
.with_env_filter(
|
.with_env_filter(
|
||||||
|
|
@ -17,10 +37,133 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
info!("wrsrvd starting");
|
info!("wrsrvd starting");
|
||||||
|
|
||||||
|
// Create the Wayland display.
|
||||||
let mut display = Display::<WayRay>::new()
|
let mut display = Display::<WayRay>::new()
|
||||||
.map_err(|e| errors::WayRayError::DisplayInit(Box::new(e)))?;
|
.map_err(|e| errors::WayRayError::DisplayInit(Box::new(e)))?;
|
||||||
let _state = WayRay::new(&mut display);
|
|
||||||
info!("compositor state initialized");
|
|
||||||
|
|
||||||
|
// Initialize the Winit backend (opens a window, creates a GlesRenderer).
|
||||||
|
let (backend, winit_event_loop) = winit::init::<GlesRenderer>().map_err(|e| {
|
||||||
|
errors::WayRayError::BackendInit(Box::<dyn std::error::Error + Send + Sync>::from(
|
||||||
|
e.to_string(),
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
info!("winit backend initialized");
|
||||||
|
|
||||||
|
// Create a virtual output matching the window size.
|
||||||
|
let window_size = backend.window_size();
|
||||||
|
let output = Output::new(
|
||||||
|
"wayray-0".to_string(),
|
||||||
|
PhysicalProperties {
|
||||||
|
size: (0, 0).into(),
|
||||||
|
subpixel: Subpixel::Unknown,
|
||||||
|
make: "WayRay".to_string(),
|
||||||
|
model: "Virtual".to_string(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let mode = Mode {
|
||||||
|
size: window_size,
|
||||||
|
refresh: 60_000, // 60 Hz in millihertz
|
||||||
|
};
|
||||||
|
output.change_current_state(Some(mode), Some(Transform::Flipped180), None, None);
|
||||||
|
output.set_preferred(mode);
|
||||||
|
|
||||||
|
// Create the global output for Wayland clients to bind to.
|
||||||
|
output.create_global::<WayRay>(&display.handle());
|
||||||
|
|
||||||
|
// Create compositor state.
|
||||||
|
let mut state = WayRay::new(&mut display, output.clone());
|
||||||
|
|
||||||
|
// Map the output into the compositor space.
|
||||||
|
state.space.map_output(&output, (0, 0));
|
||||||
|
info!("output mapped: {:?} @ {:?}", mode.size, mode.refresh);
|
||||||
|
|
||||||
|
// Create a Wayland listening socket for clients.
|
||||||
|
let listening_socket = ListeningSocketSource::new_auto()
|
||||||
|
.map_err(|e| errors::WayRayError::DisplayInit(Box::new(e)))?;
|
||||||
|
let socket_name = listening_socket.socket_name().to_os_string();
|
||||||
|
info!(?socket_name, "wayland socket created");
|
||||||
|
|
||||||
|
// Set WAYLAND_DISPLAY so child processes can find us.
|
||||||
|
// SAFETY: This is called early in main before any other threads are spawned,
|
||||||
|
// so there are no concurrent readers of the environment.
|
||||||
|
unsafe { std::env::set_var("WAYLAND_DISPLAY", &socket_name) };
|
||||||
|
|
||||||
|
// Create the calloop event loop.
|
||||||
|
let mut event_loop: smithay::reexports::calloop::EventLoop<CalloopData> =
|
||||||
|
smithay::reexports::calloop::EventLoop::try_new()
|
||||||
|
.map_err(|e| errors::WayRayError::EventLoop(Box::new(e)))?;
|
||||||
|
|
||||||
|
let loop_handle = event_loop.handle();
|
||||||
|
|
||||||
|
// Insert the Wayland listening socket as a calloop source.
|
||||||
|
// When a new client connects, insert it into the display.
|
||||||
|
loop_handle
|
||||||
|
.insert_source(listening_socket, |client_stream, _, data| {
|
||||||
|
data.display
|
||||||
|
.handle()
|
||||||
|
.insert_client(
|
||||||
|
client_stream,
|
||||||
|
Arc::new(ClientState {
|
||||||
|
compositor_state: CompositorClientState::default(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.map_err(|e| errors::WayRayError::EventLoop(Box::new(e.error)))?;
|
||||||
|
|
||||||
|
// Shared flag to signal the main loop to exit.
|
||||||
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
let running_clone = running.clone();
|
||||||
|
|
||||||
|
// Insert the Winit event loop as a calloop source.
|
||||||
|
loop_handle
|
||||||
|
.insert_source(winit_event_loop, move |event, _, _data| match event {
|
||||||
|
WinitEvent::Resized { size, scale_factor } => {
|
||||||
|
info!(?size, scale_factor, "window resized");
|
||||||
|
}
|
||||||
|
WinitEvent::Focus(focused) => {
|
||||||
|
info!(focused, "window focus changed");
|
||||||
|
}
|
||||||
|
WinitEvent::Input(_event) => {
|
||||||
|
// Input handling is Task 7 -- ignore for now.
|
||||||
|
}
|
||||||
|
WinitEvent::Redraw => {
|
||||||
|
// Rendering is Task 6 -- ignore for now.
|
||||||
|
}
|
||||||
|
WinitEvent::CloseRequested => {
|
||||||
|
info!("close requested, shutting down");
|
||||||
|
running_clone.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map_err(|e| errors::WayRayError::EventLoop(Box::new(e.error)))?;
|
||||||
|
|
||||||
|
// Keep a handle to the backend (needed for rendering in Task 6).
|
||||||
|
let _backend = backend;
|
||||||
|
|
||||||
|
let mut calloop_data = CalloopData { state, display };
|
||||||
|
|
||||||
|
info!("entering main event loop");
|
||||||
|
|
||||||
|
// Main event loop.
|
||||||
|
while running.load(Ordering::SeqCst) {
|
||||||
|
// Dispatch Wayland clients.
|
||||||
|
calloop_data
|
||||||
|
.display
|
||||||
|
.dispatch_clients(&mut calloop_data.state)
|
||||||
|
.map_err(|e| errors::WayRayError::EventLoop(Box::new(e)))?;
|
||||||
|
|
||||||
|
calloop_data
|
||||||
|
.display
|
||||||
|
.flush_clients()
|
||||||
|
.map_err(|e| errors::WayRayError::EventLoop(Box::new(e)))?;
|
||||||
|
|
||||||
|
// Dispatch calloop sources (Winit events + Wayland socket) with ~16ms timeout.
|
||||||
|
event_loop
|
||||||
|
.dispatch(Duration::from_millis(16), &mut calloop_data)
|
||||||
|
.map_err(|e| errors::WayRayError::EventLoop(Box::new(e)))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("wrsrvd shutting down");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::Space,
|
desktop::Space,
|
||||||
input::{Seat, SeatState},
|
input::{Seat, SeatState},
|
||||||
|
output::Output,
|
||||||
reexports::wayland_server::{Display, DisplayHandle},
|
reexports::wayland_server::{Display, DisplayHandle},
|
||||||
utils::{Clock, Monotonic},
|
utils::{Clock, Monotonic},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -28,11 +29,12 @@ pub struct WayRay {
|
||||||
pub space: Space<smithay::desktop::Window>,
|
pub space: Space<smithay::desktop::Window>,
|
||||||
pub seat: Seat<Self>,
|
pub seat: Seat<Self>,
|
||||||
pub clock: Clock<Monotonic>,
|
pub clock: Clock<Monotonic>,
|
||||||
|
pub output: Output,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WayRay {
|
impl WayRay {
|
||||||
/// Create a new WayRay compositor state, initializing all Smithay subsystems.
|
/// Create a new WayRay compositor state, initializing all Smithay subsystems.
|
||||||
pub fn new(display: &mut Display<Self>) -> Self {
|
pub fn new(display: &mut Display<Self>, output: Output) -> Self {
|
||||||
let dh = display.handle();
|
let dh = display.handle();
|
||||||
|
|
||||||
let compositor_state = CompositorState::new::<Self>(&dh);
|
let compositor_state = CompositorState::new::<Self>(&dh);
|
||||||
|
|
@ -58,6 +60,7 @@ impl WayRay {
|
||||||
space: Space::default(),
|
space: Space::default(),
|
||||||
seat,
|
seat,
|
||||||
clock: Clock::new(),
|
clock: Clock::new(),
|
||||||
|
output,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue