reworked Client list
This commit is contained in:
parent
5823c9ae66
commit
81536fb52c
|
@ -10,4 +10,5 @@ edition = "2018"
|
||||||
nix = "0.19.1"
|
nix = "0.19.1"
|
||||||
x11 = {version = "2.18.2", features = ["xlib"] }
|
x11 = {version = "2.18.2", features = ["xlib"] }
|
||||||
log = "0.4.13"
|
log = "0.4.13"
|
||||||
|
weak-table = "0.3.0"
|
||||||
simple_logger = "1.11.0"
|
simple_logger = "1.11.0"
|
|
@ -1,3 +1,2 @@
|
||||||
hard_tabs = true
|
|
||||||
imports_granularity = "Crate"
|
imports_granularity = "Crate"
|
||||||
wrap_comments = true
|
wrap_comments = true
|
|
@ -1,6 +1,8 @@
|
||||||
use std::io::Result;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use std::io::Result;
|
||||||
|
|
||||||
|
//mod state;
|
||||||
|
mod util;
|
||||||
mod wm;
|
mod wm;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -25,7 +27,6 @@ unsafe extern "C" fn xlib_error_handler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
simple_logger::SimpleLogger::new().init().unwrap();
|
simple_logger::SimpleLogger::new().init().unwrap();
|
||||||
info!("Hello, World!");
|
info!("Hello, World!");
|
||||||
|
|
24
src/util.rs
Normal file
24
src/util.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use std::hash::{BuildHasherDefault, Hasher};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct IdentityHasher(usize);
|
||||||
|
|
||||||
|
impl Hasher for IdentityHasher {
|
||||||
|
fn finish(&self) -> u64 {
|
||||||
|
self.0 as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, _bytes: &[u8]) {
|
||||||
|
unimplemented!("IdentityHasher only supports usize keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u64(&mut self, i: u64) {
|
||||||
|
self.0 = i as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_usize(&mut self, i: usize) {
|
||||||
|
self.0 = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type BuildIdentityHasher = BuildHasherDefault<IdentityHasher>;
|
279
src/wm.rs
279
src/wm.rs
|
@ -1,8 +1,8 @@
|
||||||
// asdf
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::{hash_map::Entry, HashMap, HashSet},
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
io::{Error, ErrorKind, Result},
|
io::{Error, ErrorKind, Result},
|
||||||
ptr::{null, null_mut},
|
ptr::{null, null_mut},
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
|
@ -39,56 +39,34 @@ impl Display {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WMAtoms {
|
pub struct WMAtoms {
|
||||||
pub protocols: Option<Atom>,
|
protocols: Atom,
|
||||||
pub delete: Option<Atom>,
|
delete_window: Atom,
|
||||||
pub active_window: Option<Atom>,
|
active_window: Atom,
|
||||||
pub take_focus: Option<Atom>,
|
take_focus: Atom,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WMAtoms {
|
impl WMAtoms {
|
||||||
pub fn init(display: Display) -> Self {
|
fn init(display: Display) -> Self {
|
||||||
|
unsafe {
|
||||||
Self {
|
Self {
|
||||||
protocols: {
|
protocols: {
|
||||||
Some(unsafe {
|
let name = CString::new("WM_PROTOCOLS").unwrap();
|
||||||
let wm_protocols_str = CString::new("WM_PROTOCOLS").unwrap();
|
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
|
||||||
XInternAtom(display.get(), wm_protocols_str.as_c_str().as_ptr(), 0)
|
|
||||||
})
|
|
||||||
.filter(|&atom| atom != 0)
|
|
||||||
},
|
},
|
||||||
delete: {
|
delete_window: {
|
||||||
Some(unsafe {
|
let name = CString::new("WM_DELETE_WINDOW").unwrap();
|
||||||
let wm_delete_str = CString::new("WM_DELETE_WINDOW").unwrap();
|
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
|
||||||
XInternAtom(display.get(), wm_delete_str.as_c_str().as_ptr(), 0)
|
|
||||||
})
|
|
||||||
.filter(|&atom| atom != 0)
|
|
||||||
},
|
},
|
||||||
active_window: {
|
active_window: {
|
||||||
Some(unsafe {
|
let name = CString::new("WM_ACTIVE_WINDOW").unwrap();
|
||||||
let atom_cstr = CString::new("_NET_ACTIVE_WINDOW").unwrap();
|
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
|
||||||
XInternAtom(display.get(), atom_cstr.as_c_str().as_ptr(), 0)
|
|
||||||
})
|
|
||||||
.filter(|&atom| atom != 0)
|
|
||||||
},
|
},
|
||||||
take_focus: {
|
take_focus: {
|
||||||
Some(unsafe {
|
let name = CString::new("WM_TAKE_FOCUS").unwrap();
|
||||||
let atom_cstr = CString::new("WM_TAKE_FOCUS").unwrap();
|
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
|
||||||
XInternAtom(display.get(), atom_cstr.as_c_str().as_ptr(), 0)
|
|
||||||
})
|
|
||||||
.filter(|&atom| atom != 0)
|
|
||||||
},
|
},
|
||||||
..Default::default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for WMAtoms {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
protocols: None,
|
|
||||||
delete: None,
|
|
||||||
active_window: None,
|
|
||||||
take_focus: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +89,12 @@ impl Default for Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for Client {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.window.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(window: xlib::Window) -> Self {
|
pub fn new(window: xlib::Window) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -128,49 +112,27 @@ impl PartialEq for Client {
|
||||||
|
|
||||||
impl Eq for Client {}
|
impl Eq for Client {}
|
||||||
|
|
||||||
use std::hash::{BuildHasherDefault, Hasher};
|
use crate::util::BuildIdentityHasher;
|
||||||
|
use weak_table::WeakHashSet;
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
|
||||||
struct IdentityHasher(usize);
|
|
||||||
|
|
||||||
impl Hasher for IdentityHasher {
|
|
||||||
fn finish(&self) -> u64 {
|
|
||||||
self.0 as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(&mut self, _bytes: &[u8]) {
|
|
||||||
unimplemented!("IdentityHasher only supports usize keys")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u64(&mut self, i: u64) {
|
|
||||||
self.0 = i as usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_usize(&mut self, i: usize) {
|
|
||||||
self.0 = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type BuildIdentityHasher = BuildHasherDefault<IdentityHasher>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct VirtualScreen {
|
struct VirtualScreen {
|
||||||
master_stack: HashMap<Window, Weak<RefCell<Client>>, BuildIdentityHasher>,
|
master_stack: WeakHashSet<Weak<Client>, BuildIdentityHasher>,
|
||||||
aux_stack: HashMap<Window, Weak<RefCell<Client>>, BuildIdentityHasher>,
|
aux_stack: WeakHashSet<Weak<Client>, BuildIdentityHasher>,
|
||||||
focused_client: Weak<RefCell<Client>>,
|
focused_client: Weak<Client>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualScreen {
|
impl VirtualScreen {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
master_stack: HashMap::default(),
|
master_stack: Default::default(),
|
||||||
aux_stack: HashMap::default(),
|
aux_stack: Default::default(),
|
||||||
focused_client: Weak::new(),
|
focused_client: Weak::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_window(&self, window: &Window) -> bool {
|
fn contains_client(&self, client: &Rc<Client>) -> bool {
|
||||||
self.master_stack.contains_key(window) || self.aux_stack.contains_key(window)
|
self.master_stack.contains(client) || self.aux_stack.contains(client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,10 +157,10 @@ impl XLibState {
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
display: display.clone(),
|
atoms: WMAtoms::init(display.clone()),
|
||||||
|
display,
|
||||||
root,
|
root,
|
||||||
screen,
|
screen,
|
||||||
atoms: WMAtoms::init(display),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +176,7 @@ impl XLibState {
|
||||||
self.screen
|
self.screen
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grab_key(&self, window: xlib::Window, keycode: i32, mask: u32) {
|
pub fn grab_key(&self, window: xlib::Window, keycode: i32, mod_mask: u32) {
|
||||||
let numlock_mask = self.numlock_mask();
|
let numlock_mask = self.numlock_mask();
|
||||||
let modifiers = vec![0, LockMask, numlock_mask, LockMask | numlock_mask];
|
let modifiers = vec![0, LockMask, numlock_mask, LockMask | numlock_mask];
|
||||||
for &modifier in modifiers.iter() {
|
for &modifier in modifiers.iter() {
|
||||||
|
@ -222,7 +184,7 @@ impl XLibState {
|
||||||
xlib::XGrabKey(
|
xlib::XGrabKey(
|
||||||
self.dpy(),
|
self.dpy(),
|
||||||
keycode,
|
keycode,
|
||||||
mask | modifier,
|
mod_mask | modifier,
|
||||||
window,
|
window,
|
||||||
1, /* true */
|
1, /* true */
|
||||||
GrabModeAsync,
|
GrabModeAsync,
|
||||||
|
@ -282,13 +244,11 @@ impl XLibState {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_event(&self, window: xlib::Window, proto: Option<xlib::Atom>) -> bool {
|
fn send_event(&self, window: xlib::Window, proto: xlib::Atom) -> bool {
|
||||||
if proto.is_some()
|
if self.check_for_protocol(window, proto) {
|
||||||
&& self.check_for_protocol(window, proto.unwrap())
|
|
||||||
&& self.atoms.protocols.is_some()
|
|
||||||
{
|
|
||||||
let mut data = xlib::ClientMessageData::default();
|
let mut data = xlib::ClientMessageData::default();
|
||||||
data.set_long(0, proto.unwrap() as i64);
|
data.set_long(0, proto as i64);
|
||||||
|
|
||||||
let mut event = XEvent {
|
let mut event = XEvent {
|
||||||
client_message: xlib::XClientMessageEvent {
|
client_message: xlib::XClientMessageEvent {
|
||||||
type_: xlib::ClientMessage,
|
type_: xlib::ClientMessage,
|
||||||
|
@ -297,7 +257,7 @@ impl XLibState {
|
||||||
send_event: 0,
|
send_event: 0,
|
||||||
window,
|
window,
|
||||||
format: 32,
|
format: 32,
|
||||||
message_type: self.atoms.protocols.unwrap(),
|
message_type: self.atoms.protocols,
|
||||||
data,
|
data,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -306,10 +266,10 @@ impl XLibState {
|
||||||
xlib::XSendEvent(self.dpy(), window, 0, xlib::NoEventMask, &mut event);
|
xlib::XSendEvent(self.dpy(), window, 0, xlib::NoEventMask, &mut event);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn numlock_mask(&self) -> u32 {
|
fn numlock_mask(&self) -> u32 {
|
||||||
|
@ -350,8 +310,8 @@ pub struct WMStateMut {
|
||||||
// u64 : window to move
|
// u64 : window to move
|
||||||
// (i32, i32) : initial window position
|
// (i32, i32) : initial window position
|
||||||
resize_window: Option<(u64, (i32, i32))>,
|
resize_window: Option<(u64, (i32, i32))>,
|
||||||
clients: HashMap<Window, Rc<RefCell<Client>>>,
|
clients: HashSet<Rc<Client>, BuildIdentityHasher>,
|
||||||
focused_client: Weak<RefCell<Client>>,
|
focused_client: Weak<Client>,
|
||||||
current_vscreen: usize,
|
current_vscreen: usize,
|
||||||
virtual_screens: Vec<VirtualScreen>,
|
virtual_screens: Vec<VirtualScreen>,
|
||||||
}
|
}
|
||||||
|
@ -361,7 +321,7 @@ impl Default for WMStateMut {
|
||||||
Self {
|
Self {
|
||||||
move_window: None,
|
move_window: None,
|
||||||
resize_window: None,
|
resize_window: None,
|
||||||
clients: HashMap::new(),
|
clients: Default::default(),
|
||||||
focused_client: Weak::new(),
|
focused_client: Weak::new(),
|
||||||
current_vscreen: 0,
|
current_vscreen: 0,
|
||||||
virtual_screens: vec![VirtualScreen::new()],
|
virtual_screens: vec![VirtualScreen::new()],
|
||||||
|
@ -372,111 +332,106 @@ impl Default for WMStateMut {
|
||||||
impl WMStateMut {
|
impl WMStateMut {
|
||||||
fn stack_unstacked_clients(&mut self) {
|
fn stack_unstacked_clients(&mut self) {
|
||||||
info!("[stack_unstacked_clients] ");
|
info!("[stack_unstacked_clients] ");
|
||||||
let current_vscreen = self.current_vscreen;
|
|
||||||
|
|
||||||
self.clients
|
self.clients
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(w, c)| {
|
.filter(|&c| !c.floating && self.is_client_stacked(c))
|
||||||
!c.borrow().floating
|
.for_each(|c| {
|
||||||
&& !self.is_client_stacked(w)
|
|
||||||
})
|
|
||||||
.map(|(w, c)| (w.clone(), Rc::downgrade(c)))
|
|
||||||
.collect::<Vec<(u64, Weak<RefCell<Client>>)>>()
|
|
||||||
.iter()
|
|
||||||
.for_each(|(w, c)| {
|
|
||||||
info!(
|
info!(
|
||||||
"[stack_unstacked_clients] inserting Window({:?}) into aux_stack",
|
"[stack_unstacked_clients] inserting Client({:?}) into aux_stack",
|
||||||
w
|
c
|
||||||
);
|
);
|
||||||
|
|
||||||
self.virtual_screens[current_vscreen]
|
self.virtual_screens[self.current_vscreen]
|
||||||
.aux_stack
|
.aux_stack
|
||||||
.insert(w.clone(), c.clone());
|
.insert(c.clone());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_client_stacked(&self, window: &Window) -> bool {
|
fn is_client_stacked(&self, client: &Rc<Client>) -> bool {
|
||||||
self.virtual_screens
|
self.virtual_screens
|
||||||
.iter()
|
.iter()
|
||||||
.any(|vs| vs.contains_window(window))
|
.any(|vs| vs.contains_client(client))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn client_for_window(&self, window: &Window) -> Option<Rc<RefCell<Client>>> {
|
fn client_for_window(&self, window: &Window) -> Option<Rc<Client>> {
|
||||||
self.clients
|
self.clients
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&(w, _)| *w == *window)
|
.filter(|&c| c.window == *window)
|
||||||
.next()
|
.next()
|
||||||
.map(|(_, c)| c.clone())
|
.map(|c| c.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_stack_for_client(&mut self, window: &Window) {
|
fn switch_stack_for_client(&mut self, window: &Window) {
|
||||||
if let Some(client) = self.client_for_window(window) {
|
if let Some(client) = self.client_for_window(window) {
|
||||||
info!("[switch_stack_for_client] client: {:#?}", client.borrow());
|
info!("[switch_stack_for_client] client: {:#?}", client);
|
||||||
client.borrow_mut().floating = false;
|
|
||||||
|
|
||||||
if self.virtual_screens[self.current_vscreen]
|
if self.virtual_screens[self.current_vscreen]
|
||||||
.master_stack
|
.master_stack
|
||||||
.contains_key(window)
|
.contains(&client)
|
||||||
{
|
{
|
||||||
self.virtual_screens[self.current_vscreen]
|
self.virtual_screens[self.current_vscreen]
|
||||||
.master_stack
|
.master_stack
|
||||||
.remove(window);
|
.remove(&client);
|
||||||
self.virtual_screens[self.current_vscreen]
|
self.virtual_screens[self.current_vscreen]
|
||||||
.aux_stack
|
.aux_stack
|
||||||
.insert(*window, Rc::downgrade(&client));
|
.insert(client.clone());
|
||||||
info!("[switch_stack_for_client] moved to aux stack");
|
info!("[switch_stack_for_client] moved to aux stack");
|
||||||
} else {
|
} else {
|
||||||
self.virtual_screens[self.current_vscreen]
|
self.virtual_screens[self.current_vscreen]
|
||||||
.aux_stack
|
.aux_stack
|
||||||
.remove(window);
|
.remove(&client);
|
||||||
self.virtual_screens[self.current_vscreen]
|
self.virtual_screens[self.current_vscreen]
|
||||||
.master_stack
|
.master_stack
|
||||||
.insert(*window, Rc::downgrade(&client));
|
.insert(client.clone());
|
||||||
info!("[switch_stack_for_client] moved to master stack");
|
info!("[switch_stack_for_client] moved to master stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.clients.replace(Rc::new(Client {
|
||||||
|
floating: false,
|
||||||
|
..*client
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh_screen(&mut self) {
|
fn refresh_screen(&mut self) {
|
||||||
let current_vscreen = self.current_vscreen;
|
let current_vscreen = self.current_vscreen;
|
||||||
|
|
||||||
self.virtual_screens
|
|
||||||
.get_mut(current_vscreen)
|
|
||||||
.and_then(|vs| {
|
|
||||||
vs.master_stack.retain(|_, c| {
|
|
||||||
c.upgrade().is_some() && !c.upgrade().unwrap().borrow().floating
|
|
||||||
});
|
|
||||||
vs.aux_stack.retain(|_, c| {
|
|
||||||
c.upgrade().is_some() && !c.upgrade().unwrap().borrow().floating
|
|
||||||
});
|
|
||||||
|
|
||||||
Some(())
|
|
||||||
});
|
|
||||||
|
|
||||||
self.stack_unstacked_clients();
|
self.stack_unstacked_clients();
|
||||||
|
|
||||||
if self.virtual_screens[current_vscreen]
|
if let Some(vs) = self.virtual_screens.get_mut(self.current_vscreen) {
|
||||||
.master_stack
|
vs.master_stack.retain(|c| !c.floating);
|
||||||
.is_empty()
|
vs.aux_stack.retain(|c| !c.floating);
|
||||||
{
|
|
||||||
|
if vs.master_stack.is_empty() {
|
||||||
info!("[refresh_screen] master stack was empty, pushing first client if exists:");
|
info!("[refresh_screen] master stack was empty, pushing first client if exists:");
|
||||||
|
vs.aux_stack.iter().filter(|c| !c.floating).next().map(|c| {
|
||||||
self.virtual_screens[current_vscreen]
|
info!("[arrange_clients] Client({:#?})", c);
|
||||||
.aux_stack
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, c)| !c.upgrade().unwrap().borrow().floating)
|
|
||||||
.next()
|
|
||||||
.map(|(w, c)| (w.clone(), c.clone()))
|
|
||||||
.and_then(|(w, c)| {
|
|
||||||
info!("[arrange_clients] Window({:#?})", w);
|
|
||||||
|
|
||||||
self.virtual_screens[current_vscreen]
|
self.virtual_screens[current_vscreen]
|
||||||
.master_stack
|
.master_stack
|
||||||
.insert(w, c);
|
.insert(c.clone());
|
||||||
self.virtual_screens[current_vscreen].aux_stack.remove(&w)
|
self.virtual_screens[current_vscreen].aux_stack.remove(&c);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Key {
|
||||||
|
keycode: i32,
|
||||||
|
mod_mask: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Button {
|
||||||
|
button: i32,
|
||||||
|
mod_mask: u32,
|
||||||
|
button_mask: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum KeyOrButton {
|
||||||
|
Key(Key),
|
||||||
|
Button(Button),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WMState {
|
pub struct WMState {
|
||||||
|
@ -532,10 +487,9 @@ impl WMState {
|
||||||
.add_key_handler("M", Mod1Mask, Self::handle_switch_stack)
|
.add_key_handler("M", Mod1Mask, Self::handle_switch_stack)
|
||||||
.add_key_handler("Q", Mod1Mask, |state, event| unsafe {
|
.add_key_handler("Q", Mod1Mask, |state, event| unsafe {
|
||||||
if event.key.subwindow != 0 {
|
if event.key.subwindow != 0 {
|
||||||
if state.xlib_state.atoms.delete.is_none()
|
if !state
|
||||||
|| !state
|
|
||||||
.xlib_state
|
.xlib_state
|
||||||
.send_event(event.key.subwindow, state.xlib_state.atoms.delete)
|
.send_event(event.key.subwindow, state.xlib_state.atoms.delete_window)
|
||||||
{
|
{
|
||||||
xlib::XKillClient(state.dpy(), event.key.subwindow);
|
xlib::XKillClient(state.dpy(), event.key.subwindow);
|
||||||
}
|
}
|
||||||
|
@ -659,28 +613,26 @@ impl WMState {
|
||||||
|
|
||||||
let _ = Some(self.mut_state.borrow_mut())
|
let _ = Some(self.mut_state.borrow_mut())
|
||||||
.and_then(|mut state| {
|
.and_then(|mut state| {
|
||||||
if !state.clients.contains_key(&event.window) {
|
if state.client_for_window(&event.window).is_none() {
|
||||||
info!("[MapRequest] new client: {:#?}", event.window);
|
info!("[MapRequest] new client: {:#?}", event.window);
|
||||||
Some(
|
let client = Rc::new(Client::new(event.window));
|
||||||
state
|
state.clients.insert(client.clone());
|
||||||
.clients
|
|
||||||
.entry(event.window)
|
Some(client)
|
||||||
.or_insert_with(|| Rc::new(RefCell::new(Client::new(event.window))))
|
|
||||||
.clone(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
unsafe {
|
unsafe {
|
||||||
xlib::XMapWindow(self.dpy(), c.borrow().window);
|
xlib::XMapWindow(self.dpy(), c.window);
|
||||||
|
|
||||||
xlib::XSelectInput(
|
xlib::XSelectInput(
|
||||||
self.dpy(),
|
self.dpy(),
|
||||||
event.window,
|
event.window,
|
||||||
EnterWindowMask
|
EnterWindowMask
|
||||||
| FocusChangeMask | PropertyChangeMask
|
| FocusChangeMask
|
||||||
|
| PropertyChangeMask
|
||||||
| StructureNotifyMask,
|
| StructureNotifyMask,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -688,12 +640,8 @@ impl WMState {
|
||||||
self.buttons
|
self.buttons
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|&(button, mod_mask, button_mask)| {
|
.for_each(|&(button, mod_mask, button_mask)| {
|
||||||
self.xlib_state.grab_button(
|
self.xlib_state
|
||||||
c.borrow().window,
|
.grab_button(c.window, button, mod_mask, button_mask);
|
||||||
button,
|
|
||||||
mod_mask,
|
|
||||||
button_mask,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.arrange_clients();
|
self.arrange_clients();
|
||||||
|
@ -708,7 +656,7 @@ impl WMState {
|
||||||
|
|
||||||
if event.send_event == 0 {
|
if event.send_event == 0 {
|
||||||
let _ = Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
let _ = Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||||
if state.clients.contains_key(&event.window) {
|
if state.client_for_window(&event.window).is_none() {
|
||||||
let client = state.clients.remove(&event.window);
|
let client = state.clients.remove(&event.window);
|
||||||
info!("[UnmapNotify] removing client: {:#?}", client);
|
info!("[UnmapNotify] removing client: {:#?}", client);
|
||||||
}
|
}
|
||||||
|
@ -833,15 +781,11 @@ impl WMState {
|
||||||
xlib::CurrentTime,
|
xlib::CurrentTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
xlib::XDeleteProperty(
|
xlib::XDeleteProperty(self.dpy(), self.root(), self.xlib_state.atoms.active_window);
|
||||||
self.dpy(),
|
|
||||||
self.root(),
|
|
||||||
self.xlib_state.atoms.active_window.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_client(&self, client: Rc<RefCell<Client>>) {
|
fn focus_client(&self, client: Rc<Client>) {
|
||||||
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||||
let current_vscreen = state.current_vscreen;
|
let current_vscreen = state.current_vscreen;
|
||||||
|
|
||||||
|
@ -868,7 +812,7 @@ impl WMState {
|
||||||
xlib::XChangeProperty(
|
xlib::XChangeProperty(
|
||||||
self.dpy(),
|
self.dpy(),
|
||||||
self.root(),
|
self.root(),
|
||||||
self.xlib_state.atoms.active_window.unwrap(),
|
self.xlib_state.atoms.active_window,
|
||||||
xlib::XA_WINDOW,
|
xlib::XA_WINDOW,
|
||||||
32,
|
32,
|
||||||
xlib::PropModeReplace,
|
xlib::PropModeReplace,
|
||||||
|
@ -1028,7 +972,6 @@ impl WMState {
|
||||||
assert!(direction == 1 || direction == -1);
|
assert!(direction == 1 || direction == -1);
|
||||||
|
|
||||||
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||||
|
|
||||||
// hide all windows from current virtual screen
|
// hide all windows from current virtual screen
|
||||||
state.virtual_screens[state.current_vscreen]
|
state.virtual_screens[state.current_vscreen]
|
||||||
.master_stack
|
.master_stack
|
||||||
|
|
Loading…
Reference in a new issue