tiling: Add support for placeholder nodes
This commit is contained in:
parent
f00dda7591
commit
8f2aa4e8a5
1 changed files with 171 additions and 14 deletions
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
grabs::ResizeEdge,
|
grabs::ResizeEdge,
|
||||||
layout::Orientation,
|
layout::Orientation,
|
||||||
CosmicSurface, OutputNotMapped, OverviewMode, ResizeDirection, ResizeMode,
|
CosmicSurface, OutputNotMapped, OverviewMode, ResizeDirection, ResizeMode, Trigger,
|
||||||
},
|
},
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -29,7 +29,7 @@ use smithay::{
|
||||||
backend::renderer::{
|
backend::renderer::{
|
||||||
element::{
|
element::{
|
||||||
utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement},
|
utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement},
|
||||||
AsRenderElements, RenderElement,
|
AsRenderElements, Id, RenderElement,
|
||||||
},
|
},
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
|
|
@ -147,6 +147,7 @@ pub struct TilingLayout {
|
||||||
queues: HashMap<OutputData, TreeQueue>,
|
queues: HashMap<OutputData, TreeQueue>,
|
||||||
standby_tree: Option<Tree<Data>>,
|
standby_tree: Option<Tree<Data>>,
|
||||||
pending_blockers: Vec<TilingBlocker>,
|
pending_blockers: Vec<TilingBlocker>,
|
||||||
|
placeholder_id: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -161,6 +162,9 @@ pub enum Data {
|
||||||
mapped: CosmicMapped,
|
mapped: CosmicMapped,
|
||||||
last_geometry: Rectangle<i32, Logical>,
|
last_geometry: Rectangle<i32, Logical>,
|
||||||
},
|
},
|
||||||
|
Placeholder {
|
||||||
|
last_geometry: Rectangle<i32, Logical>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
|
|
@ -194,6 +198,12 @@ impl Data {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn is_placeholder(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Data::Placeholder { .. } => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn orientation(&self) -> Orientation {
|
fn orientation(&self) -> Orientation {
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -225,7 +235,7 @@ impl Data {
|
||||||
|
|
||||||
sizes.insert(idx, new_size);
|
sizes.insert(idx, new_size);
|
||||||
}
|
}
|
||||||
Data::Mapped { .. } => panic!("Adding window to leaf?"),
|
_ => panic!("Adding window to leaf?"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,7 +244,7 @@ impl Data {
|
||||||
Data::Group { sizes, .. } => {
|
Data::Group { sizes, .. } => {
|
||||||
sizes.swap(i, j);
|
sizes.swap(i, j);
|
||||||
}
|
}
|
||||||
Data::Mapped { .. } => panic!("Swapping windows to a leaf?"),
|
_ => panic!("Swapping windows to a leaf?"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,7 +273,7 @@ impl Data {
|
||||||
*sizes.last_mut().unwrap() += overflow;
|
*sizes.last_mut().unwrap() += overflow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data::Mapped { .. } => panic!("Added window to leaf?"),
|
_ => panic!("Added window to leaf?"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,6 +281,7 @@ impl Data {
|
||||||
match self {
|
match self {
|
||||||
Data::Group { last_geometry, .. } => last_geometry,
|
Data::Group { last_geometry, .. } => last_geometry,
|
||||||
Data::Mapped { last_geometry, .. } => last_geometry,
|
Data::Mapped { last_geometry, .. } => last_geometry,
|
||||||
|
Data::Placeholder { last_geometry } => last_geometry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -301,7 +312,7 @@ impl Data {
|
||||||
}
|
}
|
||||||
*last_geometry = geo;
|
*last_geometry = geo;
|
||||||
}
|
}
|
||||||
Data::Mapped { last_geometry, .. } => {
|
Data::Mapped { last_geometry, .. } | Data::Placeholder { last_geometry } => {
|
||||||
*last_geometry = geo;
|
*last_geometry = geo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +321,7 @@ impl Data {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Data::Group { sizes, .. } => sizes.len(),
|
Data::Group { sizes, .. } => sizes.len(),
|
||||||
Data::Mapped { .. } => 1,
|
_ => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,6 +339,7 @@ impl TilingLayout {
|
||||||
queues: HashMap::new(),
|
queues: HashMap::new(),
|
||||||
standby_tree: None,
|
standby_tree: None,
|
||||||
pending_blockers: Vec::new(),
|
pending_blockers: Vec::new(),
|
||||||
|
placeholder_id: Id::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,6 +563,44 @@ impl TilingLayout {
|
||||||
Some(output)
|
Some(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unmap_as_placeholder(&mut self, window: &CosmicMapped) -> Option<(Output, NodeId)> {
|
||||||
|
let node_id = window.tiling_node_id.lock().unwrap().clone()?;
|
||||||
|
let output = {
|
||||||
|
self.queues
|
||||||
|
.iter()
|
||||||
|
.find(|(_, queue)| {
|
||||||
|
queue
|
||||||
|
.trees
|
||||||
|
.back()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.get(&node_id)
|
||||||
|
.map(|node| node.data().is_mapped(Some(window)))
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
|
.map(|(o, _)| o.output.clone())?
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = self
|
||||||
|
.queues
|
||||||
|
.get_mut(&output)
|
||||||
|
.unwrap()
|
||||||
|
.trees
|
||||||
|
.back_mut()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.get_mut(&node_id)
|
||||||
|
.unwrap()
|
||||||
|
.data_mut();
|
||||||
|
*data = Data::Placeholder {
|
||||||
|
last_geometry: data.geometry().clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
window.output_leave(&output);
|
||||||
|
window.set_tiled(false);
|
||||||
|
Some((output, node_id))
|
||||||
|
}
|
||||||
|
|
||||||
fn unmap_window_internal(&mut self, mapped: &CosmicMapped) {
|
fn unmap_window_internal(&mut self, mapped: &CosmicMapped) {
|
||||||
let tiling_node_id = mapped.tiling_node_id.lock().unwrap().as_ref().cloned();
|
let tiling_node_id = mapped.tiling_node_id.lock().unwrap().as_ref().cloned();
|
||||||
if let Some(node_id) = tiling_node_id {
|
if let Some(node_id) = tiling_node_id {
|
||||||
|
|
@ -1018,6 +1068,7 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
Data::Placeholder { .. } => return FocusResult::None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1144,6 +1195,7 @@ impl TilingLayout {
|
||||||
Data::Mapped { mapped, .. } => {
|
Data::Mapped { mapped, .. } => {
|
||||||
return FocusResult::Some(mapped.clone().into());
|
return FocusResult::Some(mapped.clone().into());
|
||||||
}
|
}
|
||||||
|
Data::Placeholder { .. } => return FocusResult::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1274,7 +1326,7 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
Some(mapped.windows().map(|(s, _)| s))
|
Some(mapped.windows().map(|(s, _)| s))
|
||||||
}
|
}
|
||||||
Data::Group { .. } => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
@ -1511,6 +1563,52 @@ impl TilingLayout {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn drop_window(
|
||||||
|
&mut self,
|
||||||
|
window: CosmicMapped,
|
||||||
|
output: &Output,
|
||||||
|
_cursor_pos: Point<f64, Logical>,
|
||||||
|
) -> Point<i32, Logical> {
|
||||||
|
// TODO: placeholder until we have proper logic in `element_under` to utilize
|
||||||
|
let queue = if self.queues.contains_key(output) {
|
||||||
|
self.queues.get_mut(output)
|
||||||
|
} else {
|
||||||
|
self.queues.values_mut().next()
|
||||||
|
};
|
||||||
|
let tree = if let Some(queue) = queue {
|
||||||
|
queue.trees.back_mut().map(|x| &mut x.0)
|
||||||
|
} else {
|
||||||
|
self.standby_tree.as_mut()
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
window.output_enter(&output, window.bbox());
|
||||||
|
window.set_bounds(output.geometry().size);
|
||||||
|
|
||||||
|
if let Some(id) = tree.root_node_id().and_then(|root_id| {
|
||||||
|
tree.traverse_pre_order_ids(root_id)
|
||||||
|
.unwrap()
|
||||||
|
.find(|id| tree.get(id).unwrap().data().is_placeholder())
|
||||||
|
}) {
|
||||||
|
let data = tree.get_mut(&id).unwrap().data_mut();
|
||||||
|
let geo = data.geometry().clone();
|
||||||
|
|
||||||
|
*data = Data::Mapped {
|
||||||
|
mapped: window,
|
||||||
|
last_geometry: geo,
|
||||||
|
};
|
||||||
|
output.geometry().loc + geo.loc
|
||||||
|
} else {
|
||||||
|
self.map_internal(
|
||||||
|
window.clone(),
|
||||||
|
output,
|
||||||
|
Option::<std::iter::Empty<_>>::None,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
output.geometry().loc + self.element_geometry(&window).unwrap().loc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn last_active_window<'a>(
|
fn last_active_window<'a>(
|
||||||
tree: &Tree<Data>,
|
tree: &Tree<Data>,
|
||||||
mut focus_stack: impl Iterator<Item = &'a CosmicMapped>,
|
mut focus_stack: impl Iterator<Item = &'a CosmicMapped>,
|
||||||
|
|
@ -1723,6 +1821,7 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Data::Placeholder { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2023,6 +2122,8 @@ impl TilingLayout {
|
||||||
let mut window_elements = Vec::new();
|
let mut window_elements = Vec::new();
|
||||||
let mut popup_elements = Vec::new();
|
let mut popup_elements = Vec::new();
|
||||||
|
|
||||||
|
let is_mouse_tiling = matches!(overview, OverviewMode::Started(Trigger::Pointer(_), _));
|
||||||
|
|
||||||
// all gone windows and fade them out
|
// all gone windows and fade them out
|
||||||
let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() {
|
let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() {
|
||||||
let (geometries, _) = if let Some(transition) = draw_groups {
|
let (geometries, _) = if let Some(transition) = draw_groups {
|
||||||
|
|
@ -2034,6 +2135,8 @@ impl TilingLayout {
|
||||||
// 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 - transition,
|
1.0 - transition,
|
||||||
transition,
|
transition,
|
||||||
|
&self.placeholder_id,
|
||||||
|
is_mouse_tiling,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -2065,6 +2168,8 @@ impl TilingLayout {
|
||||||
seat,
|
seat,
|
||||||
transition,
|
transition,
|
||||||
transition,
|
transition,
|
||||||
|
&self.placeholder_id,
|
||||||
|
is_mouse_tiling,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -2105,8 +2210,11 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const OUTER_GAP: i32 = 8;
|
const OUTER_GAP_KEYBOARD: i32 = 8;
|
||||||
const INNER_GAP: i32 = 16;
|
const INNER_GAP_KEYBOARD: i32 = 16;
|
||||||
|
|
||||||
|
const OUTER_GAP_MOUSE: i32 = 32;
|
||||||
|
const INNER_GAP_MOUSE: i32 = 16;
|
||||||
|
|
||||||
fn geometries_for_groupview<R>(
|
fn geometries_for_groupview<R>(
|
||||||
tree: &Tree<Data>,
|
tree: &Tree<Data>,
|
||||||
|
|
@ -2115,6 +2223,8 @@ fn geometries_for_groupview<R>(
|
||||||
seat: Option<&Seat<State>>,
|
seat: Option<&Seat<State>>,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
transition: f32,
|
transition: f32,
|
||||||
|
placeholder_id: &Id,
|
||||||
|
mouse_tiling: bool,
|
||||||
) -> Option<(
|
) -> Option<(
|
||||||
HashMap<NodeId, Rectangle<i32, Logical>>,
|
HashMap<NodeId, Rectangle<i32, Logical>>,
|
||||||
Vec<CosmicMappedRenderElement<R>>,
|
Vec<CosmicMappedRenderElement<R>>,
|
||||||
|
|
@ -2127,8 +2237,20 @@ 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 outer_gap: i32 = (OUTER_GAP as f32 * transition).round() as i32;
|
let outer_gap: i32 = (if mouse_tiling {
|
||||||
let inner_gap: i32 = (INNER_GAP as f32 * transition).round() as i32;
|
OUTER_GAP_MOUSE
|
||||||
|
} else {
|
||||||
|
OUTER_GAP_KEYBOARD
|
||||||
|
} as f32
|
||||||
|
* transition)
|
||||||
|
.round() as i32;
|
||||||
|
let inner_gap: i32 = (if mouse_tiling {
|
||||||
|
INNER_GAP_MOUSE
|
||||||
|
} else {
|
||||||
|
INNER_GAP_KEYBOARD
|
||||||
|
} as f32
|
||||||
|
* transition)
|
||||||
|
.round() as i32;
|
||||||
|
|
||||||
let mut stack = vec![Rectangle::from_loc_and_size(
|
let mut stack = vec![Rectangle::from_loc_and_size(
|
||||||
non_exclusive_zone.loc + Point::from((outer_gap, outer_gap)),
|
non_exclusive_zone.loc + Point::from((outer_gap, outer_gap)),
|
||||||
|
|
@ -2227,6 +2349,19 @@ where
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
} else if mouse_tiling && node.parent() == Some(&root) {
|
||||||
|
elements.push(
|
||||||
|
IndicatorShader::element(
|
||||||
|
renderer,
|
||||||
|
Key::Group(Arc::downgrade(alive)),
|
||||||
|
geo,
|
||||||
|
4,
|
||||||
|
8,
|
||||||
|
alpha * 0.40,
|
||||||
|
GROUP_COLOR,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
geometries.insert(node_id.clone(), geo);
|
geometries.insert(node_id.clone(), geo);
|
||||||
|
|
@ -2305,7 +2440,7 @@ where
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.any(|id| id == focused_id)
|
.any(|id| id == focused_id)
|
||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(mouse_tiling)
|
||||||
{
|
{
|
||||||
elements.push(
|
elements.push(
|
||||||
BackdropShader::element(
|
BackdropShader::element(
|
||||||
|
|
@ -2332,6 +2467,26 @@ where
|
||||||
geo.loc += (inner_gap, inner_gap).into();
|
geo.loc += (inner_gap, inner_gap).into();
|
||||||
geo.size -= (inner_gap * 2, inner_gap * 2).into();
|
geo.size -= (inner_gap * 2, inner_gap * 2).into();
|
||||||
|
|
||||||
|
geometries.insert(node_id.clone(), geo);
|
||||||
|
}
|
||||||
|
Data::Placeholder { .. } => {
|
||||||
|
geo.loc += (outer_gap, outer_gap).into();
|
||||||
|
geo.size -= (outer_gap * 2, outer_gap * 2).into();
|
||||||
|
geo.loc += (inner_gap, inner_gap).into();
|
||||||
|
geo.size -= (inner_gap * 2, inner_gap * 2).into();
|
||||||
|
|
||||||
|
elements.push(
|
||||||
|
BackdropShader::element(
|
||||||
|
renderer,
|
||||||
|
placeholder_id.clone(),
|
||||||
|
geo,
|
||||||
|
8.,
|
||||||
|
alpha * 0.4,
|
||||||
|
GROUP_COLOR,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
geometries.insert(node_id.clone(), geo);
|
geometries.insert(node_id.clone(), geo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2616,7 +2771,8 @@ where
|
||||||
if indicator_thickness > 0 || data.is_group() {
|
if indicator_thickness > 0 || data.is_group() {
|
||||||
let mut geo = geo.clone();
|
let mut geo = geo.clone();
|
||||||
if data.is_group() {
|
if data.is_group() {
|
||||||
let outer_gap: i32 = (OUTER_GAP as f32 * percentage).round() as i32;
|
let outer_gap: i32 =
|
||||||
|
(OUTER_GAP_KEYBOARD as f32 * percentage).round() as i32;
|
||||||
geo.loc += (outer_gap, outer_gap).into();
|
geo.loc += (outer_gap, outer_gap).into();
|
||||||
geo.size -= (outer_gap * 2, outer_gap * 2).into();
|
geo.size -= (outer_gap * 2, outer_gap * 2).into();
|
||||||
|
|
||||||
|
|
@ -2638,6 +2794,7 @@ where
|
||||||
match data {
|
match data {
|
||||||
Data::Mapped { mapped, .. } => mapped.clone().into(),
|
Data::Mapped { mapped, .. } => mapped.clone().into(),
|
||||||
Data::Group { alive, .. } => Key::Group(Arc::downgrade(alive)),
|
Data::Group { alive, .. } => Key::Group(Arc::downgrade(alive)),
|
||||||
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
geo,
|
geo,
|
||||||
if data.is_group() {
|
if data.is_group() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue