use xcb::x::{ self, DeleteProperty, EnterNotifyEvent, FocusInEvent, InputFocus, NotifyDetail, NotifyMode, SetInputFocus, Window, }; use crate::{error::*, WM}; impl WM<'_> { /// When a new window is entered, focus it. pub fn handle_enter_notify(&mut self, e: EnterNotifyEvent) -> Result<()> { if (e.mode() != NotifyMode::Normal || e.detail() == NotifyDetail::Inferior) && e.event() != self.root { return Ok(()); } self.focus_window(e.event()); self.conn.flush()?; Ok(()) } /// When a new window requests focus, focus it. pub fn handle_focus_in(&mut self, e: FocusInEvent) -> Result<()> { if self .clients .focused_mut() .map(|c| c.window() != e.event()) .unwrap_or(true) { self.focus_window(e.event()); self.conn.flush()?; } Ok(()) } /// Attempt to focus the given window, even if it isn't managed. /// This function sends multiple requests without checking them, so `conn.flush()` should be called after. pub fn focus_window(&mut self, window: Window) { if let Some((mon, i)) = self.clients.find_client_pos(window) { self.refocus(mon, i); } else { self.conn.send_request(&SetInputFocus { revert_to: InputFocus::PointerRoot, focus: window, time: x::CURRENT_TIME, }); self.conn.send_request(&DeleteProperty { window, property: self.atoms.net_active_window, }); } } /// Refocus on the client with the given co-ordinates, setting X11 properties as required. /// If the given index is invalid, focus on the root instead. /// This function sends multiple requests without checking them, so `conn.flush()` should be called after. pub fn refocus(&mut self, mon: usize, i: usize) { self.unfocus(); if let Some(new) = self.clients.set_focused(mon, i) { new.set_border(self.conn, self.colours.border_focused()); // TODO: reset urgent flag // TODO: something to do with grabbuttons // TODO: set input focus // TODO: set active window // TODO: send wmtakefocus event } else { // TODO: focus on root } } /// Unfocus the currently focused window, if it exists. /// This function sends multiple requests without checking them, so `conn.flush()` should be called after. pub fn unfocus(&mut self) { if let Some(old) = self.clients.focused_mut() { old.set_border(self.conn, self.colours.border_normal()); } } }