commit 8d854765c3bce1d1f83e3aaf10249d182ed728fa
parent c807c214a39e1e3d41c1a1380f7edcca5e23cfff
Author: deurzen <m.deurzen@tum.de>
Date: Thu, 11 Mar 2021 09:33:43 +0100
refactors placement handling
Diffstat:
3 files changed, 289 insertions(+), 61 deletions(-)
diff --git a/src/core/model.rs b/src/core/model.rs
@@ -4,7 +4,6 @@ use crate::client::Client;
use crate::common::Change;
use crate::common::Direction;
use crate::common::Index;
-use crate::common::Placement;
use crate::common::FOCUSED_FRAME_COLOR;
use crate::common::FOCUSED_STICKY_FRAME_COLOR;
use crate::common::FREE_EXTENTS;
@@ -25,6 +24,14 @@ use crate::stack::StackManager;
use crate::workspace::Buffer;
use crate::workspace::BufferKind;
use crate::workspace::Workspace;
+use crate::zone::Layout;
+use crate::zone::Placement;
+use crate::zone::PlacementKind;
+use crate::zone::Frame;
+use crate::zone::Decoration;
+use crate::zone::ZoneContent;
+use crate::zone::ZoneId;
+use crate::zone::ZoneManager;
#[allow(unused_imports)]
use crate::util::Util;
@@ -60,6 +67,7 @@ pub struct Model<'a> {
conn: &'a mut dyn Connection,
stack: StackManager,
stacking_order: Vec<Window>,
+ zone_manager: ZoneManager,
pid_map: HashMap<Pid, Window>,
client_map: HashMap<Window, Client>,
window_map: HashMap<Window, Window>,
@@ -92,6 +100,7 @@ impl<'a> Model<'a> {
conn,
stack: StackManager::new(),
stacking_order: Vec::new(),
+ zone_manager: ZoneManager::new(),
pid_map: HashMap::new(),
client_map: HashMap::new(),
window_map: HashMap::new(),
@@ -120,18 +129,35 @@ impl<'a> Model<'a> {
mouse_bindings: &MouseBindings,
) -> Self {
info!("initializing window manager");
+ model.acquire_partitions();
let workspaces =
["main", "web", "term", "4", "5", "6", "7", "8", "9", "10"];
for (i, &workspace_name) in workspaces.iter().enumerate() {
- model
- .workspaces
- .push_back(Workspace::new(workspace_name, i as u32));
+ let region = model
+ .partitions
+ .active_element()
+ .unwrap()
+ .screen()
+ .placeable_region();
+
+ let id = model.zone_manager.new_zone(
+ None,
+ ZoneContent::Layout(
+ Layout::new(),
+ Cycle::new(Vec::new(), true),
+ ),
+ );
+
+ model.workspaces.push_back(Workspace::new(
+ workspace_name,
+ i as u32,
+ id,
+ ));
}
model.workspaces.activate_for(&Selector::AtIndex(0));
- model.acquire_partitions();
model.conn.init_wm_properties(WM_NAME!(), &workspaces);
model.conn.set_current_desktop(0);
@@ -321,24 +347,35 @@ impl<'a> Model<'a> {
// TODO: zone change
let region = self.active_screen().placeable_region();
- for placement in
- workspace.arrange_with_filter(region, &self.client_map, |client| {
+ for placement in workspace.arrange_with_filter(
+ &mut self.zone_manager,
+ region,
+ &self.client_map,
+ |client| {
// TODO: zone change
Self::is_applyable(client)
- })
- {
- let frame = self.frame(placement.window).unwrap();
+ },
+ ) {
+ match placement.kind {
+ PlacementKind::Client(window) => {
+ let frame = self.frame(window).unwrap();
- if placement.region.is_some() {
- // TODO: zone change
- self.update_client_placement(&placement);
- // TODO: zone change
- self.place_client(placement.window);
+ // TODO: sort placements by .region = Some > None
+ if placement.region.is_some() {
+ // TODO: zone change
+ self.update_client_placement(&placement);
+ // TODO: zone change
+ self.place_client(window);
+
+ self.map_client(frame);
+ } else {
+ self.unmap_client(frame);
+ }
+ },
+ PlacementKind::Tab(size) => {},
+ PlacementKind::Layout => {},
+ };
- self.map_client(frame);
- } else {
- self.unmap_client(frame);
- }
}
if must_apply_stack {
@@ -764,8 +801,18 @@ impl<'a> Model<'a> {
self.conn
.set_icccm_window_state(window, IcccmWindowState::Normal);
- if let Some(workspace) = self.workspaces.get_mut(workspace) {
- workspace.add_client(window, &InsertPos::Back);
+ if let Some(current_workspace) = self.workspaces.get(workspace) {
+ let parent_zone = current_workspace
+ .active_zone()
+ .and_then(|id| self.zone_manager.nearest_cycle(id));
+
+ let id = self
+ .zone_manager
+ .new_zone(parent_zone, ZoneContent::Client(window));
+
+ let current_workspace = self.workspaces.get_mut(workspace).unwrap();
+ current_workspace.add_zone(id, &InsertPos::AfterActive);
+ current_workspace.add_client(window, &InsertPos::Back);
}
if let Some(parent) = parent {
@@ -928,9 +975,7 @@ impl<'a> Model<'a> {
) -> bool {
// TODO: zone change
// method == LayoutMethod::Free
- !client.is_floating()
- && !client.is_disowned()
- && client.is_managed()
+ !client.is_floating() && !client.is_disowned() && client.is_managed()
}
fn is_free(
@@ -942,13 +987,13 @@ impl<'a> Model<'a> {
|| client.is_disowned()
|| !client.is_managed())
// TODO: zone change
- // || self
- // .workspaces
- // .get(client.workspace())
- // .unwrap()
- // .layout_config()
- // .method
- // == LayoutMethod::Free)
+ // || self
+ // .workspaces
+ // .get(client.workspace())
+ // .unwrap()
+ // .layout_config()
+ // .method
+ // == LayoutMethod::Free)
}
fn is_focusable(
@@ -998,7 +1043,9 @@ impl<'a> Model<'a> {
}
}
+ let id = self.zone_manager.client_zone(window);
self.workspaces.get_mut(workspace).map(|w| {
+ w.remove_zone(id);
w.remove_client(window);
w.remove_icon(window);
});
@@ -1042,8 +1089,14 @@ impl<'a> Model<'a> {
placement: &Placement,
// method: LayoutMethod,
) {
- let client = self.client_mut(placement.window).unwrap();
- client.set_frame_extents(placement.extents);
+ match placement.kind {
+ PlacementKind::Client(window) => {
+ let client = self.client_mut(window).unwrap();
+ client.set_frame_extents(placement.decoration.frame.map(|f| f.extents));
+ }
+ _ => {}
+ }
+
// LayoutMethod::Free => client.set_free_region(®ion),
// LayoutMethod::Tile => client.set_tile_region(®ion),
@@ -2259,10 +2312,23 @@ impl<'a> Model<'a> {
},
}
+ let id = self.zone_manager.client_zone(window);
+ let extents = *client.frame_extents();
+
let placement = Placement {
- window,
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(region),
- extents: *client.frame_extents(),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: extents.map(|e| {
+ Frame {
+ extents: e,
+ colors: Default::default(),
+ }
+ }),
+ }
};
// TODO: zone change
@@ -2306,10 +2372,23 @@ impl<'a> Model<'a> {
Edge::Bottom => region.pos.y += step,
}
+ let id = self.zone_manager.client_zone(window);
+ let extents = *client.frame_extents();
+
let placement = Placement {
- window,
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(region),
- extents: *client.frame_extents(),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: extents.map(|e| {
+ Frame {
+ extents: e,
+ colors: Default::default(),
+ }
+ }),
+ }
};
// TODO: zone change
@@ -2373,16 +2452,29 @@ impl<'a> Model<'a> {
region.pos.x -= width_shift;
region.pos.y -= height_shift;
+ let id = self.zone_manager.client_zone(window);
+ let extents = *client.frame_extents();
+
let placement = Placement {
- window,
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(region),
- extents: *client.frame_extents(),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: extents.map(|e| {
+ Frame {
+ extents: e,
+ colors: Default::default(),
+ }
+ }),
+ }
};
// TODO: zone change
self.update_client_placement(&placement);
// TODO: zone change
- self.place_client(placement.window);
+ self.place_client(window);
}
}
}
@@ -2472,12 +2564,25 @@ impl<'a> Model<'a> {
},
}
+ let window = client.window();
+ let id = self.zone_manager.client_zone(window);
let region = region.with_extents(&frame_extents);
+ let extents = *client.frame_extents();
let placement = Placement {
- window,
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(region),
- extents: *client.frame_extents(),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: extents.map(|e| {
+ Frame {
+ extents: e,
+ colors: Default::default(),
+ }
+ }),
+ }
};
// TODO: zone change
@@ -2527,22 +2632,34 @@ impl<'a> Model<'a> {
if let Some(window_region) =
self.move_buffer.window_region()
{
+ let window = client.window();
+ let id = self.zone_manager.client_zone(window);
+ let extents = *client.frame_extents();
+
let placement = Placement {
- window: client.window(),
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(Region {
pos: window_region.pos + grip_pos.dist(*pos),
dim: client.free_region().dim,
}),
- extents: *client.frame_extents(),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: extents.map(|e| {
+ Frame {
+ extents: e,
+ colors: Default::default(),
+ }
+ }),
+ }
};
// TODO: zone change
- self.update_client_placement(
- &placement,
- );
+ self.update_client_placement(&placement);
// TODO: zone change
- self.place_client(placement.window);
+ self.place_client(window);
}
}
}
@@ -2642,16 +2759,27 @@ impl<'a> Model<'a> {
return;
}
+ let window = client.window();
+ let id = self.zone_manager.client_zone(window);
+
let placement = Placement {
- window: client.window(),
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(region),
- extents: Some(frame_extents),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: Some(Frame {
+ extents: frame_extents,
+ colors: Default::default(),
+ }),
+ }
};
// TODO: zone change
self.update_client_placement(&placement);
// TODO: zone change
- self.place_client(placement.window);
+ self.place_client(window);
}
}
}
@@ -3196,18 +3324,29 @@ impl<'a> Model<'a> {
});
if let Some(region) = region {
+ let id = self.zone_manager.client_zone(window);
+ let extents = *client.frame_extents();
+
let placement = Placement {
- window,
+ kind: PlacementKind::Client(window),
+ zone: id,
region: Some(region),
- extents: *client.frame_extents(),
+ // TODO: zone change: should be proper frame
+ decoration: Decoration {
+ border: None,
+ frame: extents.map(|e| {
+ Frame {
+ extents: e,
+ colors: Default::default(),
+ }
+ }),
+ }
};
// TODO: zone change
- self.update_client_placement(
- &placement,
- );
+ self.update_client_placement(&placement);
// TODO: zone change
- self.place_client(placement.window);
+ self.place_client(window);
}
}
} else {
diff --git a/src/core/workspace.rs b/src/core/workspace.rs
@@ -4,10 +4,12 @@ use crate::common::Direction;
use crate::common::Ident;
use crate::common::Identify;
use crate::common::Index;
-use crate::common::Placement;
use crate::cycle::Cycle;
use crate::cycle::InsertPos;
use crate::cycle::Selector;
+use crate::zone::Placement;
+use crate::zone::ZoneId;
+use crate::zone::ZoneManager;
use winsys::common::Edge;
use winsys::common::Grip;
@@ -130,6 +132,8 @@ pub struct Scratchpad {
pub struct Workspace {
number: Ident,
name: String,
+ root_zone: ZoneId,
+ zones: Cycle<ZoneId>,
clients: Cycle<Window>,
icons: Cycle<Window>,
}
@@ -138,10 +142,13 @@ impl Workspace {
pub fn new(
name: impl Into<String>,
number: Ident,
+ root_zone: ZoneId,
) -> Self {
Self {
number,
name: name.into(),
+ root_zone,
+ zones: Cycle::new(Vec::new(), true),
clients: Cycle::new(Vec::new(), true),
icons: Cycle::new(Vec::new(), true),
}
@@ -193,6 +200,10 @@ impl Workspace {
self.clients.stack_after_focus()
}
+ pub fn active_zone(&self) -> Option<ZoneId> {
+ self.zones.active_element().copied()
+ }
+
pub fn focused_client(&self) -> Option<Window> {
self.clients.active_element().copied()
}
@@ -225,6 +236,14 @@ impl Workspace {
self.clients.next_element(dir).copied()
}
+ pub fn add_zone(
+ &mut self,
+ id: ZoneId,
+ insert: &InsertPos,
+ ) {
+ self.zones.insert_at(insert, id);
+ }
+
pub fn add_client(
&mut self,
window: Window,
@@ -257,6 +276,13 @@ impl Workspace {
Some(prev_active)
}
+ pub fn remove_zone(
+ &mut self,
+ id: ZoneId,
+ ) -> Option<Window> {
+ self.zones.remove_for(&Selector::AtIdent(id))
+ }
+
pub fn remove_client(
&mut self,
window: Window,
@@ -270,6 +296,7 @@ impl Workspace {
pub fn arrange_with_filter<F>(
&self,
+ zone_manager: &mut ZoneManager,
screen_region: Region,
client_map: &HashMap<Window, Client>,
filter: F,
@@ -279,6 +306,7 @@ impl Workspace {
{
if !self.clients.is_empty() {
// TODO: zone change
+ // zone_manager.arrange(self.root_zone)
Vec::with_capacity(0)
} else {
Vec::with_capacity(0)
diff --git a/src/core/zone.rs b/src/core/zone.rs
@@ -90,6 +90,16 @@ pub enum PlacementKind {
Layout,
}
+impl PlacementKind {
+ pub fn from_zone_content(content: &ZoneContent) -> Self {
+ match content {
+ ZoneContent::Client(window) => PlacementKind::Client(*window),
+ ZoneContent::Tab(zones) => PlacementKind::Tab(zones.len()),
+ ZoneContent::Layout(..) => PlacementKind::Layout,
+ }
+ }
+}
+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Placement {
pub kind: PlacementKind,
@@ -395,6 +405,34 @@ impl ZoneManager {
id
}
+ pub fn get_zone(
+ &self,
+ id: ZoneId,
+ ) -> &Zone {
+ self.zone_map.get(&id).unwrap()
+ }
+
+ pub fn get_zone_mut(
+ &mut self,
+ id: ZoneId,
+ ) -> &mut Zone {
+ self.zone_map.get_mut(&id).unwrap()
+ }
+
+ pub fn remove_zone(
+ &mut self,
+ id: ZoneId,
+ ) {
+ self.client_zones.remove(&id);
+ }
+
+ pub fn client_zone(
+ &self,
+ client: Window,
+ ) -> ZoneId {
+ *self.client_zones.get(&client).unwrap()
+ }
+
pub fn nearest_cycle(
&self,
id: ZoneId,
@@ -493,7 +531,7 @@ impl ZoneManager {
let mut zone_changes: Vec<(ZoneId, ZoneChange)> = Vec::new();
- let placements = match &content {
+ let mut placements = match &content {
ZoneContent::Client(window) => {
return vec![Placement {
kind: PlacementKind::Client(*window),
@@ -517,7 +555,18 @@ impl ZoneManager {
.collect::<Vec<(ZoneId, ZoneChange)>>(),
);
- match zones.active_element() {
+ let active_element = zones.active_element();
+ zones.iter().filter(|&id| {
+ if let Some(active_element) = active_element {
+ active_element != id
+ } else {
+ true
+ }
+ }).for_each(|&id| {
+ zone_changes.push((id, ZoneChange::Visible(false)));
+ });
+
+ match active_element {
None => placements,
Some(&id) => {
let subzones = self.gather_subzones(id, true);
@@ -604,9 +653,21 @@ impl ZoneManager {
zone_changes.iter().for_each(|(id, change)| {
let zone = self.zone_map.get_mut(id).unwrap();
+ let placement_kind = PlacementKind::from_zone_content(&zone.content);
+ let region = zone.region;
+ let decoration = zone.decoration;
match *change {
- ZoneChange::Visible(is_visible) => zone.is_visible = is_visible,
+ ZoneChange::Visible(is_visible) => {
+ placements.push(Placement {
+ kind: placement_kind,
+ zone: *id,
+ region: Some(region),
+ decoration,
+ });
+
+ zone.is_visible = is_visible;
+ },
ZoneChange::Active(is_active) => zone.is_active = is_active,
ZoneChange::Region(region) => zone.region = region,
ZoneChange::Decoration(decoration) => {