<commit_before>extern crate libc;

use x11::xlib;
use x11::xlib::Window;
use super::super::libx;

use super::config::Config;
use super::Container;
use super::Workspaces;
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    1
}

fn load_resource(mut context: &mut libx::Context) {
    use std::mem;
    use std::ffi;
    let screen = context.screen_num;
    let root = context.root;
    let display = context.display;
    let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
    // let gc = libx::create_gc(self.context, self.id, 0, values);
    let gc = libx::default_gc(*context, screen);

    unsafe {
        let black = xlib::XBlackPixel(display, screen);
        let white = xlib::XWhitePixel(display, screen);

        xlib::XSetLineAttributes(display, gc, 5, 0, 0, 0);

        let cmap = xlib::XDefaultColormap(display, screen);
        let mut color: xlib::XColor = mem::zeroed();
        let name = ffi::CString::new("blue").unwrap().as_ptr();
        let r = xlib::XParseColor(display, cmap, name, &mut color);
        xlib::XAllocColor(display, cmap, &mut color);

        context.gc = gc;
        context.focus_bg = black;
        context.focus_fg = color.pixel;
        context.unfocus_bg = black;
        context.unfocus_fg = black;
    }
}

pub struct WindowManager {
    pub context: libx::Context,
    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	let res = libx::open_display(None);
        let mut context = match res {
            Some(c) => {
                c
            }
            None => {
                panic!("can't open display")
            }
        };

	context.screen_num  = libx::default_screen(context);
	context.root = libx::root_window(context, context.screen_num);
        load_resource(&mut context);

