summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotwm.rs49
-rw-r--r--src/main.rs99
-rw-r--r--src/safe_x11/window.rs21
3 files changed, 121 insertions, 48 deletions
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<String>)>,
cw_idx: usize,
pub window_list: Vec<XWindow>,
}
@@ -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<usize> {
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<String>)>;
+
+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::<i32>().unwrap();
- println!("Parsing y");
let y = args[1].parse::<i32>().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::<i32>().unwrap();
+ let h = args[1].parse::<i32>().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");
}
}