mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
Make screenshot UI render target-aware
This commit is contained in:
@@ -402,14 +402,17 @@ animations {
|
|||||||
// To preview and set up this rule, check the preview-render option
|
// To preview and set up this rule, check the preview-render option
|
||||||
// in the debug section of the config.
|
// in the debug section of the config.
|
||||||
//
|
//
|
||||||
// WARNING: the window is NOT blocked out from the screenshot UI.
|
// WARNING: the window is NOT blocked out from third-party screenshot tools.
|
||||||
// If you open the screenshot UI while screencasting, blocked out windows
|
// If you open some screenshot tool with preview while screencasting,
|
||||||
// WILL BE VISIBLE on the screencast.
|
// blocked out windows WILL BE VISIBLE on the screencast.
|
||||||
|
//
|
||||||
|
// The built-in screenshot UI is not affected though, you can use it safely,
|
||||||
|
// and windows will remain blocked out even when screencasting it.
|
||||||
block-out-from "screencast"
|
block-out-from "screencast"
|
||||||
|
|
||||||
// You can also block out the window out of all screen captures, including
|
// You can also block out the window out of all screen captures, including
|
||||||
// the screenshot UI. This way you avoid accidentally showing the window
|
// third-party screenshot tools. This way you avoid accidentally showing
|
||||||
// on a screencast when opening the screenshot UI.
|
// the window on a screencast when opening a third-party screenshot preview.
|
||||||
block-out-from "screen-capture"
|
block-out-from "screen-capture"
|
||||||
|
|
||||||
// You can amend the window's minimum and maximum size in logical pixels.
|
// You can amend the window's minimum and maximum size in logical pixels.
|
||||||
@@ -459,7 +462,7 @@ window-rule {
|
|||||||
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
|
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
|
||||||
match app-id=r#"^org\.gnome\.World\.Secrets$"#
|
match app-id=r#"^org\.gnome\.World\.Secrets$"#
|
||||||
|
|
||||||
// Warning: will be visible when opening the screenshot UI.
|
// Warning: will be visible on third-party screenshot tools.
|
||||||
block-out-from "screencast"
|
block-out-from "screencast"
|
||||||
|
|
||||||
// Use this instead to block out from all screen captures.
|
// Use this instead to block out from all screen captures.
|
||||||
|
|||||||
+27
-21
@@ -2307,7 +2307,7 @@ impl Niri {
|
|||||||
if self.screenshot_ui.is_open() {
|
if self.screenshot_ui.is_open() {
|
||||||
elements.extend(
|
elements.extend(
|
||||||
self.screenshot_ui
|
self.screenshot_ui
|
||||||
.render_output(output)
|
.render_output(output, target)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(OutputRenderElements::from),
|
.map(OutputRenderElements::from),
|
||||||
);
|
);
|
||||||
@@ -3104,31 +3104,37 @@ impl Niri {
|
|||||||
let size = transform.transform_size(size);
|
let size = transform.transform_size(size);
|
||||||
|
|
||||||
let scale = Scale::from(output.current_scale().fractional_scale());
|
let scale = Scale::from(output.current_scale().fractional_scale());
|
||||||
let elements = self.render::<GlesRenderer>(
|
let targets = [
|
||||||
renderer,
|
RenderTarget::Output,
|
||||||
&output,
|
RenderTarget::Screencast,
|
||||||
true,
|
|
||||||
RenderTarget::ScreenCapture,
|
RenderTarget::ScreenCapture,
|
||||||
);
|
];
|
||||||
let elements = elements.iter().rev();
|
let textures = targets.map(|target| {
|
||||||
|
let elements = self.render::<GlesRenderer>(renderer, &output, true, target);
|
||||||
|
let elements = elements.iter().rev();
|
||||||
|
|
||||||
let res = render_to_texture(
|
let res = render_to_texture(
|
||||||
renderer,
|
renderer,
|
||||||
size,
|
size,
|
||||||
scale,
|
scale,
|
||||||
Transform::Normal,
|
Transform::Normal,
|
||||||
Fourcc::Abgr8888,
|
Fourcc::Abgr8888,
|
||||||
elements,
|
elements,
|
||||||
);
|
);
|
||||||
let screenshot = match res {
|
|
||||||
Ok((texture, _)) => texture,
|
if let Err(err) = &res {
|
||||||
Err(err) => {
|
|
||||||
warn!("error rendering output {}: {err:?}", output.name());
|
warn!("error rendering output {}: {err:?}", output.name());
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
Some((output, screenshot))
|
res
|
||||||
|
});
|
||||||
|
|
||||||
|
if textures.iter().any(|res| res.is_err()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let textures = textures.map(|res| res.unwrap().0);
|
||||||
|
Some((output, textures))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
+21
-13
@@ -19,6 +19,7 @@ use smithay::utils::{Physical, Point, Rectangle, Size, Transform};
|
|||||||
|
|
||||||
use crate::niri_render_elements;
|
use crate::niri_render_elements;
|
||||||
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
|
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
|
||||||
|
use crate::render_helpers::RenderTarget;
|
||||||
|
|
||||||
const BORDER: i32 = 2;
|
const BORDER: i32 = 2;
|
||||||
|
|
||||||
@@ -42,8 +43,9 @@ pub struct OutputData {
|
|||||||
size: Size<i32, Physical>,
|
size: Size<i32, Physical>,
|
||||||
scale: i32,
|
scale: i32,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
texture: GlesTexture,
|
// Output, screencast, screen capture.
|
||||||
texture_buffer: TextureBuffer<GlesTexture>,
|
texture: [GlesTexture; 3],
|
||||||
|
texture_buffer: [TextureBuffer<GlesTexture>; 3],
|
||||||
buffers: [SolidColorBuffer; 8],
|
buffers: [SolidColorBuffer; 8],
|
||||||
locations: [Point<i32, Physical>; 8],
|
locations: [Point<i32, Physical>; 8],
|
||||||
}
|
}
|
||||||
@@ -65,7 +67,8 @@ impl ScreenshotUi {
|
|||||||
pub fn open(
|
pub fn open(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &GlesRenderer,
|
renderer: &GlesRenderer,
|
||||||
screenshots: HashMap<Output, GlesTexture>,
|
// Output, screencast, screen capture.
|
||||||
|
screenshots: HashMap<Output, [GlesTexture; 3]>,
|
||||||
default_output: Output,
|
default_output: Output,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if screenshots.is_empty() {
|
if screenshots.is_empty() {
|
||||||
@@ -110,13 +113,9 @@ impl ScreenshotUi {
|
|||||||
let output_mode = output.current_mode().unwrap();
|
let output_mode = output.current_mode().unwrap();
|
||||||
let size = transform.transform_size(output_mode.size);
|
let size = transform.transform_size(output_mode.size);
|
||||||
let scale = output.current_scale().integer_scale();
|
let scale = output.current_scale().integer_scale();
|
||||||
let texture_buffer = TextureBuffer::from_texture(
|
let texture_buffer = texture.clone().map(|texture| {
|
||||||
renderer,
|
TextureBuffer::from_texture(renderer, texture, scale, Transform::Normal, None)
|
||||||
texture.clone(),
|
});
|
||||||
scale,
|
|
||||||
Transform::Normal,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
let buffers = [
|
let buffers = [
|
||||||
SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]),
|
SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]),
|
||||||
SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]),
|
SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]),
|
||||||
@@ -243,7 +242,11 @@ impl ScreenshotUi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_output(&self, output: &Output) -> ArrayVec<ScreenshotUiRenderElement, 9> {
|
pub fn render_output(
|
||||||
|
&self,
|
||||||
|
output: &Output,
|
||||||
|
target: RenderTarget,
|
||||||
|
) -> ArrayVec<ScreenshotUiRenderElement, 9> {
|
||||||
let _span = tracy_client::span!("ScreenshotUi::render_output");
|
let _span = tracy_client::span!("ScreenshotUi::render_output");
|
||||||
|
|
||||||
let Self::Open { output_data, .. } = self else {
|
let Self::Open { output_data, .. } = self else {
|
||||||
@@ -269,10 +272,15 @@ impl ScreenshotUi {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// The screenshot itself goes last.
|
// The screenshot itself goes last.
|
||||||
|
let index = match target {
|
||||||
|
RenderTarget::Output => 0,
|
||||||
|
RenderTarget::Screencast => 1,
|
||||||
|
RenderTarget::ScreenCapture => 2,
|
||||||
|
};
|
||||||
elements.push(
|
elements.push(
|
||||||
PrimaryGpuTextureRenderElement(TextureRenderElement::from_texture_buffer(
|
PrimaryGpuTextureRenderElement(TextureRenderElement::from_texture_buffer(
|
||||||
(0., 0.),
|
(0., 0.),
|
||||||
&output_data.texture_buffer,
|
&output_data.texture_buffer[index],
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
@@ -307,7 +315,7 @@ impl ScreenshotUi {
|
|||||||
.to_buffer(1, Transform::Normal, &data.size.to_logical(1));
|
.to_buffer(1, Transform::Normal, &data.size.to_logical(1));
|
||||||
|
|
||||||
let mapping = renderer
|
let mapping = renderer
|
||||||
.copy_texture(&data.texture, buf_rect, Fourcc::Abgr8888)
|
.copy_texture(&data.texture[0], buf_rect, Fourcc::Abgr8888)
|
||||||
.context("error copying texture")?;
|
.context("error copying texture")?;
|
||||||
let copy = renderer
|
let copy = renderer
|
||||||
.map_texture(&mapping)
|
.map_texture(&mapping)
|
||||||
|
|||||||
Reference in New Issue
Block a user