diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 646b8d89..75bec651 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -84,10 +84,15 @@ impl WinitState { .with_context(|| "Failed to submit buffer for display")?; #[cfg(feature = "debug")] self.fps.displayed(); - state.send_frames(&self.output, &states, |_| None); + state.send_frames(&self.output); + state.update_primary_output(&self.output, &states); + state.send_dmabuf_feedback(&self.output, &states, |_| None); if damage.is_some() { - let mut output_presentation_feedback = - state.take_presentation_feedback(&self.output, &states); + let mut output_presentation_feedback = state + .shell + .read() + .unwrap() + .take_presentation_feedback(&self.output, &states); output_presentation_feedback.presented( state.clock.now(), self.output diff --git a/src/backend/x11.rs b/src/backend/x11.rs index 7bf27077..e3f8817d 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -236,10 +236,15 @@ impl Surface { .with_context(|| "Failed to submit buffer for display")?; #[cfg(feature = "debug")] self.fps.displayed(); - state.send_frames(&self.output, &states, |_| None); + state.send_frames(&self.output); + state.update_primary_output(&self.output, &states); + state.send_dmabuf_feedback(&self.output, &states, |_| None); if damage.is_some() { - let mut output_presentation_feedback = - state.take_presentation_feedback(&self.output, &states); + let mut output_presentation_feedback = state + .shell + .read() + .unwrap() + .take_presentation_feedback(&self.output, &states); output_presentation_feedback.presented( state.clock.now(), self.output diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 1d58ce4d..c26c052f 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -13,9 +13,14 @@ use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{ }; use keyframe::{ease, functions::EaseInOutCubic}; use smithay::{ - backend::input::TouchSlot, + backend::{input::TouchSlot, renderer::element::RenderElementStates}, desktop::{ - layer_map_for_output, space::SpaceElement, utils::surface_primary_scanout_output, + layer_map_for_output, + space::SpaceElement, + utils::{ + surface_presentation_feedback_flags_from_states, surface_primary_scanout_output, + take_presentation_feedback_surface_tree, OutputPresentationFeedback, + }, LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, }, input::{ @@ -3156,6 +3161,54 @@ impl Shell { self.workspaces .set_theme(theme.clone(), xdg_activation_state); } + + pub fn take_presentation_feedback( + &self, + output: &Output, + render_element_states: &RenderElementStates, + ) -> OutputPresentationFeedback { + let mut output_presentation_feedback = OutputPresentationFeedback::new(output); + + let active = self.active_space(output); + active.mapped().for_each(|mapped| { + mapped.active_window().take_presentation_feedback( + &mut output_presentation_feedback, + surface_primary_scanout_output, + |surface, _| { + surface_presentation_feedback_flags_from_states(surface, render_element_states) + }, + ); + }); + + self.override_redirect_windows.iter().for_each(|or| { + if let Some(wl_surface) = or.wl_surface() { + take_presentation_feedback_surface_tree( + &wl_surface, + &mut output_presentation_feedback, + surface_primary_scanout_output, + |surface, _| { + surface_presentation_feedback_flags_from_states( + surface, + render_element_states, + ) + }, + ) + } + }); + + let map = smithay::desktop::layer_map_for_output(output); + for layer_surface in map.layers() { + layer_surface.take_presentation_feedback( + &mut output_presentation_feedback, + surface_primary_scanout_output, + |surface, _| { + surface_presentation_feedback_flags_from_states(surface, render_element_states) + }, + ); + } + + output_presentation_feedback + } } fn workspace_set_idx<'a>( diff --git a/src/state.rs b/src/state.rs index 258de36c..303451fd 100644 --- a/src/state.rs +++ b/src/state.rs @@ -43,9 +43,8 @@ use smithay::{ layer_map_for_output, utils::{ send_dmabuf_feedback_surface_tree, send_frames_surface_tree, - surface_presentation_feedback_flags_from_states, surface_primary_scanout_output, - take_presentation_feedback_surface_tree, update_surface_primary_scanout_output, - with_surfaces_surface_tree, OutputPresentationFeedback, + surface_primary_scanout_output, update_surface_primary_scanout_output, + with_surfaces_surface_tree, }, PopupManager, }, @@ -578,31 +577,146 @@ impl State { } impl Common { - pub fn send_frames( + pub fn update_primary_output( + &self, + output: &Output, + render_element_states: &RenderElementStates, + ) { + let shell = self.shell.read().unwrap(); + // TODO: also set preferred scale + + // grabs + for seat in shell + .seats + .iter() + .filter(|seat| &seat.active_output() == output) + { + if let Some(move_grab) = seat.user_data().get::() { + if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { + for (window, _) in grab_state.element().windows() { + window.with_surfaces(|surface, states| { + let primary_scanout_output = update_surface_primary_scanout_output( + surface, + output, + states, + render_element_states, + default_primary_scanout_output_compare, + ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale.set_preferred_scale( + output.current_scale().fractional_scale(), + ); + }); + } + }); + } + } + } + } + + // sticky window + shell + .workspaces + .sets + .get(output) + .unwrap() + .sticky_layer + .mapped() + .for_each(|mapped| { + for (window, _) in mapped.windows() { + window.with_surfaces(|surface, states| { + let primary_scanout_output = update_surface_primary_scanout_output( + surface, + output, + states, + render_element_states, + default_primary_scanout_output_compare, + ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } + }); + } + }); + + // normal windows + let active = shell.active_space(output); + active.mapped().for_each(|mapped| { + for (window, _) in mapped.windows() { + window.with_surfaces(|surface, states| { + let primary_scanout_output = update_surface_primary_scanout_output( + surface, + output, + states, + render_element_states, + default_primary_scanout_output_compare, + ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } + }); + } + }); + + // OR windows + shell.override_redirect_windows.iter().for_each(|or| { + if let Some(wl_surface) = or.wl_surface() { + with_surfaces_surface_tree(&wl_surface, |surface, states| { + let primary_scanout_output = update_surface_primary_scanout_output( + surface, + output, + states, + render_element_states, + default_primary_scanout_output_compare, + ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } + }); + } + }); + + // layer surfaces + let map = smithay::desktop::layer_map_for_output(output); + for layer_surface in map.layers() { + layer_surface.with_surfaces(|surface, states| { + let primary_scanout_output = update_surface_primary_scanout_output( + surface, + output, + states, + render_element_states, + default_primary_scanout_output_compare, + ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } + }); + } + } + + pub fn send_dmabuf_feedback( &self, output: &Output, render_element_states: &RenderElementStates, mut dmabuf_feedback: impl FnMut(DrmNode) -> Option, ) { - let time = self.clock.now(); - let throttle = Some(Duration::from_secs(1)); let shell = self.shell.read().unwrap(); if let Some(session_lock) = shell.session_lock.as_ref() { if let Some(lock_surface) = session_lock.surfaces.get(output) { - with_surfaces_surface_tree(lock_surface.wl_surface(), |_surface, states| { - with_fractional_scale(states, |fraction_scale| { - fraction_scale - .set_preferred_scale(output.current_scale().fractional_scale()); - }); - }); - send_frames_surface_tree( - lock_surface.wl_surface(), - output, - time, - Some(Duration::ZERO), - surface_primary_scanout_output, - ); if let Some(feedback) = advertised_node_for_surface(lock_surface.wl_surface(), &self.display_handle) .and_then(|source| dmabuf_feedback(source)) @@ -629,45 +743,37 @@ impl Common { .iter() .filter(|seat| &seat.active_output() == output) { - let cursor_status = seat - .user_data() - .get::>() - .map(|cell| { - let mut cursor_status = cell.borrow_mut(); - if let CursorImageStatus::Surface(ref surface) = *cursor_status { - if !surface.alive() { - *cursor_status = CursorImageStatus::default_named(); + if let Some(move_grab) = seat.user_data().get::() { + if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { + for (window, _) in grab_state.element().windows() { + if let Some(feedback) = window + .wl_surface() + .and_then(|wl_surface| { + advertised_node_for_surface(&wl_surface, &self.display_handle) + }) + .and_then(|source| dmabuf_feedback(source)) + { + window.send_dmabuf_feedback( + output, + &feedback, + render_element_states, + surface_primary_scanout_output, + ); } } - cursor_status.clone() - }) - .unwrap_or(CursorImageStatus::default_named()); - - if let CursorImageStatus::Surface(wl_surface) = cursor_status { - send_frames_surface_tree(&wl_surface, output, time, Some(Duration::ZERO), |_, _| { - None - }) + } } + } - if let Some(move_grab) = seat.user_data().get::() { - if let Some(grab_state) = move_grab.borrow().as_ref() { - let window = grab_state.window(); - window.with_surfaces(|surface, states| { - let primary_scanout_output = update_surface_primary_scanout_output( - surface, - output, - states, - render_element_states, - default_primary_scanout_output_compare, - ); - if let Some(output) = primary_scanout_output { - with_fractional_scale(states, |fraction_scale| { - fraction_scale - .set_preferred_scale(output.current_scale().fractional_scale()); - }); - } - }); - window.send_frame(output, time, throttle, surface_primary_scanout_output); + shell + .workspaces + .sets + .get(output) + .unwrap() + .sticky_layer + .mapped() + .for_each(|mapped| { + for (window, _) in mapped.windows() { if let Some(feedback) = window .wl_surface() .and_then(|wl_surface| { @@ -683,34 +789,11 @@ impl Common { ); } } - } - } + }); - shell - .workspaces - .sets - .get(output) - .unwrap() - .sticky_layer - .mapped() - .for_each(|mapped| { - let window = mapped.active_window(); - window.with_surfaces(|surface, states| { - let primary_scanout_output = update_surface_primary_scanout_output( - surface, - output, - states, - render_element_states, - |_current_output, _current_state, next_output, _next_state| next_output, - ); - if let Some(output) = primary_scanout_output { - with_fractional_scale(states, |fraction_scale| { - fraction_scale - .set_preferred_scale(output.current_scale().fractional_scale()); - }); - } - }); - window.send_frame(output, time, throttle, surface_primary_scanout_output); + let active = shell.active_space(output); + active.mapped().for_each(|mapped| { + for (window, _) in mapped.windows() { if let Some(feedback) = window .wl_surface() .and_then(|wl_surface| { @@ -725,86 +808,11 @@ impl Common { surface_primary_scanout_output, ); } - }); - - let active = shell.active_space(output); - active.mapped().for_each(|mapped| { - let window = mapped.active_window(); - window.with_surfaces(|surface, states| { - let primary_scanout_output = update_surface_primary_scanout_output( - surface, - output, - states, - render_element_states, - |_current_output, _current_state, next_output, _next_state| next_output, - ); - if let Some(output) = primary_scanout_output { - with_fractional_scale(states, |fraction_scale| { - fraction_scale - .set_preferred_scale(output.current_scale().fractional_scale()); - }); - } - }); - window.send_frame(output, time, throttle, surface_primary_scanout_output); - if let Some(feedback) = window - .wl_surface() - .and_then(|wl_surface| { - advertised_node_for_surface(&wl_surface, &self.display_handle) - }) - .and_then(|source| dmabuf_feedback(source)) - { - window.send_dmabuf_feedback( - output, - &feedback, - render_element_states, - surface_primary_scanout_output, - ); } }); - active.minimized_windows.iter().for_each(|m| { - let window = m.window.active_window(); - window.send_frame(output, time, throttle, |_, _| None); - }); - - for space in shell - .workspaces - .spaces_for_output(output) - .filter(|w| w.handle != active.handle) - { - space.mapped().for_each(|mapped| { - let window = mapped.active_window(); - window.send_frame(output, time, throttle, |_, _| None); - }); - space.minimized_windows.iter().for_each(|m| { - let window = m.window.active_window(); - window.send_frame(output, time, throttle, |_, _| None); - }) - } shell.override_redirect_windows.iter().for_each(|or| { if let Some(wl_surface) = or.wl_surface() { - with_surfaces_surface_tree(&wl_surface, |surface, states| { - let primary_scanout_output = update_surface_primary_scanout_output( - surface, - output, - states, - render_element_states, - default_primary_scanout_output_compare, - ); - if let Some(output) = primary_scanout_output { - with_fractional_scale(states, |fraction_scale| { - fraction_scale - .set_preferred_scale(output.current_scale().fractional_scale()); - }); - } - }); - send_frames_surface_tree( - &wl_surface, - output, - time, - throttle, - surface_primary_scanout_output, - ); if let Some(feedback) = advertised_node_for_surface(&wl_surface, &self.display_handle) .and_then(|source| dmabuf_feedback(source)) @@ -828,22 +836,6 @@ impl Common { let map = smithay::desktop::layer_map_for_output(output); for layer_surface in map.layers() { - layer_surface.with_surfaces(|surface, states| { - let primary_scanout_output = update_surface_primary_scanout_output( - surface, - output, - states, - render_element_states, - default_primary_scanout_output_compare, - ); - if let Some(output) = primary_scanout_output { - with_fractional_scale(states, |fraction_scale| { - fraction_scale - .set_preferred_scale(output.current_scale().fractional_scale()); - }); - } - }); - layer_surface.send_frame(output, time, throttle, surface_primary_scanout_output); if let Some(feedback) = advertised_node_for_surface(layer_surface.wl_surface(), &self.display_handle) .and_then(|source| dmabuf_feedback(source)) @@ -864,53 +856,118 @@ impl Common { } } - pub fn take_presentation_feedback( - &self, - output: &Output, - render_element_states: &RenderElementStates, - ) -> OutputPresentationFeedback { - let mut output_presentation_feedback = OutputPresentationFeedback::new(output); + pub fn send_frames(&self, output: &Output) { + let time = self.clock.now(); + let throttle = Some(Duration::from_secs(1)); let shell = self.shell.read().unwrap(); + if let Some(session_lock) = shell.session_lock.as_ref() { + if let Some(lock_surface) = session_lock.surfaces.get(output) { + with_surfaces_surface_tree(lock_surface.wl_surface(), |_surface, states| { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + }); + send_frames_surface_tree(lock_surface.wl_surface(), output, time, None, |_, _| { + Some(output.clone()) + }); + } + } + + for seat in shell + .seats + .iter() + .filter(|seat| &seat.active_output() == output) + { + let cursor_status = seat + .user_data() + .get::>() + .map(|lock| { + let mut cursor_status = lock.lock().unwrap(); + if let CursorImageStatus::Surface(ref surface) = *cursor_status { + if !surface.alive() { + *cursor_status = CursorImageStatus::default_named(); + } + } + cursor_status.clone() + }) + .unwrap_or(CursorImageStatus::default_named()); + + if let CursorImageStatus::Surface(wl_surface) = cursor_status { + send_frames_surface_tree(&wl_surface, output, time, Some(Duration::ZERO), |_, _| { + None + }) + } + + if let Some(move_grab) = seat.user_data().get::() { + if let Some(grab_state) = move_grab.lock().unwrap().as_ref() { + for (window, _) in grab_state.element().windows() { + window.send_frame(output, time, throttle, surface_primary_scanout_output); + } + } + } + } + + shell + .workspaces + .sets + .get(output) + .unwrap() + .sticky_layer + .mapped() + .for_each(|mapped| { + for (window, _) in mapped.windows() { + window.send_frame(output, time, throttle, surface_primary_scanout_output); + } + }); + let active = shell.active_space(output); active.mapped().for_each(|mapped| { - mapped.active_window().take_presentation_feedback( - &mut output_presentation_feedback, - surface_primary_scanout_output, - |surface, _| { - surface_presentation_feedback_flags_from_states(surface, render_element_states) - }, - ); + for (window, _) in mapped.windows() { + window.send_frame(output, time, throttle, surface_primary_scanout_output); + } }); + // other (throttled) windows + active.minimized_windows.iter().for_each(|m| { + for (window, _) in m.window.windows() { + window.send_frame(output, time, throttle, |_, _| None); + } + }); + for space in shell + .workspaces + .spaces_for_output(output) + .filter(|w| w.handle != active.handle) + { + space.mapped().for_each(|mapped| { + for (window, _) in mapped.windows() { + window.send_frame(output, time, throttle, |_, _| None); + } + }); + space.minimized_windows.iter().for_each(|m| { + for (window, _) in m.window.windows() { + window.send_frame(output, time, throttle, |_, _| None); + } + }) + } + shell.override_redirect_windows.iter().for_each(|or| { if let Some(wl_surface) = or.wl_surface() { - take_presentation_feedback_surface_tree( + send_frames_surface_tree( &wl_surface, - &mut output_presentation_feedback, + output, + time, + throttle, surface_primary_scanout_output, - |surface, _| { - surface_presentation_feedback_flags_from_states( - surface, - render_element_states, - ) - }, - ) + ); } }); let map = smithay::desktop::layer_map_for_output(output); for layer_surface in map.layers() { - layer_surface.take_presentation_feedback( - &mut output_presentation_feedback, - surface_primary_scanout_output, - |surface, _| { - surface_presentation_feedback_flags_from_states(surface, render_element_states) - }, - ); + layer_surface.send_frame(output, time, throttle, surface_primary_scanout_output); } - - output_presentation_feedback } }