fix: support per-corner radius

also adjusts the radius by half of the outline thickness. I believe this is the radius at the center of the outline.
This commit is contained in:
Ashley Wulber 2025-09-24 17:50:23 -04:00 committed by Victoria Brekenfeld
parent b3aa10436a
commit c6320eec0c
5 changed files with 67 additions and 28 deletions

View file

@ -173,7 +173,7 @@ impl From<Id> for Key {
#[derive(PartialEq)] #[derive(PartialEq)]
struct IndicatorSettings { struct IndicatorSettings {
thickness: u8, thickness: u8,
radius: u8, radius: [u8; 4],
alpha: f32, alpha: f32,
color: [f32; 3], color: [f32; 3],
} }
@ -195,7 +195,7 @@ impl IndicatorShader {
key: impl Into<Key>, key: impl Into<Key>,
mut element_geo: Rectangle<i32, Local>, mut element_geo: Rectangle<i32, Local>,
thickness: u8, thickness: u8,
radius: u8, radius: [u8; 4],
alpha: f32, alpha: f32,
active_window_hint: [f32; 3], active_window_hint: [f32; 3],
) -> PixelShaderElement { ) -> PixelShaderElement {
@ -208,8 +208,7 @@ impl IndicatorShader {
key, key,
element_geo, element_geo,
thickness, thickness,
// FIXME, this seems to look OK, but I doubt it is correct radius,
radius + thickness,
alpha, alpha,
active_window_hint, active_window_hint,
) )
@ -220,7 +219,7 @@ impl IndicatorShader {
key: impl Into<Key>, key: impl Into<Key>,
geo: Rectangle<i32, Local>, geo: Rectangle<i32, Local>,
thickness: u8, thickness: u8,
radius: u8, radius: [u8; 4],
alpha: f32, alpha: f32,
color: [f32; 3], color: [f32; 3],
) -> PixelShaderElement { ) -> PixelShaderElement {
@ -263,7 +262,15 @@ impl IndicatorShader {
[color[0] * alpha, color[1] * alpha, color[2] * alpha], [color[0] * alpha, color[1] * alpha, color[2] * alpha],
), ),
Uniform::new("thickness", thickness), Uniform::new("thickness", thickness),
Uniform::new("radius", radius as f32), Uniform::new(
"radius",
[
radius[0] as f32 + thickness / 2.,
radius[1] as f32 + thickness / 2.,
radius[2] as f32 + thickness / 2.,
radius[3] as f32 + thickness / 2.,
],
),
], ],
Kind::Unspecified, Kind::Unspecified,
); );
@ -376,7 +383,7 @@ pub fn init_shaders(renderer: &mut GlesRenderer) -> Result<(), GlesError> {
&[ &[
UniformName::new("color", UniformType::_3f), UniformName::new("color", UniformType::_3f),
UniformName::new("thickness", UniformType::_1f), UniformName::new("thickness", UniformType::_1f),
UniformName::new("radius", UniformType::_1f), UniformName::new("radius", UniformType::_4f),
], ],
)?; )?;
let rectangle_shader = renderer.compile_custom_pixel_shader( let rectangle_shader = renderer.compile_custom_pixel_shader(

View file

@ -8,10 +8,14 @@ varying vec2 v_coords;
uniform vec3 color; uniform vec3 color;
uniform float thickness; uniform float thickness;
uniform float radius; uniform vec4 radius;
float rounded_box(vec2 center, vec2 size, float radius) { float rounded_box(in vec2 p, in vec2 b, in vec4 r)
return length(max(abs(center) - size + radius, 0.0)) - radius; {
r.xy = (p.x > 0.0) ? r.xy : r.zw;
r.x = (p.y > 0.0) ? r.x : r.y;
vec2 q = abs(p) - b + r.x;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
} }
void main() { void main() {

View file

@ -134,12 +134,16 @@ impl MoveGrabState {
let guard = corners.lock().unwrap(); let guard = corners.lock().unwrap();
// TODO support multiple radius values // TODO support multiple radius values
Some(guard.top_left) Some([
guard.top_right,
guard.bottom_right,
guard.top_left,
guard.bottom_left,
])
}) })
}) })
.unwrap_or(self.indicator_thickness); .unwrap_or([self.indicator_thickness; 4]);
tracing::error!("{radius}");
let focus_element = if self.indicator_thickness > 0 { let focus_element = if self.indicator_thickness > 0 {
Some( Some(
CosmicMappedRenderElement::from(IndicatorShader::focus_element( CosmicMappedRenderElement::from(IndicatorShader::focus_element(
@ -188,7 +192,12 @@ impl MoveGrabState {
Key::Window(Usage::SnappingIndicator, self.window.key()), Key::Window(Usage::SnappingIndicator, self.window.key()),
overlay_geometry, overlay_geometry,
thickness, thickness,
theme.radius_s()[0] as u8, // TODO: Fix once shaders support 4 corner radii customization [
theme.radius_s()[0] as u8,
theme.radius_s()[1] as u8,
theme.radius_s()[2] as u8,
theme.radius_s()[3] as u8,
],
1.0, 1.0,
[ [
active_window_hint.red, active_window_hint.red,

View file

@ -1615,10 +1615,15 @@ impl FloatingLayout {
let guard = corners.lock().unwrap(); let guard = corners.lock().unwrap();
// TODO support multiple radius values // TODO support multiple radius values
Some(guard.top_left) Some([
guard.top_right,
guard.bottom_right,
guard.top_left,
guard.bottom_left,
])
}) })
}) })
.unwrap_or(indicator_thickness); .unwrap_or([indicator_thickness; 4]);
if indicator_thickness > 0 { if indicator_thickness > 0 {
let element = IndicatorShader::focus_element( let element = IndicatorShader::focus_element(
renderer, renderer,

View file

@ -4483,7 +4483,7 @@ where
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
geo, geo,
4, 4,
if render_active_child { 16 } else { 8 }, [if render_active_child { 16 } else { 8 }; 4],
alpha * if render_potential_group { 0.40 } else { 1.0 }, alpha * if render_potential_group { 0.40 } else { 1.0 },
group_color, group_color,
) )
@ -4500,7 +4500,7 @@ where
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
geo, geo,
4, 4,
8, [8; 4],
alpha * 0.40, alpha * 0.40,
group_color, group_color,
) )
@ -4563,7 +4563,7 @@ where
Key::Group(Arc::downgrade(alive)), Key::Group(Arc::downgrade(alive)),
geo, geo,
4, 4,
8, [8; 4],
alpha * 0.15, alpha * 0.15,
group_color, group_color,
) )
@ -4799,7 +4799,7 @@ where
Key::Window(Usage::PotentialGroupIndicator, mapped.key()), Key::Window(Usage::PotentialGroupIndicator, mapped.key()),
geo, geo,
4, 4,
8, [8; 4],
alpha * 0.40, alpha * 0.40,
group_color, group_color,
) )
@ -5035,10 +5035,15 @@ where
let guard = corners.lock().unwrap(); let guard = corners.lock().unwrap();
// TODO support multiple radius values // TODO support multiple radius values
Some(guard.top_left) Some([
guard.top_right,
guard.bottom_right,
guard.top_left,
guard.bottom_left,
])
}) })
}) })
.unwrap_or(indicator_thickness); .unwrap_or([indicator_thickness; 4]);
if is_minimizing && indicator_thickness > 0 { if is_minimizing && indicator_thickness > 0 {
elements.push(CosmicMappedRenderElement::FocusIndicator( elements.push(CosmicMappedRenderElement::FocusIndicator(
IndicatorShader::focus_element( IndicatorShader::focus_element(
@ -5323,11 +5328,15 @@ where
let guard = corners.lock().unwrap(); let guard = corners.lock().unwrap();
// TODO support multiple radius values Some([
Some(guard.top_left) guard.top_right,
guard.bottom_right,
guard.top_left,
guard.bottom_left,
])
}) })
}) })
.unwrap_or(indicator_thickness); .unwrap_or([indicator_thickness; 4]);
swap_elements.push(CosmicMappedRenderElement::FocusIndicator( swap_elements.push(CosmicMappedRenderElement::FocusIndicator(
IndicatorShader::focus_element( IndicatorShader::focus_element(
renderer, renderer,
@ -5423,11 +5432,16 @@ where
let guard = corners.lock().unwrap(); let guard = corners.lock().unwrap();
// TODO support multiple radius values // TODO support multiple radius values
Some(guard.top_left) Some([
guard.top_right,
guard.bottom_right,
guard.top_left,
guard.bottom_left,
])
}) })
}) })
.unwrap_or(indicator_thickness), .unwrap_or([indicator_thickness; 4]),
_ => 1, _ => [1; 4],
}; };
if !swap_desc if !swap_desc
.as_ref() .as_ref()