diff options
author | Matias Linares <matiaslina@openmailbox.org> | 2015-11-29 11:57:19 -0300 |
---|---|---|
committer | Matias Linares <matiaslina@openmailbox.org> | 2015-11-29 11:57:48 -0300 |
commit | d5e55aab6499a89e9dfaf5b976938bfe3e2f6aee (patch) | |
tree | 52efc28076c31fdd2522ed8b7871a7dd99ad0c87 /src/dotwm.rs | |
parent | e1ec354306742a5804a20e2651cf49945cd17287 (diff) | |
download | dotwm-d5e55aab6499a89e9dfaf5b976938bfe3e2f6aee.tar.gz |
Begin ef EWMH support and sticky movement
The implementationn of the EWMH and ICCCM support is incomplete. I need to
check how to implement on the right way.
Diffstat (limited to 'src/dotwm.rs')
-rw-r--r-- | src/dotwm.rs | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/src/dotwm.rs b/src/dotwm.rs index cd909b5..b3ed782 100644 --- a/src/dotwm.rs +++ b/src/dotwm.rs @@ -4,11 +4,15 @@ use x11::xlib; use x11::xlib::{ Display, XErrorEvent, + Atom, + XChangeProperty, }; use safe_x11::{ open_display, close_display, + atom, + screen_size, }; use safe_x11::window::XWindow; @@ -16,6 +20,7 @@ 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)] @@ -30,6 +35,21 @@ unsafe extern "C" fn error_handler(d: *mut Display, evptr: *mut XErrorEvent) -> 0 } +#[derive(Hash,Eq,PartialEq)] +pub enum WmAtom { + Protocols, + DeleteWindow, +} + +#[derive(Hash,Eq,PartialEq)] +pub enum NetAtom { + NetSupported, + NetFullscreen, + NetWmState, + NetActive, +} + +/// State of the window manager. pub struct DotWM { /// Reference to the X display. pub display: *mut Display, @@ -37,7 +57,12 @@ pub struct DotWM { pub window_list: Vec<XWindow>, /// Check if the window manager needs to end. pub finish: bool, - // Map with the keys as (key, mod) + /// Vec holding atoms for ICCCM support + pub wmatoms: HashMap<WmAtom, Atom>, + /// Vec holding atoms for EWHM support + pub netatoms: HashMap<NetAtom, Atom>, + /// Number of the active desctop + current_desktop: usize, cw_idx: usize, } @@ -47,18 +72,45 @@ impl DotWM { pub fn new() -> DotWM { let d = open_display("").unwrap(); unsafe { xlib::XSetErrorHandler(Some(error_handler)) }; - // Some testings. + + // Add substructure notify mask + let root = unsafe { xlib::XDefaultRootWindow(d) }; + unsafe { - let root = xlib::XDefaultRootWindow(d); let mut attrs: xlib::XSetWindowAttributes = uninitialized(); attrs.event_mask = xlib::SubstructureNotifyMask; xlib::XChangeWindowAttributes(d, root, xlib::CWEventMask, &mut attrs); } + // Get the wmatoms + let mut wmatoms = HashMap::new(); + wmatoms.insert(WmAtom::Protocols, atom(d, "WM_PROTOCOLS")); + wmatoms.insert(WmAtom::DeleteWindow, atom(d, "WM_DELETE_WINDOW")); + + // Get the netatoms + let mut netatoms = HashMap::new(); + netatoms.insert(NetAtom::NetSupported, atom(d, "_NET_SUPPORTED")); + netatoms.insert(NetAtom::NetFullscreen, atom(d, "_NET_WM_STATE_FULLSCREEN")); + netatoms.insert(NetAtom::NetWmState, atom(d, "_NET_ACTIVE_WINDOW")); + netatoms.insert(NetAtom::NetActive, atom(d, "_NET_WM_STATE")); + + // Propagate EWHM support + unsafe { + let atomvec: Vec<&Atom> = netatoms.values().collect(); + let len: i32 = netatoms.len() as i32; + let atomptr = atomvec.as_ptr(); + + XChangeProperty(d, root, netatoms[&NetAtom::NetSupported], xlib::XA_ATOM, + 32, xlib::PropModeReplace, atomptr as *const u8, len); + } + DotWM { display: d, cw_idx: 0, finish: false, + wmatoms: wmatoms, + netatoms: netatoms, + current_desktop: 0, window_list: vec![], } } @@ -82,6 +134,14 @@ impl DotWM { } } + 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 + } + } + pub fn remove_window(&mut self, w: xlib::Window) { let pos = self.window_list.iter().position(|xw| xw.inner == w); @@ -140,6 +200,52 @@ impl DotWM { 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() + } } impl Drop for DotWM { |