commit a0ce39f7bede1ae9ab926667d4dce797c3e8fa01
parent ccbb1679d69a87ee0f104d3909acb3eacd20c970
Author: deurzen <m.deurzen@tum.de>
Date: Sun, 14 Mar 2021 23:25:25 +0100
implements zone activation
Diffstat:
5 files changed, 129 insertions(+), 166 deletions(-)
diff --git a/src/core/client.rs b/src/core/client.rs
@@ -1,7 +1,7 @@
-use crate::common::Ident;
-use crate::common::Identify;
use crate::common::Decoration;
use crate::common::Frame;
+use crate::common::Ident;
+use crate::common::Identify;
use crate::zone::ZoneId;
use winsys::common::Extents;
diff --git a/src/core/common.rs b/src/core/common.rs
@@ -1,8 +1,8 @@
use winsys::common::Dim;
use winsys::common::Extents;
+use winsys::common::Padding;
use winsys::common::Pos;
use winsys::common::Region;
-use winsys::common::Padding;
use winsys::common::Window;
use std::ops::Add;
diff --git a/src/core/model.rs b/src/core/model.rs
@@ -2,13 +2,13 @@ use crate::binding::KeyBindings;
use crate::binding::MouseBindings;
use crate::client::Client;
use crate::common::Change;
+use crate::common::Decoration;
use crate::common::Direction;
+use crate::common::Frame;
use crate::common::Index;
use crate::common::FREE_DECORATION;
-use crate::common::NO_DECORATION;
use crate::common::MIN_WINDOW_DIM;
-use crate::common::Decoration;
-use crate::common::Frame;
+use crate::common::NO_DECORATION;
use crate::consume::get_spawner_pid;
use crate::cycle::Cycle;
use crate::cycle::InsertPos;
@@ -402,7 +402,7 @@ impl<'a> Model<'a> {
let (free, regular): (Vec<Window>, Vec<Window>) = regular.iter().partition(|&&window| {
self.client(window).map_or(true, |client| {
- let id = self.zone_manager.client_id(client.window());
+ let id = client.zone();
let zone = self.zone_manager.zone(id);
zone.method() == PlacementMethod::Free || client.is_free()
@@ -506,24 +506,6 @@ impl<'a> Model<'a> {
self.conn.update_client_list_stacking(&client_list_stacking);
}
- fn zone(
- &self,
- window: Window,
- ) -> Option<&Zone> {
- self.zone_manager
- .client_id_checked(window)
- .and_then(|id| self.zone_manager.zone_checked(id))
- }
-
- fn zone_mut(
- &mut self,
- window: Window,
- ) -> Option<&mut Zone> {
- self.zone_manager
- .client_id_checked(window)
- .and_then(move |id| self.zone_manager.zone_checked_mut(id))
- }
-
fn window(
&self,
window: Window,
@@ -977,7 +959,7 @@ impl<'a> Model<'a> {
client: &Client,
) -> bool {
client.is_floating() && (!client.is_fullscreen() || client.is_in_window()) || {
- let id = self.zone_manager.client_id(client.window());
+ let id = client.zone();
let zone = self.zone_manager.zone(id);
zone.method() == PlacementMethod::Free
@@ -1008,6 +990,7 @@ impl<'a> Model<'a> {
let parent = client.parent();
let producer = client.producer();
let workspace = client.workspace();
+ let id = client.zone();
info!("removing client with window {:#0x}", window);
@@ -1029,10 +1012,8 @@ impl<'a> Model<'a> {
}
}
- let id = self.zone_manager.client_id(window);
self.workspaces.get_mut(workspace).map(|w| {
w.remove_zone(id);
- w.remove_client(window);
w.remove_icon(window);
});
@@ -1313,10 +1294,13 @@ impl<'a> Model<'a> {
dir: Direction,
) {
let workspace = self.active_workspace();
+ let client_map = &self.client_map;
+ let zone_manager = &self.zone_manager;
+
let windows = self
.workspaces
.get_mut(workspace)
- .and_then(|ws| ws.cycle_focus(dir));
+ .and_then(|ws| ws.cycle_focus(dir, client_map, zone_manager));
if let Some((_, window)) = windows {
self.focus(window);
@@ -1753,7 +1737,6 @@ impl<'a> Model<'a> {
if let Some(client) = self.client(window) {
let active_workspace_index = client.workspace();
let workspace_index = client.workspace();
- let id = self.zone_manager.client_id(client.window());
let client = self.client_mut(window).unwrap();
let must_float = !client.is_floating();
@@ -1828,6 +1811,7 @@ impl<'a> Model<'a> {
let client = client.unwrap();
let client_workspace_index = client.workspace();
+ let id = client.zone();
if client_workspace_index != active_workspace_index {
self.activate_workspace(client_workspace_index);
@@ -1844,10 +1828,13 @@ impl<'a> Model<'a> {
client.set_urgent(false);
}
- let workspace = self.workspace_mut(client_workspace_index);
- workspace.focus_client(window);
+ self.zone_manager.activate_zone(id);
+
+ self
+ .workspaces
+ .get_mut(client_workspace_index)
+ .and_then(|ws| ws.focus_client(window));
- let id = self.zone_manager.client_id(window);
if let Some(config) = self.zone_manager.cycle_config(id) {
if config.persistent {
self.apply_layout(client_workspace_index, false);
@@ -1912,9 +1899,6 @@ impl<'a> Model<'a> {
) {
if let Some(client) = self.client(window) {
let must_fullscreen = !client.is_fullscreen();
- let id = self.zone_manager.client_id(client.window());
-
- let must_float = client.is_floating() || client.is_disowned();
if must_fullscreen {
self.fullscreen(window);
@@ -2313,7 +2297,7 @@ impl<'a> Model<'a> {
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: self.zone_manager.client_id(window),
+ zone: client.zone(),
region: Some(region),
decoration: *client.decoration(),
};
@@ -2360,7 +2344,7 @@ impl<'a> Model<'a> {
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: self.zone_manager.client_id(window),
+ zone: client.zone(),
region: Some(region),
decoration: *client.decoration(),
};
@@ -2423,7 +2407,7 @@ impl<'a> Model<'a> {
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: self.zone_manager.client_id(window),
+ zone: client.zone(),
region: Some(region),
decoration: *client.decoration(),
};
@@ -2514,11 +2498,10 @@ impl<'a> Model<'a> {
let window = client.window();
let region = region.with_extents(&frame_extents);
-
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: self.zone_manager.client_id(window),
+ zone: client.zone(),
region: Some(region),
decoration: *client.decoration(),
};
@@ -2574,7 +2557,7 @@ impl<'a> Model<'a> {
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: self.zone_manager.client_id(window),
+ zone: client.zone(),
region: Some(region),
decoration: *client.decoration(),
};
@@ -2626,10 +2609,10 @@ impl<'a> Model<'a> {
let current_pos = *pos;
let previous_region = *client.previous_region();
- let frame_extents = client.frame_extents();
+ let decoration = client.decoration();
let (pos, mut dim) = client
.free_region()
- .without_extents(&frame_extents)
+ .without_extents(&decoration.extents())
.values();
let top_grip = grip.is_top_grip();
@@ -2659,7 +2642,7 @@ impl<'a> Model<'a> {
pos,
dim,
})
- .with_extents(&frame_extents);
+ .with_extents(&decoration.extents());
if top_grip {
region.pos.y =
@@ -2676,21 +2659,12 @@ impl<'a> Model<'a> {
}
let window = client.window();
- let id = self.zone_manager.client_id(window);
-
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: id,
+ zone: client.zone(),
region: Some(region),
- // TODO: zone change: should be proper frame
- decoration: Decoration {
- border: None,
- frame: Some(Frame {
- extents: frame_extents,
- colors: Default::default(),
- }),
- },
+ decoration: *decoration,
};
self.update_client_placement(&placement);
@@ -3221,7 +3195,7 @@ impl<'a> Model<'a> {
let placement = Placement {
method: PlacementMethod::Free,
kind: PlacementKind::Client(window),
- zone: self.zone_manager.client_id(window),
+ zone: client.zone(),
region: Some(region),
decoration: *client.decoration(),
};
diff --git a/src/core/workspace.rs b/src/core/workspace.rs
@@ -1,12 +1,12 @@
use crate::client::Client;
+use crate::common::Border;
use crate::common::Change;
+use crate::common::Decoration;
use crate::common::Direction;
+use crate::common::Frame;
use crate::common::Ident;
use crate::common::Identify;
use crate::common::Index;
-use crate::common::Decoration;
-use crate::common::Frame;
-use crate::common::Border;
use crate::common::FREE_DECORATION;
use crate::common::NO_DECORATION;
use crate::cycle::Cycle;
@@ -340,33 +340,26 @@ impl Workspace {
.unzip();
let mut placements = zone_manager.arrange(self.root_zone, &to_ignore_ids);
- placements.extend(to_ignore_clients
- .iter()
- .map(|&client| {
- let (method, region, decoration) =
- if client.is_fullscreen() && !client.is_in_window() {
- (
- PlacementMethod::Tile,
- screen_region,
- NO_DECORATION,
- )
- } else {
- (
- PlacementMethod::Free,
- *client.free_region(),
- FREE_DECORATION,
- )
- };
-
- Placement {
- method: method,
- kind: PlacementKind::Client(client.window()),
- zone: client.zone(),
- region: Some(region),
- decoration: decoration,
- }
- })
- );
+ placements.extend(to_ignore_clients.iter().map(|&client| {
+ let (method, region, decoration) =
+ if client.is_fullscreen() && !client.is_in_window() {
+ (PlacementMethod::Tile, screen_region, NO_DECORATION)
+ } else {
+ (
+ PlacementMethod::Free,
+ *client.free_region(),
+ FREE_DECORATION,
+ )
+ };
+
+ Placement {
+ method,
+ kind: PlacementKind::Client(client.window()),
+ zone: client.zone(),
+ region: Some(region),
+ decoration,
+ }
+ }));
placements
} else {
@@ -377,12 +370,22 @@ impl Workspace {
pub fn cycle_focus(
&mut self,
dir: Direction,
+ client_map: &HashMap<Window, Client>,
+ zone_manager: &ZoneManager,
) -> Option<(Window, Window)> {
if self.clients.len() < 2 {
return None;
}
- // TODO: zone change
+ let window = self.clients.active_element().unwrap();
+ let id = client_map.get(window).unwrap().zone();
+ let config = zone_manager.active_layoutconfig(id);
+
+ if let Some(config) = config {
+ if !config.wraps && self.clients.next_will_wrap(dir) {
+ return None;
+ }
+ }
let prev_active = *self.clients.active_element()?;
let now_active = *self.clients.cycle_active(dir)?;
diff --git a/src/core/zone.rs b/src/core/zone.rs
@@ -1,10 +1,13 @@
-use crate::common::Ident;
-use crate::common::Identify;
+use crate::common::Border;
use crate::common::Decoration;
use crate::common::Frame;
-use crate::common::Border;
+use crate::common::Ident;
+use crate::common::Identify;
+use crate::common::FREE_DECORATION;
+use crate::common::NO_DECORATION;
use crate::cycle::Cycle;
use crate::cycle::InsertPos;
+use crate::cycle::Selector;
use winsys::common::Dim;
use winsys::common::Extents;
@@ -158,7 +161,7 @@ impl LayoutKind {
match *self {
LayoutKind::Float => LayoutConfig {
method: PlacementMethod::Free,
- decoration: Default::default(),
+ decoration: FREE_DECORATION,
root_only: true,
gap: false,
persistent: false,
@@ -167,7 +170,7 @@ impl LayoutKind {
},
LayoutKind::SingleFloat => LayoutConfig {
method: PlacementMethod::Free,
- decoration: Default::default(),
+ decoration: FREE_DECORATION,
root_only: true,
gap: false,
persistent: true,
@@ -176,10 +179,7 @@ impl LayoutKind {
},
LayoutKind::Center => LayoutConfig {
method: PlacementMethod::Tile,
- decoration: Decoration {
- frame: None,
- border: None,
- },
+ decoration: NO_DECORATION,
root_only: false,
gap: true,
persistent: false,
@@ -188,10 +188,7 @@ impl LayoutKind {
},
LayoutKind::Monocle => LayoutConfig {
method: PlacementMethod::Tile,
- decoration: Decoration {
- frame: None,
- border: None,
- },
+ decoration: NO_DECORATION,
root_only: false,
gap: true,
persistent: false,
@@ -349,13 +346,7 @@ impl LayoutKind {
let n = active_map.len();
if n == 1 {
- return vec![(
- Disposition::Changed(*region, Decoration {
- border: None,
- frame: None,
- }),
- true,
- )];
+ return vec![(Disposition::Changed(*region, NO_DECORATION), true)];
}
let (n_main, n_stack) = stack_split(n, data.main_count);
@@ -461,13 +452,7 @@ impl LayoutKind {
let n = active_map.len();
if n == 1 {
- return vec![(
- Disposition::Changed(*region, Decoration {
- border: None,
- frame: None,
- }),
- true,
- )];
+ return vec![(Disposition::Changed(*region, NO_DECORATION), true)];
}
let cw = (dim.w as f32
@@ -666,7 +651,6 @@ pub struct Zone {
content: ZoneContent,
region: Region,
decoration: Decoration,
- is_active: bool,
is_visible: bool,
}
@@ -684,11 +668,7 @@ impl Zone {
method: PlacementMethod::Free,
content,
region,
- decoration: Decoration {
- border: None,
- frame: None,
- },
- is_active: true,
+ decoration: NO_DECORATION,
is_visible: true,
})
}
@@ -727,13 +707,6 @@ impl Zone {
}
}
- pub fn set_active(
- &mut self,
- is_active: bool,
- ) {
- self.is_active = is_active;
- }
-
pub fn set_region(
&mut self,
region: Region,
@@ -755,7 +728,6 @@ impl Zone {
enum ZoneChange {
Visible(bool),
- Active(bool),
Region(Region),
Decoration(Decoration),
Method(PlacementMethod),
@@ -763,14 +735,12 @@ enum ZoneChange {
pub struct ZoneManager {
zone_map: HashMap<ZoneId, Zone>,
- client_zones: HashMap<Window, ZoneId>,
}
impl ZoneManager {
pub fn new() -> Self {
Self {
zone_map: HashMap::new(),
- client_zones: HashMap::new(),
}
}
@@ -780,14 +750,6 @@ impl ZoneManager {
content: ZoneContent,
) -> ZoneId {
let (id, zone) = Zone::new(parent, content, Region::new(0, 0, 0, 0));
-
- match &zone.content {
- ZoneContent::Client(window) => {
- self.client_zones.insert(*window, id);
- },
- _ => {},
- };
-
let parent = parent.and_then(|p| self.zone_map.get_mut(&p));
if let Some(parent) = parent {
@@ -803,6 +765,33 @@ impl ZoneManager {
id
}
+ pub fn activate_zone(
+ &mut self,
+ id: ZoneId,
+ ) {
+ if let Some(cycle_id) = self.next_cycle(id) {
+ let cycle = self.zone_mut(cycle_id);
+
+ match cycle.content {
+ ZoneContent::Tab(ref mut zones) | ZoneContent::Layout(_, ref mut zones) => {
+ zones.activate_for(&Selector::AtIdent(id));
+ self.activate_zone(cycle_id);
+ }
+ _ => {}
+ }
+ }
+ }
+
+ pub fn active_layoutconfig(
+ &self,
+ id: ZoneId,
+ ) -> Option<LayoutConfig> {
+ let cycle = self.nearest_cycle(id);
+ let cycle = self.zone(cycle);
+
+ cycle.config()
+ }
+
pub fn zone_checked(
&self,
id: ZoneId,
@@ -831,25 +820,11 @@ impl ZoneManager {
self.zone_map.get_mut(&id).unwrap()
}
- pub fn remove_zone(
- &mut self,
- id: ZoneId,
- ) {
- self.client_zones.remove(&id);
- }
-
- pub fn client_id_checked(
+ pub fn parent_id(
&self,
- client: Window,
+ id: ZoneId,
) -> Option<ZoneId> {
- self.client_zones.get(&client).map(|&id| id)
- }
-
- pub fn client_id(
- &self,
- client: Window,
- ) -> ZoneId {
- *self.client_zones.get(&client).unwrap()
+ self.zone_map.get(&id).and_then(|zone| zone.parent)
}
pub fn cycle_config(
@@ -886,14 +861,27 @@ impl ZoneManager {
}
}
- pub fn set_active(
- &mut self,
+ pub fn next_cycle(
+ &self,
id: ZoneId,
- active: bool,
- ) {
- if let Some(zone) = self.zone_map.get_mut(&id) {
- zone.is_active = active;
+ ) -> Option<ZoneId> {
+ let mut next = self.parent_id(id);
+
+ while next.is_some() {
+ let next_id = next.unwrap();
+ let zone = self.zone_map.get(&next_id).unwrap();
+
+ match zone.content {
+ ZoneContent::Tab(_) | ZoneContent::Layout(..) => {
+ return next;
+ },
+ _ => {
+ next = self.parent_id(next_id);
+ },
+ }
}
+
+ None
}
fn gather_subzones(
@@ -1019,6 +1007,7 @@ impl ZoneManager {
}
},
ZoneContent::Layout(layout, zones) => {
+ let active_element = zones.active_element();
let mut subplacements = Vec::new();
let mut placements = vec![Placement {
method,
@@ -1038,7 +1027,7 @@ impl ZoneManager {
®ion,
zones
.iter()
- .map(|id| self.zone_map.get(id).unwrap().is_active)
+ .map(|id| Some(id) == active_element)
.collect(),
);
@@ -1094,9 +1083,6 @@ impl ZoneManager {
ZoneChange::Visible(is_visible) => {
zone.is_visible = is_visible;
},
- ZoneChange::Active(is_active) => {
- zone.is_active = is_active;
- },
ZoneChange::Region(region) => {
zone.region = region;
},