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 9f14aa0613ba02f99ead82e00e6c0819042a707f
parent fb0dff8589d4206fcddf029ecbf8a9f8c76a7106
Author: deurzen <m.deurzen@tum.de>
Date:   Fri,  2 Apr 2021 10:58:11 +0200

fixes {Scroll,Num}Lock key binding detection bug

Diffstat:
Msrc/core/model.rs | 73++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/core/workspace.rs | 11++++++-----
Msrc/core/zone.rs | 11++++++-----
Msrc/winsys/xdata/input.rs | 6+++++-
Msrc/winsys/xdata/xconnection.rs | 6+++---
5 files changed, 60 insertions(+), 47 deletions(-)

diff --git a/src/core/model.rs b/src/core/model.rs @@ -203,6 +203,14 @@ impl<'model> Model<'model> { } #[inline(always)] + fn window_unchecked( + &self, + window: Window, + ) -> Window { + self.window(window).unwrap() + } + + #[inline(always)] fn frame( &self, window: Window, @@ -215,6 +223,14 @@ impl<'model> Model<'model> { } #[inline(always)] + fn frame_unchecked( + &self, + window: Window, + ) -> Window { + self.frame(window).unwrap() + } + + #[inline(always)] fn client_any( &self, mut window: Window, @@ -235,7 +251,7 @@ impl<'model> Model<'model> { window = inside; } - self.client_map.get(&window).unwrap() + &self.client_map[&window] } #[inline(always)] @@ -293,9 +309,9 @@ impl<'model> Model<'model> { .connected_outputs() .into_iter() .enumerate() - .map(|(i, s)| { - s.compute_placeable_region(); - Partition::new(s, i) + .map(|(i, screen)| { + screen.compute_placeable_region(); + Partition::new(screen, i) }) .collect(); @@ -330,17 +346,13 @@ impl<'model> Model<'model> { &self, index: Index, ) { - if index != self.active_workspace() { - return; - } - - info!("applying layout on workspace {}", index); - let workspace = match self.workspaces.get(index) { - Some(workspace) => workspace, - None => return, + Some(workspace) if index == self.active_workspace() => workspace, + _ => return, }; + info!("applying layout on workspace {}", index); + let (show, hide): (Vec<Placement>, Vec<Placement>) = workspace .arrange( &self.zone_manager, @@ -351,7 +363,7 @@ impl<'model> Model<'model> { .into_iter() .partition(|placement| placement.region != PlacementRegion::NoRegion); - show.iter().for_each(|placement| { + show.into_iter().for_each(|placement| { match placement.kind { PlacementTarget::Client(window) => { let client = &self.client_map[&window]; @@ -365,7 +377,7 @@ impl<'model> Model<'model> { }; }); - hide.iter().for_each(|placement| { + hide.into_iter().for_each(|placement| { match placement.kind { PlacementTarget::Client(window) => { self.unmap_client(&self.client_map[&window]); @@ -380,17 +392,13 @@ impl<'model> Model<'model> { &self, index: Index, ) { - if index != self.active_workspace() { - return; - } - - info!("applying stack on workspace {}", index); - let workspace = match self.workspaces.get(index) { - Some(workspace) => workspace, - None => return, + Some(workspace) if index == self.active_workspace() => workspace, + _ => return, }; + info!("applying stack on workspace {}", index); + 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); @@ -400,20 +408,19 @@ impl<'model> Model<'model> { let stack = workspace .stack_after_focus() .into_iter() - .map(|window| self.frame(window).unwrap()) + .map(|window| self.frame_unchecked(window)) .collect::<Vec<Window>>(); - let (regular, fullscreen): (Vec<Window>, Vec<Window>) = - stack.iter().partition(|&&window| { - let client = self.client_unchecked(window); - !client.is_fullscreen() || client.is_contained() - }); + let (regular, fullscreen): (Vec<_>, Vec<_>) = stack.iter().partition(|&&window| { + let client = self.client_unchecked(window); + !client.is_fullscreen() || client.is_contained() + }); - let (free, regular): (Vec<Window>, Vec<Window>) = regular + let (free, regular): (Vec<_>, Vec<_>) = regular .into_iter() .partition(|&window| self.is_free(self.client_unchecked(window))); - let mut windows: Vec<Window> = desktop + let mut windows = desktop .into_iter() .chain(below.into_iter()) .chain(dock.into_iter()) @@ -423,7 +430,7 @@ impl<'model> Model<'model> { .chain(above.into_iter()) .chain(notification) .into_iter() - .collect(); + .collect::<Vec<Window>>(); // handle {above,below}-other relationships self.stack_manager @@ -491,8 +498,8 @@ impl<'model> Model<'model> { let mut client_list_stacking = client_list; let stack_windows = stack .into_iter() - .map(|window| self.window(window).unwrap()) - .collect::<Vec<Window>>(); + .map(|window| self.window_unchecked(window)) + .collect::<Vec<_>>(); client_list_stacking.retain(|&window| !stack_windows.contains(&window)); client_list_stacking = client_list_stacking diff --git a/src/core/workspace.rs b/src/core/workspace.rs @@ -27,6 +27,7 @@ use winsys::window::Window; use std::cell::Cell; use std::cell::RefCell; use std::collections::HashMap; +use std::collections::HashSet; use std::collections::VecDeque; #[derive(Clone, Copy)] @@ -228,7 +229,7 @@ impl Workspace { self.clients .borrow() .iter() - .for_each(|window| func(client_map.get(window).unwrap())); + .for_each(|window| func(&client_map[window])); } #[inline(always)] @@ -242,7 +243,7 @@ impl Workspace { self.clients .borrow() .iter() - .for_each(|window| func(client_map.get(window).unwrap())); + .for_each(|window| func(&client_map[window])); } #[inline(always)] @@ -418,12 +419,12 @@ impl Workspace { zone_manager.zone(self.root_zone).set_region(screen_region); - let (to_ignore_ids, to_ignore_clients): (Vec<_>, Vec<_>) = self + let (to_ignore_ids, to_ignore_clients): (HashSet<_>, Vec<_>) = self .clients .borrow() .iter() .chain(self.icons.borrow().iter()) - .map(|window| client_map.get(window).unwrap()) + .map(|window| &client_map[window]) .filter(|&client| ignore_filter(client)) .map(|client| (client.zone(), client)) .unzip(); @@ -498,7 +499,7 @@ impl Workspace { } let prev_active = self.clients.borrow().active_element()?.to_owned(); - let id = client_map.get(&prev_active).unwrap().zone(); + let id = client_map[&prev_active].zone(); let config = zone_manager.active_layoutconfig(id); if let Some(config) = config { diff --git a/src/core/zone.rs b/src/core/zone.rs @@ -22,6 +22,7 @@ use winsys::window::Window; use std::cell::Cell; use std::collections::HashMap; +use std::collections::HashSet; use std::sync::atomic; use std::vec::Vec; @@ -188,7 +189,7 @@ impl ZoneManager { ZoneContent::Tab(zones) | ZoneContent::Layout(_, zones) => { zones.insert_at(&InsertPos::AfterActive, id) }, - _ => panic!("attempted to insert into non-cycle"), + _ => unreachable!("attempted to insert into non-cycle"), } } @@ -384,7 +385,7 @@ impl ZoneManager { if let Some(parent) = zone.parent.get() { next = parent; } else { - panic!("no nearest cycle found"); + unreachable!("no nearest cycle found"); } } } @@ -466,7 +467,7 @@ impl ZoneManager { pub fn arrange( &self, zone: ZoneId, - to_ignore: &Vec<ZoneId>, + to_ignore: &HashSet<ZoneId>, ) -> Vec<Placement> { let cycle = self.nearest_cycle(zone); let zone = self.zone_map.get(&cycle).unwrap(); @@ -476,7 +477,7 @@ impl ZoneManager { let method = match &zone.content { ZoneContent::Tab(_) => PlacementMethod::Tile, ZoneContent::Layout(layout, _) => layout.config().method, - _ => panic!("attempting to derive method from non-cycle"), + _ => unreachable!("attempting to derive method from non-cycle"), }; self.arrange_subzones(cycle, region, decoration, method, to_ignore) @@ -488,7 +489,7 @@ impl ZoneManager { region: Region, decoration: Decoration, method: PlacementMethod, - to_ignore: &Vec<ZoneId>, + to_ignore: &HashSet<ZoneId>, ) -> Vec<Placement> { let zone = self.zone_map.get(&id).unwrap(); let content = &zone.content; diff --git a/src/winsys/xdata/input.rs b/src/winsys/xdata/input.rs @@ -115,7 +115,11 @@ impl MouseShortcut { ) -> Result<Self> { Ok(Self { button: Button::try_from(detail)?, - modifiers: Modifier::iter().filter(|m| m.was_held(state)).collect(), + modifiers: Modifier::iter() + .filter(|&m| { + m.was_held(state) && m != Modifier::NumLock && m != Modifier::ScrollLock + }) + .collect(), }) } diff --git a/src/winsys/xdata/xconnection.rs b/src/winsys/xdata/xconnection.rs @@ -1517,12 +1517,12 @@ impl<'conn, Conn: connection::Connection> Connection for XConnection<'conn, Conn key_codes: &[&KeyCode], mouse_bindings: &[&(MouseEventKey, MouseShortcut)], ) { - for &m in &[0, u16::from(ModMask::M2)] { + for &m in &[0, u16::from(ModMask::M2), u16::from(ModMask::M5)] { for k in key_codes { drop(self.conn.grab_key( false, self.screen.root, - if m != 0 { k.mask | m } else { k.mask }, + k.mask | m, k.code, xproto::GrabMode::ASYNC, xproto::GrabMode::ASYNC, @@ -1533,7 +1533,7 @@ impl<'conn, Conn: connection::Connection> Connection for XConnection<'conn, Conn drop(self.conn.grab_button( false, self.screen.root, - u32::from(self.mouse_event_mask) as u16, + u32::from(self.mouse_event_mask) as u16 | m, xproto::GrabMode::ASYNC, xproto::GrabMode::ASYNC, x11rb::NONE,