diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 02919412..7dd57ac4 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -9,3 +9,9 @@ pub struct KmsState {} pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Result<()> { unimplemented!() } + +impl KmsState { + pub fn schedule_render(&mut self, output: &Output) { + unimplemented!(); + } +} \ No newline at end of file diff --git a/src/backend/x11.rs b/src/backend/x11.rs index a4ee857d..fba76855 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -104,6 +104,7 @@ impl X11State { { slog_scope::error!("Error rendering: {}", err); } + surface.pending = false; } }) .with_context(|| "Failed to add output to event loop")?; @@ -113,6 +114,7 @@ impl X11State { surface, output: output.clone(), render: ping.clone(), + pending: true, #[cfg(feature = "debug")] fps: Fps::default(), _global, @@ -122,6 +124,15 @@ impl X11State { ping.ping(); Ok(output) } + + pub fn schedule_render(&mut self, output: &Output) { + if let Some(surface) = self.surfaces.iter_mut().find(|s| s.output == *output) { + if !surface.pending { + surface.pending = true; + surface.render.ping(); + } + } + } } pub struct Surface { @@ -129,6 +140,7 @@ pub struct Surface { surface: X11Surface, output: Output, render: ping::Ping, + pending: bool, #[cfg(feature = "debug")] fps: Fps, _global: GlobalDrop, @@ -274,19 +286,8 @@ pub fn init_backend(event_loop: &mut EventLoop, state: &mut State) -> Res } } - X11Event::PresentCompleted { window_id } | X11Event::Refresh { window_id } => { - if let Some(surface) = state - .backend - .x11() - .surfaces - .iter_mut() - .find(|s| s.window.id() == window_id) - { - surface.render.ping(); - } - } - X11Event::Input(event) => state.process_x11_event(event), + _ => {}, }) .map_err(|_| anyhow::anyhow!("Failed to insert X11 Backend into event loop"))?; @@ -345,5 +346,9 @@ impl State { }; self.common.process_input_event(event); + // TODO actually figure out the output + for output in self.common.spaces.outputs() { + self.backend.schedule_render(output); + } } } diff --git a/src/main.rs b/src/main.rs index 0f10571a..7837f4a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ fn main() -> Result<()> { // init wayland let display = init_wayland_display(&mut event_loop)?; // init state - let mut state = state::State::new(display); + let mut state = state::State::new(display, event_loop.handle()); // init backend backend::init_backend_auto(&mut event_loop, &mut state)?; diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 9d474459..cb7d242f 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -334,6 +334,13 @@ fn check_grab_preconditions( } fn commit(surface: &WlSurface, state: &mut State) { + // TODO figure out which output the surface is on. + for output in state.common.spaces.outputs() {//.cloned().collect::>().into_iter() { + state.backend.schedule_render(output); + // let space = state.common.spaces.active_space(output); + // get output for surface + } + let state = &mut state.common; if let Some(toplevel) = state.pending_toplevels.iter().find(|toplevel| { diff --git a/src/state.rs b/src/state.rs index 4784665f..d7860cdb 100644 --- a/src/state.rs +++ b/src/state.rs @@ -5,10 +5,13 @@ use crate::{ shell::{init_shell, workspaces::Workspaces, ShellStates}, }; use smithay::{ - reexports::wayland_server::Display, + reexports::{ + calloop::LoopHandle, + wayland_server::Display, + }, wayland::{ data_device::{default_action_chooser, init_data_device}, - output::xdg::init_xdg_output_manager, + output::{xdg::init_xdg_output_manager, Output}, seat::Seat, shell::xdg::ToplevelSurface, shm::init_shm_global, @@ -26,6 +29,7 @@ pub struct State { pub struct Common { pub display: Rc>, + pub event_loop_handle: LoopHandle<'static, State>, pub spaces: Workspaces, pub shell: ShellStates, @@ -87,10 +91,21 @@ impl BackendData { _ => unreachable!("Called winit in non winit backend"), } } + + pub fn schedule_render(&mut self, output: &Output) { + match self { + BackendData::Winit(_) => {}, // We cannot do this on the winit backend. + // Winit has a very strict render-loop and skipping frames breaks atleast the wayland winit-backend. + // Swapping with damage (which should be empty on these frames) is likely good enough anyway. + BackendData::X11(ref mut state) => state.schedule_render(output), + BackendData::Kms(ref mut state) => state.schedule_render(output), + _ => unreachable!("No backend was initialized"), + } + } } impl State { - pub fn new(mut display: Display) -> State { + pub fn new(mut display: Display, handle: LoopHandle<'static, State>) -> State { init_shm_global(&mut display, vec![], None); init_xdg_output_manager(&mut display, None); let shell_handles = init_shell(&mut display); @@ -105,6 +120,7 @@ impl State { State { common: Common { display: Rc::new(RefCell::new(display)), + event_loop_handle: handle, spaces: Workspaces::new(), shell: shell_handles,