mod1 clicking window raises it to foreground
This commit is contained in:
parent
6148343d37
commit
d0312261fb
123
src/wm.rs
123
src/wm.rs
|
@ -13,9 +13,9 @@ use x11::{
|
||||||
xlib::{
|
xlib::{
|
||||||
Atom, ButtonPressMask, ButtonReleaseMask, CWEventMask, ControlMask, EnterWindowMask,
|
Atom, ButtonPressMask, ButtonReleaseMask, CWEventMask, ControlMask, EnterWindowMask,
|
||||||
FocusChangeMask, GrabModeAsync, LeaveWindowMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask,
|
FocusChangeMask, GrabModeAsync, LeaveWindowMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask,
|
||||||
Mod4Mask, Mod5Mask, PointerMotionMask, PropertyChangeMask, ShiftMask,
|
Mod4Mask, Mod5Mask, PointerMotionMask, PropertyChangeMask, ShiftMask, StructureNotifyMask,
|
||||||
StructureNotifyMask, SubstructureNotifyMask, SubstructureRedirectMask, Window,
|
SubstructureNotifyMask, SubstructureRedirectMask, Window, XDefaultScreen, XEvent,
|
||||||
XDefaultScreen, XErrorEvent, XEvent, XInternAtom, XOpenDisplay, XRootWindow,
|
XInternAtom, XOpenDisplay, XRootWindow,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,6 +297,8 @@ impl Default for WMStateMut {
|
||||||
pub struct WMState {
|
pub struct WMState {
|
||||||
xlib_state: XLibState,
|
xlib_state: XLibState,
|
||||||
key_handlers: Vec<(i32, u32, Arc<dyn Fn(&Self, &XEvent)>)>,
|
key_handlers: Vec<(i32, u32, Arc<dyn Fn(&Self, &XEvent)>)>,
|
||||||
|
// (button, mod_mask, button_mask)
|
||||||
|
buttons: Vec<(u32, u32, i64)>,
|
||||||
event_handlers: Vec<Arc<dyn Fn(&Self, &XEvent)>>,
|
event_handlers: Vec<Arc<dyn Fn(&Self, &XEvent)>>,
|
||||||
mut_state: RefCell<WMStateMut>,
|
mut_state: RefCell<WMStateMut>,
|
||||||
}
|
}
|
||||||
|
@ -308,6 +310,7 @@ impl WMState {
|
||||||
mut_state: RefCell::new(WMStateMut::default()),
|
mut_state: RefCell::new(WMStateMut::default()),
|
||||||
key_handlers: vec![],
|
key_handlers: vec![],
|
||||||
event_handlers: vec![],
|
event_handlers: vec![],
|
||||||
|
buttons: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +360,8 @@ impl WMState {
|
||||||
| StructureNotifyMask
|
| StructureNotifyMask
|
||||||
| SubstructureNotifyMask
|
| SubstructureNotifyMask
|
||||||
| EnterWindowMask
|
| EnterWindowMask
|
||||||
| PointerMotionMask;
|
| PointerMotionMask
|
||||||
|
| ButtonPressMask;
|
||||||
|
|
||||||
xlib::XChangeWindowAttributes(state.dpy(), state.root(), CWEventMask, &mut wa);
|
xlib::XChangeWindowAttributes(state.dpy(), state.root(), CWEventMask, &mut wa);
|
||||||
|
|
||||||
|
@ -376,21 +380,36 @@ impl WMState {
|
||||||
event
|
event
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.event_handlers.iter().for_each(|handler| {
|
||||||
|
handler(&self, &event);
|
||||||
|
});
|
||||||
|
|
||||||
match event.get_type() {
|
match event.get_type() {
|
||||||
xlib::MapRequest => {
|
xlib::MapRequest => {
|
||||||
let event = unsafe { &event.map_request };
|
let event = unsafe { &event.map_request };
|
||||||
|
|
||||||
let _ = self.mut_state.try_borrow_mut().and_then(|mut_state| {
|
let _ = self
|
||||||
let (mut focused_client, mut clients) = RefMut::map_split(mut_state, |t| {
|
.mut_state
|
||||||
(&mut t.focused_client, &mut t.clients)
|
.try_borrow_mut()
|
||||||
});
|
.ok()
|
||||||
|
.and_then(|mut m| {
|
||||||
clients.entry(event.window).or_insert_with(|| {
|
if !m.clients.contains_key(&event.window) {
|
||||||
unsafe { xlib::XMapWindow(self.dpy(), event.window) };
|
Some(
|
||||||
|
m.clients
|
||||||
let c = Arc::new(Client {
|
.entry(event.window)
|
||||||
window: event.window,
|
.or_insert_with(|| {
|
||||||
});
|
Arc::new(Client {
|
||||||
|
window: event.window,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.clone(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.and_then(|c| {
|
||||||
|
unsafe { xlib::XMapWindow(self.dpy(), c.window) };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
xlib::XSelectInput(
|
xlib::XSelectInput(
|
||||||
|
@ -399,21 +418,18 @@ impl WMState {
|
||||||
EnterWindowMask
|
EnterWindowMask
|
||||||
| FocusChangeMask
|
| FocusChangeMask
|
||||||
| PropertyChangeMask
|
| PropertyChangeMask
|
||||||
| StructureNotifyMask,
|
| StructureNotifyMask | ButtonPressMask,
|
||||||
)
|
);
|
||||||
};
|
|
||||||
|
|
||||||
if focused_client.upgrade().is_none() {
|
|
||||||
*focused_client = Arc::downgrade(&c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.focus_client(c.clone());
|
self.buttons.iter().for_each(|&(button, mod_mask, button_mask)| {
|
||||||
|
self.xlib_state.grab_button(c.window, button, mod_mask, button_mask);
|
||||||
|
});
|
||||||
|
|
||||||
c
|
self.focus_client(c);
|
||||||
|
|
||||||
|
Some(())
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
xlib::UnmapNotify => {
|
xlib::UnmapNotify => {
|
||||||
let event = unsafe { &event.unmap };
|
let event = unsafe { &event.unmap };
|
||||||
|
@ -478,25 +494,31 @@ impl WMState {
|
||||||
.and_then(|c| Some(c.clone()))
|
.and_then(|c| Some(c.clone()))
|
||||||
}) {
|
}) {
|
||||||
Some(client) => {
|
Some(client) => {
|
||||||
let _ = self.mut_state.try_borrow_mut().and_then(|s| {
|
|
||||||
let mut focused_client = RefMut::map(s, |s| &mut s.focused_client);
|
|
||||||
|
|
||||||
let _ = focused_client.upgrade().and_then(|c| {
|
|
||||||
self.unfocus_client(c.clone());
|
|
||||||
|
|
||||||
Some(())
|
|
||||||
});
|
|
||||||
|
|
||||||
*focused_client = Arc::downgrade(&client);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
|
|
||||||
self.focus_client(client);
|
self.focus_client(client);
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
xlib::ButtonPress => {
|
||||||
|
let event = unsafe { &event.button };
|
||||||
|
|
||||||
|
match self.mut_state.try_borrow().ok().and_then(|mut_state| {
|
||||||
|
mut_state
|
||||||
|
.clients
|
||||||
|
.get(&event.subwindow)
|
||||||
|
.and_then(|c| Some(c.clone()))
|
||||||
|
}) {
|
||||||
|
Some(client) => {
|
||||||
|
self.focus_client(client.clone());
|
||||||
|
println!("raising window {:?}", client.window);
|
||||||
|
unsafe {
|
||||||
|
xlib::XRaiseWindow(self.dpy(), client.window);
|
||||||
|
xlib::XSync(self.dpy(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
xlib::KeyPress => {
|
xlib::KeyPress => {
|
||||||
let clean_mask = self.xlib_state.clean_mask();
|
let clean_mask = self.xlib_state.clean_mask();
|
||||||
|
|
||||||
|
@ -509,9 +531,7 @@ impl WMState {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => self.event_handlers.iter().for_each(|handler| {
|
_ => {}
|
||||||
handler(&self, &event);
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,7 +544,8 @@ impl WMState {
|
||||||
self.xlib_state.root()
|
self.xlib_state.root()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grab_button(self, button: u32, mod_mask: u32, button_mask: i64) -> Self {
|
pub fn grab_button(mut self, button: u32, mod_mask: u32, button_mask: i64) -> Self {
|
||||||
|
self.buttons.push((button, mod_mask, button_mask));
|
||||||
self.xlib_state
|
self.xlib_state
|
||||||
.grab_button(self.root(), button, mod_mask, button_mask);
|
.grab_button(self.root(), button, mod_mask, button_mask);
|
||||||
|
|
||||||
|
@ -571,6 +592,20 @@ impl WMState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_client(&self, client: Arc<Client>) {
|
fn focus_client(&self, client: Arc<Client>) {
|
||||||
|
let _ = self.mut_state.try_borrow_mut().and_then(|m| {
|
||||||
|
let mut focused_client = RefMut::map(m, |m| &mut m.focused_client);
|
||||||
|
match focused_client.upgrade() {
|
||||||
|
Some(c) => {
|
||||||
|
self.unfocus_client(c.clone());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
*focused_client = Arc::downgrade(&client);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
xlib::XSetInputFocus(
|
xlib::XSetInputFocus(
|
||||||
self.dpy(),
|
self.dpy(),
|
||||||
|
|
Loading…
Reference in a new issue