1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-16 22:31:03 +02:00

feat(launcher): add option to minimize window if focused

This commit is contained in:
pachliopta 2024-11-10 16:20:28 +11:00 committed by Jake Stanger
parent 9c13e534b7
commit 64b953ce5e
No known key found for this signature in database
GPG key ID: C51FC8F9CB0BEA61
6 changed files with 58 additions and 7 deletions

View file

@ -19,6 +19,7 @@ Optionally displays a launchable set of favourites.
| `show_icons` | `boolean` | `true` | Whether to show app icons on the button. | | `show_icons` | `boolean` | `true` | Whether to show app icons on the button. |
| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | | `icon_size` | `integer` | `32` | Size to render icon at (image icons only). |
| `reversed` | `boolean` | `false` | Whether to reverse the order of favorites/items | | `reversed` | `boolean` | `false` | Whether to reverse the order of favorites/items |
| `minimize_focused` | `boolean` | `true` | Whether to minimize a focused window when its icon is clicked. Only minimizes single windows. |
| `truncate.mode` | `'start'` or `'middle'` or `'end'` or `off` | `end` | The location of the ellipses and where to truncate text from. Applies to application names when `show_names` is enabled. | | `truncate.mode` | `'start'` or `'middle'` or `'end'` or `off` | `end` | The location of the ellipses and where to truncate text from. Applies to application names when `show_names` is enabled. |
| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | | `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. |
| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | | `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. |

View file

@ -76,6 +76,8 @@ pub enum Request {
ToplevelInfoAll, ToplevelInfoAll,
#[cfg(feature = "launcher")] #[cfg(feature = "launcher")]
ToplevelFocus(usize), ToplevelFocus(usize),
#[cfg(feature = "launcher")]
ToplevelMinimize(usize),
#[cfg(feature = "clipboard")] #[cfg(feature = "clipboard")]
CopyToClipboard(ClipboardItem), CopyToClipboard(ClipboardItem),
@ -350,6 +352,19 @@ impl Environment {
send!(env.response_tx, Response::Ok); send!(env.response_tx, Response::Ok);
} }
#[cfg(feature = "launcher")]
Msg(Request::ToplevelMinimize(id)) => {
let handle = env
.handles
.iter()
.find(|handle| handle.info().map_or(false, |info| info.id == id));
if let Some(handle) = handle {
handle.minimize();
}
send!(env.response_tx, Response::Ok);
}
#[cfg(feature = "clipboard")] #[cfg(feature = "clipboard")]
Msg(Request::CopyToClipboard(item)) => { Msg(Request::CopyToClipboard(item)) => {
env.copy_to_clipboard(item); env.copy_to_clipboard(item);

View file

@ -33,6 +33,11 @@ impl ToplevelHandle {
trace!("Activating handle"); trace!("Activating handle");
self.handle.activate(seat); self.handle.activate(seat);
} }
pub fn minimize(&self) {
trace!("Minimizing handle");
self.handle.set_minimized();
}
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]

View file

@ -36,6 +36,15 @@ impl Client {
} }
} }
/// Minimizes the toplevel with the provided ID.
#[cfg(feature = "launcher")]
pub fn toplevel_minimize(&self, handle_id: usize) {
match self.send_request(Request::ToplevelMinimize(handle_id)) {
Response::Ok => (),
_ => unreachable!(),
}
}
/// Subscribes to events from toplevels. /// Subscribes to events from toplevels.
pub fn subscribe_toplevels(&self) -> broadcast::Receiver<ToplevelEvent> { pub fn subscribe_toplevels(&self) -> broadcast::Receiver<ToplevelEvent> {
self.toplevel_channel.0.subscribe() self.toplevel_channel.0.subscribe()

View file

@ -193,24 +193,31 @@ impl ItemButton {
button.add_class("focused"); button.add_class("focused");
} }
let menu_state = Rc::new(RwLock::new(MenuState {
num_windows: item.windows.len(),
}));
{ {
let app_id = item.app_id.clone(); let app_id = item.app_id.clone();
let tx = controller_tx.clone(); let tx = controller_tx.clone();
let menu_state = menu_state.clone();
button.connect_clicked(move |button| { button.connect_clicked(move |button| {
// lazy check :| TODO: Improve this // lazy check :| TODO: Improve this
let style_context = button.style_context(); let style_context = button.style_context();
if style_context.has_class("open") { if style_context.has_class("open") {
let menu_state = read_lock!(menu_state);
if style_context.has_class("focused") && menu_state.num_windows == 1 {
try_send!(tx, ItemEvent::MinimizeItem(app_id.clone()));
} else {
try_send!(tx, ItemEvent::FocusItem(app_id.clone())); try_send!(tx, ItemEvent::FocusItem(app_id.clone()));
}
} else { } else {
try_send!(tx, ItemEvent::OpenItem(app_id.clone())); try_send!(tx, ItemEvent::OpenItem(app_id.clone()));
} }
}); });
} }
let menu_state = Rc::new(RwLock::new(MenuState {
num_windows: item.windows.len(),
}));
{ {
let app_id = item.app_id.clone(); let app_id = item.app_id.clone();
let tx = tx.clone(); let tx = tx.clone();

View file

@ -56,6 +56,12 @@ pub struct LauncherModule {
#[serde(default = "crate::config::default_false")] #[serde(default = "crate::config::default_false")]
reversed: bool, reversed: bool,
/// Whether to minimize a window if it is focused when clicked.
///
/// **Default**: `true`
#[serde(default = "crate::config::default_true")]
minimize_focused: bool,
// -- common -- // -- common --
/// Truncate application names on the bar if they get too long. /// Truncate application names on the bar if they get too long.
/// See [truncate options](module-level-options#truncate-mode). /// See [truncate options](module-level-options#truncate-mode).
@ -111,6 +117,7 @@ pub enum ItemEvent {
FocusItem(String), FocusItem(String),
FocusWindow(usize), FocusWindow(usize),
OpenItem(String), OpenItem(String),
MinimizeItem(String),
} }
enum ItemOrWindow { enum ItemOrWindow {
@ -290,6 +297,7 @@ impl Module<gtk::Box> for LauncherModule {
}); });
// listen to ui events // listen to ui events
let minimize_focused = self.minimize_focused;
let wl = context.client::<wayland::Client>(); let wl = context.client::<wayland::Client>();
spawn(async move { spawn(async move {
while let Some(event) = rx.recv().await { while let Some(event) = rx.recv().await {
@ -318,8 +326,10 @@ impl Module<gtk::Box> for LauncherModule {
} else { } else {
send_async!(tx, ModuleUpdateEvent::ClosePopup); send_async!(tx, ModuleUpdateEvent::ClosePopup);
let minimize_window = matches!(event, ItemEvent::MinimizeItem(_));
let id = match event { let id = match event {
ItemEvent::FocusItem(app_id) => { ItemEvent::FocusItem(app_id) | ItemEvent::MinimizeItem(app_id) => {
lock!(items).get(&app_id).and_then(|item| { lock!(items).get(&app_id).and_then(|item| {
item.windows item.windows
.iter() .iter()
@ -338,11 +348,15 @@ impl Module<gtk::Box> for LauncherModule {
.find_map(|(_, item)| item.windows.get(&id)) .find_map(|(_, item)| item.windows.get(&id))
{ {
debug!("Focusing window {id}: {}", window.name); debug!("Focusing window {id}: {}", window.name);
if minimize_window && minimize_focused {
wl.toplevel_minimize(window.id);
} else {
wl.toplevel_focus(window.id); wl.toplevel_focus(window.id);
} }
} }
} }
} }
}
}); });
Ok(()) Ok(())