From 05bfd598a060beafe1a20ff759e499987f1ce87b Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Mon, 9 Nov 2015 01:33:33 -0300 Subject: Focus handling. For now this have some bugs. Some complex programs (i.e. thunar, firefox) will spawn a lot of XCreateEvents and the last window it's not focused correctly. Also the enter notify should work on an input instead hovering the window --- src/dotwm.rs | 37 ++++++++++++++++++++++++++++++++++++- src/event.rs | 8 ++++++++ src/main.rs | 13 ++++++++++++- src/safe_x11/mod.rs | 1 - src/safe_x11/window.rs | 2 +- 5 files changed, 57 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/dotwm.rs b/src/dotwm.rs index 2d64584..77f09b3 100644 --- a/src/dotwm.rs +++ b/src/dotwm.rs @@ -104,14 +104,18 @@ impl DotWM { } pub fn add_window(&mut self, w: xlib::Window) { + 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.cw_idx = self.window_list.len() - 1; + self.focus_current_window(); } } pub fn current_window(&self) -> Option<&XWindow> { + println!("trying to get {} from list of len {}", self.cw_idx, self.window_list.len()); if self.cw_idx < self.window_list.len() { self.window_list.get(self.cw_idx) } else { @@ -121,15 +125,46 @@ impl DotWM { pub fn remove_window(&mut self, w: xlib::Window) { let pos = self.window_list.iter().position(|xw| xw.inner == w); + println!("Removing widnow {}: pos: {:?}", w, pos); match pos { Some(idx) => { + let new_idx = if idx == 0 { usize::max_value() } else { idx - 1 }; self.window_list.remove(idx); - self.cw_idx = usize::max_value(); + 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(); + } + + pub fn find_window(&self, w: xlib::Window) -> Option { + self.window_list.iter().position(|xw| xw.inner == w) + } + + + fn focus_current_window(&self) { + if let Some(win) = self.current_window() { + win.set_border_width(1); + win.set_border_color("red"); + } + } + + fn unfocus_current_window(&self) { + if let Some(win) = self.current_window() { + win.set_border_width(1); + win.set_border_color("black"); + } + } } impl Drop for DotWM { diff --git a/src/event.rs b/src/event.rs index e15ee18..366ca28 100644 --- a/src/event.rs +++ b/src/event.rs @@ -6,6 +6,8 @@ use x11::xlib::{ XCrossingEvent, XCreateWindowEvent, XDestroyWindowEvent, + XUnmapEvent, + XMapEvent, XConfigureEvent, }; @@ -24,6 +26,8 @@ pub enum Event { Generic(XEvent), Create(XCreateWindowEvent), Destroy(XDestroyWindowEvent), + Unmap(XUnmapEvent), + Map(XMapEvent), Configure(XConfigureEvent), NoEvent } @@ -39,6 +43,8 @@ impl fmt::Debug for Event { &Event::Leave(ev) => format!("Enter({})", XEvent::from(ev).get_type()), &Event::Create(ev) => format!("Create({})", XEvent::from(ev).get_type()), &Event::Destroy(ev) => format!("Destroy({})", XEvent::from(ev).get_type()), + &Event::Unmap(ev) => format!("Unmap({})", XEvent::from(ev).get_type()), + &Event::Map(ev) => format!("Map({})", XEvent::from(ev).get_type()), &Event::Configure(ev) => format!("Configure({})", XEvent::from(ev).get_type()), &Event::NoEvent => format!("NoEvent"), }; @@ -60,6 +66,8 @@ pub fn next_event(display: *mut Display) -> Event { 8 => Event::Leave(XCrossingEvent::from(ev)), 16 => Event::Create(XCreateWindowEvent::from(ev)), 17 => Event::Destroy(XDestroyWindowEvent::from(ev)), + 18 => Event::Unmap(XUnmapEvent::from(ev)), + 19 => Event::Map(XMapEvent::from(ev)), 22 => Event::Configure(XConfigureEvent::from(ev)), e => { println!("Unknown event {}", e); diff --git a/src/main.rs b/src/main.rs index c89544d..feda9e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,8 @@ fn main() { dotwm.add_binding(keysym::XK_Return, xlib::Mod4Mask, exec, &["xterm"]); + dotwm.add_binding(keysym::XK_p, xlib::Mod4Mask, exec, + &["dmenu_run"]); dotwm.add_binding(keysym::XK_h, xlib::Mod4Mask, move_win, &["-10", "0"]); dotwm.add_binding(keysym::XK_j, xlib::Mod4Mask, move_win, &["0", "10"]); dotwm.add_binding(keysym::XK_k, xlib::Mod4Mask, move_win, &["0", "-10"]); @@ -57,6 +59,7 @@ fn main() { // Main loop loop { let event = next_event(dotwm.display); + println!("Event {:?}", event); match event { Event::Key(mut e, true) => { let keysym = unsafe { xlib::XLookupKeysym(&mut e, 0) as u32 }; @@ -69,7 +72,15 @@ fn main() { let create_event = xlib::XCreateWindowEvent::from(e); dotwm.add_window(create_event.window); } - _ => println!("Catched event! {:?}", event), + Event::Destroy(e) => { + dotwm.remove_window(e.window); + }, + Event::Enter(e) => { + if let Some(idx) = dotwm.find_window(e.window) { + dotwm.change_focus_of(idx); + } + }, + _ => (), } } } diff --git a/src/safe_x11/mod.rs b/src/safe_x11/mod.rs index 199c402..bdfd7cf 100644 --- a/src/safe_x11/mod.rs +++ b/src/safe_x11/mod.rs @@ -140,7 +140,6 @@ pub fn grab_key(display: *mut Display, key: u32, modifiers: u32, owner_events: b pub fn next_xevent(display: *mut Display) -> XEvent { unsafe { let mut last_event: XEvent = uninitialized(); - println!("xevent: getting next event!"); xlib::XNextEvent(display, &mut last_event); last_event } diff --git a/src/safe_x11/window.rs b/src/safe_x11/window.rs index 624fea4..d2fc9ea 100644 --- a/src/safe_x11/window.rs +++ b/src/safe_x11/window.rs @@ -50,7 +50,7 @@ impl XWindow { unsafe { xlib::XSetWindowBorderWidth(self.display, self.inner, size) }; } - pub fn set_boder_color>>(&self, color: T) { + pub fn set_border_color>>(&self, color: T) { let c = get_color(self.display, color); unsafe { XSetWindowBorder(self.display, self.inner, c); } } -- cgit v1.2.3-54-g00ecf