mirror of
https://github.com/marcoallegretti/WEFT_OS.git
synced 2026-03-27 01:13:09 +00:00
fix(compositor): correct Smithay 0.7 API usage
- Fix smithay feature name: renderer_gles -> renderer_gl - Rewrite winit backend: WinitEventLoop as calloop source, render_output free function, bind() returning (renderer, framebuffer), socket creation via add_socket_auto, correct WinitEvent::Redraw variant - Fix InputMethodHandler: add dismiss_popup, remove nonexistent popup_done, use smithay::wayland::input_method::PopupSurface not XDG variant - Remove nonexistent CursorShapeHandler trait; add TabletSeatHandler impl (required bound for delegate_cursor_shape!) - Add state.running bool; remove LoopSignal::is_stopped() call (does not exist) - Remove unused direct deps: calloop-wayland-source, wayland-protocols, wayland-protocols-wlr - Split CI into cross-platform and linux-only jobs; install Wayland system dependencies in linux-only job
This commit is contained in:
parent
feb69be199
commit
f70a998f67
3 changed files with 103 additions and 129 deletions
|
|
@ -22,10 +22,6 @@ smithay = { version = "0.7", default-features = false, features = [
|
||||||
"desktop",
|
"desktop",
|
||||||
] }
|
] }
|
||||||
calloop = { version = "0.14", features = ["executor"] }
|
calloop = { version = "0.14", features = ["executor"] }
|
||||||
calloop-wayland-source = "0.4"
|
|
||||||
wayland-server = "0.31"
|
|
||||||
wayland-protocols = { version = "0.32", features = ["server", "unstable"] }
|
|
||||||
wayland-protocols-wlr = { version = "0.3", features = ["server"] }
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,35 @@ use std::time::Duration;
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
renderer::{damage::OutputDamageTracker, gles::GlesRenderer},
|
renderer::{
|
||||||
winit::{self, WinitEvent, WinitEventLoop, WinitGraphicsBackend},
|
damage::OutputDamageTracker, element::surface::WaylandSurfaceRenderElement,
|
||||||
|
gles::GlesRenderer,
|
||||||
},
|
},
|
||||||
desktop::{space::space_render_elements, Space, Window},
|
winit::{self, WinitEvent},
|
||||||
output::{Mode as OutputMode, Output, PhysicalProperties, Scale, Subpixel},
|
},
|
||||||
reexports::{calloop::EventLoop, wayland_server::Display},
|
output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel},
|
||||||
utils::Transform,
|
reexports::calloop::EventLoop,
|
||||||
|
utils::{Rectangle, Transform},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{input, state::WeftCompositorState};
|
use crate::{input, state::WeftCompositorState};
|
||||||
|
|
||||||
pub fn run() -> anyhow::Result<()> {
|
pub fn run() -> anyhow::Result<()> {
|
||||||
let mut display: Display<WeftCompositorState> = Display::new()?;
|
let mut display =
|
||||||
|
smithay::reexports::wayland_server::Display::<WeftCompositorState>::new()?;
|
||||||
let display_handle = display.handle();
|
let display_handle = display.handle();
|
||||||
|
|
||||||
let mut event_loop: EventLoop<'static, WeftCompositorState> = EventLoop::try_new()?;
|
let mut event_loop: EventLoop<'static, WeftCompositorState> = EventLoop::try_new()?;
|
||||||
let loop_handle = event_loop.handle();
|
let loop_handle = event_loop.handle();
|
||||||
let loop_signal = event_loop.get_signal();
|
let loop_signal = event_loop.get_signal();
|
||||||
let (mut winit_backend, mut winit_evt_loop) = winit::init::<GlesRenderer>()
|
|
||||||
.map_err(|e| anyhow::anyhow!("winit backend init failed: {e}"))?;
|
|
||||||
|
|
||||||
let initial_size = winit_backend.window_size();
|
let (mut backend, winit) = winit::init()
|
||||||
|
.map_err(|e| anyhow::anyhow!("winit init failed: {e}"))?;
|
||||||
|
|
||||||
|
let mode = OutputMode {
|
||||||
|
size: backend.window_size(),
|
||||||
|
refresh: 60_000,
|
||||||
|
};
|
||||||
let output = Output::new(
|
let output = Output::new(
|
||||||
"WEFT-winit".to_string(),
|
"WEFT-winit".to_string(),
|
||||||
PhysicalProperties {
|
PhysicalProperties {
|
||||||
|
|
@ -33,138 +40,107 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
model: "Winit".to_string(),
|
model: "Winit".to_string(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let _wl_output_global = output.create_global::<WeftCompositorState>(&display_handle);
|
let _global = output.create_global::<WeftCompositorState>(&display_handle);
|
||||||
|
|
||||||
let initial_mode = OutputMode {
|
|
||||||
size: initial_size,
|
|
||||||
refresh: 60_000,
|
|
||||||
};
|
|
||||||
output.change_current_state(
|
output.change_current_state(
|
||||||
Some(initial_mode),
|
Some(mode),
|
||||||
Some(Transform::Flipped180),
|
Some(Transform::Flipped180),
|
||||||
None,
|
None,
|
||||||
Some((0, 0).into()),
|
Some((0, 0).into()),
|
||||||
);
|
);
|
||||||
output.set_preferred(initial_mode);
|
output.set_preferred(mode);
|
||||||
|
|
||||||
|
// Open the Wayland socket so clients can connect.
|
||||||
|
let socket_name = display
|
||||||
|
.add_socket_auto()
|
||||||
|
.map_err(|e| anyhow::anyhow!("Wayland socket creation failed: {e}"))?;
|
||||||
|
std::env::set_var("WAYLAND_DISPLAY", &socket_name);
|
||||||
|
tracing::info!(?socket_name, "Wayland compositor socket open");
|
||||||
|
|
||||||
let mut state = WeftCompositorState::new(
|
let mut state = WeftCompositorState::new(
|
||||||
display_handle,
|
display_handle,
|
||||||
loop_signal,
|
loop_signal,
|
||||||
loop_handle,
|
loop_handle.clone(),
|
||||||
"seat-0".to_string(),
|
"seat-0".to_string(),
|
||||||
);
|
);
|
||||||
state.space.map_output(&output, (0, 0));
|
state.space.map_output(&output, (0, 0));
|
||||||
|
|
||||||
let mut damage_tracker = OutputDamageTracker::from_output(&output);
|
let mut damage_tracker = OutputDamageTracker::from_output(&output);
|
||||||
let start = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
|
|
||||||
loop {
|
// WinitEventLoop implements calloop's EventSource; insert it so Winit events
|
||||||
let dispatch_result = dispatch_winit_events(
|
// arrive through the same dispatch loop as all other compositor sources.
|
||||||
&mut winit_evt_loop,
|
loop_handle
|
||||||
&mut state,
|
.insert_source(winit, move |event, _, state| match event {
|
||||||
&output,
|
WinitEvent::Resized { size, .. } => {
|
||||||
&mut damage_tracker,
|
|
||||||
);
|
|
||||||
|
|
||||||
if dispatch_result.is_err() || !state.running {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
display.dispatch_clients(&mut state)?;
|
|
||||||
|
|
||||||
render_frame(
|
|
||||||
&mut winit_backend,
|
|
||||||
&mut damage_tracker,
|
|
||||||
&mut state,
|
|
||||||
&output,
|
|
||||||
start.elapsed(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
display.flush_clients()?;
|
|
||||||
|
|
||||||
// Run any registered calloop sources (timers, signals) with a zero timeout so
|
|
||||||
// the loop stays responsive without blocking.
|
|
||||||
event_loop.dispatch(Some(Duration::ZERO), &mut state)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dispatch_winit_events(
|
|
||||||
evt_loop: &mut WinitEventLoop,
|
|
||||||
state: &mut WeftCompositorState,
|
|
||||||
output: &Output,
|
|
||||||
damage_tracker: &mut OutputDamageTracker,
|
|
||||||
) -> Result<(), ()> {
|
|
||||||
evt_loop
|
|
||||||
.dispatch_new_events(|event| match event {
|
|
||||||
WinitEvent::Resized { size, scale_factor } => {
|
|
||||||
let new_mode = OutputMode {
|
let new_mode = OutputMode {
|
||||||
size,
|
size,
|
||||||
refresh: 60_000,
|
refresh: 60_000,
|
||||||
};
|
};
|
||||||
output.change_current_state(
|
output.change_current_state(Some(new_mode), None, None, None);
|
||||||
Some(new_mode),
|
|
||||||
None,
|
|
||||||
Some(Scale::Fractional(scale_factor)),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
output.set_preferred(new_mode);
|
output.set_preferred(new_mode);
|
||||||
state.space.map_output(output, (0, 0));
|
state.space.map_output(&output, (0, 0));
|
||||||
*damage_tracker = OutputDamageTracker::from_output(output);
|
damage_tracker = OutputDamageTracker::from_output(&output);
|
||||||
}
|
}
|
||||||
WinitEvent::Input(input_event) => {
|
WinitEvent::Input(input_event) => {
|
||||||
input::process_input_event(state, input_event);
|
input::process_input_event(state, input_event);
|
||||||
}
|
}
|
||||||
WinitEvent::Focus(_focused) => {}
|
WinitEvent::Redraw => {
|
||||||
WinitEvent::Refresh => {}
|
let size = backend.window_size();
|
||||||
WinitEvent::CloseRequested => {
|
let full_damage = Rectangle::from_size(size);
|
||||||
state.running = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map_err(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_frame(
|
{
|
||||||
backend: &mut WinitGraphicsBackend<GlesRenderer>,
|
let (renderer, mut framebuffer) = backend.bind().unwrap();
|
||||||
damage_tracker: &mut OutputDamageTracker,
|
smithay::desktop::space::render_output::<
|
||||||
state: &mut WeftCompositorState,
|
_,
|
||||||
output: &Output,
|
WaylandSurfaceRenderElement<GlesRenderer>,
|
||||||
elapsed: Duration,
|
_,
|
||||||
) -> anyhow::Result<()> {
|
_,
|
||||||
backend
|
>(
|
||||||
.bind()
|
&output,
|
||||||
.map_err(|e| anyhow::anyhow!("framebuffer bind failed: {e}"))?;
|
|
||||||
|
|
||||||
let age = backend.buffer_age().unwrap_or(0);
|
|
||||||
let renderer = backend.renderer();
|
|
||||||
|
|
||||||
let elements =
|
|
||||||
space_render_elements::<GlesRenderer, Window, &Space<Window>>(
|
|
||||||
renderer,
|
renderer,
|
||||||
|
&mut framebuffer,
|
||||||
|
1.0,
|
||||||
|
0,
|
||||||
[&state.space],
|
[&state.space],
|
||||||
output,
|
&[],
|
||||||
1.0_f64,
|
&mut damage_tracker,
|
||||||
|
[0.1_f32, 0.1, 0.1, 1.0],
|
||||||
)
|
)
|
||||||
.map_err(|e| anyhow::anyhow!("render element collection failed: {e}"))?;
|
.unwrap();
|
||||||
|
}
|
||||||
|
backend.submit(Some(&[full_damage])).unwrap();
|
||||||
|
|
||||||
let result = damage_tracker
|
state.space.elements().for_each(|window| {
|
||||||
.render_output(renderer, age, &elements, [0.1_f32, 0.1, 0.1, 1.0])
|
|
||||||
.map_err(|e| anyhow::anyhow!("render_output failed: {e}"))?;
|
|
||||||
|
|
||||||
backend
|
|
||||||
.submit(result.damage.as_deref())
|
|
||||||
.map_err(|e| anyhow::anyhow!("buffer submit failed: {e}"))?;
|
|
||||||
|
|
||||||
// Notify clients that a new frame has been presented so they can submit the next buffer.
|
|
||||||
for window in state.space.elements() {
|
|
||||||
window.send_frame(
|
window.send_frame(
|
||||||
output,
|
&output,
|
||||||
elapsed,
|
start_time.elapsed(),
|
||||||
Some(Duration::from_secs(1) / 60),
|
Some(Duration::ZERO),
|
||||||
|_, _| Some(output.clone()),
|
|_, _| Some(output.clone()),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
state.space.refresh();
|
||||||
|
state.popups.cleanup();
|
||||||
|
let _ = state.display_handle.flush_clients();
|
||||||
|
|
||||||
|
// Request the next redraw to drive continuous rendering.
|
||||||
|
backend.window().request_redraw();
|
||||||
}
|
}
|
||||||
|
WinitEvent::CloseRequested => {
|
||||||
|
state.running = false;
|
||||||
|
state.loop_signal.stop();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
})
|
||||||
|
.map_err(|e| anyhow::anyhow!("winit source insertion failed: {e}"))?;
|
||||||
|
|
||||||
|
// The idle callback dispatches pending Wayland client requests after each
|
||||||
|
// calloop iteration so protocol handlers in state receive them promptly.
|
||||||
|
event_loop.run(None, &mut state, move |state| {
|
||||||
|
if let Err(e) = display.dispatch_clients(state) {
|
||||||
|
tracing::error!("Wayland client dispatch failed: {e}");
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::utils::on_commit_buffer_handler,
|
backend::{input::TabletToolDescriptor, renderer::utils::on_commit_buffer_handler},
|
||||||
delegate_compositor, delegate_cursor_shape, delegate_dmabuf, delegate_input_method_manager,
|
delegate_compositor, delegate_cursor_shape, delegate_dmabuf, delegate_input_method_manager,
|
||||||
delegate_layer_shell, delegate_output, delegate_pointer_constraints, delegate_presentation,
|
delegate_layer_shell, delegate_output, delegate_pointer_constraints, delegate_presentation,
|
||||||
delegate_seat, delegate_shm, delegate_text_input_manager, delegate_xdg_shell,
|
delegate_seat, delegate_shm, delegate_text_input_manager,
|
||||||
|
delegate_xdg_shell,
|
||||||
desktop::{
|
desktop::{
|
||||||
layer_map_for_output, PopupKind, PopupManager, Space, Window, WindowSurfaceType,
|
layer_map_for_output, PopupKind, PopupManager, Space, Window, WindowSurfaceType,
|
||||||
},
|
},
|
||||||
|
|
@ -23,13 +24,13 @@ use smithay::{
|
||||||
utils::{Logical, Point, Rectangle},
|
utils::{Logical, Point, Rectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{CompositorClientState, CompositorHandler, CompositorState},
|
compositor::{CompositorClientState, CompositorHandler, CompositorState},
|
||||||
cursor_shape::{CursorShapeHandler, CursorShapeManagerState},
|
cursor_shape::CursorShapeManagerState,
|
||||||
dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier},
|
dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier},
|
||||||
input_method::{InputMethodHandler, InputMethodManagerState},
|
input_method::{InputMethodHandler, InputMethodManagerState, PopupSurface as ImPopupSurface},
|
||||||
|
tablet_manager::TabletSeatHandler,
|
||||||
output::OutputManagerState,
|
output::OutputManagerState,
|
||||||
pointer_constraints::{PointerConstraintsHandler, PointerConstraintsState},
|
pointer_constraints::{PointerConstraintsHandler, PointerConstraintsState},
|
||||||
presentation::{PresentationHandler, PresentationState},
|
presentation::{PresentationHandler, PresentationState},
|
||||||
seat::WaylandFocus,
|
|
||||||
shell::{
|
shell::{
|
||||||
wlr_layer::{Layer, LayerSurface, WlrLayerShellHandler, WlrLayerShellState},
|
wlr_layer::{Layer, LayerSurface, WlrLayerShellHandler, WlrLayerShellState},
|
||||||
xdg::{PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState},
|
xdg::{PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState},
|
||||||
|
|
@ -322,9 +323,9 @@ delegate_text_input_manager!(WeftCompositorState);
|
||||||
// --- InputMethodHandler ---
|
// --- InputMethodHandler ---
|
||||||
|
|
||||||
impl InputMethodHandler for WeftCompositorState {
|
impl InputMethodHandler for WeftCompositorState {
|
||||||
fn new_popup(&mut self, _surface: PopupSurface) {}
|
fn new_popup(&mut self, _surface: ImPopupSurface) {}
|
||||||
fn popup_repositioned(&mut self, _surface: PopupSurface) {}
|
fn dismiss_popup(&mut self, _surface: ImPopupSurface) {}
|
||||||
fn popup_done(&mut self, _surface: PopupSurface) {}
|
fn popup_repositioned(&mut self, _surface: ImPopupSurface) {}
|
||||||
|
|
||||||
fn parent_geometry(&self, parent_surface: &WlSurface) -> Rectangle<i32, Logical> {
|
fn parent_geometry(&self, parent_surface: &WlSurface) -> Rectangle<i32, Logical> {
|
||||||
self.space
|
self.space
|
||||||
|
|
@ -355,12 +356,13 @@ impl PointerConstraintsHandler for WeftCompositorState {
|
||||||
|
|
||||||
delegate_pointer_constraints!(WeftCompositorState);
|
delegate_pointer_constraints!(WeftCompositorState);
|
||||||
|
|
||||||
// --- CursorShapeHandler ---
|
// --- TabletSeatHandler (required by delegate_cursor_shape!) ---
|
||||||
|
|
||||||
impl CursorShapeHandler for WeftCompositorState {
|
impl TabletSeatHandler for WeftCompositorState {
|
||||||
fn cursor_shape_state(&mut self) -> &mut CursorShapeManagerState {
|
fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, image: CursorImageStatus) {
|
||||||
&mut self.cursor_shape_state
|
self.cursor_image_status = image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CursorShapeManagerState has no handler trait; it calls SeatHandler::cursor_image directly.
|
||||||
delegate_cursor_shape!(WeftCompositorState);
|
delegate_cursor_shape!(WeftCompositorState);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue