summaryrefslogtreecommitdiff
path: root/src/desktop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/desktop.rs')
-rw-r--r--src/desktop.rs178
1 files changed, 178 insertions, 0 deletions
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();
+ }
+ }
+}