	let mut wm = WindowManager {
            context: context,
            config: Config::load(),
            workspaces: Workspaces::new(context)
        };
        wm
    }

    pub fn clean(&mut self) {
        libx::close_display(self.context);
    }

    pub fn handle_create(&mut self, event: &xlib::XCreateWindowEvent) {
        if event.override_redirect != 0 {
            return;
        }

        let attrs = libx::get_window_attributes(self.context, event.window);
        println!("{} attr {} {}", event.window, attrs.width, attrs.height);
        // get window property
        let n = libx::get_text_property(self.context, event.window, xlib::XA_WM_NAME);
        match n {
            Some(s) => {debug!("create window {} for {}", event.window, s);}
            None => {}
        }

        // let atoms = libx::get_wm_protocols(self.context, event.window);
        // for a in atoms.iter() {
        //     println!("atom {}", a);
        //     let name = libx::get_atom_name(self.context, *a);
        //     match name {
        //         Some(n) => println!("name {}", n),
        //         None => println!("name {}", a),
        //     };
        // }
    }

    pub fn handle_destroy(&mut self, event: &xlib::XDestroyWindowEvent) {
        self.workspaces.remove_window(event.window);
        if self.workspaces.get_focus().is_none() {
            self.workspaces.set_focus(self.context.root);
        }
    }

    pub fn handle_map_request(&mut self, event: &xlib::XMapRequestEvent) {

        // add app top-level window to workspace
        // let window = Window::new(self.context, event.window);
        let manage = Workspaces::can_manage(self.context, event.window);

        if manage {
            debug!("top level window");
            let mut container = Container::from_id(self.context, event.window);
            container.map();
            // container.focus();
            // change attributes before display
            let mask = 0x420010;
            let mask = xlib::EnterWindowMask | xlib::PropertyChangeMask;
            libx::select_input(self.context, container.id, mask);

            if self.config.titlebar_height > 0 {
                container.titlebar_height = self.config.titlebar_height as usize;
            }
            self.workspaces.insert_window(container);
        }
        else {
            libx::map_window(self.context, event.window);
        }
    }

    pub fn handle_client_message(&mut self, event: &xlib::XClientMessageEvent) {
        println!("message type {}", event.message_type);
        let s = libx::get_atom_name(self.context, event.message_type);
        match s {
            Some(v) => println!("{}", &v),
            None => {}
        }

        match event.format {
            8 => {
                for i in 0..20 {
                    println!("{}", event.data.get_byte(i));
                }
            }
            16 => {
                for i in 0..10 {
                    println!("{}", event.data.get_short(i))
                }
            }
            32 => {
                for i in 0..5 {
                    let a = event.data.get_long(i);
                    if a != 0{
                        let s = libx::get_atom_name(self.context, a as xlib::Atom);
                        match s {
                            Some(v) => println!("{}", v),
                            None => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }

    pub fn handle_button_motion(&mut self, event: &xlib::XMotionEvent) {
        let (window, _) = libx::get_input_focus(self.context);
        if window != event.window {
            self.workspaces.set_focus(event.window);
        }
    }

    pub fn handle_button_press(&mut self, event: &xlib::XButtonEvent) {
        let id = match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let client = c.query_point(event.x, event.y);
                match client {
                    Some(c) => {
                        c.id
                    }
                    None => { return }
                }
            }
            None => { return }
        };
        self.workspaces.set_focus(id);
    }
    pub fn handle_key_release(&mut self, event: &xlib::XKeyEvent) {
        if event.state > 0 {
            let sym = libx::lookup_keysym(*event, 0);
            let b = handler::KeyBind {
                key: sym,
                mask: event.state,
            };
            debug!("key {} {}", event.state, sym);

            match self.config.bindsyms.get_mut(&b) {
                Some(handler) => {
                    handler.handle(&mut self.workspaces, self.context);
                }
                None => {<commit_msg>focus on client or self<commit_after>extern crate libc;

use x11::xlib;
use x11::xlib::Window;
use super::super::libx;

use super::config::Config;
use super::Container;
use super::Workspaces;
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    1
}

fn load_resource(mut context: &mut libx::Context) {
    use std::mem;
    use std::ffi;
    let screen = context.screen_num;
    let root = context.root;
    let display = context.display;
    let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
    // let gc = libx::create_gc(self.context, self.id, 0, values);
    let gc = libx::default_gc(*context, screen);

    unsafe {
        let black = xlib::XBlackPixel(display, screen);
        let white = xlib::XWhitePixel(display, screen);

        xlib::XSetLineAttributes(display, gc, 5, 0, 0, 0);

        let cmap = xlib::XDefaultColormap(display, screen);
        let mut color: xlib::XColor = mem::zeroed();
        let name = ffi::CString::new("blue").unwrap().as_ptr();
        let r = xlib::XParseColor(display, cmap, name, &mut color);
        xlib::XAllocColor(display, cmap, &mut color);

        context.gc = gc;
        context.focus_bg = black;
        context.focus_fg = color.pixel;
        context.unfocus_bg = black;
        context.unfocus_fg = black;
    }
}

pub struct WindowManager {
    pub context: libx::Context,
    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	let res = libx::open_display(None);
        let mut context = match res {
            Some(c) => {
                c
            }
            None => {
                panic!("can't open display")
            }
        };

	context.screen_num  = libx::default_screen(context);
	context.root = libx::root_window(context, context.screen_num);
        load_resource(&mut context);

	let mut wm = WindowManager {
            context: context,
            config: Config::load(),
            workspaces: Workspaces::new(context)
        };
        wm
    }

    pub fn clean(&mut self) {
        libx::close_display(self.context);
    }

    pub fn handle_create(&mut self, event: &xlib::XCreateWindowEvent) {
        if event.override_redirect != 0 {
            return;
        }

        let attrs = libx::get_window_attributes(self.context, event.window);
        println!("{} attr {} {}", event.window, attrs.width, attrs.height);
        // get window property
        let n = libx::get_text_property(self.context, event.window, xlib::XA_WM_NAME);
        match n {
            Some(s) => {debug!("create window {} for {}", event.window, s);}
            None => {}
        }

        // let atoms = libx::get_wm_protocols(self.context, event.window);
        // for a in atoms.iter() {
        //     println!("atom {}", a);
        //     let name = libx::get_atom_name(self.context, *a);
        //     match name {
        //         Some(n) => println!("name {}", n),
        //         None => println!("name {}", a),
        //     };
        // }
    }

    pub fn handle_destroy(&mut self, event: &xlib::XDestroyWindowEvent) {
        self.workspaces.remove_window(event.window);
        if self.workspaces.get_focus().is_none() {
            self.workspaces.set_focus(self.context.root);
        }
    }

    pub fn handle_map_request(&mut self, event: &xlib::XMapRequestEvent) {

        // add app top-level window to workspace
        // let window = Window::new(self.context, event.window);
        let manage = Workspaces::can_manage(self.context, event.window);

        if manage {
            debug!("top level window");
            let mut container = Container::from_id(self.context, event.window);
            container.map();
            // container.focus();
            // change attributes before display
            let mask = 0x420010;
            let mask = xlib::EnterWindowMask | xlib::PropertyChangeMask;
            libx::select_input(self.context, container.id, mask);

            if self.config.titlebar_height > 0 {
                container.titlebar_height = self.config.titlebar_height as usize;
            }
            self.workspaces.insert_window(container);
        }
        else {
            libx::map_window(self.context, event.window);
        }
    }

    pub fn handle_client_message(&mut self, event: &xlib::XClientMessageEvent) {
        println!("message type {}", event.message_type);
        let s = libx::get_atom_name(self.context, event.message_type);
        match s {
            Some(v) => println!("{}", &v),
            None => {}
        }

        match event.format {
            8 => {
                for i in 0..20 {
                    println!("{}", event.data.get_byte(i));
                }
            }
            16 => {
                for i in 0..10 {
                    println!("{}", event.data.get_short(i))
                }
            }
            32 => {
                for i in 0..5 {
                    let a = event.data.get_long(i);
                    if a != 0{
                        let s = libx::get_atom_name(self.context, a as xlib::Atom);
                        match s {
                            Some(v) => println!("{}", v),
                            None => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }

    pub fn handle_button_motion(&mut self, event: &xlib::XMotionEvent) {
        let (window, _) = libx::get_input_focus(self.context);
        if window != event.window {
            self.workspaces.set_focus(event.window);
        }
    }

    pub fn handle_button_press(&mut self, event: &xlib::XButtonEvent) {
        let id = match self.workspaces.get_container(event.window) {
            Some((_,container)) => {
                let client = container.query_point(event.x, event.y);
                match client {
                    Some(c) => {
                        c.id
                    }
                    None => { container.id }
                }
            }
            None => { return }
        };
        self.workspaces.set_focus(id);
    }
    pub fn handle_key_release(&mut self, event: &xlib::XKeyEvent) {
        if event.state > 0 {
            let sym = libx::lookup_keysym(*event, 0);
            let b = handler::KeyBind {
                key: sym,
                mask: event.state,
            };
            debug!("key {} {}", event.state, sym);

            match self.config.bindsyms.get_mut(&b) {
                Some(handler) => {
                    handler.handle(&mut self.workspaces, self.context);
                }
                None => {
{'fraction_non_alphanumeric': 0.13349408154318282, 'fraction_numerical': 0.005114715767938039, 'mean_word_length': 1.6638769949396652, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7558672', 'n_tokens_mistral': 4123, 'n_tokens_neox': 3968, 'n_words': 842}