tiling: highlight backgrounds
This commit is contained in:
parent
20f4dcb466
commit
24d3b794fe
4 changed files with 116 additions and 74 deletions
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue