diff --git a/watchers/src/watchers/x11_connection.rs b/watchers/src/watchers/x11_connection.rs index 173591d..6f6f969 100644 --- a/watchers/src/watchers/x11_connection.rs +++ b/watchers/src/watchers/x11_connection.rs @@ -67,33 +67,38 @@ impl X11Client { }) } - pub fn active_window_data(&mut self) -> anyhow::Result { + pub fn active_window_data(&mut self) -> anyhow::Result> { self.execute_with_reconnect(|client| { - let focus: Window = client.find_active_window()?; - - let name = client.get_property( - focus, - client.intern_atom("_NET_WM_NAME")?, - "_NET_WM_NAME", - client.intern_atom("UTF8_STRING")?, - u32::MAX, - )?; - let class = client.get_property( - focus, - AtomEnum::WM_CLASS.into(), - "WM_CLASS", - AtomEnum::STRING.into(), - u32::MAX, - )?; - - let title = str::from_utf8(&name.value).with_context(|| "Invalid title UTF")?; - let (instance, class) = parse_wm_class(&class)?; - - Ok(WindowData { - title: title.to_string(), - app_id: class, - wm_instance: instance, - }) + let focus = client.find_active_window()?; + + match focus { + Some(window) => { + let name = client.get_property( + window, + client.intern_atom("_NET_WM_NAME")?, + "_NET_WM_NAME", + client.intern_atom("UTF8_STRING")?, + u32::MAX, + )?; + let class = client.get_property( + window, + AtomEnum::WM_CLASS.into(), + "WM_CLASS", + AtomEnum::STRING.into(), + u32::MAX, + )?; + + let title = str::from_utf8(&name.value).with_context(|| "Invalid title UTF")?; + let (instance, class) = parse_wm_class(&class)?; + + Ok(Some(WindowData { + title: title.to_string(), + app_id: class, + wm_instance: instance, + })) + } + None => Ok(None), + } }) } @@ -122,7 +127,7 @@ impl X11Client { .atom) } - fn find_active_window(&self) -> anyhow::Result { + fn find_active_window(&self) -> anyhow::Result> { let window: Atom = AtomEnum::WINDOW.into(); let net_active_window = self.intern_atom("_NET_ACTIVE_WINDOW")?; let active_window = self.get_property( @@ -134,20 +139,28 @@ impl X11Client { )?; if active_window.format == 32 && active_window.length == 1 { - active_window + let window_id = active_window .value32() .ok_or(anyhow!("Invalid message. Expected value with format = 32"))? .next() - .ok_or(anyhow!("Active window is not found")) + .ok_or(anyhow!("Active window is not found"))?; + + // Check if the window_id is 0 (no active window) + if window_id == 0 { + return Ok(None); + } + + Ok(Some(window_id)) } else { // Query the input focus - Ok(self - .connection - .get_input_focus() - .with_context(|| "Failed to get input focus")? - .reply() - .with_context(|| "Failed to read input focus from reply")? - .focus) + Ok(Some( + self.connection + .get_input_focus() + .with_context(|| "Failed to get input focus")? + .reply() + .with_context(|| "Failed to read input focus from reply")? + .focus, + )) } } } diff --git a/watchers/src/watchers/x11_window.rs b/watchers/src/watchers/x11_window.rs index 1534a6e..6269317 100644 --- a/watchers/src/watchers/x11_window.rs +++ b/watchers/src/watchers/x11_window.rs @@ -30,17 +30,33 @@ impl WindowWatcher { async fn send_active_window(&mut self, client: &ReportClient) -> anyhow::Result<()> { let data = self.client.active_window_data()?; - if data.app_id != self.last_app_id - || data.title != self.last_title - || data.wm_instance != self.last_wm_instance + let (app_id, title, wm_instance) = match data { + Some(window_data) => ( + window_data.app_id, + window_data.title, + window_data.wm_instance, + ), + None => { + // No active window, set all values to "aw-none" + ( + "aw-none".to_string(), + "aw-none".to_string(), + "aw-none".to_string(), + ) + } + }; + + if app_id != self.last_app_id + || title != self.last_title + || wm_instance != self.last_wm_instance { debug!( r#"Changed window app_id="{}", title="{}", wm_instance="{}""#, - data.app_id, data.title, data.wm_instance + app_id, title, wm_instance ); - self.last_app_id = data.app_id.clone(); - self.last_title = data.title.clone(); - self.last_wm_instance = data.wm_instance.clone(); + self.last_app_id = app_id.clone(); + self.last_title = title.clone(); + self.last_wm_instance = wm_instance.clone(); } self.send_active_window_with_instance(