Diff
diff --git a/src/tab_bar.rs b/src/tab_bar.rs
index efdf967..e9c637c 100644
--- a/src/tab_bar.rs
+++ b/src/tab_bar.rs
@@ -106,7 +106,7 @@ impl TabBar {
&mut self,
connection: &RustConnection,
font: &Font,
- windows: &[Window],
+ windows: &[(Window, String)],
focused_window: Option<Window>,
) -> Result<(), X11Error> {
connection.change_gc(
@@ -142,7 +142,7 @@ impl TabBar {
let tab_width = self.width / windows.len() as u16;
let mut x_position: i16 = 0;
- for (index, &window) in windows.iter().enumerate() {
+ for (index, &(window, ref title)) in windows.iter().enumerate() {
let is_focused = Some(window) == focused_window;
let scheme = if is_focused {
&self.scheme_selected
@@ -150,11 +150,10 @@ impl TabBar {
&self.scheme_normal
};
- let title = self.get_window_title(connection, window);
let display_title = if title.is_empty() {
format!("Window {}", index + 1)
} else {
- title
+ title.clone()
};
let text_width = font.text_width(&display_title);
@@ -213,24 +212,9 @@ impl TabBar {
}
}
- fn get_window_title(&self, connection: &RustConnection, window: Window) -> String {
- connection
- .get_property(false, window, AtomEnum::WM_NAME, AtomEnum::STRING, 0, 1024)
- .ok()
- .and_then(|cookie| cookie.reply().ok())
- .and_then(|reply| {
- if reply.value.is_empty() {
- None
- } else {
- std::str::from_utf8(&reply.value).ok().map(|s| s.to_string())
- }
- })
- .unwrap_or_default()
- }
-
pub fn get_clicked_window(
&self,
- windows: &[Window],
+ windows: &[(Window, String)],
click_x: i16,
) -> Option<Window> {
if windows.is_empty() {
@@ -240,7 +224,7 @@ impl TabBar {
let tab_width = self.width / windows.len() as u16;
let tab_index = (click_x as u16 / tab_width) as usize;
- windows.get(tab_index).copied()
+ windows.get(tab_index).map(|&(win, _)| win)
}
pub fn reposition(
diff --git a/src/window_manager.rs b/src/window_manager.rs
index 6ff405c..6792422 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -42,6 +42,7 @@ struct AtomCache {
net_wm_window_type_dialog: Atom,
wm_name: Atom,
net_wm_name: Atom,
+ utf8_string: Atom,
wm_normal_hints: Atom,
wm_hints: Atom,
wm_transient_for: Atom,
@@ -94,6 +95,7 @@ impl AtomCache {
let wm_name = AtomEnum::WM_NAME.into();
let net_wm_name = connection.intern_atom(false, b"_NET_WM_NAME")?.reply()?.atom;
+ let utf8_string = connection.intern_atom(false, b"UTF8_STRING")?.reply()?.atom;
let wm_normal_hints = AtomEnum::WM_NORMAL_HINTS.into();
let wm_hints = AtomEnum::WM_HINTS.into();
let wm_transient_for = AtomEnum::WM_TRANSIENT_FOR.into();
@@ -111,6 +113,7 @@ impl AtomCache {
net_wm_window_type_dialog,
wm_name,
net_wm_name,
+ utf8_string,
wm_normal_hints,
wm_hints,
wm_transient_for,
@@ -690,23 +693,23 @@ impl WindowManager {
fn update_tab_bars(&mut self) -> WmResult<()> {
for (monitor_index, monitor) in self.monitors.iter().enumerate() {
if let Some(tab_bar) = self.tab_bars.get_mut(monitor_index) {
- let visible_windows: Vec<Window> = self
+ let visible_windows: Vec<(Window, String)> = self
.windows
.iter()
- .filter(|&&window| {
+ .filter_map(|&window| {
if let Some(client) = self.clients.get(&window) {
if client.monitor_index != monitor_index
|| self.floating_windows.contains(&window)
|| self.fullscreen_windows.contains(&window)
{
- return false;
+ return None;
+ }
+ if (client.tags & monitor.tagset[monitor.selected_tags_index]) != 0 {
+ return Some((window, client.name.clone()));
}
- (client.tags & monitor.tagset[monitor.selected_tags_index]) != 0
- } else {
- false
}
+ None
})
- .copied()
.collect();
let focused_window = monitor.selected_client;
@@ -2274,6 +2277,7 @@ impl WindowManager {
};
self.focus(Some(next_window))?;
+ self.update_tab_bars()?;
Ok(())
}
@@ -2768,6 +2772,7 @@ impl WindowManager {
}
}
self.focus(Some(event.event))?;
+ self.update_tab_bars()?;
}
}
Event::MotionNotify(event) => {
@@ -2785,6 +2790,7 @@ impl WindowManager {
let visible = self.visible_windows_on_monitor(monitor_index);
if let Some(&win) = visible.first() {
self.focus(Some(win))?;
+ self.update_tab_bars()?;
}
}
}
@@ -2885,24 +2891,24 @@ impl WindowManager {
self.selected_monitor = monitor_index;
}
- let visible_windows: Vec<Window> = self
+ let visible_windows: Vec<(Window, String)> = self
.windows
.iter()
- .filter(|&&window| {
+ .filter_map(|&window| {
if let Some(client) = self.clients.get(&window) {
if client.monitor_index != monitor_index
|| self.floating_windows.contains(&window)
|| self.fullscreen_windows.contains(&window)
{
- return false;
+ return None;
}
let monitor_tags = self.monitors.get(monitor_index).map(|m| m.tagset[m.selected_tags_index]).unwrap_or(0);
- (client.tags & monitor_tags) != 0
- } else {
- false
+ if (client.tags & monitor_tags) != 0 {
+ return Some((window, client.name.clone()));
+ }
}
+ None
})
- .copied()
.collect();
if let Some(clicked_window) = tab_bar.get_clicked_window(&visible_windows, event.event_x) {
@@ -2915,6 +2921,7 @@ impl WindowManager {
}
} else if event.child != x11rb::NONE {
self.focus(Some(event.child))?;
+ self.update_tab_bars()?;
if event.detail == ButtonIndex::M1.into() {
self.drag_window(event.child)?;
@@ -3474,19 +3481,42 @@ impl WindowManager {
}
fn update_window_title(&mut self, window: Window) -> WmResult<()> {
- let name = self.connection
+ let net_name = self.connection
+ .get_property(
+ false,
+ window,
+ self.atoms.net_wm_name,
+ self.atoms.utf8_string,
+ 0,
+ 256,
+ )
+ .ok()
+ .and_then(|cookie| cookie.reply().ok());
+
+ if let Some(name) = net_name {
+ if !name.value.is_empty() {
+ if let Ok(title) = String::from_utf8(name.value.clone()) {
+ if let Some(client) = self.clients.get_mut(&window) {
+ client.name = title;
+ return Ok(());
+ }
+ }
+ }
+ }
+
+ let wm_name = self.connection
.get_property(
false,
window,
- x11rb::protocol::xproto::AtomEnum::WM_NAME,
+ self.atoms.wm_name,
x11rb::protocol::xproto::AtomEnum::STRING,
0,
256,
)?
.reply()?;
- if !name.value.is_empty() {
- if let Ok(title) = String::from_utf8(name.value.clone()) {
+ if !wm_name.value.is_empty() {
+ if let Ok(title) = String::from_utf8(wm_name.value.clone()) {
if let Some(client) = self.clients.get_mut(&window) {
client.name = title;
}