From 975aabe3362baf56e47d0ba022f7ea35f7bc5c7f Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Mon, 9 Nov 2015 05:53:12 -0300 Subject: ExecFn Rewrite. This now allows to call a ExecFn with a &mut DotWM by parameter. This help to do some things like do the window swapping. through mod4 + tab. Also the bindings are not longer on the wm, because this generates some problems with the ExecFn. Also, now it's posible to resize the windows :) --- src/dotwm.rs | 49 +++++++++++++++---------- src/main.rs | 99 ++++++++++++++++++++++++++++++++++++++++---------- src/safe_x11/window.rs | 21 +++++++---- 3 files changed, 121 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/dotwm.rs b/src/dotwm.rs index 77f09b3..952fc8c 100644 --- a/src/dotwm.rs +++ b/src/dotwm.rs @@ -2,15 +2,11 @@ use x11::xlib; use x11::xlib::{ Display, XErrorEvent, - XEvent, - - GrabModeAsync, }; use safe_x11::{ open_display, close_display, - grab_key, }; use safe_x11::window::XWindow; @@ -18,7 +14,6 @@ use safe_x11::window::XWindow; use std::ptr; use std::process::exit; use std::mem::uninitialized; -use std::collections::HashMap; use libc::c_int; #[allow(unused_variables)] @@ -33,13 +28,9 @@ unsafe extern "C" fn error_handler(d: *mut Display, evptr: *mut XErrorEvent) -> 0 } -/// Defines a callback to call no certains events. -pub type ExecFn = fn(&DotWM, XEvent, &[String]) -> bool; - pub struct DotWM { pub display: *mut Display, // Map with the keys as (key, mod) - bindings: HashMap<(u32, u32), (ExecFn, Vec)>, cw_idx: usize, pub window_list: Vec, } @@ -60,7 +51,6 @@ impl DotWM { DotWM { display: d, - bindings: HashMap::new(), cw_idx: 0, window_list: vec![], } @@ -87,6 +77,7 @@ impl DotWM { /// dotwm.add_binding(keysym::XK_Return, xlib::Mod4Mask, exec, /// &["xterm"]); /// ``` + /* pub fn add_binding(&mut self, key: u32, modifiers: u32, func: ExecFn, args: &[&str]) { grab_key(self.display, key, modifiers, true, GrabModeAsync, GrabModeAsync); let mut v = vec![]; @@ -95,13 +86,16 @@ impl DotWM { } self.bindings.insert((key, modifiers), (func, v)); } + */ + /* pub fn exec_func(&mut self, key: u32, modifiers: u32, ev: xlib::XEvent) { if let Some(&(func, ref args)) = self.bindings.get(&(key, modifiers)) { let v = args.clone(); func(&self, ev, &v); } } + */ pub fn add_window(&mut self, w: xlib::Window) { self.unfocus_current_window(); @@ -115,7 +109,6 @@ impl DotWM { } pub fn current_window(&self) -> Option<&XWindow> { - println!("trying to get {} from list of len {}", self.cw_idx, self.window_list.len()); if self.cw_idx < self.window_list.len() { self.window_list.get(self.cw_idx) } else { @@ -125,7 +118,6 @@ impl DotWM { pub fn remove_window(&mut self, w: xlib::Window) { let pos = self.window_list.iter().position(|xw| xw.inner == w); - println!("Removing widnow {}: pos: {:?}", w, pos); match pos { Some(idx) => { @@ -147,23 +139,40 @@ impl DotWM { w.raise(); } + /// Find a given window and returns it's position on the window_list. pub fn find_window(&self, w: xlib::Window) -> Option { self.window_list.iter().position(|xw| xw.inner == w) } + /// Focus the next window. + /// + /// There're 3 posibilities. There's no window, there's one window or there + /// are more windows. + pub fn focus_next(&mut self) { + if self.window_list.len() > 0 { + // Unfocus the current window. + let prev_win = &self.window_list[self.cw_idx]; + prev_win.unfocus(); + + // And give focus to the next one. + let next_win_idx = if self.cw_idx < self.window_list.len() - 1 { + self.cw_idx + 1 + } else { + 0 + }; + + let curr_win = &self.window_list[next_win_idx]; + curr_win.focus(); + self.cw_idx = next_win_idx; + } + } fn focus_current_window(&self) { - if let Some(win) = self.current_window() { - win.set_border_width(1); - win.set_border_color("red"); - } + self.current_window().map(|x| x.focus()); } fn unfocus_current_window(&self) { - if let Some(win) = self.current_window() { - win.set_border_width(1); - win.set_border_color("black"); - } + self.current_window().map(|x| x.unfocus()); } } diff --git a/src/main.rs b/src/main.rs index feda9e0..1374446 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,13 +9,30 @@ pub mod event; use dotwm::DotWM; use command::exec_cmd; use event::{Event,next_event}; + +use safe_x11::grab_key; + use std::ops::Deref; use std::process; +use std::collections::HashMap; use x11::xlib; +use x11::xlib::GrabModeAsync; +use x11::xlib::XEvent; use x11::keysym; -fn exec(_: &DotWM, _: xlib::XEvent, args: &[String]) -> bool { +/// Defines a callback to call no certains events. +pub type ExecFn = fn(&mut DotWM, XEvent, &[String]) -> bool; +type BindingHash = HashMap<(u32, u32), (ExecFn, Vec)>; + +fn exec_func(wm: &mut DotWM, bindings: &mut BindingHash, key: u32, modifiers: u32, ev: xlib::XEvent) { + if let Some(&(func, ref args)) = bindings.get(&(key, modifiers)) { + let v = args.clone(); + func(wm, ev, &v); + } +} + +fn exec(_: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool { if let Some(program) = args.first() { let mut prog_args = vec![]; for arg in args[1..].iter() { @@ -26,10 +43,8 @@ fn exec(_: &DotWM, _: xlib::XEvent, args: &[String]) -> bool { true } -fn move_win(wm: &DotWM, _: xlib::XEvent, args: &[String]) -> bool { - println!("Parsing x"); +fn move_win(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool { let x = args[0].parse::().unwrap(); - println!("Parsing y"); let y = args[1].parse::().unwrap(); if let Some(ref win) = wm.current_window() { win.move_offset(x, y); @@ -37,24 +52,62 @@ fn move_win(wm: &DotWM, _: xlib::XEvent, args: &[String]) -> bool { true } -fn quit_dotwm(_: &DotWM, _: xlib::XEvent, _: &[String]) -> bool { +fn resize_win(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool { + let w = args[0].parse::().unwrap(); + let h = args[1].parse::().unwrap(); + + if let Some(ref win) = wm.current_window() { + win.resize(w, h); + }; + + true +} + +fn focus_next(wm: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool { + wm.focus_next(); + true +} + +fn quit_dotwm(_: &mut DotWM, _: xlib::XEvent, _: &[String]) -> bool { process::exit(0); } +fn add_binding(wm: &mut DotWM, bindings: &mut BindingHash, + key: u32, modifiers: u32, func: ExecFn, args: &[&str]) { + grab_key(wm.display, key, modifiers, true, GrabModeAsync, GrabModeAsync); + let mut v = vec![]; + for arg in args { + v.push(arg.to_string()); + } + bindings.insert((key, modifiers), (func, v)); +} + fn main() { println!("Creating dotwm"); let mut dotwm = DotWM::new(); + let mut bindings: BindingHash = HashMap::new(); - dotwm.add_binding(keysym::XK_Return, xlib::Mod4Mask, exec, - &["xterm"]); - dotwm.add_binding(keysym::XK_p, xlib::Mod4Mask, exec, - &["dmenu_run"]); - dotwm.add_binding(keysym::XK_h, xlib::Mod4Mask, move_win, &["-10", "0"]); - dotwm.add_binding(keysym::XK_j, xlib::Mod4Mask, move_win, &["0", "10"]); - dotwm.add_binding(keysym::XK_k, xlib::Mod4Mask, move_win, &["0", "-10"]); - dotwm.add_binding(keysym::XK_l, xlib::Mod4Mask, move_win, &["10", "0"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_Return, xlib::Mod4Mask, exec, + &["xterm"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_p, xlib::Mod4Mask, exec, + &["dmenu_run"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_Tab, xlib::Mod4Mask, focus_next, &[]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_h, xlib::Mod4Mask, move_win, &["-10", "0"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_j, xlib::Mod4Mask, move_win, &["0", "10"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_k, xlib::Mod4Mask, move_win, &["0", "-10"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_l, xlib::Mod4Mask, move_win, &["10", "0"]); - dotwm.add_binding(keysym::XK_q, xlib::Mod4Mask | xlib::ShiftMask, quit_dotwm, &[]); + // Resize + add_binding(&mut dotwm,&mut bindings, keysym::XK_h, xlib::Mod4Mask | xlib::ControlMask, + resize_win, &["-10", "0"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_j, xlib::Mod4Mask | xlib::ControlMask, + resize_win, &["0", "10"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_k, xlib::Mod4Mask | xlib::ControlMask, + resize_win, &["0", "-10"]); + add_binding(&mut dotwm,&mut bindings, keysym::XK_l, xlib::Mod4Mask | xlib::ControlMask, + resize_win, &["10", "0"]); + + add_binding(&mut dotwm, &mut bindings, keysym::XK_q, xlib::Mod4Mask | xlib::ShiftMask, quit_dotwm, &[]); // Main loop loop { @@ -65,14 +118,20 @@ fn main() { let keysym = unsafe { xlib::XLookupKeysym(&mut e, 0) as u32 }; let mask = e.state; - dotwm.exec_func(keysym, mask, xlib::XEvent::from(e)); + exec_func(&mut dotwm, &mut bindings, keysym, mask, xlib::XEvent::from(e)); }, - Event::Create(e) => { - // XCreateWindowEvent - let create_event = xlib::XCreateWindowEvent::from(e); - dotwm.add_window(create_event.window); + Event::Map(e) => { + // If the window has override_redirect setted to true, this should not + // be handled by the wm. + let map_event = xlib::XMapEvent::from(e); + if map_event.override_redirect == 0 { + println!("Adding window"); + dotwm.add_window(map_event.window); + } else { + println!("Map event 0 :("); + } } - Event::Destroy(e) => { + Event::Unmap(e) => { dotwm.remove_window(e.window); }, Event::Enter(e) => { diff --git a/src/safe_x11/window.rs b/src/safe_x11/window.rs index d2fc9ea..24b5b62 100644 --- a/src/safe_x11/window.rs +++ b/src/safe_x11/window.rs @@ -83,9 +83,9 @@ impl XWindow { /// Returns the window attributes from certain window. pub fn attributes(&self) -> XWindowAttributes { unsafe { - let attrptr: *mut XWindowAttributes = uninitialized(); - XGetWindowAttributes(self.display, self.inner, attrptr); - ptr::read(attrptr) + let mut attrptr: XWindowAttributes = uninitialized(); + XGetWindowAttributes(self.display, self.inner, &mut attrptr); + attrptr } } @@ -94,10 +94,6 @@ impl XWindow { unsafe { let mut attributes: XWindowAttributes = uninitialized(); XGetWindowAttributes(self.display, self.inner, &mut attributes); - println!("Moving window({:x}), {} + {} = {}, {} + {} = {}", - self.inner as u64, - attributes.x, xoffset, attributes.x + xoffset, - attributes.y, yoffset, attributes.y + yoffset); XMoveWindow(self.display, self.inner, attributes.x + xoffset, attributes.y + yoffset); @@ -131,7 +127,7 @@ impl XWindow { } } - /// Raise the focus of the window. + /// Raise the focus of the window and set a border. pub fn focus(&self) { let attrs = self.attributes(); if attrs.map_state == IsViewable { @@ -140,5 +136,14 @@ impl XWindow { RevertToParent, CurrentTime) }; } + self.raise(); + self.set_border_width(1); + self.set_border_color("red"); + } + + /// Give a black border. + pub fn unfocus(&self) { + self.set_border_width(1); + self.set_border_color("black"); } } -- cgit v1.2.3-54-g00ecf