clients iteration 1, probably wont work tho
This commit is contained in:
parent
81536fb52c
commit
5608f1d9da
|
@ -10,5 +10,5 @@ edition = "2018"
|
|||
nix = "0.19.1"
|
||||
x11 = {version = "2.18.2", features = ["xlib"] }
|
||||
log = "0.4.13"
|
||||
weak-table = "0.3.0"
|
||||
weak-table = {path = "/mnt/storage/rust/weak-table-rs"}
|
||||
simple_logger = "1.11.0"
|
218
src/clients.rs
Normal file
218
src/clients.rs
Normal file
|
@ -0,0 +1,218 @@
|
|||
use std::{
|
||||
borrow::{Borrow, BorrowMut},
|
||||
collections::HashSet,
|
||||
ops::{Deref, DerefMut},
|
||||
rc::Rc,
|
||||
};
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
rc::Weak,
|
||||
};
|
||||
|
||||
use weak_table::WeakHashSet;
|
||||
use x11::xlib::Window;
|
||||
|
||||
use crate::util::BuildIdentityHasher;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Client {
|
||||
window: Window,
|
||||
floating: bool,
|
||||
size: (i32, i32),
|
||||
position: (i32, i32),
|
||||
}
|
||||
|
||||
impl Hash for Client {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.window.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Client {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.window == other.window
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Client {}
|
||||
|
||||
trait ClientKey {
|
||||
fn key(&self) -> u64;
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for (dyn ClientKey + 'a) {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.key() == other.key()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Eq for (dyn ClientKey + 'a) {}
|
||||
|
||||
impl<'a> Hash for (dyn ClientKey + 'a) {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.key().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientKey for Client {
|
||||
fn key(&self) -> u64 {
|
||||
self.window
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientKey for Rc<Client> {
|
||||
fn key(&self) -> u64 {
|
||||
self.window
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientKey for Window {
|
||||
fn key(&self) -> u64 {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Borrow<dyn ClientKey + 'a> for Client {
|
||||
fn borrow(&self) -> &(dyn ClientKey + 'a) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Borrow<dyn ClientKey + 'a> for Rc<Client> {
|
||||
fn borrow(&self) -> &(dyn ClientKey + 'a) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
trait ClientList {
|
||||
fn contains_key<T>(&self, key: &T) -> bool
|
||||
where
|
||||
T: ClientKey;
|
||||
|
||||
fn get_with_key<T>(&self, key: &T) -> Option<Rc<Client>>
|
||||
where
|
||||
T: ClientKey;
|
||||
|
||||
fn remove_key<T>(&mut self, key: &T) -> bool
|
||||
where
|
||||
T: ClientKey;
|
||||
}
|
||||
|
||||
struct Clients(HashSet<Rc<Client>, BuildIdentityHasher>);
|
||||
|
||||
impl Default for Clients {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Clients {
|
||||
type Target = HashSet<Rc<Client>, BuildIdentityHasher>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Clients {
|
||||
fn deref_mut(&mut self) -> &mut HashSet<Rc<Client>, BuildIdentityHasher> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientList for Clients {
|
||||
fn contains_key<T>(&self, key: &T) -> bool
|
||||
where
|
||||
T: ClientKey,
|
||||
{
|
||||
self.0.contains(key as &dyn ClientKey)
|
||||
}
|
||||
|
||||
fn get_with_key<T>(&self, key: &T) -> Option<Rc<Client>>
|
||||
where
|
||||
T: ClientKey,
|
||||
{
|
||||
self.0.get(key as &dyn ClientKey).cloned()
|
||||
}
|
||||
|
||||
fn remove_key<T>(&mut self, key: &T) -> bool
|
||||
where
|
||||
T: ClientKey,
|
||||
{
|
||||
self.0.remove(key as &dyn ClientKey)
|
||||
}
|
||||
}
|
||||
|
||||
struct ClientRefs(WeakHashSet<Weak<Client>, BuildIdentityHasher>);
|
||||
|
||||
impl Default for ClientRefs {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ClientRefs {
|
||||
type Target = WeakHashSet<Weak<Client>, BuildIdentityHasher>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ClientRefs {
|
||||
fn deref_mut(&mut self) -> &mut WeakHashSet<Weak<Client>, BuildIdentityHasher> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientList for ClientRefs {
|
||||
fn contains_key<T>(&self, key: &T) -> bool
|
||||
where
|
||||
T: ClientKey,
|
||||
{
|
||||
self.0.contains(key as &dyn ClientKey)
|
||||
}
|
||||
|
||||
fn get_with_key<T>(&self, key: &T) -> Option<Rc<Client>>
|
||||
where
|
||||
T: ClientKey,
|
||||
{
|
||||
self.0.get(key as &dyn ClientKey)
|
||||
}
|
||||
|
||||
fn remove_key<T>(&mut self, key: &T) -> bool
|
||||
where
|
||||
T: ClientKey,
|
||||
{
|
||||
self.0.remove(key as &dyn ClientKey)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn client_lists_test() {
|
||||
let mut clients: Clients = Default::default();
|
||||
|
||||
clients.insert(Rc::new(Client {
|
||||
window: 1,
|
||||
floating: false,
|
||||
position: (1, 1),
|
||||
size: (1, 1),
|
||||
}));
|
||||
|
||||
assert!(clients.contains_key(&1u64));
|
||||
|
||||
let mut client_refs = ClientRefs::default();
|
||||
|
||||
client_refs.insert(clients.get_with_key(&1u64).unwrap());
|
||||
|
||||
assert!(client_refs.contains_key(&1u64));
|
||||
|
||||
clients.remove_key(&1u64);
|
||||
|
||||
assert!(!client_refs.contains_key(&1u64));
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ use log::info;
|
|||
use std::io::Result;
|
||||
|
||||
//mod state;
|
||||
mod clients;
|
||||
mod util;
|
||||
mod wm;
|
||||
|
||||
|
@ -31,7 +32,7 @@ fn main() -> Result<()> {
|
|||
simple_logger::SimpleLogger::new().init().unwrap();
|
||||
info!("Hello, World!");
|
||||
|
||||
wm::WMState::init().run();
|
||||
//wm::WMState::init().run();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
674
src/wm.rs
674
src/wm.rs
|
@ -1,9 +1,12 @@
|
|||
/*
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
cell::RefCell,
|
||||
collections::{hash_map::Entry, HashMap, HashSet},
|
||||
collections::HashSet,
|
||||
ffi::CString,
|
||||
hash::{Hash, Hasher},
|
||||
io::{Error, ErrorKind, Result},
|
||||
ops::Deref,
|
||||
ptr::{null, null_mut},
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
|
@ -70,48 +73,6 @@ impl WMAtoms {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Client {
|
||||
window: Window,
|
||||
floating: bool,
|
||||
size: (i32, i32),
|
||||
position: (i32, i32),
|
||||
}
|
||||
|
||||
impl Default for Client {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
window: 0,
|
||||
floating: false,
|
||||
size: (0, 0),
|
||||
position: (0, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Client {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.window.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(window: xlib::Window) -> Self {
|
||||
Self {
|
||||
window,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Client {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.window == other.window
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Client {}
|
||||
|
||||
use crate::util::BuildIdentityHasher;
|
||||
use weak_table::WeakHashSet;
|
||||
|
||||
|
@ -132,7 +93,7 @@ impl VirtualScreen {
|
|||
}
|
||||
|
||||
fn contains_client(&self, client: &Rc<Client>) -> bool {
|
||||
self.master_stack.contains(client) || self.aux_stack.contains(client)
|
||||
self.master_stack.contains(client.as_ref()) || self.aux_stack.contains(client.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,125 +260,6 @@ impl XLibState {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WMStateMut {
|
||||
//move_window:
|
||||
// u64 : window to move
|
||||
// (i32, i32) : initial cursor position
|
||||
// (i32, i32) : initial window position
|
||||
move_window: Option<(u64, (i32, i32), (i32, i32))>,
|
||||
//resize_window:
|
||||
// u64 : window to move
|
||||
// (i32, i32) : initial window position
|
||||
resize_window: Option<(u64, (i32, i32))>,
|
||||
clients: HashSet<Rc<Client>, BuildIdentityHasher>,
|
||||
focused_client: Weak<Client>,
|
||||
current_vscreen: usize,
|
||||
virtual_screens: Vec<VirtualScreen>,
|
||||
}
|
||||
|
||||
impl Default for WMStateMut {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
move_window: None,
|
||||
resize_window: None,
|
||||
clients: Default::default(),
|
||||
focused_client: Weak::new(),
|
||||
current_vscreen: 0,
|
||||
virtual_screens: vec![VirtualScreen::new()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WMStateMut {
|
||||
fn stack_unstacked_clients(&mut self) {
|
||||
info!("[stack_unstacked_clients] ");
|
||||
|
||||
self.clients
|
||||
.iter()
|
||||
.filter(|&c| !c.floating && self.is_client_stacked(c))
|
||||
.for_each(|c| {
|
||||
info!(
|
||||
"[stack_unstacked_clients] inserting Client({:?}) into aux_stack",
|
||||
c
|
||||
);
|
||||
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.insert(c.clone());
|
||||
});
|
||||
}
|
||||
|
||||
fn is_client_stacked(&self, client: &Rc<Client>) -> bool {
|
||||
self.virtual_screens
|
||||
.iter()
|
||||
.any(|vs| vs.contains_client(client))
|
||||
}
|
||||
|
||||
fn client_for_window(&self, window: &Window) -> Option<Rc<Client>> {
|
||||
self.clients
|
||||
.iter()
|
||||
.filter(|&c| c.window == *window)
|
||||
.next()
|
||||
.map(|c| c.clone())
|
||||
}
|
||||
|
||||
fn switch_stack_for_client(&mut self, window: &Window) {
|
||||
if let Some(client) = self.client_for_window(window) {
|
||||
info!("[switch_stack_for_client] client: {:#?}", client);
|
||||
|
||||
if self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.contains(&client)
|
||||
{
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.remove(&client);
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.insert(client.clone());
|
||||
info!("[switch_stack_for_client] moved to aux stack");
|
||||
} else {
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.remove(&client);
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.insert(client.clone());
|
||||
info!("[switch_stack_for_client] moved to master stack");
|
||||
}
|
||||
|
||||
self.clients.replace(Rc::new(Client {
|
||||
floating: false,
|
||||
..*client
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
fn refresh_screen(&mut self) {
|
||||
let current_vscreen = self.current_vscreen;
|
||||
|
||||
self.stack_unstacked_clients();
|
||||
|
||||
if let Some(vs) = self.virtual_screens.get_mut(self.current_vscreen) {
|
||||
vs.master_stack.retain(|c| !c.floating);
|
||||
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:");
|
||||
vs.aux_stack.iter().filter(|c| !c.floating).next().map(|c| {
|
||||
info!("[arrange_clients] Client({:#?})", c);
|
||||
|
||||
self.virtual_screens[current_vscreen]
|
||||
.master_stack
|
||||
.insert(c.clone());
|
||||
self.virtual_screens[current_vscreen].aux_stack.remove(&c);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Key {
|
||||
keycode: i32,
|
||||
mod_mask: u32,
|
||||
|
@ -436,21 +278,41 @@ enum KeyOrButton {
|
|||
|
||||
pub struct WMState {
|
||||
xlib_state: XLibState,
|
||||
key_handlers: Vec<(i32, u32, Rc<dyn Fn(&Self, &XEvent)>)>,
|
||||
key_handlers: Vec<(i32, u32, Rc<dyn Fn(&mut Self, &XEvent)>)>,
|
||||
// (button, mod_mask, button_mask)
|
||||
buttons: Vec<(u32, u32, i64)>,
|
||||
event_handlers: Vec<Rc<dyn Fn(&Self, &XEvent)>>,
|
||||
mut_state: RefCell<WMStateMut>,
|
||||
event_handlers: Vec<Rc<dyn Fn(&mut Self, &XEvent)>>,
|
||||
|
||||
// MutState:
|
||||
|
||||
//move_window:
|
||||
// u64 : window to move
|
||||
// (i32, i32) : initial cursor position
|
||||
// (i32, i32) : initial window position
|
||||
move_window: Option<(u64, (i32, i32), (i32, i32))>,
|
||||
//resize_window:
|
||||
// u64 : window to move
|
||||
// (i32, i32) : initial window position
|
||||
resize_window: Option<(u64, (i32, i32))>,
|
||||
clients: HashSet<Rc<Client>, BuildIdentityHasher>,
|
||||
focused_client: Weak<Client>,
|
||||
current_vscreen: usize,
|
||||
virtual_screens: Vec<VirtualScreen>,
|
||||
}
|
||||
|
||||
impl WMState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
xlib_state: XLibState::new(),
|
||||
mut_state: RefCell::new(WMStateMut::default()),
|
||||
key_handlers: vec![],
|
||||
event_handlers: vec![],
|
||||
buttons: vec![],
|
||||
move_window: None,
|
||||
resize_window: None,
|
||||
clients: Default::default(),
|
||||
focused_client: Weak::new(),
|
||||
current_vscreen: 0,
|
||||
virtual_screens: vec![VirtualScreen::new()],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,7 +382,103 @@ impl WMState {
|
|||
state
|
||||
}
|
||||
|
||||
pub fn run(self) -> Self {
|
||||
// MutState Functions:
|
||||
|
||||
fn stack_unstacked_clients(&mut self) {
|
||||
info!("[stack_unstacked_clients] ");
|
||||
|
||||
let unstacked_clients = self
|
||||
.clients
|
||||
.iter()
|
||||
.filter(|&c| !c.floating && !self.is_client_stacked(c))
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
unstacked_clients.iter().for_each(|c| {
|
||||
info!(
|
||||
"[stack_unstacked_clients] inserting Client({:?}) into aux_stack",
|
||||
c
|
||||
);
|
||||
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.insert(c.clone());
|
||||
});
|
||||
}
|
||||
|
||||
fn is_client_stacked(&self, client: &Rc<Client>) -> bool {
|
||||
self.virtual_screens
|
||||
.iter()
|
||||
.any(|vs| vs.contains_client(client))
|
||||
}
|
||||
|
||||
fn client_for_window(&self, window: Window) -> Option<Rc<Client>> {
|
||||
self.clients
|
||||
.iter()
|
||||
.filter(|&c| c.window == window)
|
||||
.next()
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn switch_stack_for_client(&mut self, client: Rc<Client>) {
|
||||
info!("[switch_stack_for_client] client: {:#?}", client);
|
||||
|
||||
if self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.contains(client.as_ref())
|
||||
{
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.remove(client.as_ref());
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.insert(client.clone());
|
||||
info!("[switch_stack_for_client] moved to aux stack");
|
||||
} else {
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.remove(client.as_ref());
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.insert(client.clone());
|
||||
info!("[switch_stack_for_client] moved to master stack");
|
||||
}
|
||||
|
||||
self.clients.replace(Client::new_rc(InnerClient {
|
||||
floating: false,
|
||||
..**client.as_ref()
|
||||
}));
|
||||
}
|
||||
|
||||
fn refresh_screen(&mut self) {
|
||||
let current_vscreen = self.current_vscreen;
|
||||
|
||||
self.stack_unstacked_clients();
|
||||
|
||||
if let Some(vs) = self.virtual_screens.get_mut(self.current_vscreen) {
|
||||
vs.master_stack.retain(|c| !c.0.borrow().floating);
|
||||
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:");
|
||||
vs.aux_stack.iter().filter(|c| !c.floating).next().map(|c| {
|
||||
info!("[arrange_clients] Client({:#?})", c);
|
||||
|
||||
self.virtual_screens[current_vscreen]
|
||||
.master_stack
|
||||
.insert(c.clone());
|
||||
self.virtual_screens[current_vscreen]
|
||||
.aux_stack
|
||||
.remove(c.as_ref());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(mut self) -> Self {
|
||||
let event_handlers = self.event_handlers.clone();
|
||||
let key_handlers = self.key_handlers.clone();
|
||||
|
||||
loop {
|
||||
let event = unsafe {
|
||||
let mut event: xlib::XEvent = std::mem::MaybeUninit::zeroed().assume_init();
|
||||
|
@ -529,9 +487,9 @@ impl WMState {
|
|||
event
|
||||
};
|
||||
|
||||
self.event_handlers.iter().for_each(|handler| {
|
||||
handler(&self, &event);
|
||||
});
|
||||
for handler in event_handlers.iter() {
|
||||
handler(&mut self, &event);
|
||||
}
|
||||
|
||||
match event.get_type() {
|
||||
xlib::MapRequest => {
|
||||
|
@ -555,12 +513,12 @@ impl WMState {
|
|||
xlib::KeyPress => {
|
||||
let clean_mask = self.xlib_state.clean_mask();
|
||||
|
||||
self.key_handlers.iter().for_each(|(key, mask, handler)| {
|
||||
key_handlers.iter().for_each(|(key, mask, handler)| {
|
||||
if unsafe {
|
||||
event.key.keycode == *key as u32
|
||||
&& event.key.state & clean_mask == *mask & clean_mask
|
||||
} {
|
||||
handler(&self, &event);
|
||||
handler(&mut self, &event);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -588,7 +546,7 @@ impl WMState {
|
|||
#[allow(dead_code)]
|
||||
pub fn add_event_handler<F>(mut self, handler: F) -> Self
|
||||
where
|
||||
F: Fn(&Self, &XEvent) + 'static,
|
||||
F: Fn(&mut Self, &XEvent) + 'static,
|
||||
{
|
||||
self.event_handlers.push(Rc::new(handler));
|
||||
|
||||
|
@ -598,7 +556,7 @@ impl WMState {
|
|||
pub fn add_key_handler<S, F>(mut self, key: S, mask: u32, handler: F) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
F: Fn(&Self, &XEvent) + 'static,
|
||||
F: Fn(&mut Self, &XEvent) + 'static,
|
||||
{
|
||||
let keycode = self.xlib_state.keycode(key);
|
||||
|
||||
|
@ -608,32 +566,21 @@ impl WMState {
|
|||
self
|
||||
}
|
||||
|
||||
fn map_request(&self, event: &xlib::XMapRequestEvent) {
|
||||
fn map_request(&mut self, event: &xlib::XMapRequestEvent) {
|
||||
info!("[MapRequest] event: {:#?}", event);
|
||||
|
||||
let _ = Some(self.mut_state.borrow_mut())
|
||||
.and_then(|mut state| {
|
||||
if state.client_for_window(&event.window).is_none() {
|
||||
if self.client_for_window(event.window).is_none() {
|
||||
info!("[MapRequest] new client: {:#?}", event.window);
|
||||
let client = Rc::new(Client::new(event.window));
|
||||
state.clients.insert(client.clone());
|
||||
self.clients.insert(client.clone());
|
||||
|
||||
Some(client)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.and_then(|c| {
|
||||
unsafe {
|
||||
xlib::XMapWindow(self.dpy(), c.window);
|
||||
xlib::XMapWindow(self.dpy(), client.window);
|
||||
|
||||
xlib::XSelectInput(
|
||||
self.dpy(),
|
||||
event.window,
|
||||
EnterWindowMask
|
||||
| FocusChangeMask
|
||||
| PropertyChangeMask
|
||||
| StructureNotifyMask,
|
||||
EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -641,59 +588,47 @@ impl WMState {
|
|||
.iter()
|
||||
.for_each(|&(button, mod_mask, button_mask)| {
|
||||
self.xlib_state
|
||||
.grab_button(c.window, button, mod_mask, button_mask);
|
||||
.grab_button(client.window, button, mod_mask, button_mask);
|
||||
});
|
||||
|
||||
self.arrange_clients();
|
||||
self.focus_client(c.clone());
|
||||
|
||||
Some(())
|
||||
});
|
||||
self.focus_client(&client);
|
||||
}
|
||||
}
|
||||
|
||||
fn unmap_notify(&self, event: &xlib::XUnmapEvent) {
|
||||
fn unmap_notify(&mut self, event: &xlib::XUnmapEvent) {
|
||||
info!("[UnmapNotify] event: {:#?}", event);
|
||||
|
||||
if event.send_event == 0 {
|
||||
let _ = Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||
if state.client_for_window(&event.window).is_none() {
|
||||
let client = state.clients.remove(&event.window);
|
||||
if let Some(client) = self.client_for_window(event.window) {
|
||||
self.clients.remove(&client);
|
||||
info!("[UnmapNotify] removing client: {:#?}", client);
|
||||
}
|
||||
|
||||
Some(())
|
||||
});
|
||||
}
|
||||
|
||||
self.arrange_clients();
|
||||
}
|
||||
|
||||
fn destroy_notify(&self, event: &xlib::XDestroyWindowEvent) {
|
||||
fn destroy_notify(&mut self, event: &xlib::XDestroyWindowEvent) {
|
||||
info!("[DestroyNotify] event: {:?}", event);
|
||||
|
||||
let _ = Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||
let _entry = state.clients.remove(&event.window);
|
||||
if let Some(client) = self.client_for_window(event.window) {
|
||||
self.clients.remove(&client);
|
||||
|
||||
info!("[DestroyNotify] removed entry: {:?}", _entry);
|
||||
|
||||
Some(())
|
||||
});
|
||||
info!("[DestroyNotify] removed entry: {:?}", client);
|
||||
}
|
||||
|
||||
self.arrange_clients();
|
||||
}
|
||||
|
||||
fn configure_request(&self, event: &xlib::XConfigureRequestEvent) {
|
||||
fn configure_request(&mut self, event: &xlib::XConfigureRequestEvent) {
|
||||
info!("[ConfigureRequest] event: {:?}", event);
|
||||
|
||||
match self.mut_state.borrow_mut().clients.entry(event.window) {
|
||||
Entry::Occupied(entry) => {
|
||||
info!(
|
||||
"[ConfigureRequest] found Client for Window({:?}): {:#?}",
|
||||
event.window,
|
||||
entry.get()
|
||||
);
|
||||
match self.client_for_window(event.window) {
|
||||
Some(client) => {
|
||||
info!("[ConfigureRequest] found Client {:#?}", client,);
|
||||
|
||||
self.configure_client(entry.get().clone());
|
||||
self.configure_client(&client);
|
||||
}
|
||||
_ => {
|
||||
info!(
|
||||
|
@ -722,61 +657,36 @@ impl WMState {
|
|||
}
|
||||
}
|
||||
|
||||
fn enter_notify(&self, event: &xlib::XCrossingEvent) {
|
||||
fn enter_notify(&mut self, event: &xlib::XCrossingEvent) {
|
||||
info!("[EnterNotify] event: {:?}", event);
|
||||
|
||||
Some(self.mut_state.borrow())
|
||||
.and_then(|state| {
|
||||
state
|
||||
.clients
|
||||
.get(&event.window)
|
||||
.and_then(|c| Some(c.clone()))
|
||||
})
|
||||
.and_then(|c| {
|
||||
info!(
|
||||
"[EnterNotify] focusing Client for Window({:?})",
|
||||
event.window
|
||||
);
|
||||
self.focus_client(c);
|
||||
|
||||
Some(())
|
||||
});
|
||||
if let Some(client) = self.client_for_window(event.window) {
|
||||
info!("[EnterNotify] focusing Client ({:?})", client);
|
||||
self.focus_client(&client);
|
||||
}
|
||||
}
|
||||
|
||||
fn button_press(&self, event: &xlib::XButtonEvent) {
|
||||
fn button_press(&mut self, event: &xlib::XButtonEvent) {
|
||||
info!("[ButtonPress] event: {:?}", event);
|
||||
|
||||
Some(self.mut_state.borrow())
|
||||
.and_then(|state| {
|
||||
state
|
||||
.clients
|
||||
.get(&event.subwindow)
|
||||
.and_then(|c| Some(c.clone()))
|
||||
})
|
||||
.and_then(|c| {
|
||||
info!(
|
||||
"[ButtonPress] focusing Client for Window({:?})",
|
||||
event.window
|
||||
);
|
||||
|
||||
self.focus_client(c.clone());
|
||||
if let Some(client) = self.client_for_window(event.subwindow) {
|
||||
info!("[ButtonPress] focusing Client ({:?})", client);
|
||||
self.focus_client(&client);
|
||||
|
||||
info!("[ButtonPress] raising Window({:?})", event.window);
|
||||
|
||||
unsafe {
|
||||
xlib::XRaiseWindow(self.dpy(), c.borrow().window);
|
||||
xlib::XRaiseWindow(self.dpy(), client.window);
|
||||
xlib::XSync(self.dpy(), 0);
|
||||
}
|
||||
|
||||
Some(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn unfocus_client(&self, client: Rc<RefCell<Client>>) {
|
||||
fn unfocus_client(&self, client: &Rc<Client>) {
|
||||
unsafe {
|
||||
xlib::XSetInputFocus(
|
||||
self.dpy(),
|
||||
client.borrow().window,
|
||||
client.window,
|
||||
xlib::RevertToPointerRoot,
|
||||
xlib::CurrentTime,
|
||||
);
|
||||
|
@ -785,26 +695,19 @@ impl WMState {
|
|||
}
|
||||
}
|
||||
|
||||
fn focus_client(&self, client: Rc<Client>) {
|
||||
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||
let current_vscreen = state.current_vscreen;
|
||||
fn focus_client(&mut self, client: &Rc<Client>) {
|
||||
if let Some(focused_client) = self.focused_client.upgrade() {
|
||||
self.unfocus_client(&focused_client);
|
||||
}
|
||||
|
||||
state
|
||||
.focused_client
|
||||
.upgrade()
|
||||
.and_then(|c| Some(self.unfocus_client(c)));
|
||||
self.focused_client = Rc::downgrade(client);
|
||||
|
||||
state.focused_client = Rc::downgrade(&client);
|
||||
|
||||
state.virtual_screens[current_vscreen].focused_client = state.focused_client.clone();
|
||||
|
||||
Some(())
|
||||
});
|
||||
self.virtual_screens[self.current_vscreen].focused_client = self.focused_client.clone();
|
||||
|
||||
unsafe {
|
||||
xlib::XSetInputFocus(
|
||||
self.dpy(),
|
||||
client.borrow().window,
|
||||
client.window,
|
||||
xlib::RevertToPointerRoot,
|
||||
xlib::CurrentTime,
|
||||
);
|
||||
|
@ -816,13 +719,13 @@ impl WMState {
|
|||
xlib::XA_WINDOW,
|
||||
32,
|
||||
xlib::PropModeReplace,
|
||||
&client.borrow().window as *const u64 as *const _,
|
||||
&client.window as *const u64 as *const _,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
self.xlib_state
|
||||
.send_event(client.borrow().window, self.xlib_state.atoms.take_focus);
|
||||
.send_event(client.window, self.xlib_state.atoms.take_focus);
|
||||
}
|
||||
|
||||
fn arrange_clients(&self) {
|
||||
|
@ -833,13 +736,12 @@ impl WMState {
|
|||
)
|
||||
};
|
||||
|
||||
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||
if !state.clients.is_empty() {
|
||||
if !self.clients.is_empty() {
|
||||
info!("[arrange_clients] refreshing screen");
|
||||
state.refresh_screen();
|
||||
self.refresh_screen();
|
||||
|
||||
let window_w = {
|
||||
if state.virtual_screens[state.current_vscreen]
|
||||
if self.virtual_screens[self.current_vscreen]
|
||||
.aux_stack
|
||||
.is_empty()
|
||||
{
|
||||
|
@ -849,97 +751,64 @@ impl WMState {
|
|||
}
|
||||
};
|
||||
|
||||
for (i, (_, weak_client)) in state.virtual_screens[state.current_vscreen]
|
||||
.master_stack
|
||||
if let Some(vc) = self.virtual_screens.get_mut(self.current_vscreen) {
|
||||
vc.master_stack
|
||||
.iter()
|
||||
.zip(std::iter::repeat(vc.master_stack.len()))
|
||||
.enumerate()
|
||||
{
|
||||
let client = weak_client.upgrade().unwrap();
|
||||
.chain(
|
||||
vc.aux_stack
|
||||
.iter()
|
||||
.zip(std::iter::repeat(vc.aux_stack.len()))
|
||||
.enumerate(),
|
||||
)
|
||||
.for_each(|(i, (client, length))| {
|
||||
let (mut wc, size, position) = {
|
||||
let window_h = screen_h / length as i32;
|
||||
|
||||
let mut wc = {
|
||||
let mut client = client.borrow_mut();
|
||||
let window_h = screen_h
|
||||
/ state.virtual_screens[state.current_vscreen]
|
||||
.master_stack
|
||||
.len() as i32;
|
||||
|
||||
client.size = (window_w, window_h);
|
||||
client.position = (0, window_h * i as i32);
|
||||
let size = (window_w, window_h);
|
||||
let position = (0, window_h * i as i32);
|
||||
|
||||
(
|
||||
xlib::XWindowChanges {
|
||||
x: client.position.0,
|
||||
y: client.position.1,
|
||||
width: client.size.0,
|
||||
height: client.size.1,
|
||||
x: position.0,
|
||||
y: position.1,
|
||||
width: size.0,
|
||||
height: size.1,
|
||||
border_width: 0,
|
||||
sibling: 0,
|
||||
stack_mode: 0,
|
||||
}
|
||||
},
|
||||
size,
|
||||
position,
|
||||
)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
xlib::XConfigureWindow(
|
||||
self.dpy(),
|
||||
client.borrow().window,
|
||||
client.window,
|
||||
(xlib::CWY | xlib::CWX | xlib::CWHeight | xlib::CWWidth) as u32,
|
||||
&mut wc,
|
||||
);
|
||||
|
||||
self.configure_client(client.clone());
|
||||
self.clients.replace(Client::new_rc(InnerClient {
|
||||
size,
|
||||
position,
|
||||
..**client
|
||||
}));
|
||||
|
||||
self.configure_client(&client);
|
||||
|
||||
xlib::XSync(self.dpy(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i, (_, weak_client)) in state.virtual_screens[state.current_vscreen]
|
||||
.aux_stack
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
let client = weak_client.upgrade().unwrap();
|
||||
|
||||
let mut wc = {
|
||||
let mut client = client.borrow_mut();
|
||||
let window_h = screen_h
|
||||
/ state.virtual_screens[state.current_vscreen].aux_stack.len() as i32;
|
||||
|
||||
client.size = (window_w, window_h);
|
||||
client.position = (window_w, window_h * i as i32);
|
||||
|
||||
xlib::XWindowChanges {
|
||||
x: client.position.0,
|
||||
y: client.position.1,
|
||||
width: client.size.0,
|
||||
height: client.size.1,
|
||||
border_width: 0,
|
||||
sibling: 0,
|
||||
stack_mode: 0,
|
||||
}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
xlib::XConfigureWindow(
|
||||
self.dpy(),
|
||||
client.borrow().window,
|
||||
(xlib::CWY | xlib::CWX | xlib::CWHeight | xlib::CWWidth) as u32,
|
||||
&mut wc,
|
||||
);
|
||||
|
||||
self.configure_client(client.clone());
|
||||
|
||||
xlib::XSync(self.dpy(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_client(&self, client: Rc<RefCell<Client>>) {
|
||||
fn configure_client(&self, client: &Rc<Client>) {
|
||||
let mut event = {
|
||||
let client = client.borrow();
|
||||
|
||||
xlib::XConfigureEvent {
|
||||
type_: xlib::ConfigureNotify,
|
||||
display: self.dpy(),
|
||||
|
@ -968,61 +837,49 @@ impl WMState {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_change_virtual_screen(&self, direction: i32) {
|
||||
fn handle_change_virtual_screen(&mut self, direction: i32) {
|
||||
assert!(direction == 1 || direction == -1);
|
||||
|
||||
Some(self.mut_state.borrow_mut()).and_then(|mut state| {
|
||||
// hide all windows from current virtual screen
|
||||
state.virtual_screens[state.current_vscreen]
|
||||
self.virtual_screens[self.current_vscreen]
|
||||
.master_stack
|
||||
.iter()
|
||||
.chain(
|
||||
state.virtual_screens[state.current_vscreen]
|
||||
.aux_stack
|
||||
.iter(),
|
||||
)
|
||||
.for_each(|(_, c)| {
|
||||
if let Some(c) = c.upgrade() {
|
||||
let c = c.borrow();
|
||||
unsafe {
|
||||
.chain(self.virtual_screens[self.current_vscreen].aux_stack.iter())
|
||||
.for_each(|c| unsafe {
|
||||
xlib::XMoveWindow(self.dpy(), c.window, c.size.0 * -2, c.position.1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// change current_vscreen variable
|
||||
let mut new_vscreen = state.current_vscreen as isize + direction as isize;
|
||||
let mut new_vscreen = self.current_vscreen as isize + direction as isize;
|
||||
|
||||
if new_vscreen >= state.virtual_screens.len() as isize {
|
||||
state.virtual_screens.push(VirtualScreen::new());
|
||||
if new_vscreen >= self.virtual_screens.len() as isize {
|
||||
self.virtual_screens.push(VirtualScreen::new());
|
||||
} else if new_vscreen < 0 {
|
||||
new_vscreen = state.virtual_screens.len() as isize - 1;
|
||||
new_vscreen = self.virtual_screens.len() as isize - 1;
|
||||
}
|
||||
|
||||
state.current_vscreen = new_vscreen as usize;
|
||||
|
||||
Some(())
|
||||
});
|
||||
self.current_vscreen = new_vscreen as usize;
|
||||
|
||||
self.arrange_clients();
|
||||
|
||||
// focus the focused cliend of the new virtual screen
|
||||
let client = self.mut_state.borrow().virtual_screens
|
||||
[self.mut_state.borrow().current_vscreen]
|
||||
if let Some(client) = self.virtual_screens[self.current_vscreen]
|
||||
.focused_client
|
||||
.to_owned();
|
||||
|
||||
client.upgrade().and_then(|c| Some(self.focus_client(c)));
|
||||
.upgrade()
|
||||
{
|
||||
self.focus_client(&client);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_switch_stack(&self, event: &XEvent) {
|
||||
self.mut_state
|
||||
.borrow_mut()
|
||||
.switch_stack_for_client(unsafe { &event.button.subwindow });
|
||||
fn handle_switch_stack(&mut self, event: &XEvent) {
|
||||
if let Some(client) = self.client_for_window(event.button.subwindow) {
|
||||
self.switch_stack_for_client(client);
|
||||
}
|
||||
|
||||
self.arrange_clients();
|
||||
}
|
||||
|
||||
fn handle_toggle_floating(&self, event: &XEvent) {
|
||||
fn handle_toggle_floating(&mut self, event: &XEvent) {
|
||||
if event.get_type() == xlib::ButtonPress {
|
||||
let event = unsafe { event.button };
|
||||
let clean_mask = self.xlib_state.clean_mask();
|
||||
|
@ -1031,31 +888,28 @@ impl WMState {
|
|||
&& event.state & clean_mask == Mod1Mask & clean_mask
|
||||
&& event.subwindow != 0
|
||||
{
|
||||
self.mut_state
|
||||
.borrow_mut()
|
||||
.clients
|
||||
.entry(event.subwindow)
|
||||
.and_modify(|c| {
|
||||
let mut c = c.borrow_mut();
|
||||
if let Some(client) = self.client_for_window(event.subwindow) {
|
||||
info!(
|
||||
"[handle_toggle_floating] {:#?} floating -> {:?}",
|
||||
c, !c.floating
|
||||
client, !client.floating
|
||||
);
|
||||
c.floating = !c.floating;
|
||||
});
|
||||
|
||||
self.clients.replace(Client::new_rc(InnerClient {
|
||||
floating: !client.floating,
|
||||
..**client
|
||||
}));
|
||||
}
|
||||
|
||||
self.arrange_clients();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_move_window(&self, event: &XEvent) {
|
||||
fn handle_move_window(&mut self, event: &XEvent) {
|
||||
let clean_mask = self.xlib_state.clean_mask();
|
||||
|
||||
let move_window = self.mut_state.borrow_mut().move_window;
|
||||
|
||||
if unsafe {
|
||||
move_window.is_none()
|
||||
self.move_window.is_none()
|
||||
&& event.get_type() == xlib::ButtonPress
|
||||
&& event.button.button == 1
|
||||
&& event.button.state & clean_mask == Mod1Mask & clean_mask
|
||||
|
@ -1069,7 +923,7 @@ impl WMState {
|
|||
(attr.x, attr.y)
|
||||
};
|
||||
|
||||
self.mut_state.borrow_mut().move_window = Some(unsafe {
|
||||
self.move_window = Some(unsafe {
|
||||
(
|
||||
event.button.subwindow,
|
||||
(event.button.x, event.button.y),
|
||||
|
@ -1077,21 +931,22 @@ impl WMState {
|
|||
)
|
||||
});
|
||||
|
||||
self.mut_state
|
||||
.borrow_mut()
|
||||
.clients
|
||||
.entry(unsafe { event.button.subwindow })
|
||||
.and_modify(|c| c.borrow_mut().floating = true);
|
||||
if let Some(client) = self.client_for_window(event.button.subwindow) {
|
||||
self.clients.replace(Client::new_rc(InnerClient {
|
||||
floating: true,
|
||||
..**client
|
||||
}));
|
||||
}
|
||||
|
||||
self.arrange_clients();
|
||||
} else if unsafe {
|
||||
move_window.is_some()
|
||||
self.move_window.is_some()
|
||||
&& event.get_type() == xlib::ButtonRelease
|
||||
&& event.button.button == 1
|
||||
} {
|
||||
self.mut_state.borrow_mut().move_window = None;
|
||||
} else if move_window.is_some() && event.get_type() == xlib::MotionNotify {
|
||||
let move_window = move_window.unwrap();
|
||||
self.move_window = None;
|
||||
} else if self.move_window.is_some() && event.get_type() == xlib::MotionNotify {
|
||||
let move_window = self.move_window.unwrap();
|
||||
|
||||
let attr = unsafe {
|
||||
let mut attr: xlib::XWindowAttributes =
|
||||
|
@ -1131,10 +986,10 @@ impl WMState {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_resize_window(&self, event: &XEvent) {
|
||||
fn handle_resize_window(&mut self, event: &XEvent) {
|
||||
let clean_mask = self.xlib_state.clean_mask();
|
||||
|
||||
let resize_window = self.mut_state.borrow().resize_window;
|
||||
let resize_window = self.resize_window;
|
||||
|
||||
if unsafe {
|
||||
resize_window.is_none()
|
||||
|
@ -1149,8 +1004,7 @@ impl WMState {
|
|||
|
||||
xlib::XGetWindowAttributes(self.dpy(), event.button.subwindow, &mut attr);
|
||||
|
||||
self.mut_state.borrow_mut().resize_window =
|
||||
Some((event.button.subwindow, (attr.x, attr.y)));
|
||||
self.resize_window = Some((event.button.subwindow, (attr.x, attr.y)));
|
||||
|
||||
xlib::XWarpPointer(
|
||||
self.dpy(),
|
||||
|
@ -1165,11 +1019,12 @@ impl WMState {
|
|||
);
|
||||
};
|
||||
|
||||
self.mut_state
|
||||
.borrow_mut()
|
||||
.clients
|
||||
.entry(unsafe { event.button.subwindow })
|
||||
.and_modify(|c| c.borrow_mut().floating = true);
|
||||
if let Some(client) = self.client_for_window(unsafe { event.button.subwindow }) {
|
||||
self.clients.replace(Client::new_rc(InnerClient {
|
||||
floating: true,
|
||||
..**client
|
||||
}));
|
||||
}
|
||||
|
||||
self.arrange_clients();
|
||||
} else if unsafe {
|
||||
|
@ -1177,7 +1032,7 @@ impl WMState {
|
|||
&& event.get_type() == xlib::ButtonRelease
|
||||
&& event.button.button == 3
|
||||
} {
|
||||
self.mut_state.borrow_mut().resize_window = None;
|
||||
self.resize_window = None;
|
||||
} else if resize_window.is_some() && event.get_type() == xlib::MotionNotify {
|
||||
let resize_window = resize_window.unwrap();
|
||||
|
||||
|
@ -1261,3 +1116,4 @@ impl WMState {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue