tileme 0.0.3

(Not yet) A tiling window manager for Windows 10
use crate::windows::Window;
use crate::ring::{Ring, Selector};
use winapi::shared::windef::HWND;
use winapi::um::winuser::{SetForegroundWindow, GetForegroundWindow, IsIconic};

#[derive(Debug)]
pub struct VirtualDesktop {
    pub(crate) name: String,
    windows: Ring<Window>,
    minimized: Ring<Window>,
}

impl PartialEq for VirtualDesktop {
    fn eq(&self, other: &Self) -> bool {
        // TODO: better way to handle it?
        self.name == other.name
    }
}

impl VirtualDesktop {
    /// Construct a new Workspace with the given name and choice of Layouts
    pub fn new(name: impl Into<String>) -> VirtualDesktop {
        VirtualDesktop {
            name: name.into(),
            windows: Ring::new(Vec::new()),
            minimized: Ring::new(Vec::new()),
        }
    }

    /// Add a window to virtual desktop
    pub fn push_window(&mut self, window: Window) {
        let minimized = unsafe { IsIconic(window.hwnd()) } > 0;
        if minimized {
            self.minimized.push(window);
        } else {
            self.windows.push(window)
        }
    }

    /// Remove a window from virtual desktop
    pub fn pull_window_by_hwnd(&mut self, hwnd: HWND) -> Option<Window> {
        let condition = |window: &Window| window.hwnd() == hwnd;
        let selector = Selector::Condition(&condition);
        self.windows.remove(&selector).or(self.minimized.remove(&selector))
    }

    /// Sets a focused window on this virtual desktop, if present
    pub fn set_focus_by_hwnd(&mut self, hwnd: HWND) {
        let condition = |window: &Window| window.hwnd() == hwnd;
        let selector = Selector::Condition(&condition);
        self.windows.focus(&selector);
    }

    pub fn set_minimized(&mut self, hwnd: HWND) {
        let condition = |window: &Window| window.hwnd() == hwnd;
        let selector = Selector::Condition(&condition);
        match self.windows.remove(&selector) {
            Some(window) => self.minimized.push(window),
            None => {
                let i = self.minimized.index(&selector);
                if i.is_none() {
                    println!("Virtual desktop `{}` was requested to set window {:?} minimized, \
                              but it is not present there!", self.name, hwnd);
                }
            }
        }
    }

    pub fn set_unminimized(&mut self, hwnd: HWND) {
        let condition = |window: &Window| window.hwnd() == hwnd;
        let selector = Selector::Condition(&condition);
        match self.minimized.remove(&selector) {
            Some(window) => self.windows.push(window),
            None => {
                let i = self.windows.index(&selector);
                if i.is_none() {
                    println!("Virtual desktop `{}` was requested to set window {:?} unminimized, \
                              but it is not present there!", self.name, hwnd);
                }
            }
        }
    }

    /// Grab a focus to the focused window of this virtual desktop.
    /// If the virtual desktop has zero windows, this function will do nothing.
    pub fn grab_focus(&self) {
        let maybe_focused = self.windows.focused();
        match maybe_focused {
            Some(window) => {
                let result = unsafe{ SetForegroundWindow(window.hwnd()) };
                if result == 0 {
                    println!("Failed to grab focus on {:?}", window);
                }
            },
            None => {},
        }
    }

    /// Ensure that focus is set correctly
    pub(crate) fn update_focus(&mut self) {
        self.set_focus_by_hwnd(unsafe{ GetForegroundWindow() });
    }
}