summaryrefslogtreecommitdiff
path: root/src/dotwm.rs
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2015-11-29 11:57:19 -0300
committerMatias Linares <matiaslina@openmailbox.org>2015-11-29 11:57:48 -0300
commitd5e55aab6499a89e9dfaf5b976938bfe3e2f6aee (patch)
tree52efc28076c31fdd2522ed8b7871a7dd99ad0c87 /src/dotwm.rs
parente1ec354306742a5804a20e2651cf49945cd17287 (diff)
downloaddotwm-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.rs112
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 {