tiling: highlight backgrounds

This commit is contained in:
Victoria Brekenfeld 2023-05-30 13:20:46 +02:00
parent 20f4dcb466
commit 24d3b794fe
4 changed files with 116 additions and 74 deletions

View file

@ -82,8 +82,7 @@ pub type GlMultiFrame<'a, 'b, 'frame> =
pub type GlMultiError = MultiError<GbmGlesBackend<GlowRenderer>, GbmGlesBackend<GlowRenderer>>; pub type GlMultiError = MultiError<GbmGlesBackend<GlowRenderer>, GbmGlesBackend<GlowRenderer>>;
pub static CLEAR_COLOR: [f32; 4] = [0.153, 0.161, 0.165, 1.0]; pub static CLEAR_COLOR: [f32; 4] = [0.153, 0.161, 0.165, 1.0];
pub static ACTIVE_GROUP_COLOR: [f32; 3] = [0.678, 0.635, 0.619]; pub static GROUP_COLOR: [f32; 3] = [0.788, 0.788, 0.788];
pub static GROUP_COLOR: [f32; 3] = [0.431, 0.404, 0.396];
pub static FOCUS_INDICATOR_COLOR: [f32; 3] = [0.580, 0.921, 0.921]; pub static FOCUS_INDICATOR_COLOR: [f32; 3] = [0.580, 0.921, 0.921];
pub static OUTLINE_SHADER: &str = include_str!("./shaders/rounded_outline.frag"); pub static OUTLINE_SHADER: &str = include_str!("./shaders/rounded_outline.frag");
@ -136,6 +135,7 @@ impl From<Id> for Key {
#[derive(PartialEq)] #[derive(PartialEq)]
struct IndicatorSettings { struct IndicatorSettings {
thickness: u8, thickness: u8,
radius: u8,
alpha: f32, alpha: f32,
color: [f32; 3], color: [f32; 3],
} }
@ -158,13 +158,20 @@ impl IndicatorShader {
mut element_geo: Rectangle<i32, Logical>, mut element_geo: Rectangle<i32, Logical>,
thickness: u8, thickness: u8,
alpha: f32, alpha: f32,
color: [f32; 3],
) -> PixelShaderElement { ) -> PixelShaderElement {
let t = thickness as i32; let t = thickness as i32;
element_geo.loc -= (t, t).into(); element_geo.loc -= (t, t).into();
element_geo.size += (t * 2, t * 2).into(); element_geo.size += (t * 2, t * 2).into();
IndicatorShader::element(renderer, key, element_geo, thickness, alpha, color) IndicatorShader::element(
renderer,
key,
element_geo,
thickness,
thickness * 2,
alpha,
FOCUS_INDICATOR_COLOR,
)
} }
pub fn element<R: AsGlowRenderer>( pub fn element<R: AsGlowRenderer>(
@ -172,11 +179,13 @@ impl IndicatorShader {
key: impl Into<Key>, key: impl Into<Key>,
geo: Rectangle<i32, Logical>, geo: Rectangle<i32, Logical>,
thickness: u8, thickness: u8,
radius: u8,
alpha: f32, alpha: f32,
color: [f32; 3], color: [f32; 3],
) -> PixelShaderElement { ) -> PixelShaderElement {
let settings = IndicatorSettings { let settings = IndicatorSettings {
thickness, thickness,
radius,
alpha, alpha,
color, color,
}; };
@ -210,7 +219,7 @@ impl IndicatorShader {
vec![ vec![
Uniform::new("color", color), Uniform::new("color", color),
Uniform::new("thickness", thickness), Uniform::new("thickness", thickness),
Uniform::new("radius", thickness * 2.0), Uniform::new("radius", radius as f32),
], ],
); );
cache.insert(key.clone(), (settings, elem)); cache.insert(key.clone(), (settings, elem));

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{
backend::render::{element::AsGlowRenderer, IndicatorShader, FOCUS_INDICATOR_COLOR}, backend::render::{element::AsGlowRenderer, IndicatorShader},
shell::{ shell::{
element::{window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement}, element::{window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement},
focus::target::{KeyboardFocusTarget, PointerFocusTarget}, focus::target::{KeyboardFocusTarget, PointerFocusTarget},
@ -64,13 +64,12 @@ impl MoveGrabState {
let mut elements: Vec<I> = Vec::new(); let mut elements: Vec<I> = Vec::new();
if self.indicator_thickness > 0 { if self.indicator_thickness > 0 {
elements.push( elements.push(
CosmicMappedRenderElement::from(IndicatorShader::element( CosmicMappedRenderElement::from(IndicatorShader::focus_element(
renderer, renderer,
self.window.clone(), self.window.clone(),
Rectangle::from_loc_and_size(render_location, self.window.geometry().size), Rectangle::from_loc_and_size(render_location, self.window.geometry().size),
self.indicator_thickness, self.indicator_thickness,
1.0, 1.0,
FOCUS_INDICATOR_COLOR,
)) ))
.into(), .into(),
); );

View file

@ -13,7 +13,7 @@ use smithay::{
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
backend::render::{element::AsGlowRenderer, IndicatorShader, FOCUS_INDICATOR_COLOR}, backend::render::{element::AsGlowRenderer, IndicatorShader},
shell::{ shell::{
element::{window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement}, element::{window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement},
grabs::ResizeEdge, grabs::ResizeEdge,
@ -388,7 +388,6 @@ impl FloatingLayout {
), ),
indicator_thickness, indicator_thickness,
alpha, alpha,
FOCUS_INDICATOR_COLOR,
); );
elements.insert(0, element.into()); elements.insert(0, element.into());
} }

View file

@ -2,8 +2,8 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::AsGlowRenderer, BackdropShader, IndicatorShader, Key, ACTIVE_GROUP_COLOR, element::AsGlowRenderer, BackdropShader, IndicatorShader, Key, FOCUS_INDICATOR_COLOR,
FOCUS_INDICATOR_COLOR, GROUP_COLOR, GROUP_COLOR,
}, },
shell::{ shell::{
element::{window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement}, element::{window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement},
@ -1651,7 +1651,7 @@ impl TilingLayout {
non_exclusive_zone, non_exclusive_zone,
seat, // TODO: Would be better to be an old focus, seat, // TODO: Would be better to be an old focus,
// but for that we have to associate focus with a tree (and animate focus changes properly) // but for that we have to associate focus with a tree (and animate focus changes properly)
1.0 - percentage, 1.0 - transition,
transition, transition,
) )
} else { } else {
@ -1680,7 +1680,7 @@ impl TilingLayout {
renderer, renderer,
non_exclusive_zone, non_exclusive_zone,
seat, seat,
percentage, transition,
transition, transition,
) )
} else { } else {
@ -1699,7 +1699,7 @@ impl TilingLayout {
output_scale, output_scale,
percentage, percentage,
if let Some(transition) = draw_groups { if let Some(transition) = draw_groups {
let diff = (3u8.abs_diff(indicator_thickness) as f32 * transition).round() as u8; let diff = (4u8.abs_diff(indicator_thickness) as f32 * transition).round() as u8;
if 3 > indicator_thickness { if 3 > indicator_thickness {
indicator_thickness + diff indicator_thickness + diff
} else { } else {
@ -1738,63 +1738,76 @@ where
{ {
// we need to recalculate geometry for all elements, if we are drawing groups // we need to recalculate geometry for all elements, if we are drawing groups
if let Some(root) = tree.root_node_id() { if let Some(root) = tree.root_node_id() {
let mut stack = vec![non_exclusive_zone]; const OUTER_GAP: i32 = 8;
let outer_gap: i32 = (OUTER_GAP as f32 * transition).round() as i32;
const INNER_GAP: i32 = 16;
let inner_gap: i32 = (INNER_GAP as f32 * transition).round() as i32;
let mut stack = vec![Rectangle::from_loc_and_size(
non_exclusive_zone.loc + Point::from((outer_gap, outer_gap)),
(non_exclusive_zone.size.to_point() - Point::from((outer_gap * 2, outer_gap * 2)))
.to_size(),
)];
let mut elements = Vec::new(); let mut elements = Vec::new();
let mut geometries = HashMap::new(); let mut geometries = HashMap::new();
const GAP: i32 = 16;
let gap: i32 = (GAP as f32 * transition).round() as i32;
let alpha = alpha * transition; let alpha = alpha * transition;
let focused = seat let focused = seat
.and_then(|seat| TilingLayout::currently_focused_node(&tree, seat)) .and_then(|seat| TilingLayout::currently_focused_node(&tree, seat))
.map(|(id, _)| id); .map(|(id, _)| id);
let has_potential_groups = if let Some(focused_id) = focused.as_ref() {
let focused_node = tree.get(focused_id).unwrap();
if let Some(parent) = focused_node.parent() {
let parent_node = tree.get(parent).unwrap();
parent_node.children().len() > 2
|| parent_node.children().iter().any(|id| {
let data = tree.get(id).unwrap().data();
data.is_group() && data.orientation() == parent_node.data().orientation()
})
} else {
false
}
} else {
false
};
for node_id in tree.traverse_pre_order_ids(root).unwrap() { for node_id in tree.traverse_pre_order_ids(root).unwrap() {
if let Some(mut geo) = stack.pop() { if let Some(mut geo) = stack.pop() {
// zoom in windows
geo.loc += (gap, gap).into();
geo.size -= (gap * 2, gap * 2).into();
let node: &Node<Data> = tree.get(&node_id).unwrap(); let node: &Node<Data> = tree.get(&node_id).unwrap();
let data = node.data(); let data = node.data();
let is_potential_group = if let Some(focused_id) = focused.as_ref() { let render_potential_group = has_potential_groups
// 1. focused can move into us directly && (if let Some(focused_id) = focused.as_ref() {
if let Some(parent) = node.parent() { // `focused` can move into us directly
let parent_data = tree.get(parent).unwrap().data(); if let Some(parent) = node.parent() {
let parent_data = tree.get(parent).unwrap().data();
let idx = tree let idx = tree
.children_ids(parent) .children_ids(parent)
.unwrap() .unwrap()
.position(|id| id == &node_id) .position(|id| id == &node_id)
.unwrap(); .unwrap();
if let Some(focused_idx) = tree if let Some(focused_idx) = tree
.children_ids(parent) .children_ids(parent)
.unwrap() .unwrap()
.position(|id| id == focused_id) .position(|id| id == focused_id)
{ {
// only direct neighbors // only direct neighbors
focused_idx.abs_diff(idx) == 1 focused_idx.abs_diff(idx) == 1
// skip neighbors, if this is a group of two windows // skip neighbors, if this is a group of two windows
&& !(parent_data.len() == 2 && data.is_mapped(None)) && !(parent_data.len() == 2 && data.is_mapped(None))
// skip groups of two in opposite orientation to indicate move between // skip groups of two in opposite orientation to indicate move between
&& !(parent_data.len() == 2 && if data.is_group() { parent_data.orientation() != data.orientation() } else { false } ) && !(parent_data.len() == 2 && if data.is_group() { parent_data.orientation() != data.orientation() } else { false } )
} else {
false
}
} else { } else {
false false
} }
} } else {
// 2. focused can move out into us false
else { });
tree.children_ids(&node_id).unwrap().any(|child_id| {
tree.children_ids(child_id)
.unwrap()
.any(|child_id| child_id == focused_id)
})
}
} else {
false
};
match data { match data {
Data::Group { Data::Group {
@ -1803,30 +1816,29 @@ where
sizes, sizes,
alive, alive,
} => { } => {
let has_active_child = if let Some(focused_id) = focused.as_ref() { let render_active_child = if let Some(focused_id) = focused.as_ref() {
tree.children_ids(&node_id) !has_potential_groups
.unwrap() && tree
.any(|child_id| child_id == focused_id) .children_ids(&node_id)
.unwrap()
.any(|child_id| child_id == focused_id)
} else { } else {
false false
}; };
if (is_potential_group || has_active_child) && &node_id != root { if (render_potential_group || render_active_child) && &node_id != root {
elements.push( elements.push(
IndicatorShader::element( IndicatorShader::element(
renderer, renderer,
Key::Group(Arc::downgrade(&alive)), Key::Group(Arc::downgrade(&alive)),
geo, geo,
3, 4,
alpha, if render_active_child { 16 } else { 8 },
if has_active_child { alpha * if render_potential_group { 0.14 } else { 1.0 },
ACTIVE_GROUP_COLOR GROUP_COLOR,
} else {
GROUP_COLOR
},
) )
.into(), .into(),
) );
} }
geometries.insert(node_id.clone(), geo); geometries.insert(node_id.clone(), geo);
@ -1876,26 +1888,50 @@ where
} }
} }
Data::Mapped { mapped, .. } => { Data::Mapped { mapped, .. } => {
if is_potential_group { geo.loc += (outer_gap, outer_gap).into();
geo.size -= (outer_gap * 2, outer_gap * 2).into();
if render_potential_group {
elements.push( elements.push(
IndicatorShader::element( IndicatorShader::element(
renderer, renderer,
mapped.clone(), mapped.clone(),
geo, geo,
3, 4,
alpha, 8,
alpha * if render_potential_group { 0.4 } else { 1.0 },
GROUP_COLOR, GROUP_COLOR,
) )
.into(), .into(),
); );
geo.loc += (outer_gap, outer_gap).into();
geo.size -= (outer_gap * 2, outer_gap * 2).into();
} }
if is_potential_group elements.push(
|| node.parent().map(|parent| parent == root).unwrap_or(false) BackdropShader::element(
{ renderer,
geo.loc += (gap, gap).into(); mapped.clone(),
geo.size -= (gap * 2, gap * 2).into(); geo,
} 8.,
alpha
* if focused
.as_ref()
.map(|focused_id| focused_id == &node_id)
.unwrap_or(false)
{
0.4
} else {
0.15
},
GROUP_COLOR,
)
.into(),
);
geo.loc += (inner_gap, inner_gap).into();
geo.size -= (inner_gap * 2, inner_gap * 2).into();
geometries.insert(node_id.clone(), geo); geometries.insert(node_id.clone(), geo);
} }
@ -2157,7 +2193,6 @@ where
geo, geo,
indicator_thickness, indicator_thickness,
1.0, 1.0,
FOCUS_INDICATOR_COLOR,
); );
elements.push(element.into()); elements.push(element.into());
} }