mirror of
https://github.com/marcoallegretti/WEFT_OS.git
synced 2026-03-27 01:13:09 +00:00
fix(compositor): correct remaining Smithay 0.7 API issues
- Remove nonexistent TextInputHandler trait impl - Add missing cursor_position_hint to PointerConstraintsHandler - Rewrite winit/drm backends: ListeningSocketSource + insert_client for per-client WeftClientState; Generic<Display<D>> for dispatch - Remove calloop direct dep; use via smithay::reexports::calloop - Remove unused imports in input.rs
This commit is contained in:
parent
f70a998f67
commit
3ebe50ef31
5 changed files with 105 additions and 83 deletions
|
|
@ -21,7 +21,6 @@ smithay = { version = "0.7", default-features = false, features = [
|
||||||
"wayland_frontend",
|
"wayland_frontend",
|
||||||
"desktop",
|
"desktop",
|
||||||
] }
|
] }
|
||||||
calloop = { version = "0.14", features = ["executor"] }
|
|
||||||
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"
|
||||||
|
|
|
||||||
|
|
@ -5,66 +5,68 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux DRM/KMS backend.
|
// Linux DRM/KMS backend.
|
||||||
|
// GPU enumeration and rendering are deferred; this skeleton establishes the
|
||||||
|
// session, socket, and event loop that the full implementation will extend.
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn run() -> anyhow::Result<()> {
|
pub fn run() -> anyhow::Result<()> {
|
||||||
use std::time::Duration;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
allocator::gbm::{GbmAllocator, GbmBufferFlags, GbmDevice},
|
session::{libseat::LibSeatSession, Session},
|
||||||
drm::{DrmDevice, DrmDeviceFd, DrmNode, NodeType},
|
|
||||||
egl::EGLDevice,
|
|
||||||
libinput::{LibinputInputBackend, LibinputSessionInterface},
|
|
||||||
renderer::{
|
|
||||||
damage::OutputDamageTracker,
|
|
||||||
gles::GlesRenderer,
|
|
||||||
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer},
|
|
||||||
},
|
|
||||||
session::{
|
|
||||||
libseat::{LibSeatSession, LibSeatSessionNotifier},
|
|
||||||
Session,
|
|
||||||
},
|
|
||||||
udev::{UdevBackend, UdevEvent},
|
udev::{UdevBackend, UdevEvent},
|
||||||
},
|
},
|
||||||
desktop::{space::space_render_elements, Space, Window},
|
reexports::calloop::{generic::Generic, EventLoop, Interest, Mode, PostAction},
|
||||||
output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel},
|
wayland::socket::ListeningSocketSource,
|
||||||
reexports::{
|
|
||||||
calloop::{
|
|
||||||
timer::{TimeoutAction, Timer},
|
|
||||||
EventLoop, Interest, Mode, PostAction,
|
|
||||||
},
|
|
||||||
wayland_server::Display,
|
|
||||||
},
|
|
||||||
utils::Transform,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{input, state::WeftCompositorState};
|
use crate::state::{WeftClientState, WeftCompositorState};
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
// Open a libseat session to gain DRM device access without root.
|
// Gain DRM device access without root via libseat.
|
||||||
let (session, notifier) = LibSeatSession::new()
|
let (session, _notifier) = LibSeatSession::new()
|
||||||
.map_err(|e| anyhow::anyhow!("libseat session failed: {e}"))?;
|
.map_err(|e| anyhow::anyhow!("libseat session failed: {e}"))?;
|
||||||
|
|
||||||
// Discover GPU nodes via udev.
|
let listening_socket = ListeningSocketSource::new_auto()
|
||||||
|
.map_err(|e| anyhow::anyhow!("Wayland socket creation failed: {e}"))?;
|
||||||
|
let socket_name = listening_socket.socket_name().to_os_string();
|
||||||
|
std::env::set_var("WAYLAND_DISPLAY", &socket_name);
|
||||||
|
tracing::info!(?socket_name, "Wayland compositor socket open");
|
||||||
|
|
||||||
|
loop_handle
|
||||||
|
.insert_source(listening_socket, |client_stream, _, state| {
|
||||||
|
state
|
||||||
|
.display_handle
|
||||||
|
.insert_client(client_stream, Arc::new(WeftClientState::default()))
|
||||||
|
.unwrap();
|
||||||
|
})
|
||||||
|
.map_err(|e| anyhow::anyhow!("socket source insertion failed: {e}"))?;
|
||||||
|
|
||||||
|
loop_handle
|
||||||
|
.insert_source(
|
||||||
|
Generic::new(display, Interest::READ, Mode::Level),
|
||||||
|
|_, display, state| {
|
||||||
|
// Safety: the display is owned by this Generic source and is never
|
||||||
|
// dropped while the event loop runs.
|
||||||
|
unsafe {
|
||||||
|
display.get_mut().dispatch_clients(state).unwrap();
|
||||||
|
}
|
||||||
|
Ok(PostAction::Continue)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.map_err(|e| anyhow::anyhow!("display source insertion failed: {e}"))?;
|
||||||
|
|
||||||
|
// Enumerate GPU nodes via udev; hotplug events arrive through calloop.
|
||||||
let udev_backend = UdevBackend::new(session.seat())?;
|
let udev_backend = UdevBackend::new(session.seat())?;
|
||||||
|
loop_handle
|
||||||
let mut state = WeftCompositorState::new(
|
.insert_source(udev_backend, move |event, _, _state| match event {
|
||||||
display_handle,
|
|
||||||
loop_signal.clone(),
|
|
||||||
loop_handle.clone(),
|
|
||||||
session.seat(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Register the udev backend with calloop so device hotplug is handled.
|
|
||||||
loop_handle.insert_source(udev_backend, {
|
|
||||||
let signal = loop_signal.clone();
|
|
||||||
move |event, _, _state| match event {
|
|
||||||
UdevEvent::Added { device_id, path } => {
|
UdevEvent::Added { device_id, path } => {
|
||||||
tracing::info!(?device_id, ?path, "GPU device added");
|
tracing::info!(?device_id, ?path, "GPU device added");
|
||||||
}
|
}
|
||||||
|
|
@ -73,22 +75,19 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
UdevEvent::Removed { device_id } => {
|
UdevEvent::Removed { device_id } => {
|
||||||
tracing::info!(?device_id, "GPU device removed");
|
tracing::info!(?device_id, "GPU device removed");
|
||||||
signal.stop();
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})?;
|
.map_err(|e| anyhow::anyhow!("udev source insertion failed: {e}"))?;
|
||||||
|
|
||||||
|
let mut state = WeftCompositorState::new(
|
||||||
|
display_handle,
|
||||||
|
loop_signal,
|
||||||
|
loop_handle,
|
||||||
|
session.seat(),
|
||||||
|
);
|
||||||
|
|
||||||
tracing::info!("DRM/KMS backend initialised; entering event loop");
|
tracing::info!("DRM/KMS backend initialised; entering event loop");
|
||||||
|
event_loop.run(None, &mut state, |_| {})?;
|
||||||
loop {
|
|
||||||
display.dispatch_clients(&mut state)?;
|
|
||||||
display.flush_clients()?;
|
|
||||||
event_loop.dispatch(Some(Duration::from_millis(16)), &mut state)?;
|
|
||||||
|
|
||||||
if loop_signal.is_stopped() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::time::Duration;
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
|
|
@ -9,11 +9,15 @@ use smithay::{
|
||||||
winit::{self, WinitEvent},
|
winit::{self, WinitEvent},
|
||||||
},
|
},
|
||||||
output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel},
|
output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel},
|
||||||
reexports::calloop::EventLoop,
|
reexports::calloop::{generic::Generic, EventLoop, Interest, Mode, PostAction},
|
||||||
utils::{Rectangle, Transform},
|
utils::{Rectangle, Transform},
|
||||||
|
wayland::socket::ListeningSocketSource,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{input, state::WeftCompositorState};
|
use crate::{
|
||||||
|
input,
|
||||||
|
state::{WeftClientState, WeftCompositorState},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn run() -> anyhow::Result<()> {
|
pub fn run() -> anyhow::Result<()> {
|
||||||
let mut display =
|
let mut display =
|
||||||
|
|
@ -49,13 +53,38 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
);
|
);
|
||||||
output.set_preferred(mode);
|
output.set_preferred(mode);
|
||||||
|
|
||||||
// Open the Wayland socket so clients can connect.
|
// Create the listening socket; each connecting client is inserted with
|
||||||
let socket_name = display
|
// default per-client data so CompositorHandler::client_compositor_state works.
|
||||||
.add_socket_auto()
|
let listening_socket = ListeningSocketSource::new_auto()
|
||||||
.map_err(|e| anyhow::anyhow!("Wayland socket creation failed: {e}"))?;
|
.map_err(|e| anyhow::anyhow!("Wayland socket creation failed: {e}"))?;
|
||||||
|
let socket_name = listening_socket.socket_name().to_os_string();
|
||||||
std::env::set_var("WAYLAND_DISPLAY", &socket_name);
|
std::env::set_var("WAYLAND_DISPLAY", &socket_name);
|
||||||
tracing::info!(?socket_name, "Wayland compositor socket open");
|
tracing::info!(?socket_name, "Wayland compositor socket open");
|
||||||
|
|
||||||
|
loop_handle
|
||||||
|
.insert_source(listening_socket, |client_stream, _, state| {
|
||||||
|
state
|
||||||
|
.display_handle
|
||||||
|
.insert_client(client_stream, Arc::new(WeftClientState::default()))
|
||||||
|
.unwrap();
|
||||||
|
})
|
||||||
|
.map_err(|e| anyhow::anyhow!("socket source insertion failed: {e}"))?;
|
||||||
|
|
||||||
|
// Register the display fd so calloop dispatches Wayland client messages when readable.
|
||||||
|
loop_handle
|
||||||
|
.insert_source(
|
||||||
|
Generic::new(display, Interest::READ, Mode::Level),
|
||||||
|
|_, display, state| {
|
||||||
|
// Safety: the display is owned by this Generic source and is never dropped
|
||||||
|
// while the event loop runs.
|
||||||
|
unsafe {
|
||||||
|
display.get_mut().dispatch_clients(state).unwrap();
|
||||||
|
}
|
||||||
|
Ok(PostAction::Continue)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.map_err(|e| anyhow::anyhow!("display source insertion failed: {e}"))?;
|
||||||
|
|
||||||
let mut state = WeftCompositorState::new(
|
let mut state = WeftCompositorState::new(
|
||||||
display_handle,
|
display_handle,
|
||||||
loop_signal,
|
loop_signal,
|
||||||
|
|
@ -67,8 +96,8 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
let mut damage_tracker = OutputDamageTracker::from_output(&output);
|
let mut damage_tracker = OutputDamageTracker::from_output(&output);
|
||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
|
|
||||||
// WinitEventLoop implements calloop's EventSource; insert it so Winit events
|
// WinitEventLoop implements calloop's EventSource; Winit events arrive
|
||||||
// arrive through the same dispatch loop as all other compositor sources.
|
// through the same dispatch loop as all other compositor sources.
|
||||||
loop_handle
|
loop_handle
|
||||||
.insert_source(winit, move |event, _, state| match event {
|
.insert_source(winit, move |event, _, state| match event {
|
||||||
WinitEvent::Resized { size, .. } => {
|
WinitEvent::Resized { size, .. } => {
|
||||||
|
|
@ -123,7 +152,7 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
state.popups.cleanup();
|
state.popups.cleanup();
|
||||||
let _ = state.display_handle.flush_clients();
|
let _ = state.display_handle.flush_clients();
|
||||||
|
|
||||||
// Request the next redraw to drive continuous rendering.
|
// Request next redraw to drive continuous rendering.
|
||||||
backend.window().request_redraw();
|
backend.window().request_redraw();
|
||||||
}
|
}
|
||||||
WinitEvent::CloseRequested => {
|
WinitEvent::CloseRequested => {
|
||||||
|
|
@ -134,13 +163,7 @@ pub fn run() -> anyhow::Result<()> {
|
||||||
})
|
})
|
||||||
.map_err(|e| anyhow::anyhow!("winit source insertion failed: {e}"))?;
|
.map_err(|e| anyhow::anyhow!("winit source insertion failed: {e}"))?;
|
||||||
|
|
||||||
// The idle callback dispatches pending Wayland client requests after each
|
event_loop.run(None, &mut state, |_| {})?;
|
||||||
// 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(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,9 @@ use smithay::{
|
||||||
TouchCancelEvent, TouchDownEvent, TouchFrameEvent, TouchMotionEvent, TouchUpEvent,
|
TouchCancelEvent, TouchDownEvent, TouchFrameEvent, TouchMotionEvent, TouchUpEvent,
|
||||||
},
|
},
|
||||||
input::{
|
input::{
|
||||||
keyboard::{FilterResult, KeysymHandle, ModifiersState},
|
keyboard::FilterResult,
|
||||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
pointer::{AxisFrame, ButtonEvent, MotionEvent},
|
||||||
},
|
},
|
||||||
reexports::wayland_server::protocol::wl_pointer,
|
|
||||||
utils::{Logical, Point, Serial, SERIAL_COUNTER},
|
utils::{Logical, Point, Serial, SERIAL_COUNTER},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@ use smithay::{
|
||||||
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},
|
||||||
},
|
},
|
||||||
shm::{ShmHandler, ShmState},
|
shm::{ShmHandler, ShmState},
|
||||||
text_input::{TextInputHandler, TextInputManagerState},
|
text_input::TextInputManagerState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -310,14 +311,7 @@ impl PresentationHandler for WeftCompositorState {
|
||||||
|
|
||||||
delegate_presentation!(WeftCompositorState);
|
delegate_presentation!(WeftCompositorState);
|
||||||
|
|
||||||
// --- TextInputHandler ---
|
// TextInputManagerState has no handler trait; delegate macro only requires SeatHandler.
|
||||||
|
|
||||||
impl TextInputHandler for WeftCompositorState {
|
|
||||||
fn text_input_state(&mut self) -> &mut TextInputManagerState {
|
|
||||||
&mut self.text_input_state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate_text_input_manager!(WeftCompositorState);
|
delegate_text_input_manager!(WeftCompositorState);
|
||||||
|
|
||||||
// --- InputMethodHandler ---
|
// --- InputMethodHandler ---
|
||||||
|
|
@ -352,6 +346,14 @@ impl PointerConstraintsHandler for WeftCompositorState {
|
||||||
_pointer: &smithay::input::pointer::PointerHandle<Self>,
|
_pointer: &smithay::input::pointer::PointerHandle<Self>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cursor_position_hint(
|
||||||
|
&mut self,
|
||||||
|
_surface: &WlSurface,
|
||||||
|
_pointer: &smithay::input::pointer::PointerHandle<Self>,
|
||||||
|
_location: smithay::utils::Point<f64, Logical>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate_pointer_constraints!(WeftCompositorState);
|
delegate_pointer_constraints!(WeftCompositorState);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue