added screenshot keybinds, fixed focus behaviour
This commit is contained in:
parent
61dbfc3a3d
commit
e924e8efc0
|
@ -155,6 +155,7 @@ struct VirtualScreen {
|
|||
struct VirtualScreenStore {
|
||||
screens: Vec<VirtualScreen>,
|
||||
current_idx: usize,
|
||||
last_idx: Option<usize>,
|
||||
}
|
||||
|
||||
impl Default for ClientState {
|
||||
|
@ -274,6 +275,14 @@ impl ClientState {
|
|||
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)> {
|
||||
self.floating_clients.iter().chain(self.clients.iter())
|
||||
}
|
||||
|
@ -292,18 +301,6 @@ impl ClientState {
|
|||
.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)]
|
||||
pub fn iter_current_screen(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
||||
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) {
|
||||
self.virtual_screens
|
||||
.rotate_right(n.rem(self.virtual_screens.len()));
|
||||
|
@ -394,6 +397,12 @@ impl ClientState {
|
|||
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
|
||||
returns false. If this function returns `true` you have to call `arrange_clients` after.
|
||||
|
@ -785,6 +794,7 @@ impl VirtualScreenStore {
|
|||
Self {
|
||||
screens,
|
||||
current_idx: 0,
|
||||
last_idx: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -808,20 +818,42 @@ impl VirtualScreenStore {
|
|||
self.screens.iter_mut()
|
||||
}
|
||||
|
||||
fn rotate_left(&mut self, n: usize) {
|
||||
let l = self.screens.len();
|
||||
let a = n % l;
|
||||
let b = self.current_idx % l;
|
||||
|
||||
self.current_idx = ((b + l) + a) % l;
|
||||
fn go_back(&mut self) -> usize {
|
||||
self.last_idx
|
||||
.and_then(|n| Some(self.go_to_nth(n)))
|
||||
.unwrap_or(self.current_idx)
|
||||
}
|
||||
|
||||
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 a = n % l;
|
||||
let b = self.current_idx % 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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use log4rs::{
|
|||
use state::WMConfig;
|
||||
|
||||
mod clients;
|
||||
mod clients2;
|
||||
mod state;
|
||||
mod util;
|
||||
mod xlib;
|
||||
|
|
146
src/state.rs
146
src/state.rs
|
@ -34,7 +34,6 @@ pub struct WindowManager {
|
|||
keybinds: Vec<KeyBinding>,
|
||||
xlib: XLib,
|
||||
|
||||
last_rotation: Option<Direction>,
|
||||
config: WMConfig,
|
||||
}
|
||||
|
||||
|
@ -85,7 +84,6 @@ impl WindowManager {
|
|||
move_resize_window: MoveResizeInfo::None,
|
||||
keybinds: Vec::new(),
|
||||
xlib,
|
||||
last_rotation: None,
|
||||
config,
|
||||
}
|
||||
.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.xlib.make_key("M", self.config.mod_key),
|
||||
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.xlib.make_key("Q", self.config.mod_key),
|
||||
Self::kill_client,
|
||||
|
@ -146,11 +167,6 @@ impl WindowManager {
|
|||
|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.xlib
|
||||
.make_key("Return", self.config.mod_key | ShiftMask),
|
||||
|
@ -216,6 +232,10 @@ impl WindowManager {
|
|||
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
|
||||
|
||||
self.add_keybind(KeyBinding::new(
|
||||
|
@ -243,66 +263,66 @@ impl WindowManager {
|
|||
|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.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
|
||||
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
|
||||
// Press Mod + `2` to move go to the `2`th virtual screen
|
||||
self.add_keybind(KeyBinding::new(
|
||||
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
|
||||
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
|
||||
// Press Mod + `3` to move go to the `3`th virtual screen
|
||||
self.add_keybind(KeyBinding::new(
|
||||
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
|
||||
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
|
||||
// Press Mod + `4` to move go to the `4`th virtual screen
|
||||
self.add_keybind(KeyBinding::new(
|
||||
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
|
||||
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
|
||||
// Press Mod + `5` to move go to the `5`th virtual screen
|
||||
self.add_keybind(KeyBinding::new(
|
||||
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.xlib.make_key("5", self.config.mod_key | ShiftMask),
|
||||
rotate_west::<5>,
|
||||
self.xlib.make_key("6", self.config.mod_key),
|
||||
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) {
|
||||
if let Some(dir) = self.last_rotation {
|
||||
self.rotate_virtual_screen(!dir);
|
||||
}
|
||||
self.clients.rotate_back();
|
||||
|
||||
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) {
|
||||
info!("rotateing VS: {:?}", dir);
|
||||
|
||||
self.last_rotation = Some(dir);
|
||||
|
||||
match dir {
|
||||
Direction::West(n) => self.clients.rotate_left(n),
|
||||
Direction::East(n) => self.clients.rotate_right(n),
|
||||
|
@ -382,7 +405,6 @@ impl WindowManager {
|
|||
}
|
||||
|
||||
self.arrange_clients();
|
||||
self.focus_any();
|
||||
}
|
||||
|
||||
fn focus_any(&mut self) {
|
||||
|
@ -400,7 +422,8 @@ impl WindowManager {
|
|||
|
||||
let k = self
|
||||
.clients
|
||||
.iter_master_stack()
|
||||
.iter_floating_visible()
|
||||
.chain(self.clients.iter_master_stack())
|
||||
.map(|(k, _)| k)
|
||||
// get the first client on the stack thats not already focused
|
||||
.filter(|&&k| focused.map(|f| f != k).unwrap_or(true))
|
||||
|
@ -417,7 +440,8 @@ impl WindowManager {
|
|||
|
||||
let k = self
|
||||
.clients
|
||||
.iter_aux_stack()
|
||||
.iter_floating_visible()
|
||||
.chain(self.clients.iter_aux_stack())
|
||||
.map(|(k, _)| k)
|
||||
// get the first client on the stack thats not already focused
|
||||
.filter(|&&k| focused.map(|f| f != k).unwrap_or(true))
|
||||
|
@ -498,15 +522,21 @@ impl WindowManager {
|
|||
}
|
||||
|
||||
fn arrange_clients(&mut self) {
|
||||
self.clients
|
||||
.iter_visible()
|
||||
.for_each(|(_, c)| self.xlib.move_resize_client(c));
|
||||
self.clients.iter_visible().for_each(|(_, c)| {
|
||||
self.xlib.move_resize_client(c);
|
||||
//self.xlib.expose_client(c);
|
||||
});
|
||||
|
||||
self.hide_hidden_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();
|
||||
}
|
||||
}
|
||||
|
@ -760,7 +790,7 @@ impl KeyBinding {
|
|||
impl Default for WMConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
num_virtualscreens: 5,
|
||||
num_virtualscreens: 10,
|
||||
mod_key: Mod4Mask,
|
||||
gap: Some(2),
|
||||
}
|
||||
|
|
46
src/xlib.rs
46
src/xlib.rs
|
@ -11,7 +11,7 @@ use x11::xlib::{
|
|||
Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen, XEvent,
|
||||
XGetTransientForHint, XGrabPointer, XInternAtom, XKillClient, XMapWindow,
|
||||
XOpenDisplay, XRaiseWindow, XRootWindow, XSetErrorHandler, XSync,
|
||||
XUngrabButton, XUngrabKey, XUngrabPointer, XWarpPointer,
|
||||
XUngrabButton, XUngrabKey, XUngrabPointer, XWarpPointer, XWindowAttributes,
|
||||
};
|
||||
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) {
|
||||
|
@ -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> {
|
||||
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) {
|
||||
let mut wc = xlib::XWindowChanges {
|
||||
x: event.x,
|
||||
|
@ -496,7 +534,7 @@ impl XLib {
|
|||
}
|
||||
|
||||
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 {
|
||||
XKillClient(self.dpy(), client.window);
|
||||
}
|
||||
|
@ -565,7 +603,7 @@ impl XLib {
|
|||
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) {
|
||||
let mut data = xlib::ClientMessageData::default();
|
||||
data.set_long(0, proto as i64);
|
||||
|
|
Loading…
Reference in a new issue