diff --git a/src/niri.rs b/src/niri.rs index a08c8ffc..0b4cc9aa 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -4283,8 +4283,29 @@ impl Niri { renderer: &mut R, output: &Output, include_pointer: bool, - mut target: RenderTarget, + target: RenderTarget, ) -> Vec> { + let mut elements = Vec::new(); + self.render_inner(renderer, output, include_pointer, target, &mut |elem| { + elements.push(elem) + }); + + if self.debug_draw_opaque_regions { + let output_scale = Scale::from(output.current_scale().fractional_scale()); + draw_opaque_regions(&mut elements, output_scale); + } + + elements + } + + pub fn render_inner( + &self, + renderer: &mut R, + output: &Output, + include_pointer: bool, + mut target: RenderTarget, + push: &mut dyn FnMut(OutputRenderElements), + ) { let _span = tracy_client::span!("Niri::render"); if target == RenderTarget::Output { @@ -4299,26 +4320,25 @@ impl Niri { let output_scale = Scale::from(output.current_scale().fractional_scale()); // The pointer goes on the top. - let mut elements = vec![]; if include_pointer && self.pointer_visibility.is_visible() { - self.render_pointer(renderer, output, &mut |elem| elements.push(elem.into())); + self.render_pointer(renderer, output, &mut |elem| push(elem.into())); } // Next, the screen transition texture. { let state = self.output_state.get(output).unwrap(); if let Some(transition) = &state.screen_transition { - elements.push(transition.render(target).into()); + push(transition.render(target).into()); } } // Next, the exit confirm dialog. self.exit_confirm_dialog - .render(renderer, output, &mut |elem| elements.push(elem.into())); + .render(renderer, output, &mut |elem| push(elem.into())); // Next, the config error notification too. if let Some(element) = self.config_error_notification.render(renderer, output) { - elements.push(element.into()); + push(element.into()); } // If the session is locked, draw the lock surface. @@ -4332,12 +4352,12 @@ impl Niri { output_scale, 1., Kind::ScanoutCandidate, - &mut |elem| elements.push(elem.into()), + &mut |elem| push(elem.into()), ); } // Draw the solid color background. - elements.push( + push( SolidColorRenderElement::from_buffer( &state.lock_color_buffer, (0., 0.), @@ -4347,10 +4367,7 @@ impl Niri { .into(), ); - if self.debug_draw_opaque_regions { - draw_opaque_regions(&mut elements, output_scale); - } - return elements; + return; } // Prepare the background elements. @@ -4366,26 +4383,23 @@ impl Niri { // If the screenshot UI is open, draw it. if self.screenshot_ui.is_open() { self.screenshot_ui - .render_output(output, target, &mut |elem| elements.push(elem.into())); + .render_output(output, target, &mut |elem| push(elem.into())); // Add the backdrop for outputs that were connected while the screenshot UI was open. - elements.push(backdrop); + push(backdrop); - if self.debug_draw_opaque_regions { - draw_opaque_regions(&mut elements, output_scale); - } - return elements; + return; } // Draw the hotkey overlay on top. if let Some(element) = self.hotkey_overlay.render(renderer, output) { - elements.push(element.into()); + push(element.into()); } // Then, the Alt-Tab switcher. self.window_mru_ui .render_output(self, output, renderer, target, &mut |elem| { - elements.push(elem.into()) + push(elem.into()) }); // Don't draw the focus ring on the workspaces while interactively moving above those @@ -4399,20 +4413,20 @@ impl Niri { // Get layer-shell elements. let layer_map = layer_map_for_output(output); - // We use macros instead of closures to avoid borrowing issues (renderer and elements go + // We use macros instead of closures to avoid borrowing issues (renderer and push() go // into different functions). macro_rules! push_popups_from_layer { ($layer:expr, $backdrop:expr, $push:expr) => {{ self.render_layer_popups(renderer, target, &layer_map, $layer, $backdrop, $push); }}; ($layer:expr, true) => {{ - push_popups_from_layer!($layer, true, &mut |elem| elements.push(elem.into())); + push_popups_from_layer!($layer, true, &mut |elem| push(elem.into())); }}; ($layer:expr, $push:expr) => {{ push_popups_from_layer!($layer, false, $push); }}; ($layer:expr) => {{ - push_popups_from_layer!($layer, false, &mut |elem| elements.push(elem.into())); + push_popups_from_layer!($layer, false, &mut |elem| push(elem.into())); }}; } macro_rules! push_normal_from_layer { @@ -4420,13 +4434,13 @@ impl Niri { self.render_layer_normal(renderer, target, &layer_map, $layer, $backdrop, $push); }}; ($layer:expr, true) => {{ - push_normal_from_layer!($layer, true, &mut |elem| elements.push(elem.into())); + push_normal_from_layer!($layer, true, &mut |elem| push(elem.into())); }}; ($layer:expr, $push:expr) => {{ push_normal_from_layer!($layer, false, $push); }}; ($layer:expr) => {{ - push_normal_from_layer!($layer, false, &mut |elem| elements.push(elem.into())); + push_normal_from_layer!($layer, false, &mut |elem| push(elem.into())); }}; } @@ -4439,16 +4453,12 @@ impl Niri { if mon.render_above_top_layer() { self.layout .render_interactive_move_for_output(renderer, output, target, &mut |elem| { - elements.push(elem.into()) + push(elem.into()) }); - mon.render_insert_hint_between_workspaces(renderer, &mut |elem| { - elements.push(elem.into()) - }); + mon.render_insert_hint_between_workspaces(renderer, &mut |elem| push(elem.into())); - mon.render_workspaces(renderer, target, focus_ring, &mut |elem| { - elements.push(elem.into()) - }); + mon.render_workspaces(renderer, target, focus_ring, &mut |elem| push(elem.into())); push_popups_from_layer!(Layer::Top); push_normal_from_layer!(Layer::Top); @@ -4460,7 +4470,7 @@ impl Niri { // We don't expect more than one workspace when render_above_top_layer(). if let Some((ws, _geo)) = mon.workspaces_with_render_geo().next() { - elements.push(ws.render_background().into()); + push(ws.render_background().into()); } } else { push_popups_from_layer!(Layer::Top); @@ -4468,19 +4478,17 @@ impl Niri { self.layout .render_interactive_move_for_output(renderer, output, target, &mut |elem| { - elements.push(elem.into()) + push(elem.into()) }); - mon.render_insert_hint_between_workspaces(renderer, &mut |elem| { - elements.push(elem.into()) - }); + mon.render_insert_hint_between_workspaces(renderer, &mut |elem| push(elem.into())); - // Macro instead of closure to avoid borrowing elements. + // Macro instead of closure to avoid borrowing push(). macro_rules! process { ($geo:expr) => {{ &mut |elem| { if let Some(elem) = scale_relocate_crop(elem, output_scale, zoom, $geo) { - elements.push(elem.into()); + push(elem.into()); } } }}; @@ -4491,9 +4499,7 @@ impl Niri { push_popups_from_layer!(Layer::Background, process!(geo)); } - mon.render_workspaces(renderer, target, focus_ring, &mut |elem| { - elements.push(elem.into()) - }); + mon.render_workspaces(renderer, target, focus_ring, &mut |elem| push(elem.into())); for (ws, geo) in mon.workspaces_with_render_geo() { push_normal_from_layer!(Layer::Bottom, process!(geo)); @@ -4503,19 +4509,13 @@ impl Niri { } } - mon.render_workspace_shadows(renderer, &mut |elem| elements.push(elem.into())); + mon.render_workspace_shadows(renderer, &mut |elem| push(elem.into())); // Then the backdrop. push_popups_from_layer!(Layer::Background, true); push_normal_from_layer!(Layer::Background, true); - elements.push(backdrop); - - if self.debug_draw_opaque_regions { - draw_opaque_regions(&mut elements, output_scale); - } - - elements + push(backdrop); } fn layers_in_render_order<'a>(