added screenshot keybinds, fixed focus behaviour

This commit is contained in:
NoOneBtw 2021-05-10 21:28:41 +02:00
parent 61dbfc3a3d
commit e924e8efc0
4 changed files with 182 additions and 81 deletions

View file

@ -155,6 +155,7 @@ struct VirtualScreen {
struct VirtualScreenStore { struct VirtualScreenStore {
screens: Vec<VirtualScreen>, screens: Vec<VirtualScreen>,
current_idx: usize, current_idx: usize,
last_idx: Option<usize>,
} }
impl Default for ClientState { impl Default for ClientState {
@ -274,6 +275,14 @@ impl ClientState {
self.floating_clients.iter() self.floating_clients.iter()
} }
pub fn iter_floating_visible(
&self,
) -> impl Iterator<Item = (&u64, &Client)> {
self.floating_clients
.iter()
.filter(move |&(k, _)| self.is_client_visible(k))
}
fn iter_all_clients(&self) -> impl Iterator<Item = (&u64, &Client)> { fn iter_all_clients(&self) -> impl Iterator<Item = (&u64, &Client)> {
self.floating_clients.iter().chain(self.clients.iter()) self.floating_clients.iter().chain(self.clients.iter())
} }
@ -292,18 +301,6 @@ impl ClientState {
.filter(move |&(k, _)| self.is_client_visible(k)) .filter(move |&(k, _)| self.is_client_visible(k))
} }
#[allow(dead_code)]
pub fn iter_visible_ordered(
&self,
) -> impl Iterator<Item = (&u64, &Client)> {
self.iter_master_stack()
.chain(
self.iter_floating()
.filter(move |&(k, _)| self.is_client_visible(k)),
)
.chain(self.iter_aux_stack())
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn iter_current_screen(&self) -> impl Iterator<Item = (&u64, &Client)> { pub fn iter_current_screen(&self) -> impl Iterator<Item = (&u64, &Client)> {
self.clients.iter().filter(move |&(k, _)| { self.clients.iter().filter(move |&(k, _)| {
@ -380,6 +377,12 @@ impl ClientState {
} }
} }
pub fn go_to_nth_virtualscreen(&mut self, n: usize) {
self.virtual_screens.go_to_nth(n);
self.arrange_virtual_screen();
}
pub fn rotate_right(&mut self, n: usize) { pub fn rotate_right(&mut self, n: usize) {
self.virtual_screens self.virtual_screens
.rotate_right(n.rem(self.virtual_screens.len())); .rotate_right(n.rem(self.virtual_screens.len()));
@ -394,6 +397,12 @@ impl ClientState {
self.arrange_virtual_screen(); self.arrange_virtual_screen();
} }
pub fn rotate_back(&mut self) {
self.virtual_screens.go_back();
self.arrange_virtual_screen();
}
/** /**
Sets a tiled client to floating and returns true, does nothing for a floating client and Sets a tiled client to floating and returns true, does nothing for a floating client and
returns false. If this function returns `true` you have to call `arrange_clients` after. returns false. If this function returns `true` you have to call `arrange_clients` after.
@ -785,6 +794,7 @@ impl VirtualScreenStore {
Self { Self {
screens, screens,
current_idx: 0, current_idx: 0,
last_idx: None,
} }
} }
@ -808,20 +818,42 @@ impl VirtualScreenStore {
self.screens.iter_mut() self.screens.iter_mut()
} }
fn rotate_left(&mut self, n: usize) { fn go_back(&mut self) -> usize {
let l = self.screens.len(); self.last_idx
let a = n % l; .and_then(|n| Some(self.go_to_nth(n)))
let b = self.current_idx % l; .unwrap_or(self.current_idx)
self.current_idx = ((b + l) + a) % l;
} }
fn rotate_right(&mut self, n: usize) { fn rotate_left(&mut self, n: usize) -> usize {
self.last_idx = Some(self.current_idx);
let l = self.screens.len(); let l = self.screens.len();
let a = n % l; let a = n % l;
let b = self.current_idx % l; let b = self.current_idx % l;
self.current_idx = ((b + l) - a) % l; self.current_idx = ((b + l) - a) % l;
self.current_idx
}
fn rotate_right(&mut self, n: usize) -> usize {
self.last_idx = Some(self.current_idx);
let l = self.screens.len();
let a = n % l;
let b = self.current_idx % l;
self.current_idx = ((b + l) + a) % l;
self.current_idx
}
fn go_to_nth(&mut self, n: usize) -> usize {
self.last_idx = Some(self.current_idx);
self.current_idx = n % self.screens.len();
self.current_idx
} }
} }

View file

@ -8,6 +8,7 @@ use log4rs::{
use state::WMConfig; use state::WMConfig;
mod clients; mod clients;
mod clients2;
mod state; mod state;
mod util; mod util;
mod xlib; mod xlib;

View file

@ -34,7 +34,6 @@ pub struct WindowManager {
keybinds: Vec<KeyBinding>, keybinds: Vec<KeyBinding>,
xlib: XLib, xlib: XLib,
last_rotation: Option<Direction>,
config: WMConfig, config: WMConfig,
} }
@ -85,7 +84,6 @@ impl WindowManager {
move_resize_window: MoveResizeInfo::None, move_resize_window: MoveResizeInfo::None,
keybinds: Vec::new(), keybinds: Vec::new(),
xlib, xlib,
last_rotation: None,
config, config,
} }
.init() .init()
@ -131,11 +129,34 @@ impl WindowManager {
}, },
)); ));
self.add_keybind(KeyBinding::new(
self.xlib.make_key("Print", 0),
|wm, _| wm.spawn("screenshot.sh", &[]),
));
self.add_keybind(KeyBinding::new(
self.xlib.make_key("Print", ShiftMask),
|wm, _| wm.spawn("screenshot.sh", &["-edit"]),
));
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("M", self.config.mod_key), self.xlib.make_key("M", self.config.mod_key),
Self::handle_switch_stack, Self::handle_switch_stack,
)); ));
self.add_keybind(KeyBinding::new(
self.xlib.make_key("F", self.config.mod_key),
|wm, _| {
wm.clients
.get_focused()
.into_option()
.map(|c| c.key())
.and_then(|k| Some(wm.clients.toggle_floating(&k)));
wm.arrange_clients();
},
));
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("Q", self.config.mod_key), self.xlib.make_key("Q", self.config.mod_key),
Self::kill_client, Self::kill_client,
@ -146,11 +167,6 @@ impl WindowManager {
|wm, _| wm.quit(), |wm, _| wm.quit(),
)); ));
self.add_keybind(KeyBinding::new(
self.xlib.make_key("T", self.config.mod_key),
|wm, _| wm.spawn("alacritty", &[]),
));
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib self.xlib
.make_key("Return", self.config.mod_key | ShiftMask), .make_key("Return", self.config.mod_key | ShiftMask),
@ -216,6 +232,10 @@ impl WindowManager {
wm.rotate_virtual_screen(Direction::East(N)); wm.rotate_virtual_screen(Direction::East(N));
} }
fn goto_nth<const N: usize>(wm: &mut WindowManager, _: &XKeyEvent) {
wm.go_to_nth_virtual_screen(N)
}
// Old keybinds // Old keybinds
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
@ -243,66 +263,66 @@ impl WindowManager {
|wm, _| wm.rotate_virtual_screen_back(), |wm, _| wm.rotate_virtual_screen_back(),
)); ));
// Mod + (Shift) + Num // Mod + Num
// Press Mod + `1` to move `1` virtual screen to the right // Press Mod + `1` to move go to the `1`th virtual screen
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("1", self.config.mod_key), self.xlib.make_key("1", self.config.mod_key),
rotate_east::<1>, goto_nth::<1>,
)); ));
// Press Mod + Shift + `1` to move `1` virtual screen to the left // Press Mod + `2` to move go to the `2`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("1", self.config.mod_key | ShiftMask),
rotate_west::<1>,
));
// Press Mod + `2` to move `2` virtual screen to the right
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("2", self.config.mod_key), self.xlib.make_key("2", self.config.mod_key),
rotate_east::<2>, goto_nth::<2>,
)); ));
// Press Mod + Shift + `2` to move `2` virtual screen to the left // Press Mod + `3` to move go to the `3`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("2", self.config.mod_key | ShiftMask),
rotate_west::<2>,
));
// Press Mod + `3` to move `3` virtual screen to the right
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("3", self.config.mod_key), self.xlib.make_key("3", self.config.mod_key),
rotate_east::<3>, goto_nth::<3>,
)); ));
// Press Mod + Shift + `3` to move `3` virtual screen to the left // Press Mod + `4` to move go to the `4`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("3", self.config.mod_key | ShiftMask),
rotate_west::<3>,
));
// Press Mod + `4` to move `4` virtual screen to the right
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("4", self.config.mod_key), self.xlib.make_key("4", self.config.mod_key),
rotate_east::<4>, goto_nth::<4>,
)); ));
// Press Mod + Shift + `4` to move `4` virtual screen to the left // Press Mod + `5` to move go to the `5`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("4", self.config.mod_key | ShiftMask),
rotate_west::<4>,
));
// Press Mod + `5` to move `5` virtual screen to the right
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("5", self.config.mod_key), self.xlib.make_key("5", self.config.mod_key),
rotate_east::<5>, goto_nth::<5>,
)); ));
// Press Mod + Shift + `5` to move `5` virtual screen to the left // Press Mod + `6` to move go to the `6`th virtual screen
self.add_keybind(KeyBinding::new( self.add_keybind(KeyBinding::new(
self.xlib.make_key("5", self.config.mod_key | ShiftMask), self.xlib.make_key("6", self.config.mod_key),
rotate_west::<5>, goto_nth::<6>,
));
// Press Mod + `7` to move go to the `7`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("7", self.config.mod_key),
goto_nth::<7>,
));
// Press Mod + `8` to move go to the `8`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("8", self.config.mod_key),
goto_nth::<8>,
));
// Press Mod + `9` to move go to the `9`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("9", self.config.mod_key),
goto_nth::<9>,
));
// Press Mod + `0` to move go to the `0`th virtual screen
self.add_keybind(KeyBinding::new(
self.xlib.make_key("0", self.config.mod_key),
goto_nth::<10>,
)); ));
} }
@ -365,16 +385,19 @@ impl WindowManager {
} }
fn rotate_virtual_screen_back(&mut self) { fn rotate_virtual_screen_back(&mut self) {
if let Some(dir) = self.last_rotation { self.clients.rotate_back();
self.rotate_virtual_screen(!dir);
self.arrange_clients();
} }
fn go_to_nth_virtual_screen(&mut self, n: usize) {
self.clients.go_to_nth_virtualscreen(n - 1);
self.arrange_clients();
} }
fn rotate_virtual_screen(&mut self, dir: Direction) { fn rotate_virtual_screen(&mut self, dir: Direction) {
info!("rotateing VS: {:?}", dir); info!("rotateing VS: {:?}", dir);
self.last_rotation = Some(dir);
match dir { match dir {
Direction::West(n) => self.clients.rotate_left(n), Direction::West(n) => self.clients.rotate_left(n),
Direction::East(n) => self.clients.rotate_right(n), Direction::East(n) => self.clients.rotate_right(n),
@ -382,7 +405,6 @@ impl WindowManager {
} }
self.arrange_clients(); self.arrange_clients();
self.focus_any();
} }
fn focus_any(&mut self) { fn focus_any(&mut self) {
@ -400,7 +422,8 @@ impl WindowManager {
let k = self let k = self
.clients .clients
.iter_master_stack() .iter_floating_visible()
.chain(self.clients.iter_master_stack())
.map(|(k, _)| k) .map(|(k, _)| k)
// get the first client on the stack thats not already focused // get the first client on the stack thats not already focused
.filter(|&&k| focused.map(|f| f != k).unwrap_or(true)) .filter(|&&k| focused.map(|f| f != k).unwrap_or(true))
@ -417,7 +440,8 @@ impl WindowManager {
let k = self let k = self
.clients .clients
.iter_aux_stack() .iter_floating_visible()
.chain(self.clients.iter_aux_stack())
.map(|(k, _)| k) .map(|(k, _)| k)
// get the first client on the stack thats not already focused // get the first client on the stack thats not already focused
.filter(|&&k| focused.map(|f| f != k).unwrap_or(true)) .filter(|&&k| focused.map(|f| f != k).unwrap_or(true))
@ -498,15 +522,21 @@ impl WindowManager {
} }
fn arrange_clients(&mut self) { fn arrange_clients(&mut self) {
self.clients self.clients.iter_visible().for_each(|(_, c)| {
.iter_visible() self.xlib.move_resize_client(c);
.for_each(|(_, c)| self.xlib.move_resize_client(c)); //self.xlib.expose_client(c);
});
self.hide_hidden_clients(); self.hide_hidden_clients();
self.raise_floating_clients(); self.raise_floating_clients();
if self.clients.get_focused().is_vacant() { // if no visible client is focused, focus any.
if !self
.clients
.iter_visible()
.any(|(k, _)| self.clients.is_focused(k))
{
self.focus_any(); self.focus_any();
} }
} }
@ -760,7 +790,7 @@ impl KeyBinding {
impl Default for WMConfig { impl Default for WMConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
num_virtualscreens: 5, num_virtualscreens: 10,
mod_key: Mod4Mask, mod_key: Mod4Mask,
gap: Some(2), gap: Some(2),
} }

View file

@ -11,7 +11,7 @@ use x11::xlib::{
Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen, XEvent, Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen, XEvent,
XGetTransientForHint, XGrabPointer, XInternAtom, XKillClient, XMapWindow, XGetTransientForHint, XGrabPointer, XInternAtom, XKillClient, XMapWindow,
XOpenDisplay, XRaiseWindow, XRootWindow, XSetErrorHandler, XSync, XOpenDisplay, XRaiseWindow, XRootWindow, XSetErrorHandler, XSync,
XUngrabButton, XUngrabKey, XUngrabPointer, XWarpPointer, XUngrabButton, XUngrabKey, XUngrabPointer, XWarpPointer, XWindowAttributes,
}; };
use xlib::GrabModeAsync; use xlib::GrabModeAsync;
@ -234,7 +234,7 @@ impl XLib {
); );
} }
self.send_event(client, self.atoms.take_focus); self.send_protocol(client, self.atoms.take_focus);
} }
pub fn unfocus_client(&self, client: &Client) { pub fn unfocus_client(&self, client: &Client) {
@ -391,6 +391,24 @@ impl XLib {
} }
} }
fn get_window_attributes(
&self,
window: Window,
) -> Option<XWindowAttributes> {
let mut wa = unsafe {
std::mem::MaybeUninit::<xlib::XWindowAttributes>::zeroed()
.assume_init()
};
if unsafe {
xlib::XGetWindowAttributes(self.dpy(), window, &mut wa) != 0
} {
Some(wa)
} else {
None
}
}
pub fn get_transient_for_window(&self, window: Window) -> Option<Window> { pub fn get_transient_for_window(&self, window: Window) -> Option<Window> {
let mut transient_for: Window = 0; let mut transient_for: Window = 0;
@ -403,6 +421,26 @@ impl XLib {
} }
} }
pub fn expose_client(&self, client: &Client) {
self.expose_window(client.window);
}
fn expose_window(&self, window: Window) {
if let Some(wa) = self.get_window_attributes(window) {
unsafe {
xlib::XClearArea(
self.dpy(),
window,
0,
0,
wa.width as u32,
wa.height as u32,
1,
);
}
}
}
pub fn configure_window(&self, event: &XConfigureRequestEvent) { pub fn configure_window(&self, event: &XConfigureRequestEvent) {
let mut wc = xlib::XWindowChanges { let mut wc = xlib::XWindowChanges {
x: event.x, x: event.x,
@ -496,7 +534,7 @@ impl XLib {
} }
pub fn kill_client(&self, client: &Client) { pub fn kill_client(&self, client: &Client) {
if !self.send_event(client, self.atoms.delete_window) { if !self.send_protocol(client, self.atoms.delete_window) {
unsafe { unsafe {
XKillClient(self.dpy(), client.window); XKillClient(self.dpy(), client.window);
} }
@ -565,7 +603,7 @@ impl XLib {
return false; return false;
} }
fn send_event(&self, client: &Client, proto: xlib::Atom) -> bool { fn send_protocol(&self, client: &Client, proto: xlib::Atom) -> bool {
if self.check_for_protocol(client, proto) { if self.check_for_protocol(client, proto) {
let mut data = xlib::ClientMessageData::default(); let mut data = xlib::ClientMessageData::default();
data.set_long(0, proto as i64); data.set_long(0, proto as i64);