aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2015-12-07 16:19:36 -0300
committerMatias Linares <matiaslina@openmailbox.org>2015-12-07 16:19:36 -0300
commit69f8194da778a692b6b0c14f43d9611c2072e8ba (patch)
tree8d9f252bf7a6db515a05800a73b35b21d1692cfb
parent12faa87415d91820503b6b1c98ebabbddc50d665 (diff)
downloaddotwm-69f8194da778a692b6b0c14f43d9611c2072e8ba.tar.gz
Implement desktops.
It's somewhat buggy. But works :). There're 2 desktops only for now, maybe later I will implement something more dynamic
-rwxr-xr-xautostart7
-rw-r--r--src/command.rs13
-rw-r--r--src/desktop.rs178
-rw-r--r--src/dotwm.rs174
-rw-r--r--src/event.rs4
-rw-r--r--src/main.rs3
-rw-r--r--src/safe_x11/mod.rs7
-rw-r--r--src/safe_x11/window.rs20
-rw-r--r--src/socket/parser.rs4
9 files changed, 291 insertions, 119 deletions
diff --git a/autostart b/autostart
index 0a155db..3fc3658 100755
--- a/autostart
+++ b/autostart
@@ -5,6 +5,8 @@ dot() {
printf "%s " $@ | netcat -U dotwm.sock
}
+nitrogen --restore &
+
dot bind Mod4 p exec dmenu_run
dot bind Mod4 Return exec xterm
dot bind Mod4 f fullscreen
@@ -29,11 +31,12 @@ dot bind Mod4 j move-win 0 10
dot bind Mod4 k move-win 0 -10
dot bind Mod4 l move-win 10 0
-
dot bind Mod4-Shift c close-win
-
dot bind Mod4 Tab focus-next
+dot bind Mod4 1 change-desktop 0
+dot bind Mod4 2 change-desktop 1
+
#netcat -U dotwm.sock <<EOF
#bind Mod4 p exec dmenu_run
#bind Mod4 Return exec xterm
diff --git a/src/command.rs b/src/command.rs
index f351e14..8f7218e 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -95,8 +95,7 @@ pub fn move_win_to(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
if let Some(ref win) = wm.current_window() {
match win.move_to(x, y) {
Ok(()) => true,
- Err(e) => {
- println!("{}", e);
+ Err(_) => {
false
}
}
@@ -194,7 +193,7 @@ pub fn resize_win_sticky(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bo
let val = xgeo.iter().skip_while(|&a| *a <= win_right).next();
if let Some(xpoint) = val {
- let new_width = (*xpoint - attrs.x);
+ let new_width = *xpoint - attrs.x;
let _ = win.resize_to(new_width, attrs.height);
}
},
@@ -205,7 +204,6 @@ pub fn resize_win_sticky(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bo
let val = ygeo.iter().skip_while(|&a| *a >= attrs.y + attrs.height).next();
if let Some(v) = val {
let diff = attrs.height - (*v - attrs.y);
- println!("Resizing to {}x{}", attrs.width, diff);
if *v - attrs.y > 0 {
let _ = win.resize_to(attrs.width, attrs.height - diff);
}
@@ -219,7 +217,6 @@ pub fn resize_win_sticky(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bo
let val = ygeo.iter().skip_while(|&a| *a <= win_bot).next();
if let Some(v) = val {
let new_height = *v - attrs.y;
- println!("Resizing to {}x{}", attrs.width, new_height);
let _ = win.resize_to(attrs.width, new_height);
}
},
@@ -274,3 +271,9 @@ pub fn add_binding(wm: &mut DotWM, bindings: &mut BindingHash,
}
bindings.insert((key, modifiers), (func, v));
}
+
+pub fn change_desktop(wm: &mut DotWM, _: xlib::XEvent, args: &[String]) -> bool {
+ let num = args[0].parse::<usize>().unwrap();
+ wm.change_desktop(num);
+ true
+}
diff --git a/src/desktop.rs b/src/desktop.rs
new file mode 100644
index 0000000..7d2a8a5
--- /dev/null
+++ b/src/desktop.rs
@@ -0,0 +1,178 @@
+use x11::xlib;
+use x11::xlib::{
+ Display,
+};
+
+use safe_x11::window::XWindow;
+use safe_x11::{
+ screen_size,
+};
+
+pub struct Desktop {
+ #[allow(dead_code)]
+ display: *mut Display,
+ #[allow(dead_code)]
+ tag: String,
+ window_list: Vec<XWindow>,
+ cw_idx: usize,
+}
+
+impl Desktop {
+ pub fn new(display: *mut Display, tag: &'static str) -> Desktop {
+ Desktop {
+ display: display,
+ tag: String::from(tag),
+ window_list: vec![],
+ cw_idx: 0,
+ }
+ }
+
+ pub fn current_window(&self) -> Option<&XWindow> {
+ if self.cw_idx < self.window_list.len() {
+ self.window_list.get(self.cw_idx)
+ } else {
+ None
+ }
+ }
+
+ pub fn current_window_mut(&mut self) -> Option<&mut XWindow> {
+ if self.cw_idx < self.window_list.len() {
+ self.window_list.get_mut(self.cw_idx)
+ } else {
+ None
+ }
+ }
+
+ /// Add a window to the current desktop
+ pub fn add_window(&mut self, w: xlib::Window) {
+ if self.find_window(w).is_some() {
+ return;
+ }
+ self.unfocus_current_window();
+ if let Some(w) = XWindow::new(self.display, w) {
+ w.select_input(xlib::EnterWindowMask);
+ self.window_list.push(w);
+ // Last windows get focus.
+ self.focus_current_window();
+ }
+ }
+
+ /// Remove a window.
+ pub fn remove_window(&mut self, w: xlib::Window) {
+ let pos = self.window_list.iter().position(|xw| xw.inner == w);
+
+ match pos {
+ Some(idx) => {
+ let new_idx = if idx == 0 { usize::max_value() } else { idx - 1 };
+ self.window_list.remove(idx);
+ self.cw_idx = new_idx;
+ self.focus_current_window();
+ },
+ None => (),
+ }
+ }
+
+ pub fn change_focus_of(&mut self, idx: usize) {
+ let w = &self.window_list[idx];
+ self.unfocus_current_window();
+ self.cw_idx = idx;
+ w.set_border_width(1);
+ w.set_border_color("red");
+ 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) {
+ self.current_window().map(|x| x.focus());
+ }
+
+ fn unfocus_current_window(&self) {
+ self.current_window().map(|x| x.unfocus());
+ }
+
+ /// Get a list of the geometries for every window in the screen (including
+ /// the screen borders. The form is (x, y).
+ ///
+ /// # Example
+ ///
+ /// Having a screen of 800x600, and a window on 10(x), 10(y) with dimensions
+ /// 400(width) and 300(height):
+ ///
+ /// ```
+ /// for (x, y) in dotwm.geometries() {
+ /// println!("x: {} - y: {}", x, y);
+ /// }
+ /// ```
+ ///
+ /// The output will be:
+ ///
+ /// ```
+ /// (0,0)
+ /// (800, 600)
+ /// (10, 10)
+ /// (410, 310)
+ /// ```
+ pub fn geometries(&self) -> Vec<(i32,i32)> {
+ let (screen_width, screen_height) = screen_size(self.display);
+ let mut result: Vec<(i32,i32)> = vec![
+ (0, 0),
+ (screen_width as i32, screen_height as i32),
+ ];
+
+ for w in self.window_list.iter() {
+ let attrs = w.attributes();
+ result.push((attrs.x, attrs.y));
+ result.push((attrs.x + attrs.width, attrs.y + attrs.height));
+ }
+
+ result
+ }
+
+ pub fn x_geometries(&self) -> Vec<i32> {
+ self.geometries().iter().map(|x| x.0).collect()
+ }
+
+ pub fn y_geometries(&self) -> Vec<i32> {
+ self.geometries().iter().map(|x| x.1).collect()
+ }
+
+
+ pub fn show_windows(&self) {
+ for win in &self.window_list {
+ win.map();
+ }
+ }
+
+ pub fn hide_windows(&self) {
+ for win in &self.window_list {
+ win.unmap();
+ }
+ }
+}
diff --git a/src/dotwm.rs b/src/dotwm.rs
index b3ed782..2781ae8 100644
--- a/src/dotwm.rs
+++ b/src/dotwm.rs
@@ -12,26 +12,36 @@ use safe_x11::{
open_display,
close_display,
atom,
- screen_size,
};
-use safe_x11::window::XWindow;
+use safe_x11::window::{
+ XWindow,
+};
+use desktop::Desktop;
use std::ptr;
use std::process::exit;
use std::mem::uninitialized;
use std::collections::HashMap;
use libc::c_int;
+use libc::c_char;
#[allow(unused_variables)]
unsafe extern "C" fn error_handler(d: *mut Display, evptr: *mut XErrorEvent) -> c_int {
- println!("ERRORR");
+ println!("ERROR");
let ev = ptr::read(evptr);
if ev.error_code == xlib::BadAccess {
println!("Another widnow manager is running :C");
exit(1);
}
+ println!("Error code {:?}", ev.error_code);
+ let mut buf: [i8; 1000] = [0i8; 1000];
+ let bufptr = buf.as_mut_ptr();
+ xlib::XGetErrorText(d, ev.error_code as c_int, bufptr as *mut c_char, 1000);
+ let string = String::from_raw_parts(bufptr as *mut u8, 1000, 1000);
+ println!("Error: {}", string);
+
0
}
@@ -53,8 +63,6 @@ pub enum NetAtom {
pub struct DotWM {
/// Reference to the X display.
pub display: *mut Display,
- /// References to all the windows.
- pub window_list: Vec<XWindow>,
/// Check if the window manager needs to end.
pub finish: bool,
/// Vec holding atoms for ICCCM support
@@ -62,8 +70,9 @@ pub struct DotWM {
/// Vec holding atoms for EWHM support
pub netatoms: HashMap<NetAtom, Atom>,
/// Number of the active desctop
- current_desktop: usize,
- cw_idx: usize,
+ pub desktop_idx: usize,
+ /// Desktops
+ pub desktops: Vec<Desktop>,
}
/// DotWM state.
@@ -106,68 +115,64 @@ impl DotWM {
DotWM {
display: d,
- cw_idx: 0,
finish: false,
wmatoms: wmatoms,
netatoms: netatoms,
- current_desktop: 0,
- window_list: vec![],
+ desktop_idx: 0,
+ desktops: vec![
+ Desktop::new(d, "main"),
+ Desktop::new(d, "other")
+ ],
}
}
+ /// this should always return a desktop.
+ pub fn current_desktop_mut(&mut self) -> &mut Desktop {
+ self.desktops.get_mut(self.desktop_idx).unwrap()
+ }
+
+ pub fn current_desktop(&self) -> &Desktop {
+ self.desktops.get(self.desktop_idx).unwrap()
+ }
+
+ /// Add a window to the current desktop
pub fn add_window(&mut self, w: xlib::Window) {
- self.unfocus_current_window();
- if let Some(w) = XWindow::new(self.display, w) {
- w.select_input(xlib::EnterWindowMask);
- self.window_list.push(w);
- // Last windows get focus.
- self.cw_idx = self.window_list.len() - 1;
- self.focus_current_window();
- }
+ self.current_desktop_mut().add_window(w);
}
pub fn current_window(&self) -> Option<&XWindow> {
- if self.cw_idx < self.window_list.len() {
- self.window_list.get(self.cw_idx)
+ let d = self.desktops.get(self.desktop_idx);
+ if let Some(desktop) = d {
+ desktop.current_window()
} else {
None
}
}
pub fn current_window_mut(&mut self) -> Option<&mut XWindow> {
- if self.cw_idx < self.window_list.len() {
- self.window_list.get_mut(self.cw_idx)
+ let d = self.desktops.get_mut(self.desktop_idx);
+ if let Some(desktop) = d {
+ desktop.current_window_mut()
} else {
None
}
}
pub fn remove_window(&mut self, w: xlib::Window) {
- let pos = self.window_list.iter().position(|xw| xw.inner == w);
-
- match pos {
- Some(idx) => {
- let new_idx = if idx == 0 { usize::max_value() } else { idx - 1 };
- self.window_list.remove(idx);
- self.cw_idx = new_idx;
- self.focus_current_window();
- },
- None => (),
- }
+ //let iter = self.desktops.iter_mut();
+ //for desktop in iter {
+ // desktop.remove_window(w);
+ //}
+ self.current_desktop_mut().remove_window(w);
}
pub fn change_focus_of(&mut self, idx: usize) {
- let w = &self.window_list[idx];
- self.unfocus_current_window();
- self.cw_idx = idx;
- w.set_border_width(1);
- w.set_border_color("red");
- w.raise();
+ self.current_desktop_mut().change_focus_of(idx);
}
/// 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)
+ self.current_desktop().find_window(w)
}
/// Focus the next window.
@@ -175,82 +180,47 @@ impl DotWM {
/// 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;
- }
+ self.current_desktop_mut().focus_next();
}
- fn focus_current_window(&self) {
- self.current_window().map(|x| x.focus());
+ pub fn x_geometries(&self) -> Vec<i32> {
+ self.current_desktop().geometries().iter().map(|x| x.0).collect()
}
- fn unfocus_current_window(&self) {
- self.current_window().map(|x| x.unfocus());
+ pub fn y_geometries(&self) -> Vec<i32> {
+ self.current_desktop().geometries().iter().map(|x| x.1).collect()
}
- /// Get a list of the geometries for every window in the screen (including
- /// the screen borders. The form is (x, y).
- ///
- /// # Example
- ///
- /// Having a screen of 800x600, and a window on 10(x), 10(y) with dimensions
- /// 400(width) and 300(height):
- ///
- /// ```
- /// for (x, y) in dotwm.geometries() {
- /// println!("x: {} - y: {}", x, y);
- /// }
- /// ```
- ///
- /// The output will be:
- ///
- /// ```
- /// (0,0)
- /// (800, 600)
- /// (10, 10)
- /// (410, 310)
- /// ```
- pub fn geometries(&self) -> Vec<(i32,i32)> {
- let (screen_width, screen_height) = screen_size(self.display);
- let mut result: Vec<(i32,i32)> = vec![
- (0, 0),
- (screen_width as i32, screen_height as i32),
- ];
-
- for w in self.window_list.iter() {
- let attrs = w.attributes();
- result.push((attrs.x, attrs.y));
- result.push((attrs.x + attrs.width, attrs.y + attrs.height));
+ pub fn change_desktop(&mut self,desktop: usize) {
+ if desktop > self.desktops.len() {
+ return;
}
- result
- }
-
- pub fn x_geometries(&self) -> Vec<i32> {
- self.geometries().iter().map(|x| x.0).collect()
- }
+ if desktop == self.desktop_idx {
+ return;
+ }
- pub fn y_geometries(&self) -> Vec<i32> {
- self.geometries().iter().map(|x| x.1).collect()
+ let new_desktop = &self.desktops[desktop];
+ let old_desktop = &self.desktops[self.desktop_idx];
+
+ new_desktop.show_windows();
+ // let mut do_not_propagate: xlib::XSetWindowAttributes = unsafe { uninitialized() };
+ // let root = root_window(self.display);
+ // do_not_propagate.do_not_propagate_mask = xlib::SubstructureNotifyMask;
+ // change_window_attributes(self.display, root, xlib::CWEventMask,
+ // &mut do_not_propagate);
+
+ old_desktop.hide_windows();
+ // let mut root_mask: xlib::XSetWindowAttributes = unsafe { uninitialized() };
+ // root_mask.event_mask = xlib::SubstructureRedirectMask|xlib::ButtonPressMask|xlib::SubstructureNotifyMask|xlib::PropertyChangeMask;
+ // change_window_attributes(self.display, root, xlib::CWEventMask,
+ // &mut root_mask);
+ self.desktop_idx = desktop;
}
}
impl Drop for DotWM {
fn drop(&mut self) {
- println!("Closing display");
close_display(self.display);
}
}
diff --git a/src/event.rs b/src/event.rs
index 6f5c427..3832a36 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -121,8 +121,8 @@ pub fn next_event(display: *mut Display) -> Event {
18 => Event::Unmap(XUnmapEvent::from(ev)),
19 => Event::Map(XMapEvent::from(ev)),
22 => Event::Configure(XConfigureEvent::from(ev)),
- e => {
- println!("Unknown event {}", e);
+ _ => {
+ // println!("Unknown event {}", e);
Event::NoEvent
},
}
diff --git a/src/main.rs b/src/main.rs
index 21425c8..2a00ff5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,6 +11,7 @@ pub mod command;
pub mod dotwm;
pub mod event;
pub mod socket;
+pub mod desktop;
use dotwm::DotWM;
use command::*;
@@ -57,8 +58,6 @@ fn main() {
let map_event = xlib::XMapEvent::from(e);
if map_event.override_redirect == 0 {
dotwm.add_window(map_event.window);
- } else {
- println!("Map event 0 :(");
}
}
Event::Unmap(e) => {
diff --git a/src/safe_x11/mod.rs b/src/safe_x11/mod.rs
index 2e368aa..9e5859a 100644
--- a/src/safe_x11/mod.rs
+++ b/src/safe_x11/mod.rs
@@ -78,10 +78,8 @@ impl<'a> fmt::Display for XSafeError<'a> {
///
pub fn open_display(display: &str) -> Result<*mut Display, XSafeError> {
let d = if display == "" {
- println!("Opening default display");
unsafe { xlib::XOpenDisplay(0x0 as *const i8) }
} else {
- println!("Opening {}", display);
let cstr = try!(CString::new(display));
unsafe { xlib::XOpenDisplay(cstr.as_ptr()) }
};
@@ -121,6 +119,10 @@ pub fn screen_size(display: *mut Display) -> (u32, u32) {
(dw, dh)
}
+pub fn root_window(display: *mut Display) -> Window {
+ unsafe { xlib::XDefaultRootWindow(display) }
+}
+
/// Grab pointer buttons.
///
/// # Example
@@ -159,7 +161,6 @@ pub fn grab_button(display: *mut Display, button: u32, modifiers: u32,
///
pub fn grab_key(display: *mut Display, key: u32, modifiers: u32, owner_events: bool,
pointer_mode: i32, keyboard_mode: i32) {
- println!("Modifiers {:x}", modifiers);
unsafe {
let default_win = xlib::XDefaultRootWindow(display);
let keycode: i32 = xlib::XKeysymToKeycode(display, key as u64) as i32;
diff --git a/src/safe_x11/window.rs b/src/safe_x11/window.rs
index 34cce64..8a3bab4 100644
--- a/src/safe_x11/window.rs
+++ b/src/safe_x11/window.rs
@@ -20,6 +20,9 @@ use x11::xlib::{
ClientMessage,ClientMessageData, NoEventMask,
XChangeProperty,
+ XChangeWindowAttributes, XSetWindowAttributes,
+
+ XMapWindow, XUnmapWindow,
};
use std::ptr;
@@ -218,7 +221,6 @@ impl XWindow {
let fs_atom_slice: &[Atom; 1] = &[fs_atom];
let fs_atom_ptr: *const u8 = unsafe { transmute(fs_atom_slice) };
- println!("Changing property!");
unsafe {
XChangeProperty(self.display, self.inner, wm_state_atom,
XA_ATOM, 32, PropModeReplace, fs_atom_ptr,
@@ -227,11 +229,25 @@ impl XWindow {
}
if fullscreen {
- println!("resizing!");
self.move_resize(0, 0, dw, dh);
self.set_border_width(0);
} else {
self.set_border_width(1);
}
}
+
+ pub fn map(&self) {
+ unsafe { XMapWindow(self.display, self.inner); }
+ }
+
+ pub fn unmap(&self) {
+ unsafe { XUnmapWindow(self.display, self.inner); }
+ }
+}
+
+pub fn change_window_attributes(display: *mut xlib::Display, win: Window, mask: u64,
+ window_attribs: *mut XSetWindowAttributes) {
+ unsafe {
+ XChangeWindowAttributes(display, win, mask, window_attribs);
+ }
}
diff --git a/src/socket/parser.rs b/src/socket/parser.rs
index bd73ff6..30487d8 100644
--- a/src/socket/parser.rs
+++ b/src/socket/parser.rs
@@ -22,7 +22,6 @@ macro_rules! simple_try {
}
fn modifier_from<'a>(s: &'a str) -> Result<u32, &'static str> {
- println!("Getted modifier {}", s);
match s {
"Mod1" => Ok(xlib::Mod1Mask),
"Mod2" => Ok(xlib::Mod2Mask),
@@ -99,6 +98,8 @@ fn key<'a>(s: &'a str) -> Result<u32, &'static str> {
"X" => Ok(keysym::XK_X),
"Y" => Ok(keysym::XK_Y),
"Z" => Ok(keysym::XK_Z),
+ "1" => Ok(keysym::XK_1),
+ "2" => Ok(keysym::XK_2),
"Tab" => Ok(keysym::XK_Tab),
"Return" => Ok(keysym::XK_Return),
_ => Err("unknown key"),
@@ -116,6 +117,7 @@ fn func<'a>(s: &'a str) -> Result<ExecFn, &'static str> {
"focus-next" => Ok(focus_next),
"close-win" => Ok(close_win),
"fullscreen" => Ok(fullscreen),
+ "change-desktop" => Ok(change_desktop),
"quit" => Ok(quit_dotwm),
_ => Err("unknown function"),
}