vim-like movement between and within stacks (S-[h,j,k,l]
)
This commit is contained in:
parent
f7189c72b2
commit
984f0763c7
|
@ -1,7 +1,5 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use std::num::NonZeroI32;
|
use std::num::NonZeroI32;
|
||||||
use std::{collections::HashMap, ops::Rem, usize};
|
use std::{ops::Rem, usize};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
|
@ -33,6 +31,7 @@ mod client {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
window: Window,
|
window: Window,
|
||||||
size: (i32, i32),
|
size: (i32, i32),
|
||||||
|
@ -279,8 +278,6 @@ impl ClientState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.focus_client(&key);
|
|
||||||
|
|
||||||
// adding a client changes the liling layout, rearrange
|
// adding a client changes the liling layout, rearrange
|
||||||
self.arrange_virtual_screen();
|
self.arrange_virtual_screen();
|
||||||
|
|
||||||
|
@ -339,6 +336,19 @@ 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)]
|
||||||
pub fn iter_current_screen(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
pub fn iter_current_screen(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
||||||
self.clients
|
self.clients
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -346,15 +356,17 @@ impl ClientState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_master_stack(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
pub fn iter_master_stack(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
||||||
self.clients
|
self.current_vs()
|
||||||
|
.master
|
||||||
.iter()
|
.iter()
|
||||||
.filter(move |&(k, _)| self.current_vs().is_in_master(k))
|
.map(move |k| (k, self.get(k).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_aux_stack(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
pub fn iter_aux_stack(&self) -> impl Iterator<Item = (&u64, &Client)> {
|
||||||
self.clients
|
self.current_vs()
|
||||||
|
.aux
|
||||||
.iter()
|
.iter()
|
||||||
.filter(move |&(k, _)| self.current_vs().is_in_aux(k))
|
.map(move |k| (k, self.get(k).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns reference to the current `VirtualScreen`.
|
/// Returns reference to the current `VirtualScreen`.
|
||||||
|
@ -414,16 +426,16 @@ impl ClientState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rotate_right(&mut self, n: Option<usize>) {
|
pub fn rotate_right(&mut self, n: usize) {
|
||||||
self.virtual_screens
|
self.virtual_screens
|
||||||
.rotate_right(n.unwrap_or(1).rem(self.virtual_screens.len()));
|
.rotate_right(n.rem(self.virtual_screens.len()));
|
||||||
|
|
||||||
self.arrange_virtual_screen();
|
self.arrange_virtual_screen();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rotate_left(&mut self, n: Option<usize>) {
|
pub fn rotate_left(&mut self, n: usize) {
|
||||||
self.virtual_screens
|
self.virtual_screens
|
||||||
.rotate_left(n.unwrap_or(1).rem(self.virtual_screens.len()));
|
.rotate_left(n.rem(self.virtual_screens.len()));
|
||||||
|
|
||||||
self.arrange_virtual_screen();
|
self.arrange_virtual_screen();
|
||||||
}
|
}
|
||||||
|
@ -529,6 +541,23 @@ impl ClientState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_stack_for_client<K>(&self, key: &K) -> Option<&Vec<u64>>
|
||||||
|
where
|
||||||
|
K: ClientKey,
|
||||||
|
{
|
||||||
|
if let Some(vs) = self.get_virtualscreen_for_client(key) {
|
||||||
|
if vs.is_in_aux(key) {
|
||||||
|
Some(&vs.aux)
|
||||||
|
} else if vs.is_in_master(key) {
|
||||||
|
Some(&vs.master)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
focuses client `key` if it contains `key` and returns a reference to the newly and the previously
|
focuses client `key` if it contains `key` and returns a reference to the newly and the previously
|
||||||
focused clients if any.
|
focused clients if any.
|
||||||
|
@ -540,11 +569,29 @@ impl ClientState {
|
||||||
where
|
where
|
||||||
K: ClientKey,
|
K: ClientKey,
|
||||||
{
|
{
|
||||||
|
let (new, old) = self.focus_client_inner(key);
|
||||||
|
|
||||||
|
info!("Swapping focus: new({:?}) old({:?})", new, old);
|
||||||
|
|
||||||
|
(new, old)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_client_inner<K>(
|
||||||
|
&mut self,
|
||||||
|
key: &K,
|
||||||
|
) -> (ClientEntry<&Client>, ClientEntry<&Client>)
|
||||||
|
where
|
||||||
|
K: ClientKey,
|
||||||
|
{
|
||||||
|
// if `key` is not a valid entry into the client list, do nothing
|
||||||
if self.contains(key) {
|
if self.contains(key) {
|
||||||
|
// check if we currently have a client focused
|
||||||
match self.focused {
|
match self.focused {
|
||||||
Some(focused) => {
|
Some(focused) => {
|
||||||
// If we are trying to focus the focused client, do nothing
|
|
||||||
if focused == key.key() {
|
if focused == key.key() {
|
||||||
|
// if `key` is a reference to the focused client
|
||||||
|
// dont bother unfocusing and refocusing the same client
|
||||||
|
|
||||||
(ClientEntry::Vacant, ClientEntry::Vacant)
|
(ClientEntry::Vacant, ClientEntry::Vacant)
|
||||||
} else {
|
} else {
|
||||||
// focus the new client and return reference to it
|
// focus the new client and return reference to it
|
||||||
|
@ -554,17 +601,18 @@ impl ClientState {
|
||||||
(self.get(key), self.get(&focused))
|
(self.get(key), self.get(&focused))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
not currently focusing any client
|
|
||||||
focus the new client and return reference to it.
|
|
||||||
*/
|
|
||||||
None => {
|
None => {
|
||||||
|
// not currently focusing any client
|
||||||
|
// just focus and return the client `key` references
|
||||||
|
|
||||||
self.focused = Some(key.key());
|
self.focused = Some(key.key());
|
||||||
(self.get(key), ClientEntry::Vacant)
|
(self.get(key), ClientEntry::Vacant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// key is not a reference to a valid client
|
// nothing happened, return nothing
|
||||||
|
|
||||||
(ClientEntry::Vacant, ClientEntry::Vacant)
|
(ClientEntry::Vacant, ClientEntry::Vacant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -573,6 +621,7 @@ impl ClientState {
|
||||||
sets `self.focused` to `None` and returns a reference to
|
sets `self.focused` to `None` and returns a reference to
|
||||||
the previously focused Client if any.
|
the previously focused Client if any.
|
||||||
*/
|
*/
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn unfocus(&mut self) -> ClientEntry<&Client> {
|
pub fn unfocus(&mut self) -> ClientEntry<&Client> {
|
||||||
match self.focused {
|
match self.focused {
|
||||||
Some(focused) => {
|
Some(focused) => {
|
||||||
|
@ -583,6 +632,7 @@ impl ClientState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn is_focused<K>(&self, key: &K) -> bool
|
pub fn is_focused<K>(&self, key: &K) -> bool
|
||||||
where
|
where
|
||||||
K: ClientKey,
|
K: ClientKey,
|
||||||
|
@ -773,6 +823,7 @@ impl<T> ClientEntry<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn is_floating(&self) -> bool {
|
pub fn is_floating(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
ClientEntry::Floating(_) => true,
|
ClientEntry::Floating(_) => true,
|
||||||
|
@ -787,6 +838,7 @@ impl<T> ClientEntry<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn is_occupied(&self) -> bool {
|
pub fn is_occupied(&self) -> bool {
|
||||||
!self.is_vacant()
|
!self.is_vacant()
|
||||||
}
|
}
|
||||||
|
|
143
src/state.rs
143
src/state.rs
|
@ -40,8 +40,10 @@ pub struct WindowManager {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Left(Option<usize>),
|
West(usize),
|
||||||
Right(Option<usize>),
|
East(usize),
|
||||||
|
North(usize),
|
||||||
|
South(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MoveResizeInfo {
|
enum MoveResizeInfo {
|
||||||
|
@ -156,12 +158,12 @@ impl WindowManager {
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
self.xlib.make_key("Left", self.config.mod_key),
|
self.xlib.make_key("Left", self.config.mod_key),
|
||||||
|wm, _| wm.rotate_virtual_screen(Direction::Left(None)),
|
|wm, _| wm.rotate_virtual_screen(Direction::west()),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
self.xlib.make_key("Right", self.config.mod_key),
|
self.xlib.make_key("Right", self.config.mod_key),
|
||||||
|wm, _| wm.rotate_virtual_screen(Direction::Right(None)),
|
|wm, _| wm.rotate_virtual_screen(Direction::east()),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
|
@ -171,22 +173,32 @@ impl WindowManager {
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
self.xlib.make_key("J", self.config.mod_key),
|
self.xlib.make_key("J", self.config.mod_key),
|
||||||
|wm, _| wm.focus_master_stack(),
|
|wm, _| wm.move_focus(Direction::south()),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
self.xlib.make_key("K", self.config.mod_key),
|
self.xlib.make_key("K", self.config.mod_key),
|
||||||
|wm, _| wm.focus_aux_stack(),
|
|wm, _| wm.move_focus(Direction::north()),
|
||||||
|
));
|
||||||
|
|
||||||
|
self.add_keybind(KeyBinding::new(
|
||||||
|
self.xlib.make_key("H", self.config.mod_key),
|
||||||
|
|wm, _| wm.move_focus(Direction::west()),
|
||||||
|
));
|
||||||
|
|
||||||
|
self.add_keybind(KeyBinding::new(
|
||||||
|
self.xlib.make_key("L", self.config.mod_key),
|
||||||
|
|wm, _| wm.move_focus(Direction::east()),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
self.xlib.make_key("J", self.config.mod_key | ShiftMask),
|
self.xlib.make_key("J", self.config.mod_key | ShiftMask),
|
||||||
|wm, _| wm.rotate_virtual_screen(Direction::Left(None)),
|
|wm, _| wm.rotate_virtual_screen(Direction::west()),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.add_keybind(KeyBinding::new(
|
self.add_keybind(KeyBinding::new(
|
||||||
self.xlib.make_key("K", self.config.mod_key | ShiftMask),
|
self.xlib.make_key("K", self.config.mod_key | ShiftMask),
|
||||||
|wm, _| wm.rotate_virtual_screen(Direction::Right(None)),
|
|wm, _| wm.rotate_virtual_screen(Direction::east()),
|
||||||
));
|
));
|
||||||
|
|
||||||
self.xlib.init();
|
self.xlib.init();
|
||||||
|
@ -226,8 +238,8 @@ impl WindowManager {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill_client(&mut self, event: &XKeyEvent) {
|
fn kill_client(&mut self, _event: &XKeyEvent) {
|
||||||
if let Some(client) = self.clients.get(&event.subwindow).into_option() {
|
if let Some(client) = self.clients.get_focused().into_option() {
|
||||||
self.xlib.kill_client(client);
|
self.xlib.kill_client(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,10 +258,13 @@ impl WindowManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_switch_stack(&mut self, event: &XKeyEvent) {
|
fn handle_switch_stack(&mut self, _event: &XKeyEvent) {
|
||||||
info!("Switching stack for window{:?}", event.subwindow);
|
if let Some(client) =
|
||||||
|
self.clients.get_focused().into_option().map(|c| c.key())
|
||||||
self.clients.switch_stack_for_client(&event.subwindow);
|
{
|
||||||
|
info!("Switching stack for window {:?}", client);
|
||||||
|
self.clients.switch_stack_for_client(&client);
|
||||||
|
}
|
||||||
|
|
||||||
self.arrange_clients();
|
self.arrange_clients();
|
||||||
}
|
}
|
||||||
|
@ -266,12 +281,16 @@ impl WindowManager {
|
||||||
self.last_rotation = Some(dir);
|
self.last_rotation = Some(dir);
|
||||||
|
|
||||||
match dir {
|
match dir {
|
||||||
Direction::Left(n) => self.clients.rotate_left(n),
|
Direction::West(n) => self.clients.rotate_left(n),
|
||||||
Direction::Right(n) => self.clients.rotate_right(n),
|
Direction::East(n) => self.clients.rotate_right(n),
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.arrange_clients();
|
self.arrange_clients();
|
||||||
|
self.focus_any();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_any(&mut self) {
|
||||||
// focus first client in all visible clients
|
// focus first client in all visible clients
|
||||||
let to_focus =
|
let to_focus =
|
||||||
self.clients.iter_visible().next().map(|(k, _)| k).cloned();
|
self.clients.iter_visible().next().map(|(k, _)| k).cloned();
|
||||||
|
@ -282,10 +301,14 @@ impl WindowManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_master_stack(&mut self) {
|
fn focus_master_stack(&mut self) {
|
||||||
|
let focused = self.clients.get_focused().into_option().map(|c| c.key());
|
||||||
|
|
||||||
let k = self
|
let k = self
|
||||||
.clients
|
.clients
|
||||||
.iter_master_stack()
|
.iter_master_stack()
|
||||||
.map(|(k, _)| k)
|
.map(|(k, _)| k)
|
||||||
|
// get the first client on the stack thats not already focused
|
||||||
|
.filter(|&&k| focused.map(|f| f != k).unwrap_or(true))
|
||||||
.next()
|
.next()
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
|
@ -295,10 +318,14 @@ impl WindowManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_aux_stack(&mut self) {
|
fn focus_aux_stack(&mut self) {
|
||||||
|
let focused = self.clients.get_focused().into_option().map(|c| c.key());
|
||||||
|
|
||||||
let k = self
|
let k = self
|
||||||
.clients
|
.clients
|
||||||
.iter_aux_stack()
|
.iter_aux_stack()
|
||||||
.map(|(k, _)| k)
|
.map(|(k, _)| k)
|
||||||
|
// get the first client on the stack thats not already focused
|
||||||
|
.filter(|&&k| focused.map(|f| f != k).unwrap_or(true))
|
||||||
.next()
|
.next()
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
|
@ -307,6 +334,58 @@ impl WindowManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_up(&mut self) {
|
||||||
|
let focused = self.clients.get_focused().into_option().map(|c| c.key());
|
||||||
|
|
||||||
|
let k = focused.and_then(|focused| {
|
||||||
|
self.clients
|
||||||
|
.get_stack_for_client(&focused)
|
||||||
|
.and_then(|stack| {
|
||||||
|
stack
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.skip_while(|&&k| k != focused)
|
||||||
|
.skip(1)
|
||||||
|
.next()
|
||||||
|
.cloned()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(k) = k {
|
||||||
|
self.focus_client(&k, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_down(&mut self) {
|
||||||
|
let focused = self.clients.get_focused().into_option().map(|c| c.key());
|
||||||
|
|
||||||
|
let k = focused.and_then(|focused| {
|
||||||
|
self.clients
|
||||||
|
.get_stack_for_client(&focused)
|
||||||
|
.and_then(|stack| {
|
||||||
|
stack
|
||||||
|
.iter()
|
||||||
|
.skip_while(|&&k| k != focused)
|
||||||
|
.skip(1)
|
||||||
|
.next()
|
||||||
|
.cloned()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(k) = k {
|
||||||
|
self.focus_client(&k, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_focus(&mut self, dir: Direction) {
|
||||||
|
match dir {
|
||||||
|
Direction::East(_) => self.focus_aux_stack(),
|
||||||
|
Direction::West(_) => self.focus_master_stack(),
|
||||||
|
Direction::North(_) => self.focus_up(),
|
||||||
|
Direction::South(_) => self.focus_down(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn hide_hidden_clients(&self) {
|
fn hide_hidden_clients(&self) {
|
||||||
self.clients
|
self.clients
|
||||||
.iter_hidden()
|
.iter_hidden()
|
||||||
|
@ -331,6 +410,10 @@ impl WindowManager {
|
||||||
self.hide_hidden_clients();
|
self.hide_hidden_clients();
|
||||||
|
|
||||||
self.raise_floating_clients();
|
self.raise_floating_clients();
|
||||||
|
|
||||||
|
if self.clients.get_focused().is_vacant() {
|
||||||
|
self.focus_any();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_client<K>(&mut self, key: &K, try_raise: bool)
|
fn focus_client<K>(&mut self, key: &K, try_raise: bool)
|
||||||
|
@ -373,11 +456,11 @@ impl WindowManager {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.clients.insert(client).unwrap();
|
self.clients.insert(client).unwrap();
|
||||||
|
self.arrange_clients();
|
||||||
|
|
||||||
self.xlib.map_window(window);
|
self.xlib.map_window(window);
|
||||||
|
|
||||||
self.focus_client(&window, true);
|
self.focus_client(&window, true);
|
||||||
|
|
||||||
self.arrange_clients();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_request(&mut self, event: &XEvent) {
|
fn map_request(&mut self, event: &XEvent) {
|
||||||
|
@ -585,13 +668,33 @@ impl Default for WMConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
fn west() -> Self {
|
||||||
|
Direction::West(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn east() -> Self {
|
||||||
|
Direction::East(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn north() -> Self {
|
||||||
|
Direction::North(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn south() -> Self {
|
||||||
|
Direction::South(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::ops::Not for Direction {
|
impl std::ops::Not for Direction {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn not(self) -> Self::Output {
|
fn not(self) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
Direction::Left(n) => Direction::Right(n),
|
Direction::West(n) => Direction::East(n),
|
||||||
Direction::Right(n) => Direction::Left(n),
|
Direction::East(n) => Direction::West(n),
|
||||||
|
Direction::North(n) => Direction::North(n),
|
||||||
|
Direction::South(n) => Direction::South(n),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
src/xlib.rs
46
src/xlib.rs
|
@ -3,14 +3,15 @@ use std::ptr::{null, null_mut};
|
||||||
use std::{ffi::CString, rc::Rc};
|
use std::{ffi::CString, rc::Rc};
|
||||||
|
|
||||||
use x11::xlib::{
|
use x11::xlib::{
|
||||||
self, Atom, ButtonPressMask, ButtonReleaseMask, CWEventMask, ControlMask,
|
self, AnyButton, AnyKey, AnyModifier, Atom, ButtonPressMask,
|
||||||
CurrentTime, EnterWindowMask, FocusChangeMask, LockMask, Mod1Mask,
|
ButtonReleaseMask, CWEventMask, ControlMask, CurrentTime, EnterWindowMask,
|
||||||
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, PointerMotionMask,
|
FocusChangeMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask,
|
||||||
PropertyChangeMask, ShiftMask, StructureNotifyMask, SubstructureNotifyMask,
|
Mod5Mask, PointerMotionMask, PropertyChangeMask, ShiftMask,
|
||||||
SubstructureRedirectMask, Window, XCloseDisplay, XConfigureRequestEvent,
|
StructureNotifyMask, SubstructureNotifyMask, SubstructureRedirectMask,
|
||||||
XDefaultScreen, XEvent, XGetTransientForHint, XGrabPointer, XInternAtom,
|
Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen, XEvent,
|
||||||
XKillClient, XMapWindow, XOpenDisplay, XRaiseWindow, XRootWindow,
|
XGetTransientForHint, XGrabPointer, XInternAtom, XKillClient, XMapWindow,
|
||||||
XSetErrorHandler, XSync, XUngrabPointer, XWarpPointer,
|
XOpenDisplay, XRaiseWindow, XRootWindow, XSetErrorHandler, XSync,
|
||||||
|
XUngrabButton, XUngrabKey, XUngrabPointer, XWarpPointer,
|
||||||
};
|
};
|
||||||
use xlib::GrabModeAsync;
|
use xlib::GrabModeAsync;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ use crate::clients::Client;
|
||||||
pub struct XLib {
|
pub struct XLib {
|
||||||
display: Display,
|
display: Display,
|
||||||
root: Window,
|
root: Window,
|
||||||
screen: i32,
|
_screen: i32,
|
||||||
atoms: Atoms,
|
atoms: Atoms,
|
||||||
global_keybinds: Vec<KeyOrButton>,
|
global_keybinds: Vec<KeyOrButton>,
|
||||||
}
|
}
|
||||||
|
@ -54,7 +55,7 @@ pub struct Display(Rc<*mut xlib::Display>);
|
||||||
|
|
||||||
impl XLib {
|
impl XLib {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (display, screen, root) = unsafe {
|
let (display, _screen, root) = unsafe {
|
||||||
let display = XOpenDisplay(null());
|
let display = XOpenDisplay(null());
|
||||||
|
|
||||||
assert_ne!(display, null_mut());
|
assert_ne!(display, null_mut());
|
||||||
|
@ -70,7 +71,7 @@ impl XLib {
|
||||||
atoms: Atoms::init(display.clone()),
|
atoms: Atoms::init(display.clone()),
|
||||||
global_keybinds: Vec::new(),
|
global_keybinds: Vec::new(),
|
||||||
root,
|
root,
|
||||||
screen,
|
_screen,
|
||||||
display,
|
display,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,6 +114,14 @@ impl XLib {
|
||||||
self.global_keybinds.push(key);
|
self.global_keybinds.push(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn ungrab_global_keybings(&self, window: Window) {
|
||||||
|
unsafe {
|
||||||
|
XUngrabButton(self.dpy(), AnyButton as u32, AnyModifier, window);
|
||||||
|
XUngrabKey(self.dpy(), AnyKey, AnyModifier, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn grab_global_keybinds(&self, window: Window) {
|
fn grab_global_keybinds(&self, window: Window) {
|
||||||
for kb in self.global_keybinds.iter() {
|
for kb in self.global_keybinds.iter() {
|
||||||
self.grab_key_or_button(window, kb);
|
self.grab_key_or_button(window, kb);
|
||||||
|
@ -218,21 +227,22 @@ impl XLib {
|
||||||
self.send_event(client, self.atoms.take_focus);
|
self.send_event(client, self.atoms.take_focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unfocus_client(&self, client: &Client) {
|
pub fn unfocus_client(&self, _client: &Client) {
|
||||||
//info!("unfocusing client: {:?}", client);
|
//info!("unfocusing client: {:?}", client);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
xlib::XSetInputFocus(
|
xlib::XSetInputFocus(
|
||||||
self.dpy(),
|
self.dpy(),
|
||||||
client.window,
|
self.root,
|
||||||
xlib::RevertToPointerRoot,
|
xlib::RevertToPointerRoot,
|
||||||
xlib::CurrentTime,
|
xlib::CurrentTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
xlib::XDeleteProperty(
|
// xlib::XDeleteProperty(
|
||||||
self.dpy(),
|
// self.dpy(),
|
||||||
self.root,
|
// self.root,
|
||||||
self.atoms.active_window,
|
// self.atoms.active_window,
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue