@@ -886,6 +886,25 @@ fn cleanup_socket() { |
| 886 | 886 | let _ = std::fs::remove_file(&path); |
| 887 | 887 | } |
| 888 | 888 | |
| 889 | +fn workspace_last_active_title( |
| 890 | + workspace: &tarmac::core::workspace::Workspace, |
| 891 | + registry: &tarmac::core::window::WindowRegistry, |
| 892 | +) -> Option<String> { |
| 893 | + workspace |
| 894 | + .focused |
| 895 | + .or_else(|| workspace.focus_history.last().copied()) |
| 896 | + .and_then(|window_id| registry.get(window_id)) |
| 897 | + .and_then(|window| { |
| 898 | + let title = window.title.trim(); |
| 899 | + if !title.is_empty() { |
| 900 | + Some(title.to_string()) |
| 901 | + } else { |
| 902 | + let app_name = window.app_name.trim(); |
| 903 | + (!app_name.is_empty()).then(|| app_name.to_string()) |
| 904 | + } |
| 905 | + }) |
| 906 | +} |
| 907 | + |
| 889 | 908 | fn update_tray(tray: &tarmac::ui::tray::TrayWidget) { |
| 890 | 909 | WM_STATE.with(|s| { |
| 891 | 910 | if let Some(state) = s.borrow().as_ref() { |
@@ -902,6 +921,7 @@ fn update_tray(tray: &tarmac::ui::tray::TrayWidget) { |
| 902 | 921 | id: ws.id.to_string(), |
| 903 | 922 | active: ws.visible, |
| 904 | 923 | windows: ws.all_window_ids().len(), |
| 924 | + last_active_title: workspace_last_active_title(ws, &state.registry), |
| 905 | 925 | switch_target, |
| 906 | 926 | }) |
| 907 | 927 | }) |
@@ -1728,6 +1748,7 @@ fn run_app() { |
| 1728 | 1748 | mod tests { |
| 1729 | 1749 | use super::*; |
| 1730 | 1750 | use tarmac::config::document::ConfigSource; |
| 1751 | + use tarmac::core::window::{WindowRegistry, WindowState}; |
| 1731 | 1752 | |
| 1732 | 1753 | fn sample_keybind(key: Key) -> LuaKeybind { |
| 1733 | 1754 | LuaKeybind { |
@@ -1797,6 +1818,24 @@ mod tests { |
| 1797 | 1818 | } |
| 1798 | 1819 | } |
| 1799 | 1820 | |
| 1821 | + fn sample_window(id: u32, app: &str, title: &str) -> WindowState { |
| 1822 | + WindowState { |
| 1823 | + id, |
| 1824 | + app_pid: 100, |
| 1825 | + app_name: app.to_string(), |
| 1826 | + app_bundle_id: format!("com.test.{app}"), |
| 1827 | + title: title.to_string(), |
| 1828 | + role: "AXWindow".to_string(), |
| 1829 | + subrole: "AXStandardWindow".to_string(), |
| 1830 | + x: 0.0, |
| 1831 | + y: 0.0, |
| 1832 | + width: 800.0, |
| 1833 | + height: 600.0, |
| 1834 | + floating: false, |
| 1835 | + minimized: false, |
| 1836 | + } |
| 1837 | + } |
| 1838 | + |
| 1800 | 1839 | #[test] |
| 1801 | 1840 | fn add_keybind_uses_unique_shortcut() { |
| 1802 | 1841 | let mut keybinds = vec![sample_keybind(Key::Period)]; |
@@ -1969,4 +2008,27 @@ mod tests { |
| 1969 | 2008 | assert_eq!(specials[0].name, "term"); |
| 1970 | 2009 | } |
| 1971 | 2010 | |
| 2011 | + #[test] |
| 2012 | + fn workspace_last_active_title_prefers_window_title_then_app_name() { |
| 2013 | + let mut registry = WindowRegistry::new(); |
| 2014 | + registry.add(sample_window(1, "Firefox", "New Tab")); |
| 2015 | + registry.add(sample_window(2, "Firefox", "")); |
| 2016 | + |
| 2017 | + let mut workspace = tarmac::core::workspace::Workspace::new(WorkspaceId::Numbered(1)); |
| 2018 | + workspace.focused = Some(1); |
| 2019 | + assert_eq!( |
| 2020 | + workspace_last_active_title(&workspace, ®istry).as_deref(), |
| 2021 | + Some("New Tab") |
| 2022 | + ); |
| 2023 | + |
| 2024 | + workspace.focused = Some(2); |
| 2025 | + assert_eq!( |
| 2026 | + workspace_last_active_title(&workspace, ®istry).as_deref(), |
| 2027 | + Some("Firefox") |
| 2028 | + ); |
| 2029 | + |
| 2030 | + workspace.focused = Some(99); |
| 2031 | + workspace.focus_history.clear(); |
| 2032 | + assert_eq!(workspace_last_active_title(&workspace, ®istry), None); |
| 2033 | + } |
| 1972 | 2034 | } |