Skip to content

Commit 54cb56b

Browse files
authored
Merge pull request #108 from howdeploy/fix/full-window-effect-subsurfaces
fix: include subsurfaces in full window replacement effects
2 parents 7cab4b8 + ec7d293 commit 54cb56b

2 files changed

Lines changed: 59 additions & 28 deletions

File tree

‎docs/docs/configuration/effects.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ Options:
104104
`windowSource`, `layerSource`, and `popupSource` accept
105105
`{include: 'full' | 'root-surface'}`. The default is `'full'`.
106106

107+
On the TTY backend, a full window source includes the root surface,
108+
subsurfaces, and server-side decorations. A full-source replacement applies
109+
to that entire image; subsurfaces are not drawn a second time above it.
110+
Popups remain independently composed. A root-surface source continues to
111+
exclude subsurfaces.
112+
107113
### Stages
108114

109115
| Stage | Purpose |

‎src/shojiwm/src/backend/tty.rs‎

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5490,20 +5490,6 @@ fn render_surface(
54905490
);
54915491
current_window_elements.extend(popup_elements);
54925492
}
5493-
if use_full_window_snapshot {
5494-
current_window_elements.extend(non_root_surface_elements_for_window(
5495-
window,
5496-
&mut backend.renderer,
5497-
physical_location,
5498-
client_physical_geometry,
5499-
output_geo.loc,
5500-
scale,
5501-
scale,
5502-
visual_state,
5503-
visual_state.opacity,
5504-
content_clip,
5505-
));
5506-
}
55075493
window_timing.popup_phase_ms =
55085494
popup_phase_started_at.elapsed().as_secs_f64() * 1000.0;
55095495
if output_render_debug_enabled() {
@@ -5533,8 +5519,8 @@ fn render_surface(
55335519
"output_render_debug: window rendered"
55345520
);
55355521
}
5536-
// Window-source effects sample only the top-level window. `Full` means
5537-
// root surface plus SSD decoration, but not popup/subsurface content.
5522+
// Full window sources include subsurfaces and SSD decorations.
5523+
// Popups remain independently composed above the window effect.
55385524
let source_clip_scale = if use_full_window_snapshot {
55395525
scale
55405526
} else {
@@ -5573,7 +5559,7 @@ fn render_surface(
55735559
})
55745560
.unwrap_or_default();
55755561
let root_surface_source_elements = if needs_root_surface_source {
5576-
root_surface_source_elements_for_window(
5562+
window_surface_source_elements_for_window(
55775563
window,
55785564
&mut backend.renderer,
55795565
physical_location,
@@ -5584,12 +5570,13 @@ fn render_surface(
55845570
visual_state,
55855571
visual_state.opacity,
55865572
content_clip,
5573+
false,
55875574
)
55885575
} else {
55895576
Vec::new()
55905577
};
55915578
let mut full_window_source_elements = if needs_full_window_source {
5592-
root_surface_source_elements_for_window(
5579+
window_surface_source_elements_for_window(
55935580
window,
55945581
&mut backend.renderer,
55955582
physical_location,
@@ -5600,6 +5587,7 @@ fn render_surface(
56005587
visual_state,
56015588
visual_state.opacity,
56025589
content_clip,
5590+
true,
56035591
)
56045592
} else {
56055593
Vec::new()
@@ -5826,7 +5814,12 @@ fn render_surface(
58265814
.ok()
58275815
});
58285816
if let Some(replace_effects) = replace_effects {
5829-
if !use_full_window_snapshot {
5817+
// Full replacement owns subsurfaces too (e.g. OBS's video preview).
5818+
// Drawing them again here bypasses the shader's visibility mask.
5819+
if !matches!(
5820+
replace_effect_slot.as_ref().map(|effect| &effect.effect.input),
5821+
Some(EffectInput::WindowSource(WindowSourceInclude::Full))
5822+
) {
58305823
current_window_elements.extend(non_root_surface_elements_for_window(
58315824
window,
58325825
&mut backend.renderer,
@@ -5842,6 +5835,20 @@ fn render_surface(
58425835
}
58435836
current_window_elements.extend(replace_effects);
58445837
} else {
5838+
if use_full_window_snapshot {
5839+
current_window_elements.extend(non_root_surface_elements_for_window(
5840+
window,
5841+
&mut backend.renderer,
5842+
physical_location,
5843+
client_physical_geometry,
5844+
output_geo.loc,
5845+
scale,
5846+
scale,
5847+
visual_state,
5848+
visual_state.opacity,
5849+
content_clip,
5850+
));
5851+
}
58455852
current_window_elements.extend(original_window_body_elements);
58465853
}
58475854
if window_effect_debug_enabled() {
@@ -7527,7 +7534,7 @@ fn transform_clipped_elements(
75277534
.collect()
75287535
}
75297536

7530-
fn root_surface_source_elements_for_window(
7537+
fn window_surface_source_elements_for_window(
75317538
window: &smithay::desktop::Window,
75327539
renderer: &mut GlesRenderer,
75337540
physical_location: Point<i32, smithay::utils::Physical>,
@@ -7538,6 +7545,7 @@ fn root_surface_source_elements_for_window(
75387545
visual: WindowVisualState,
75397546
alpha: f32,
75407547
content_clip: Option<crate::ssd::ContentClip>,
7548+
include_subsurfaces: bool,
75417549
) -> Vec<TtyRenderElements> {
75427550
if let Some(content_clip) = content_clip.filter(|clip| clip.clips_surface) {
75437551
let clipped = window_render::clipped_surface_elements(
@@ -7555,11 +7563,28 @@ fn root_surface_source_elements_for_window(
75557563
.inspect_err(|error| {
75567564
warn!(
75577565
?error,
7558-
"failed to build clipped root surface source elements"
7566+
"failed to build clipped window surface source elements"
75597567
);
75607568
})
75617569
.unwrap_or_default();
75627570

7571+
if include_subsurfaces {
7572+
return clipped
7573+
.into_iter()
7574+
.flat_map(|element| match element {
7575+
window_render::WindowClipElement::Clipped(element) => {
7576+
transform_clipped_elements(vec![element], visual)
7577+
}
7578+
window_render::WindowClipElement::Raw(element) => transform_window_elements(
7579+
vec![element],
7580+
visual,
7581+
TtyRenderElements::Window,
7582+
TtyRenderElements::TransformedWindow,
7583+
),
7584+
})
7585+
.collect();
7586+
}
7587+
75637588
let mut root_raw_element = None;
75647589
for element in clipped {
75657590
match element {
@@ -7583,13 +7608,13 @@ fn root_surface_source_elements_for_window(
75837608
}
75847609

75857610
transform_window_elements(
7586-
window_render::root_surface_elements(
7587-
window,
7588-
renderer,
7589-
physical_location,
7590-
output_scale,
7591-
alpha,
7592-
),
7611+
if include_subsurfaces {
7612+
window_render::surface_elements(window, renderer, physical_location, output_scale, alpha)
7613+
} else {
7614+
window_render::root_surface_elements(
7615+
window, renderer, physical_location, output_scale, alpha,
7616+
)
7617+
},
75937618
visual,
75947619
TtyRenderElements::Window,
75957620
TtyRenderElements::TransformedWindow,

0 commit comments

Comments
 (0)