wzrd

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in Rust
git clone git://git.deurzen.net/wzrd
Log | Files | Refs | LICENSE

commit adfc50b5dbdeed4e78f6cde59d88648e56bb2236
parent 11dbf5e86aacfb637429ac3d5796701a4524e299
Author: deurzen <m.deurzen@tum.de>
Date:   Wed, 24 Mar 2021 21:32:03 +0100

switches to Cell for Copy fields

Diffstat:
Msrc/core/client.rs | 340+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/core/consume.rs | 3++-
Msrc/core/defaults.rs | 2++
Msrc/core/model.rs | 274++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/core/util.rs | 16++++++++++++++--
Msrc/core/workspace.rs | 5+++--
Msrc/winsys/connection.rs | 2+-
Msrc/winsys/xdata/xconnection.rs | 2+-
8 files changed, 320 insertions(+), 324 deletions(-)

diff --git a/src/core/client.rs b/src/core/client.rs @@ -13,7 +13,7 @@ use winsys::hints::SizeHints; use winsys::window::Window; use winsys::window::WindowType; -use std::cell::Ref; +use std::cell::Cell; use std::cell::RefCell; use std::time::SystemTime; @@ -24,49 +24,49 @@ pub struct Client { name: RefCell<String>, class: RefCell<String>, instance: RefCell<String>, - context: RefCell<usize>, - workspace: RefCell<usize>, + context: Cell<usize>, + workspace: Cell<usize>, window_type: WindowType, - active_region: RefCell<Region>, - previous_region: RefCell<Region>, - inner_region: RefCell<Region>, - free_region: RefCell<Region>, - tile_region: RefCell<Region>, - decoration: RefCell<Decoration>, - size_hints: RefCell<Option<SizeHints>>, - warp_pos: RefCell<Option<Pos>>, + active_region: Cell<Region>, + previous_region: Cell<Region>, + inner_region: Cell<Region>, + free_region: Cell<Region>, + tile_region: Cell<Region>, + decoration: Cell<Decoration>, + size_hints: Cell<Option<SizeHints>>, + warp_pos: Cell<Option<Pos>>, parent: Option<Window>, children: RefCell<Vec<Window>>, leader: Option<Window>, producer: Option<Window>, consumers: RefCell<Vec<Window>>, - focused: RefCell<bool>, - mapped: RefCell<bool>, - managed: RefCell<bool>, - in_window: RefCell<bool>, - floating: RefCell<bool>, - fullscreen: RefCell<bool>, - iconified: RefCell<bool>, - disowned: RefCell<bool>, - sticky: RefCell<bool>, - invincible: RefCell<bool>, - urgent: RefCell<bool>, - consuming: RefCell<bool>, - producing: RefCell<bool>, + focused: Cell<bool>, + mapped: Cell<bool>, + managed: Cell<bool>, + in_window: Cell<bool>, + floating: Cell<bool>, + fullscreen: Cell<bool>, + iconified: Cell<bool>, + disowned: Cell<bool>, + sticky: Cell<bool>, + invincible: Cell<bool>, + urgent: Cell<bool>, + consuming: Cell<bool>, + producing: Cell<bool>, pid: Option<Pid>, ppid: Option<Pid>, - last_focused: RefCell<SystemTime>, + last_focused: Cell<SystemTime>, managed_since: SystemTime, - expected_unmap_count: RefCell<u8>, + expected_unmap_count: Cell<u8>, } -impl<'client> Identify for Client { +impl Identify for Client { fn id(&self) -> Ident { self.window as Ident } } -impl<'client> Client { +impl Client { pub fn new( zone: ZoneId, window: Window, @@ -85,40 +85,40 @@ impl<'client> Client { name: RefCell::new(name.into()), class: RefCell::new(class.into()), instance: RefCell::new(instance.into()), - context: RefCell::new(0), - workspace: RefCell::new(0), + context: Cell::new(0), + workspace: Cell::new(0), window_type, - active_region: RefCell::new(Default::default()), - previous_region: RefCell::new(Default::default()), - inner_region: RefCell::new(Default::default()), - free_region: RefCell::new(Default::default()), - tile_region: RefCell::new(Default::default()), - decoration: RefCell::new(Default::default()), - size_hints: RefCell::new(None), - warp_pos: RefCell::new(None), + active_region: Cell::new(Default::default()), + previous_region: Cell::new(Default::default()), + inner_region: Cell::new(Default::default()), + free_region: Cell::new(Default::default()), + tile_region: Cell::new(Default::default()), + decoration: Cell::new(Default::default()), + size_hints: Cell::new(None), + warp_pos: Cell::new(None), parent: None, children: RefCell::new(Vec::new()), leader: None, producer: None, consumers: RefCell::new(Vec::new()), - focused: RefCell::new(false), - mapped: RefCell::new(false), - managed: RefCell::new(true), - in_window: RefCell::new(false), - floating: RefCell::new(false), - fullscreen: RefCell::new(false), - iconified: RefCell::new(false), - disowned: RefCell::new(false), - sticky: RefCell::new(false), - invincible: RefCell::new(false), - urgent: RefCell::new(false), - consuming: RefCell::new(false), - producing: RefCell::new(true), + focused: Cell::new(false), + mapped: Cell::new(false), + managed: Cell::new(true), + in_window: Cell::new(false), + floating: Cell::new(false), + fullscreen: Cell::new(false), + iconified: Cell::new(false), + disowned: Cell::new(false), + sticky: Cell::new(false), + invincible: Cell::new(false), + urgent: Cell::new(false), + consuming: Cell::new(false), + producing: Cell::new(true), pid, ppid, - last_focused: RefCell::new(SystemTime::now()), + last_focused: Cell::new(SystemTime::now()), managed_since: SystemTime::now(), - expected_unmap_count: RefCell::new(0), + expected_unmap_count: Cell::new(0), } } @@ -143,8 +143,16 @@ impl<'client> Client { } #[inline] - pub fn name(&'client self) -> Ref<'client, String> { - self.name.borrow() + pub fn set_name( + &self, + name: impl Into<String>, + ) { + self.name.replace(name.into()); + } + + #[inline] + pub fn name(&self) -> String { + self.name.borrow().to_owned() } #[inline] @@ -159,16 +167,16 @@ impl<'client> Client { } #[inline] - pub fn set_name( + pub fn set_class( &self, - name: impl Into<String>, + class: impl Into<String>, ) { - self.name.replace(name.into()); + self.class.replace(class.into()); } #[inline] - pub fn class(&'client self) -> Ref<'client, String> { - self.class.borrow() + pub fn class(&self) -> String { + self.class.borrow().to_owned() } #[inline] @@ -183,16 +191,16 @@ impl<'client> Client { } #[inline] - pub fn set_class( + pub fn set_instance( &self, - class: impl Into<String>, + instance: impl Into<String>, ) { - self.class.replace(class.into()); + self.instance.replace(instance.into()); } #[inline] - pub fn instance(&'client self) -> Ref<'client, String> { - self.instance.borrow() + pub fn instance(&self) -> String { + self.instance.borrow().to_owned() } #[inline] @@ -207,19 +215,6 @@ impl<'client> Client { } #[inline] - pub fn set_instance( - &self, - instance: impl Into<String>, - ) { - self.instance.replace(instance.into()); - } - - #[inline] - pub fn context(&self) -> usize { - self.context.borrow().clone() - } - - #[inline] pub fn set_context( &self, context: usize, @@ -228,8 +223,8 @@ impl<'client> Client { } #[inline] - pub fn workspace(&self) -> usize { - self.workspace.borrow().clone() + pub fn context(&self) -> usize { + self.context.get() } #[inline] @@ -241,44 +236,33 @@ impl<'client> Client { } #[inline] - pub fn window_type(&self) -> WindowType { - self.window_type + pub fn workspace(&self) -> usize { + self.workspace.get() } #[inline] - pub fn free_region(&self) -> Region { - self.free_region.borrow().clone() + pub fn window_type(&self) -> WindowType { + self.window_type } #[inline] - pub fn tile_region(&self) -> Region { - self.tile_region.borrow().clone() + fn set_active_region( + &self, + active_region: Region, + ) { + self.set_inner_region(active_region); + let active_region = self.active_region.replace(active_region); + self.previous_region.replace(active_region); } #[inline] pub fn active_region(&self) -> Region { - self.active_region.borrow().clone() + self.active_region.get() } #[inline] pub fn previous_region(&self) -> Region { - self.previous_region.borrow().clone() - } - - #[inline] - pub fn inner_region(&self) -> Region { - self.inner_region.borrow().clone() - } - - #[inline] - fn set_active_region( - &self, - active_region: Region, - ) { - self.previous_region - .replace(self.active_region.borrow().clone()); - self.active_region.replace(active_region); - self.set_inner_region(active_region); + self.previous_region.get() } #[inline] @@ -286,8 +270,8 @@ impl<'client> Client { &self, active_region: Region, ) { - self.inner_region.replace( - if let Some(frame) = self.decoration.borrow().clone().frame { + self.inner_region + .replace(if let Some(frame) = self.decoration.get().frame { let mut inner_region = active_region - frame.extents; inner_region.pos.x = frame.extents.left; @@ -304,8 +288,7 @@ impl<'client> Client { inner_region.pos.y = 0; inner_region - }, - ); + }); } #[inline] @@ -326,18 +309,18 @@ impl<'client> Client { } #[inline] - pub fn decoration(&self) -> Decoration { - self.decoration.borrow().clone() + pub fn free_region(&self) -> Region { + self.free_region.get() } #[inline] - pub fn frame_extents(&self) -> Extents { - Extents { - left: 0, - right: 0, - top: 0, - bottom: 0, - } + self.decoration.borrow().clone() + pub fn tile_region(&self) -> Region { + self.tile_region.get() + } + + #[inline] + pub fn inner_region(&self) -> Region { + self.inner_region.get() } #[inline] @@ -349,8 +332,18 @@ impl<'client> Client { } #[inline] - pub fn size_hints(&self) -> Option<SizeHints> { - self.size_hints.borrow().clone() + pub fn decoration(&self) -> Decoration { + self.decoration.get().to_owned() + } + + #[inline] + pub fn frame_extents(&self) -> Extents { + Extents { + left: 0, + right: 0, + top: 0, + bottom: 0, + } + self.decoration.get().to_owned() } #[inline] @@ -358,12 +351,12 @@ impl<'client> Client { &self, size_hints: Option<SizeHints>, ) { - self.size_hints.replace(size_hints); + self.size_hints.set(size_hints); } #[inline] - pub fn warp_pos(&self) -> Option<Pos> { - self.warp_pos.borrow().clone() + pub fn size_hints(&self) -> Option<SizeHints> { + self.size_hints.get() } #[inline] @@ -380,6 +373,11 @@ impl<'client> Client { } #[inline] + pub fn warp_pos(&self) -> Option<Pos> { + self.warp_pos.get().to_owned() + } + + #[inline] pub fn set_parent( &mut self, parent: Window, @@ -406,7 +404,6 @@ impl<'client> Client { child: Window, ) { let mut children = self.children.borrow_mut(); - if let Some(index) = children.iter().rposition(|&c| c == child) { children.remove(index); } @@ -444,11 +441,6 @@ impl<'client> Client { } #[inline] - pub fn consumer_len(&self) -> usize { - self.consumers.borrow().len() - } - - #[inline] pub fn add_consumer( &self, consumer: Window, @@ -462,22 +454,19 @@ impl<'client> Client { consumer: Window, ) { let mut consumers = self.consumers.borrow_mut(); - if let Some(index) = consumers.iter().rposition(|&c| c == consumer) { consumers.remove(index); } } #[inline] - pub fn is_free(&self) -> bool { - self.floating.borrow().clone() - || self.disowned.borrow().clone() - || !self.managed.borrow().clone() + pub fn consumer_len(&self) -> usize { + self.consumers.borrow().len() } #[inline] - pub fn is_focused(&self) -> bool { - self.focused.borrow().clone() + pub fn is_free(&self) -> bool { + self.floating.get() || self.disowned.get() || !self.managed.get() } #[inline] @@ -485,12 +474,12 @@ impl<'client> Client { &self, focused: bool, ) { - self.focused.replace(focused); + self.focused.set(focused); } #[inline] - pub fn is_mapped(&self) -> bool { - self.mapped.borrow().clone() + pub fn is_focused(&self) -> bool { + self.focused.get() } #[inline] @@ -498,12 +487,12 @@ impl<'client> Client { &self, mapped: bool, ) { - self.mapped.replace(mapped); + self.mapped.set(mapped); } #[inline] - pub fn is_managed(&self) -> bool { - self.managed.borrow().clone() + pub fn is_mapped(&self) -> bool { + self.mapped.get() } #[inline] @@ -511,12 +500,12 @@ impl<'client> Client { &self, managed: bool, ) { - self.managed.replace(managed); + self.managed.set(managed); } #[inline] - pub fn is_in_window(&self) -> bool { - self.in_window.borrow().clone() + pub fn is_managed(&self) -> bool { + self.managed.get() } #[inline] @@ -524,12 +513,12 @@ impl<'client> Client { &self, in_window: bool, ) { - self.in_window.replace(in_window); + self.in_window.set(in_window); } #[inline] - pub fn is_floating(&self) -> bool { - self.floating.borrow().clone() + pub fn is_in_window(&self) -> bool { + self.in_window.get() } #[inline] @@ -541,8 +530,8 @@ impl<'client> Client { } #[inline] - pub fn is_fullscreen(&self) -> bool { - self.fullscreen.borrow().clone() + pub fn is_floating(&self) -> bool { + self.floating.get() } #[inline] @@ -554,8 +543,8 @@ impl<'client> Client { } #[inline] - pub fn is_iconified(&self) -> bool { - self.iconified.borrow().clone() + pub fn is_fullscreen(&self) -> bool { + self.fullscreen.get() } #[inline] @@ -567,8 +556,8 @@ impl<'client> Client { } #[inline] - pub fn is_disowned(&self) -> bool { - self.disowned.borrow().clone() + pub fn is_iconified(&self) -> bool { + self.iconified.get() } #[inline] @@ -580,8 +569,8 @@ impl<'client> Client { } #[inline] - pub fn is_sticky(&self) -> bool { - self.sticky.borrow().clone() + pub fn is_disowned(&self) -> bool { + self.disowned.get() } #[inline] @@ -593,8 +582,8 @@ impl<'client> Client { } #[inline] - pub fn is_invincible(&self) -> bool { - self.invincible.borrow().clone() + pub fn is_sticky(&self) -> bool { + self.sticky.get() } #[inline] @@ -606,8 +595,8 @@ impl<'client> Client { } #[inline] - pub fn is_urgent(&self) -> bool { - self.urgent.borrow().clone() + pub fn is_invincible(&self) -> bool { + self.invincible.get() } #[inline] @@ -619,8 +608,8 @@ impl<'client> Client { } #[inline] - pub fn is_consuming(&self) -> bool { - self.consuming.borrow().clone() + pub fn is_urgent(&self) -> bool { + self.urgent.get() } #[inline] @@ -632,8 +621,8 @@ impl<'client> Client { } #[inline] - pub fn is_producing(&self) -> bool { - self.producing.borrow().clone() + pub fn is_consuming(&self) -> bool { + self.consuming.get() } #[inline] @@ -645,6 +634,11 @@ impl<'client> Client { } #[inline] + pub fn is_producing(&self) -> bool { + self.producing.get() + } + + #[inline] pub fn pid(&self) -> Option<Pid> { self.pid } @@ -656,7 +650,7 @@ impl<'client> Client { #[inline] pub fn last_focused(&self) -> SystemTime { - self.last_focused.borrow().clone() + self.last_focused.get() } #[inline] @@ -667,17 +661,12 @@ impl<'client> Client { #[inline] pub fn expect_unmap(&self) { self.expected_unmap_count - .replace(self.expected_unmap_count.borrow().clone() + 1); - } - - #[inline] - pub fn is_expecting_unmap(&self) -> bool { - self.expected_unmap_count.borrow().clone() > 0 + .replace(self.expected_unmap_count.get() + 1); } #[inline] pub fn consume_unmap_if_expecting(&self) -> bool { - let expected_unmap_count = self.expected_unmap_count.borrow().clone(); + let expected_unmap_count = self.expected_unmap_count.get(); let expecting = expected_unmap_count > 0; if expecting { @@ -686,9 +675,14 @@ impl<'client> Client { expecting } + + #[inline] + pub fn is_expecting_unmap(&self) -> bool { + self.expected_unmap_count.get() > 0 + } } -impl<'client> PartialEq for Client { +impl PartialEq for Client { fn eq( &self, other: &Self, @@ -708,7 +702,7 @@ impl std::fmt::Debug for Hex32 { } } -impl<'client> std::fmt::Debug for Client { +impl std::fmt::Debug for Client { fn fmt( &self, f: &mut std::fmt::Formatter<'_>, diff --git a/src/core/consume.rs b/src/core/consume.rs @@ -1,4 +1,5 @@ use crate::client::Client; +use crate::util::BuildIdHasher; use winsys::connection::Pid; use winsys::window::Window; @@ -19,7 +20,7 @@ pub fn get_spawner_pid( pid: Pid, wm_pid: Pid, pid_map: &HashMap<Pid, Window>, - client_map: &HashMap<Window, Client>, + client_map: &HashMap<Window, Client, BuildIdHasher>, ) -> Option<Pid> { let mut ppid = get_parent_pid(pid); diff --git a/src/core/defaults.rs b/src/core/defaults.rs @@ -14,6 +14,8 @@ macro_rules! WM_NAME ( () => { "wzrd" }; ); +pub const WORKSPACE_NAMES: [&str; 10] = ["main", "web", "term", "4", "5", "6", "7", "8", "9", "10"]; + impl Client { pub const MIN_CLIENT_DIM: Dim = Dim { w: 75, diff --git a/src/core/model.rs b/src/core/model.rs @@ -1,3 +1,6 @@ +#[allow(unused_imports)] +use crate::util::Util; + use crate::binding::KeyBindings; use crate::binding::MouseBindings; use crate::change::Change; @@ -8,6 +11,7 @@ use crate::cycle::Cycle; use crate::cycle::InsertPos; use crate::cycle::Selector; use crate::decoration::Decoration; +use crate::defaults; use crate::error::StateChangeError; use crate::identify::Index; use crate::jump::JumpCriterium; @@ -22,15 +26,13 @@ use crate::placement::PlacementTarget; use crate::rule::Rules; use crate::stack::StackLayer; use crate::stack::StackManager; +use crate::util::BuildIdHasher; use crate::workspace::Buffer; use crate::workspace::BufferKind; use crate::workspace::Workspace; use crate::zone::ZoneContent; use crate::zone::ZoneManager; -#[allow(unused_imports)] -use crate::util::Util; - use winsys::connection::Connection; use winsys::connection::Pid; use winsys::event::Event; @@ -56,19 +58,20 @@ use winsys::window::WindowState; use winsys::window::WindowType; use std::collections::HashMap; +use std::collections::HashSet; -pub struct Model<'a> { - conn: &'a mut dyn Connection, - stack: StackManager, - stacking_order: Vec<Window>, +pub struct Model<'model> { + conn: &'model mut dyn Connection, zone_manager: ZoneManager, + stack_manager: StackManager, + stacking_order: Vec<Window>, pid_map: HashMap<Pid, Window>, - client_map: HashMap<Window, Client>, - window_map: HashMap<Window, Window>, - frame_map: HashMap<Window, Window>, - sticky_clients: Vec<Window>, - unmanaged_windows: Vec<Window>, - fullscreen_regions: HashMap<Window, Region>, + client_map: HashMap<Window, Client, BuildIdHasher>, + window_map: HashMap<Window, Window, BuildIdHasher>, + frame_map: HashMap<Window, Window, BuildIdHasher>, + sticky_clients: HashSet<Window, BuildIdHasher>, + unmanaged_windows: HashSet<Window, BuildIdHasher>, + fullscreen_regions: HashMap<Window, Region, BuildIdHasher>, partitions: Cycle<Partition>, workspaces: Cycle<Workspace>, move_buffer: Buffer, @@ -80,37 +83,34 @@ pub struct Model<'a> { jumped_from: Option<Window>, } -impl<'a> Model<'a> { +impl<'model> Model<'model> { pub fn new( - conn: &'a mut dyn Connection, + conn: &'model mut dyn Connection, key_bindings: &KeyBindings, mouse_bindings: &MouseBindings, ) -> Self { - let move_handle = conn.create_handle(); - let resize_handle = conn.create_handle(); - Self::init( Self { - conn, - stack: StackManager::new(), - stacking_order: Vec::new(), zone_manager: ZoneManager::new(), + stack_manager: StackManager::new(), + stacking_order: Vec::with_capacity(100), pid_map: HashMap::new(), - client_map: HashMap::new(), - window_map: HashMap::new(), - frame_map: HashMap::new(), - sticky_clients: Vec::new(), - unmanaged_windows: Vec::new(), - fullscreen_regions: HashMap::new(), + client_map: HashMap::with_hasher(BuildIdHasher), + window_map: HashMap::with_hasher(BuildIdHasher), + frame_map: HashMap::with_hasher(BuildIdHasher), + sticky_clients: HashSet::with_hasher(BuildIdHasher), + unmanaged_windows: HashSet::with_hasher(BuildIdHasher), + fullscreen_regions: HashMap::with_hasher(BuildIdHasher), partitions: Cycle::new(Vec::new(), false), - workspaces: Cycle::new(Vec::with_capacity(10), false), - move_buffer: Buffer::new(BufferKind::Move, move_handle), - resize_buffer: Buffer::new(BufferKind::Resize, resize_handle), + workspaces: Cycle::new(Vec::with_capacity(defaults::WORKSPACE_NAMES.len()), false), + move_buffer: Buffer::new(BufferKind::Move, conn.create_handle()), + resize_buffer: Buffer::new(BufferKind::Resize, conn.create_handle()), prev_partition: 0, prev_workspace: 0, running: true, focus: None, jumped_from: None, + conn, }, key_bindings, mouse_bindings, @@ -125,13 +125,11 @@ impl<'a> Model<'a> { 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() { + for (i, &workspace_name) in defaults::WORKSPACE_NAMES.iter().enumerate() { let region = model .partitions .active_element() - .unwrap() + .expect("no screen region found") .screen() .placeable_region(); @@ -148,15 +146,17 @@ impl<'a> Model<'a> { } model.workspaces.activate_for(&Selector::AtIndex(0)); - - model.conn.init_wm_properties(WM_NAME!(), &workspaces); model.conn.set_current_desktop(0); + model + .conn + .init_wm_properties(WM_NAME!(), &defaults::WORKSPACE_NAMES); + model.conn.grab_bindings( &key_bindings .keys() - .cloned() - .collect::<Vec<winsys::input::KeyCode>>(), + .into_iter() + .collect::<Vec<&winsys::input::KeyCode>>(), &mouse_bindings .keys() .into_iter() @@ -292,6 +292,79 @@ impl<'a> Model<'a> { } } + fn window( + &self, + window: Window, + ) -> Option<Window> { + if self.window_map.contains_key(&window) { + return Some(window); + } + + Some(self.frame_map.get(&window)?.to_owned()) + } + + fn frame( + &self, + window: Window, + ) -> Option<Window> { + if self.frame_map.contains_key(&window) { + return Some(window); + } + + Some(self.window_map.get(&window)?.to_owned()) + } + + fn client_any( + &self, + mut window: Window, + ) -> Option<&Client> { + if let Some(&inside) = self.frame_map.get(&window) { + window = inside; + } + + self.client_map.get(&window) + } + + fn client( + &self, + window: Window, + ) -> Option<&Client> { + self.client_any(window).filter(|client| client.is_managed()) + } + + fn client_any_mut( + &mut self, + mut window: Window, + ) -> Option<&mut Client> { + if let Some(inside) = self.frame_map.get(&window) { + window = *inside; + } + + self.client_map.get_mut(&window) + } + + fn client_mut( + &mut self, + window: Window, + ) -> Option<&mut Client> { + self.client_any_mut(window) + .filter(|client| client.is_managed()) + } + + fn workspace( + &self, + index: Index, + ) -> &Workspace { + self.workspaces.get(index).unwrap() + } + + fn workspace_mut( + &mut self, + index: Index, + ) -> &mut Workspace { + self.workspaces.get_mut(index).unwrap() + } + fn acquire_partitions(&mut self) { let partitions: Vec<Partition> = self .conn @@ -381,9 +454,9 @@ impl<'a> Model<'a> { None => return, }; - let desktop = self.stack.layer_windows(StackLayer::Desktop); - let below = self.stack.layer_windows(StackLayer::Below); - let dock = self.stack.layer_windows(StackLayer::Dock); + let desktop = self.stack_manager.layer_windows(StackLayer::Desktop); + let below = self.stack_manager.layer_windows(StackLayer::Below); + let dock = self.stack_manager.layer_windows(StackLayer::Dock); let stack: Vec<Window> = workspace .stack_after_focus() @@ -404,8 +477,8 @@ impl<'a> Model<'a> { .map_or(true, |client| self.is_free(client)) }); - let above = self.stack.layer_windows(StackLayer::Above); - let notification = self.stack.layer_windows(StackLayer::Notification); + let above = self.stack_manager.layer_windows(StackLayer::Above); + let notification = self.stack_manager.layer_windows(StackLayer::Notification); let mut windows: Vec<Window> = desktop .into_iter() @@ -421,7 +494,7 @@ impl<'a> Model<'a> { { // handle above-other relationships - for &window in self.stack.above_other().keys() { + for &window in self.stack_manager.above_other().keys() { let index = windows.iter().position(|&w| w == window); if let Some(index) = index { @@ -429,7 +502,7 @@ impl<'a> Model<'a> { } } - for (&window, &sibling) in self.stack.above_other() { + for (&window, &sibling) in self.stack_manager.above_other() { let index = windows.iter().position(|&w| w == sibling); if let Some(index) = index { @@ -442,7 +515,7 @@ impl<'a> Model<'a> { { // handle below-other relationships - for &window in self.stack.below_other().keys() { + for &window in self.stack_manager.below_other().keys() { let index = windows.iter().position(|&w| w == window); if let Some(index) = index { @@ -450,7 +523,7 @@ impl<'a> Model<'a> { } } - for (&window, &sibling) in self.stack.below_other() { + for (&window, &sibling) in self.stack_manager.below_other() { let index = windows.iter().position(|&w| w == sibling); if let Some(index) = index { @@ -479,6 +552,7 @@ impl<'a> Model<'a> { return; } + // TODO: keep separate client Vec, open-ended hash iteration not efficient let mut client_list: Vec<&Client> = self.client_map.values().collect::<Vec<&Client>>(); client_list.sort_by_key(|&a| a.managed_since()); @@ -504,90 +578,6 @@ impl<'a> Model<'a> { self.conn.update_client_list_stacking(&client_list_stacking); } - fn window( - &self, - window: Window, - ) -> Option<Window> { - if self.window_map.contains_key(&window) { - return Some(window); - } - - Some(*self.frame_map.get(&window)?) - } - - fn frame( - &self, - window: Window, - ) -> Option<Window> { - if self.frame_map.contains_key(&window) { - return Some(window); - } - - Some(*self.window_map.get(&window)?) - } - - fn client_any( - &self, - mut window: Window, - ) -> Option<&Client> { - if let Some(inside) = self.frame_map.get(&window) { - window = *inside; - } - - self.client_map.get(&window) - } - - fn client( - &self, - window: Window, - ) -> Option<&Client> { - self.client_any(window).and_then(|client| { - if client.is_managed() { - Some(client) - } else { - None - } - }) - } - - fn client_any_mut( - &mut self, - mut window: Window, - ) -> Option<&mut Client> { - if let Some(inside) = self.frame_map.get(&window) { - window = *inside; - } - - self.client_map.get_mut(&window) - } - - fn client_mut( - &mut self, - window: Window, - ) -> Option<&mut Client> { - self.client_any_mut(window).and_then(|client| { - if client.is_managed() { - Some(client) - } else { - None - } - }) - } - - fn workspace( - &self, - index: Index, - ) -> &Workspace { - self.workspaces.get(index).unwrap() - } - - fn workspace_mut( - &mut self, - index: Index, - ) -> &mut Workspace { - self.workspaces.get_mut(index).unwrap() - } - fn detect_rules( &self, instance: &str, @@ -636,7 +626,7 @@ impl<'a> Model<'a> { } self.conn.init_unmanaged(window); - self.unmanaged_windows.push(window); + self.unmanaged_windows.insert(window); return; } @@ -789,7 +779,7 @@ impl<'a> Model<'a> { if let Some(parent) = self.client_any_mut(parent) { let parent_frame = parent.frame(); parent.add_child(window); - self.stack.add_above_other(frame, parent_frame); + self.stack_manager.add_above_other(frame, parent_frame); } } @@ -1055,7 +1045,7 @@ impl<'a> Model<'a> { w.remove_icon(window); }); - self.stack.remove_window(window); + self.stack_manager.remove_window(window); self.frame_map.remove(&frame); self.window_map.remove(&window); self.client_map.remove(&window); @@ -2195,7 +2185,7 @@ impl<'a> Model<'a> { client.set_sticky(true); self.conn .set_window_state(window, WindowState::Sticky, true); - self.sticky_clients.push(window); + self.sticky_clients.insert(window); for workspace in self.workspaces.iter_mut() { if workspace.number() as Index != workspace_index { @@ -2226,9 +2216,7 @@ impl<'a> Model<'a> { self.conn .set_window_state(window, WindowState::Sticky, false); - if let Some(index) = self.sticky_clients.iter().position(|&s| s == window) { - self.sticky_clients.remove(index); - } + self.sticky_clients.remove(&window); for workspace in self.workspaces.iter_mut() { if workspace.number() as Index != workspace_index { @@ -2944,7 +2932,7 @@ impl<'a> Model<'a> { (Some(WindowState::Above), _) => Some(StackLayer::Above), (..) => None, } - .map(|layer| self.stack.add_window(window, layer)); + .map(|layer| self.stack_manager.add_window(window, layer)); self.apply_stack(self.active_workspace()); } @@ -3008,9 +2996,7 @@ impl<'a> Model<'a> { self.apply_layout(active_workspace, true); } - if let Some(index) = self.unmanaged_windows.iter().position(|&s| s == window) { - self.unmanaged_windows.remove(index); - } + self.unmanaged_windows.remove(&window); let client = self.client_any(window); @@ -3338,8 +3324,8 @@ impl<'a> Model<'a> { ); match mode { - StackMode::Above => self.stack.add_above_other(window, sibling), - StackMode::Below => self.stack.add_below_other(window, sibling), + StackMode::Above => self.stack_manager.add_above_other(window, sibling), + StackMode::Below => self.stack_manager.add_below_other(window, sibling), } self.apply_stack(self.active_workspace()); diff --git a/src/core/util.rs b/src/core/util.rs @@ -8,7 +8,7 @@ use winsys::input::Modifier; use winsys::input::MouseShortcut; use std::cmp::Ord; -use std::hash::BuildHasherDefault; +use std::hash::BuildHasher; use std::hash::Hasher; use std::ops::Add; use std::ops::AddAssign; @@ -43,7 +43,19 @@ impl Hasher for IdHasher { } } -pub type BuildIdHasher = BuildHasherDefault<IdHasher>; +#[derive(Default, Clone)] +pub struct BuildIdHasher; + +impl BuildHasher for BuildIdHasher { + type Hasher = IdHasher; + + #[inline] + fn build_hasher(&self) -> Self::Hasher { + Self::Hasher { + state: 0, + } + } +} pub struct Util {} diff --git a/src/core/workspace.rs b/src/core/workspace.rs @@ -14,6 +14,7 @@ use crate::placement::Placement; use crate::placement::PlacementMethod; use crate::placement::PlacementRegion; use crate::placement::PlacementTarget; +use crate::util::BuildIdHasher; use crate::zone::ZoneId; use crate::zone::ZoneManager; @@ -336,7 +337,7 @@ impl Workspace { pub fn arrange<F>( &self, zone_manager: &mut ZoneManager, - client_map: &HashMap<Window, Client>, + client_map: &HashMap<Window, Client, BuildIdHasher>, screen_region: Region, ignore_filter: F, ) -> Vec<Placement> @@ -419,7 +420,7 @@ impl Workspace { pub fn cycle_focus( &mut self, dir: Direction, - client_map: &HashMap<Window, Client>, + client_map: &HashMap<Window, Client, BuildIdHasher>, zone_manager: &ZoneManager, ) -> Option<(Window, Window)> { if self.clients.len() < 2 { diff --git a/src/winsys/connection.rs b/src/winsys/connection.rs @@ -139,7 +139,7 @@ pub trait Connection { ); fn grab_bindings( &self, - key_codes: &[KeyCode], + key_codes: &[&KeyCode], mouse_bindings: &[&(MouseEventKey, MouseShortcut)], ); fn regrab_buttons( diff --git a/src/winsys/xdata/xconnection.rs b/src/winsys/xdata/xconnection.rs @@ -1513,7 +1513,7 @@ impl<'conn, Conn: connection::Connection> Connection for XConnection<'conn, Conn fn grab_bindings( &self, - key_codes: &[KeyCode], + key_codes: &[&KeyCode], mouse_bindings: &[&(MouseEventKey, MouseShortcut)], ) { for &m in &[0, u16::from(ModMask::M2)] {