moved code around, turned resize, move window handlers into closures

This commit is contained in:
noonebtw 2021-01-12 12:24:18 +01:00
parent 7f7872ce63
commit 90f5d9b9b8

View file

@ -49,6 +49,27 @@ struct XlibState {
// (i32, i32) : initial window position // (i32, i32) : initial window position
resize_window: Option<(u64, (i32, i32))>, resize_window: Option<(u64, (i32, i32))>,
atoms: WMAtoms, atoms: WMAtoms,
event_handlers: Vec<Arc<dyn Fn(&mut Self, &XEvent)>>,
}
impl Default for XlibState {
fn default() -> Self {
let display = unsafe { xlib::XOpenDisplay(null()) };
assert_ne!(display, null_mut());
let display = Display {
0: Arc::new(AtomicPtr::new(display)),
};
Self {
display,
keys: vec![],
move_window: None,
resize_window: None,
atoms: WMAtoms::default(),
event_handlers: vec![],
}
}
} }
impl XlibState { impl XlibState {
@ -60,7 +81,7 @@ impl XlibState {
0: Arc::new(AtomicPtr::new(display)), 0: Arc::new(AtomicPtr::new(display)),
}; };
let state = Self { Ok(Self {
display: display.clone(), display: display.clone(),
keys: vec![], keys: vec![],
move_window: None, move_window: None,
@ -81,25 +102,19 @@ impl XlibState {
.filter(|&atom| atom != 0) .filter(|&atom| atom != 0)
}, },
}, },
}; event_handlers: vec![],
Ok(state)
} }
// handle_move_window
fn dpy(&self) -> *mut xlib::Display { .grab_button(
self.display.get() 1,
} Mod1Mask,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
fn root(&self) -> u64 { )
unsafe { xlib::XDefaultRootWindow(self.dpy()) } .add_event_handler(|state, event| {
} let clean_mask = state.clean_mask();
// mod1mask + mousebutton1 moves window
fn handle_move_window(&mut self, event: &xlib::XEvent) {
let clean_mask = self.clean_mask();
if unsafe { if unsafe {
self.move_window.is_none() state.move_window.is_none()
&& event.get_type() == xlib::ButtonPress && event.get_type() == xlib::ButtonPress
&& event.button.button == 1 && event.button.button == 1
&& event.button.state & clean_mask == Mod1Mask & clean_mask && event.button.state & clean_mask == Mod1Mask & clean_mask
@ -108,12 +123,12 @@ impl XlibState {
let win_pos = unsafe { let win_pos = unsafe {
let mut attr: xlib::XWindowAttributes = let mut attr: xlib::XWindowAttributes =
std::mem::MaybeUninit::uninit().assume_init(); std::mem::MaybeUninit::uninit().assume_init();
xlib::XGetWindowAttributes(self.dpy(), event.button.subwindow, &mut attr); xlib::XGetWindowAttributes(state.dpy(), event.button.subwindow, &mut attr);
(attr.x, attr.y) (attr.x, attr.y)
}; };
self.move_window = unsafe { state.move_window = unsafe {
Some(( Some((
event.button.subwindow, event.button.subwindow,
(event.button.x, event.button.y), (event.button.x, event.button.y),
@ -121,18 +136,18 @@ impl XlibState {
)) ))
}; };
} else if unsafe { } else if unsafe {
self.move_window.is_some() state.move_window.is_some()
&& event.get_type() == xlib::ButtonRelease && event.get_type() == xlib::ButtonRelease
&& event.button.button == 1 && event.button.button == 1
} { } {
self.move_window = None; state.move_window = None;
} else if self.move_window.is_some() && event.get_type() == xlib::MotionNotify { } else if state.move_window.is_some() && event.get_type() == xlib::MotionNotify {
let move_window = self.move_window.unwrap(); let move_window = state.move_window.unwrap();
let attr = unsafe { let attr = unsafe {
let mut attr: xlib::XWindowAttributes = let mut attr: xlib::XWindowAttributes =
std::mem::MaybeUninit::uninit().assume_init(); std::mem::MaybeUninit::uninit().assume_init();
xlib::XGetWindowAttributes(self.dpy(), move_window.0, &mut attr); xlib::XGetWindowAttributes(state.dpy(), move_window.0, &mut attr);
attr attr
}; };
@ -156,23 +171,27 @@ impl XlibState {
unsafe { unsafe {
xlib::XConfigureWindow( xlib::XConfigureWindow(
self.dpy(), state.dpy(),
self.move_window.unwrap().0, state.move_window.unwrap().0,
(xlib::CWX | xlib::CWY) as u32, (xlib::CWX | xlib::CWY) as u32,
&mut wc, &mut wc,
); );
xlib::XSync(self.dpy(), 0); xlib::XSync(state.dpy(), 0);
} }
} }
} })
// resize window handler
// mod1mask + mousebutton3 resizes window .grab_button(
fn handle_resize_window(&mut self, event: &xlib::XEvent) { 3,
let clean_mask = self.clean_mask(); Mod1Mask,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
)
.add_event_handler(|state, event| {
let clean_mask = state.clean_mask();
if unsafe { if unsafe {
self.resize_window.is_none() state.resize_window.is_none()
&& event.get_type() == xlib::ButtonPress && event.get_type() == xlib::ButtonPress
&& event.button.button == 3 && event.button.button == 3
&& event.button.state & clean_mask == Mod1Mask & clean_mask && event.button.state & clean_mask == Mod1Mask & clean_mask
@ -182,12 +201,12 @@ impl XlibState {
let mut attr: xlib::XWindowAttributes = let mut attr: xlib::XWindowAttributes =
std::mem::MaybeUninit::uninit().assume_init(); std::mem::MaybeUninit::uninit().assume_init();
xlib::XGetWindowAttributes(self.dpy(), event.button.subwindow, &mut attr); xlib::XGetWindowAttributes(state.dpy(), event.button.subwindow, &mut attr);
self.resize_window = Some((event.button.subwindow, (attr.x, attr.y))); state.resize_window = Some((event.button.subwindow, (attr.x, attr.y)));
xlib::XWarpPointer( xlib::XWarpPointer(
self.dpy(), state.dpy(),
0, 0,
event.button.subwindow, event.button.subwindow,
0, 0,
@ -199,18 +218,18 @@ impl XlibState {
); );
}; };
} else if unsafe { } else if unsafe {
self.resize_window.is_some() state.resize_window.is_some()
&& event.get_type() == xlib::ButtonRelease && event.get_type() == xlib::ButtonRelease
&& event.button.button == 3 && event.button.button == 3
} { } {
self.resize_window = None; state.resize_window = None;
} else if self.resize_window.is_some() && event.get_type() == xlib::MotionNotify { } else if state.resize_window.is_some() && event.get_type() == xlib::MotionNotify {
let resize_window = self.resize_window.unwrap(); let resize_window = state.resize_window.unwrap();
let attr = unsafe { let attr = unsafe {
let mut attr: xlib::XWindowAttributes = let mut attr: xlib::XWindowAttributes =
std::mem::MaybeUninit::uninit().assume_init(); std::mem::MaybeUninit::uninit().assume_init();
xlib::XGetWindowAttributes(self.dpy(), resize_window.0, &mut attr); xlib::XGetWindowAttributes(state.dpy(), resize_window.0, &mut attr);
attr attr
}; };
@ -229,20 +248,6 @@ impl XlibState {
) )
}; };
/*
xlib::XWarpPointer(
self.dpy(),
0,
resize_window.0,
0,
0,
0,
0,
width - 1,
height - 1,
);
*/
let mut wc = xlib::XWindowChanges { let mut wc = xlib::XWindowChanges {
x: attr.x, x: attr.x,
y: attr.y, y: attr.y,
@ -254,15 +259,56 @@ impl XlibState {
}; };
xlib::XConfigureWindow( xlib::XConfigureWindow(
self.dpy(), state.dpy(),
resize_window.0, resize_window.0,
(xlib::CWWidth | xlib::CWHeight) as u32, (xlib::CWWidth | xlib::CWHeight) as u32,
&mut wc, &mut wc,
); );
xlib::XSync(self.dpy(), 0); xlib::XSync(state.dpy(), 0);
} }
} }
})
.add_key_with_handler(
"T",
Mod1Mask,
|state, _| {
let _ = state.spawn("xterm", &[]);
},
)
.add_key_with_handler(
"Q",
Mod1Mask,
|state, event| unsafe {
if event.key.subwindow != 0 {
if state.atoms.delete.is_none()
|| !state.send_event(event.key.subwindow, state.atoms.delete.unwrap())
{
println!("delete atmom: {:?}", state.atoms.delete);
xlib::XKillClient(state.dpy(), event.key.subwindow);
}
}
},
)
.add_key_with_handler(
"Q",
Mod1Mask | ShiftMask,
|state, _event| {
unsafe {
xlib::XCloseDisplay(state.dpy());
}
std::process::exit(0);
},
))
}
fn dpy(&self) -> *mut xlib::Display {
self.display.get()
}
fn root(&self) -> u64 {
unsafe { xlib::XDefaultRootWindow(self.dpy()) }
} }
fn main_loop(mut self) -> Result<Self> { fn main_loop(mut self) -> Result<Self> {
@ -279,7 +325,7 @@ impl XlibState {
// cache clean mask, that way numlock_mask doesnt get called for every cmp // cache clean mask, that way numlock_mask doesnt get called for every cmp
let clean_mask = self.clean_mask(); let clean_mask = self.clean_mask();
for (key, mask, handler) in self.keys.iter() { for (key, mask, handler) in self.keys.iter().clone() {
// check if key and mask with any numlock state fit // check if key and mask with any numlock state fit
if unsafe { if unsafe {
event.key.keycode == *key as u32 event.key.keycode == *key as u32
@ -290,27 +336,35 @@ impl XlibState {
} }
} }
// handle window resizes self.event_handlers
self.handle_move_window(&event); .clone()
self.handle_resize_window(&event); .iter()
.for_each(|handler| handler(&mut self, &event));
} }
} }
fn add_key_with_handler<S: Into<String>>( fn add_event_handler<F>(mut self, handler: F) -> Self
mut self, where
key: S, F: Fn(&mut Self, &XEvent) + 'static,
mask: u32, {
handler: Box<dyn Fn(&Self, &XEvent)>, self.event_handlers.push(Arc::new(handler));
) -> Self {
let keycode = self.keycode(key);
self.keys.push((keycode, mask, Box::new(handler)));
self.grab_key(keycode, mask);
self self
} }
fn grab_key(&self, keycode: i32, mask: u32) -> &Self { fn add_key_with_handler<S, F>(
mut self,
key: S,
mask: u32,
handler: F,
) -> Self where S: Into<String>, F: Fn(&Self, &XEvent) + 'static {
let keycode = self.keycode(key);
self.keys.push((keycode, mask, Box::new(handler)));
self.grab_key(keycode, mask)
}
fn grab_key(self, keycode: i32, mask: u32) -> Self {
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() {
@ -330,11 +384,11 @@ impl XlibState {
self self
} }
fn grab_button(&self, button: u32, mod_mask: u32, button_mask: i64) -> &Self { fn grab_button(self, button: u32, mod_mask: u32, button_mask: i64) -> Self {
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() { modifiers.iter().for_each(|&modifier| {
unsafe { unsafe {
xlib::XGrabButton( xlib::XGrabButton(
self.dpy(), self.dpy(),
@ -349,7 +403,7 @@ impl XlibState {
0, 0,
); );
} }
} });
self self
} }
@ -390,7 +444,7 @@ impl XlibState {
} }
} }
fn keycode<S: Into<String>>(&self, string: S) -> i32 { fn keycode<S>(&self, string: S) -> i32 where S: Into<String> {
let c_string = CString::new(string.into()).unwrap(); let c_string = CString::new(string.into()).unwrap();
unsafe { unsafe {
let keysym = xlib::XStringToKeysym(c_string.as_ptr()); let keysym = xlib::XStringToKeysym(c_string.as_ptr());
@ -474,57 +528,6 @@ fn main() -> Result<()> {
let state = XlibState::new()?; let state = XlibState::new()?;
let state = state
.add_key_with_handler(
"T",
Mod1Mask,
Box::new(|state, _| {
let _ = state.spawn("xterm", &[]);
}),
)
.add_key_with_handler(
"F1",
Mod1Mask,
Box::new(|state, event| unsafe {
if event.key.subwindow != 0 {
xlib::XRaiseWindow(state.dpy(), event.key.subwindow);
}
}),
)
.add_key_with_handler(
"Q",
Mod1Mask,
Box::new(|state, event| unsafe {
if event.key.subwindow != 0 {
if state.atoms.delete.is_none()
|| !state.send_event(event.key.subwindow, state.atoms.delete.unwrap())
{
println!("delete atmom: {:?}", state.atoms.delete);
xlib::XKillClient(state.dpy(), event.key.subwindow);
}
}
}),
).add_key_with_handler("Q", Mod1Mask|ShiftMask, Box::new(|state, _event| {
unsafe {
xlib::XCloseDisplay(state.dpy());
}
std::process::exit(0);
}));
state
.grab_key(state.keycode("F1"), Mod1Mask)
.grab_button(
1,
Mod1Mask,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
)
.grab_button(
3,
Mod1Mask,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
);
state.main_loop()?; state.main_loop()?;
Ok(()) Ok(())