diff --git a/src/backends/traits.rs b/src/backends/traits.rs index e72f861..403e748 100644 --- a/src/backends/traits.rs +++ b/src/backends/traits.rs @@ -1,6 +1,6 @@ use super::{ window_event, - window_event::{KeyBind, MouseBind, Point}, + window_event::{KeyOrMouseBind, Point}, }; pub trait WindowServerBackend { @@ -13,23 +13,9 @@ pub trait WindowServerBackend { fn handle_event(&mut self, event: window_event::WindowEvent); /// adds a keybind to the specified `window`, or globally if `window` is `None`. - fn add_keybind(&mut self, keybind: KeyBind, window: Option); - fn remove_keybind( - &mut self, - keybind: KeyBind, - window: Option, - ); - - fn add_mousebind( - &mut self, - keybind: MouseBind, - window: Option, - ); - fn remove_mousebind( - &mut self, - keybind: MouseBind, - window: Option, - ); + /// add global keybind + fn add_keybind(&mut self, keybind: KeyOrMouseBind); + fn remove_keybind(&mut self, keybind: &KeyOrMouseBind); fn focus_window(&self, window: Self::Window); fn unfocus_window(&self, window: Self::Window); diff --git a/src/backends/window_event.rs b/src/backends/window_event.rs index 23d4467..4f21875 100644 --- a/src/backends/window_event.rs +++ b/src/backends/window_event.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use super::keycodes::{MouseButton, VirtualKeyCode}; +use super::keycodes::{KeyOrButton, MouseButton, VirtualKeyCode}; use bitflags::bitflags; #[derive(Debug)] @@ -279,7 +279,7 @@ impl FullscreenEvent { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct KeyBind { pub key: VirtualKeyCode, pub modifiers: ModifierState, @@ -299,7 +299,78 @@ impl KeyBind { } } +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct MouseBind { pub button: MouseButton, pub modifiers: ModifierState, } + +impl MouseBind { + pub fn new(button: MouseButton) -> Self { + Self { + button, + modifiers: ModifierState::empty(), + } + } + + pub fn with_mod(mut self, modifier_key: ModifierKey) -> Self { + self.modifiers.set_mod(modifier_key); + self + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct KeyOrMouseBind { + pub key: KeyOrButton, + pub modifiers: ModifierState, +} + +impl KeyOrMouseBind { + pub fn new(key: KeyOrButton) -> Self { + Self { + key, + modifiers: ModifierState::empty(), + } + } + + pub fn with_mod(mut self, modifier_key: ModifierKey) -> Self { + self.modifiers.set_mod(modifier_key); + self + } +} + +impl From<&KeyBind> for KeyOrMouseBind { + fn from(keybind: &KeyBind) -> Self { + Self { + key: KeyOrButton::Key(keybind.key), + modifiers: keybind.modifiers, + } + } +} + +impl From for KeyOrMouseBind { + fn from(keybind: KeyBind) -> Self { + Self { + key: KeyOrButton::Key(keybind.key), + modifiers: keybind.modifiers, + } + } +} + +impl From<&MouseBind> for KeyOrMouseBind { + fn from(mousebind: &MouseBind) -> Self { + Self { + key: KeyOrButton::Button(mousebind.button), + modifiers: mousebind.modifiers, + } + } +} + +impl From for KeyOrMouseBind { + fn from(mousebind: MouseBind) -> Self { + Self { + key: KeyOrButton::Button(mousebind.button), + modifiers: mousebind.modifiers, + } + } +} diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 9738f2e..dbab7ef 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -18,8 +18,8 @@ use self::keysym::{virtual_keycode_to_keysym, xev_to_mouse_button, XKeySym}; use super::{ keycodes::VirtualKeyCode, window_event::{ - ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, KeyState, - MapEvent, ModifierState, Point, UnmapEvent, WindowEvent, + ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, KeyOrMouseBind, + KeyState, MapEvent, ModifierState, Point, UnmapEvent, WindowEvent, }, WindowServerBackend, }; @@ -139,7 +139,7 @@ pub struct XLib { root: Window, screen: i32, atoms: XLibAtoms, - keybinds: Vec<()>, + keybinds: Vec, } impl Drop for XLib { @@ -420,11 +420,10 @@ impl XLib { fn grab_key_or_button( &self, + binding: &KeyOrMouseBind, window: xlib::Window, - key: KeyOrButton, - modifiers: ModifierState, ) { - let modmask = modifiers.as_modmask(self); + let modmask = binding.modifiers.as_modmask(self); let numlock_mask = self .get_numlock_mask() @@ -437,13 +436,13 @@ impl XLib { xlib::LockMask | numlock_mask, ]; - let keycode = match key { + let keycode = match binding.key { KeyOrButton::Key(key) => self.vk_to_keycode(key), KeyOrButton::Button(button) => mouse_button_to_xbutton(button), }; for modifier in modifiers.iter() { - match key { + match binding.key { KeyOrButton::Key(_) => unsafe { xlib::XGrabKey( self.dpy(), @@ -476,6 +475,57 @@ impl XLib { } } + fn ungrab_key_or_button( + &self, + binding: &KeyOrMouseBind, + window: xlib::Window, + ) { + let modmask = binding.modifiers.as_modmask(self); + + let numlock_mask = self + .get_numlock_mask() + .expect("failed to query numlock mask."); + + let modifiers = vec![ + 0, + xlib::LockMask, + numlock_mask, + xlib::LockMask | numlock_mask, + ]; + + let keycode = match binding.key { + KeyOrButton::Key(key) => self.vk_to_keycode(key), + KeyOrButton::Button(button) => mouse_button_to_xbutton(button), + }; + + for modifier in modifiers.iter() { + match binding.key { + KeyOrButton::Key(_) => unsafe { + xlib::XUngrabKey( + self.dpy(), + keycode, + modmask | modifier, + window, + ); + }, + KeyOrButton::Button(_) => unsafe { + xlib::XUngrabButton( + self.dpy(), + keycode as u32, + modmask | modifier, + window, + ); + }, + } + } + } + + fn grab_global_keybinds(&self, window: xlib::Window) { + for binding in self.keybinds.iter() { + self.grab_key_or_button(binding, window); + } + } + fn vk_to_keycode(&self, vk: VirtualKeyCode) -> i32 { unsafe { xlib::XKeysymToKeycode( @@ -538,47 +588,44 @@ impl WindowServerBackend for XLib { &mut self, event: super::window_event::WindowEvent, ) { - todo!() + match event { + WindowEvent::MapRequestEvent(event) => { + unsafe { + xlib::XMapWindow(self.dpy(), event.window); + + xlib::XSelectInput( + self.dpy(), + event.window, + xlib::EnterWindowMask + | xlib::FocusChangeMask + | xlib::PropertyChangeMask + | xlib::StructureNotifyMask, + ); + } + + self.grab_global_keybinds(event.window); + } + WindowEvent::ConfigureEvent(event) => { + self.configure_window( + event.window, + Some(event.size), + Some(event.position), + ); + } + _ => {} + } } - fn add_keybind( - &mut self, - keybind: super::window_event::KeyBind, - window: Option, - ) { - self.grab_key_or_button( - window.unwrap_or(self.root), - KeyOrButton::Key(keybind.key), - keybind.modifiers, - ); + fn add_keybind(&mut self, keybind: super::window_event::KeyOrMouseBind) { + self.grab_key_or_button(&keybind, self.root); + self.keybinds.push(keybind); } fn remove_keybind( &mut self, - keybind: super::window_event::KeyBind, - window: Option, + keybind: &super::window_event::KeyOrMouseBind, ) { - todo!() - } - - fn add_mousebind( - &mut self, - keybind: super::window_event::MouseBind, - window: Option, - ) { - self.grab_key_or_button( - window.unwrap_or(self.root), - KeyOrButton::Button(keybind.button), - keybind.modifiers, - ); - } - - fn remove_mousebind( - &mut self, - keybind: super::window_event::MouseBind, - window: Option, - ) { - todo!() + self.keybinds.retain(|kb| kb != keybind); } fn focus_window(&self, window: Self::Window) { diff --git a/src/state.rs b/src/state.rs index 566c4af..cdacae0 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc}; use log::{error, info}; -use x11::xlib::{self, Window, XEvent, XMotionEvent}; +use x11::xlib::{self, Window, XEvent}; use xlib::{ XConfigureRequestEvent, XCrossingEvent, XDestroyWindowEvent, XMapRequestEvent, XUnmapEvent, @@ -12,8 +12,9 @@ use crate::{ backends::{ keycodes::{MouseButton, VirtualKeyCode}, window_event::{ - ButtonEvent, KeyBind, KeyEvent, KeyState, ModifierKey, - ModifierState, Point, WindowEvent, + ButtonEvent, ConfigureEvent, KeyBind, KeyEvent, KeyState, MapEvent, + ModifierKey, ModifierState, MotionEvent, MouseBind, Point, + WindowEvent, }, xlib::XLib, WindowServerBackend, @@ -119,22 +120,21 @@ where } fn init(mut self) -> Self { - // TODO: fix keybinds for moving windows and stuff - // self.xlib.add_global_keybind(KeyOrButton::button( - // 1, - // self.config.mod_key, - // ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - // )); - // self.xlib.add_global_keybind(KeyOrButton::button( - // 2, - // self.config.mod_key, - // ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - // )); - // self.xlib.add_global_keybind(KeyOrButton::button( - // 3, - // self.config.mod_key, - // ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - // )); + self.backend.add_keybind( + MouseBind::new(MouseButton::Left) + .with_mod(self.config.mod_key) + .into(), + ); + self.backend.add_keybind( + MouseBind::new(MouseButton::Middle) + .with_mod(self.config.mod_key) + .into(), + ); + self.backend.add_keybind( + MouseBind::new(MouseButton::Right) + .with_mod(self.config.mod_key) + .into(), + ); self.add_keybind(KeyBinding::new( KeyBind::new(VirtualKeyCode::P).with_mod(self.config.mod_key), @@ -256,7 +256,7 @@ where } fn add_keybind(&mut self, keybind: KeyBinding) { - //self.xlib.add_global_keybind(keybind.key); + self.backend.add_keybind((&keybind.key).into()); self.keybinds.borrow_mut().push(keybind); } @@ -361,23 +361,47 @@ where let event = self.backend.next_event(); match event { - WindowEvent::KeyEvent(event @ KeyEvent { window, .. }) => { + WindowEvent::KeyEvent(event) => { self.handle_keybinds(&event); } - WindowEvent::ButtonEvent( - event @ ButtonEvent { window, .. }, - ) => { + WindowEvent::ButtonEvent(event) => { self.button_event(&event); } - // xlib::MapRequest => self.map_request(&event), - // xlib::UnmapNotify => self.unmap_notify(&event), - // xlib::ConfigureRequest => self.configure_request(&event), - // xlib::EnterNotify => self.enter_notify(&event), + WindowEvent::MapRequestEvent(MapEvent { window }) => { + if !self.clients.contains(&window) { + self.new_client(window); + } + + self.backend.handle_event(event); + } + WindowEvent::UnmapEvent(event) => { + self.clients.remove(&event.window); + self.arrange_clients(); + } + WindowEvent::EnterEvent(event) => { + self.focus_client(&event.window, false); + } + WindowEvent::MotionEvent(event) => { + self.do_move_resize_window(&event); + } + WindowEvent::ConfigureEvent(ConfigureEvent { + window, .. + }) => { + if !self.clients.contains(&window) { + self.backend.handle_event(event); + } + // TODO + // match self.clients.get(&event.window).into_option() { + // Some(client) => self + // .xlib + // .configure_client(client, self.clients.get_border()), + // None => self.xlib.configure_window(event), + // } + } + + // i dont think i actually have to handle destroy notify events. + // every window should be unmapped regardless // xlib::DestroyNotify => self.destroy_notify(&event), - // xlib::ButtonPress => self.button_press(event.as_ref()), - // xlib::ButtonRelease => self.button_release(event.as_ref()), - // xlib::MotionNotify => self.motion_notify(event.as_ref()), - // xlib::KeyPress => self.handle_keybinds(event.as_ref()), _ => {} } } @@ -397,6 +421,7 @@ where // TODO: change this somehow cuz I'm not a big fan of this "hardcoded" keybind stuff fn handle_keybinds(&mut self, event: &KeyEvent) { + // I'm not sure if this has to be a Rc> or if it would be better as a Cell<> let keybinds = self.keybinds.clone(); for kb in keybinds.borrow().iter() { @@ -406,17 +431,6 @@ where kb.call(self, event); } } - //let clean_mask = self.xlib.get_clean_mask(); - // TODO: Fix this - // for kb in self.keybinds.clone().into_iter() { - // if let KeyOrButton::Key(keycode, modmask) = kb.key { - // if keycode as u32 == event.keycode - // && modmask & clean_mask == event.state & clean_mask - // { - // (kb.closure)(self, event); - // } - // } - // } } fn handle_switch_stack(&mut self) { @@ -629,11 +643,13 @@ where Client::new_default(window) }; + // TODO //self.xlib //.configure_client(&client, self.clients.get_border()); self.clients.insert(client).unwrap(); self.arrange_clients(); + // TODO //self.xlib.map_window(window); self.focus_client(&window, true); @@ -666,6 +682,7 @@ where fn configure_request(&mut self, event: &XEvent) { let event: &XConfigureRequestEvent = event.as_ref(); + // TODO // match self.clients.get(&event.window).into_option() { // Some(client) => self // .xlib @@ -741,12 +758,12 @@ where } } - fn do_move_resize_window(&mut self, event: &XMotionEvent) { + fn do_move_resize_window(&mut self, event: &MotionEvent) { match &self.move_resize_window { MoveResizeInfo::Move(info) => { let (x, y) = ( - event.x - info.starting_cursor_pos.x, - event.y - info.starting_cursor_pos.y, + event.position.x - info.starting_cursor_pos.x, + event.position.y - info.starting_cursor_pos.y, ); if let Some(client) = @@ -762,8 +779,8 @@ where } MoveResizeInfo::Resize(info) => { let (x, y) = ( - event.x - info.starting_cursor_pos.x, - event.y - info.starting_cursor_pos.y, + event.position.x - info.starting_cursor_pos.x, + event.position.y - info.starting_cursor_pos.y, ); if let Some(client) = @@ -817,10 +834,6 @@ where } } - fn motion_notify(&mut self, event: &XMotionEvent) { - self.do_move_resize_window(event); - } - pub fn spawn(&self, command: &str, args: &[&str]) { info!("spawn: {:?} {:?}", command, args.join(" ")); match std::process::Command::new(command).args(args).spawn() {