diff options
| author | srdusr <[email protected]> | 2024-07-31 17:34:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-07-31 17:34:00 +0200 |
| commit | f166df4d979162ae09b439c87cdc64f2b0981308 (patch) | |
| tree | b337d88dec627ab1e49b91f1f3c91de06a7af692 /crates/wayland/src/winit/capture.rs | |
| parent | c180bfc34e4c74ba7cac9e0220e9c172c239fe71 (diff) | |
| download | srdwm-f166df4d979162ae09b439c87cdc64f2b0981308.tar.gz srdwm-f166df4d979162ae09b439c87cdc64f2b0981308.zip | |
Split crates/wayland/src/winit.rs (889 lines) into winit/
Pure reorganization, no behavior change - verified by diffing the
function-name and struct-name sets before/after (both identical) plus
a full cargo test pass. mod.rs keeps the module doc comment, imports,
WaylandPlatform's struct definition, and TARGET_FRAME_TIME, plus mod
declarations. The rest splits by concern:
- connect.rs: connect(), the ~200-line setup/init function.
- run.rs: accept_clients, pump_winit - the small per-poll pair.
- render.rs: render_frame, the per-frame render loop (left as one
intact ~330-line function, same reasoning as udev's render.rs: its
structure is deliberate and already documented inline, not a target
for further decomposition in a pure reorganization pass).
- capture.rs: capture_offscreen, the screencopy path.
- events.rs: handle_winit_event.
- platform.rs: `impl Platform for WaylandPlatform`.
No tests module existed in the original file, so none was split out.
A handful of methods/functions (accept_clients, pump_winit,
render_frame, capture_offscreen, handle_winit_event) went from private
to pub(super): called across what are now sibling submodules, which
Rust's privacy model doesn't let see each other's private items.
Diffstat (limited to 'crates/wayland/src/winit/capture.rs')
| -rw-r--r-- | crates/wayland/src/winit/capture.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/crates/wayland/src/winit/capture.rs b/crates/wayland/src/winit/capture.rs new file mode 100644 index 0000000..a96cff9 --- /dev/null +++ b/crates/wayland/src/winit/capture.rs @@ -0,0 +1,60 @@ +use super::*; + +impl WaylandPlatform { + + /// Re-renders the current scene into an offscreen GLES renderbuffer and + /// serves the queued screencopy captures from it. See the call site for + /// why capture cannot read the window surface directly. + pub(super) fn capture_offscreen(&mut self, captures: Vec<screencopy::PendingCapture>) -> PlatformResult<()> { + use smithay::backend::renderer::{Bind, Offscreen}; + + let size = self.output.current_mode().map(|m| m.size).unwrap_or_default(); + if size.w <= 0 || size.h <= 0 { + return Ok(()); + } + let renderer = self.backend.renderer(); + let mut target: smithay::backend::renderer::gles::GlesRenderbuffer = + renderer.create_buffer(Fourcc::Abgr8888, (size.w, size.h).into()).map_err(err)?; + let mut framebuffer = renderer.bind(&mut target).map_err(err)?; + + // Not full parity with the on-screen render loop above (no border/ + // shadow strips here, same as before this function's content/opacity + // fix) - a real, pre-existing gap in what a screenshot shows on + // this backend, flagged rather than grown further in this pass. + // Content (with each window's own `opacity`, unlike the + // `self.state.space`-based single-alpha call this replaced) and the + // bar/dock now render into the capture, at least: a screenshot used + // to only ever show titlebars for windows that had one, and never + // any layer-shell surface at all. + let hide_top_layers = self.wm.borrow().visible_windows_front_to_back().any(|w| w.fullscreen); + let mut custom_elements: Vec<crate::elements::OverlayElement<GlesRenderer>> = Vec::new(); + if !hide_top_layers { + custom_elements.extend(crate::elements::output_layer_elements(renderer, &self.output, (0, 0), |layer| matches!(layer, Layer::Top | Layer::Overlay))); + } + for id in self.wm.borrow().visible_windows_front_to_back().map(|w| w.id).collect::<Vec<_>>() { + let Some(w) = self.wm.borrow().window(id).cloned() else { continue }; + if let Some(deco) = self.state.decorations.get(&id) { + if let Ok(elem) = MemoryRenderBufferRenderElement::from_buffer(renderer, (w.geometry.x as f64, w.geometry.y as f64), deco, None, None, None, Kind::Unspecified) { + custom_elements.push(crate::elements::OverlayElement::Memory(elem)); + } + } + if let Some(dwindow) = self.state.id_to_window.get(&id) { + if let Some(surface) = crate::elements::window_wl_surface(dwindow) { + let band = if w.decorated { srdwm_core::TITLEBAR_HEIGHT as i32 } else { 0 }; + custom_elements.extend(crate::elements::surface_content_elements(renderer, &surface, (w.geometry.x, w.geometry.y + band), w.opacity)); + } + } + } + custom_elements.extend(crate::elements::output_layer_elements(renderer, &self.output, (0, 0), |layer| matches!(layer, Layer::Background | Layer::Bottom))); + + // A throwaway damage tracker, so this pass always draws the whole + // scene (age 0) and never perturbs the on-screen tracker's history. + let mut tracker = OutputDamageTracker::from_output(&self.output); + tracker + .render_output(renderer, &mut framebuffer, 0, &custom_elements, [0.05, 0.05, 0.08, 1.0]) + .map_err(err)?; + + screencopy::service_pending(captures, renderer, &framebuffer); + Ok(()) + } +} |