Skip to content

Commit e7ffc37

Browse files
authored
Merge pull request #769 from pachliopta/minimize
feat: Minimize focused window option for launcher
2 parents 9c13e53 + 64b953c commit e7ffc37

File tree

6 files changed

+58
-7
lines changed

6 files changed

+58
-7
lines changed

docs/modules/Launcher.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Optionally displays a launchable set of favourites.
1919
| `show_icons` | `boolean` | `true` | Whether to show app icons on the button. |
2020
| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). |
2121
| `reversed` | `boolean` | `false` | Whether to reverse the order of favorites/items |
22+
| `minimize_focused` | `boolean` | `true` | Whether to minimize a focused window when its icon is clicked. Only minimizes single windows. |
2223
| `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. |
2324
| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. |
2425
| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. |

src/clients/wayland/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub enum Request {
7676
ToplevelInfoAll,
7777
#[cfg(feature = "launcher")]
7878
ToplevelFocus(usize),
79+
#[cfg(feature = "launcher")]
80+
ToplevelMinimize(usize),
7981

8082
#[cfg(feature = "clipboard")]
8183
CopyToClipboard(ClipboardItem),
@@ -350,6 +352,19 @@ impl Environment {
350352

351353
send!(env.response_tx, Response::Ok);
352354
}
355+
#[cfg(feature = "launcher")]
356+
Msg(Request::ToplevelMinimize(id)) => {
357+
let handle = env
358+
.handles
359+
.iter()
360+
.find(|handle| handle.info().map_or(false, |info| info.id == id));
361+
362+
if let Some(handle) = handle {
363+
handle.minimize();
364+
}
365+
366+
send!(env.response_tx, Response::Ok);
367+
}
353368
#[cfg(feature = "clipboard")]
354369
Msg(Request::CopyToClipboard(item)) => {
355370
env.copy_to_clipboard(item);

src/clients/wayland/wlr_foreign_toplevel/handle.rs

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ impl ToplevelHandle {
3333
trace!("Activating handle");
3434
self.handle.activate(seat);
3535
}
36+
37+
pub fn minimize(&self) {
38+
trace!("Minimizing handle");
39+
self.handle.set_minimized();
40+
}
3641
}
3742

3843
#[derive(Debug, Default)]

src/clients/wayland/wlr_foreign_toplevel/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ impl Client {
3636
}
3737
}
3838

39+
/// Minimizes the toplevel with the provided ID.
40+
#[cfg(feature = "launcher")]
41+
pub fn toplevel_minimize(&self, handle_id: usize) {
42+
match self.send_request(Request::ToplevelMinimize(handle_id)) {
43+
Response::Ok => (),
44+
_ => unreachable!(),
45+
}
46+
}
47+
3948
/// Subscribes to events from toplevels.
4049
pub fn subscribe_toplevels(&self) -> broadcast::Receiver<ToplevelEvent> {
4150
self.toplevel_channel.0.subscribe()

src/modules/launcher/item.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -193,24 +193,31 @@ impl ItemButton {
193193
button.add_class("focused");
194194
}
195195

196+
let menu_state = Rc::new(RwLock::new(MenuState {
197+
num_windows: item.windows.len(),
198+
}));
199+
196200
{
197201
let app_id = item.app_id.clone();
198202
let tx = controller_tx.clone();
203+
let menu_state = menu_state.clone();
199204
button.connect_clicked(move |button| {
200205
// lazy check :| TODO: Improve this
201206
let style_context = button.style_context();
202207
if style_context.has_class("open") {
203-
try_send!(tx, ItemEvent::FocusItem(app_id.clone()));
208+
let menu_state = read_lock!(menu_state);
209+
210+
if style_context.has_class("focused") && menu_state.num_windows == 1 {
211+
try_send!(tx, ItemEvent::MinimizeItem(app_id.clone()));
212+
} else {
213+
try_send!(tx, ItemEvent::FocusItem(app_id.clone()));
214+
}
204215
} else {
205216
try_send!(tx, ItemEvent::OpenItem(app_id.clone()));
206217
}
207218
});
208219
}
209220

210-
let menu_state = Rc::new(RwLock::new(MenuState {
211-
num_windows: item.windows.len(),
212-
}));
213-
214221
{
215222
let app_id = item.app_id.clone();
216223
let tx = tx.clone();

src/modules/launcher/mod.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ pub struct LauncherModule {
5656
#[serde(default = "crate::config::default_false")]
5757
reversed: bool,
5858

59+
/// Whether to minimize a window if it is focused when clicked.
60+
///
61+
/// **Default**: `true`
62+
#[serde(default = "crate::config::default_true")]
63+
minimize_focused: bool,
64+
5965
// -- common --
6066
/// Truncate application names on the bar if they get too long.
6167
/// See [truncate options](module-level-options#truncate-mode).
@@ -111,6 +117,7 @@ pub enum ItemEvent {
111117
FocusItem(String),
112118
FocusWindow(usize),
113119
OpenItem(String),
120+
MinimizeItem(String),
114121
}
115122

116123
enum ItemOrWindow {
@@ -290,6 +297,7 @@ impl Module<gtk::Box> for LauncherModule {
290297
});
291298

292299
// listen to ui events
300+
let minimize_focused = self.minimize_focused;
293301
let wl = context.client::<wayland::Client>();
294302
spawn(async move {
295303
while let Some(event) = rx.recv().await {
@@ -318,8 +326,10 @@ impl Module<gtk::Box> for LauncherModule {
318326
} else {
319327
send_async!(tx, ModuleUpdateEvent::ClosePopup);
320328

329+
let minimize_window = matches!(event, ItemEvent::MinimizeItem(_));
330+
321331
let id = match event {
322-
ItemEvent::FocusItem(app_id) => {
332+
ItemEvent::FocusItem(app_id) | ItemEvent::MinimizeItem(app_id) => {
323333
lock!(items).get(&app_id).and_then(|item| {
324334
item.windows
325335
.iter()
@@ -338,7 +348,11 @@ impl Module<gtk::Box> for LauncherModule {
338348
.find_map(|(_, item)| item.windows.get(&id))
339349
{
340350
debug!("Focusing window {id}: {}", window.name);
341-
wl.toplevel_focus(window.id);
351+
if minimize_window && minimize_focused {
352+
wl.toplevel_minimize(window.id);
353+
} else {
354+
wl.toplevel_focus(window.id);
355+
}
342356
}
343357
}
344358
}

0 commit comments

Comments
 (0)