diff --git a/README.md b/README.md index 942057a..62093ca 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ The following messages are handled: - `rename CURRENT_NAME NEW_NAME` — Rename the desktop named `CURRENT_NAME` to `NEW_NAME`. +- `remove_desktop DESKTOP_NAME ...` — Remove the given desktops. + - `cycle_monitor next|prev` — Select the next or previous monitor. - `cycle_desktop next|prev [--skip-free|--skip-occupied]` — Select the next or previous desktop. diff --git a/bash_completion b/bash_completion index 5933244..c728a3d 100644 --- a/bash_completion +++ b/bash_completion @@ -1,6 +1,6 @@ _bspc() { - local messages='get set list list_desktops list_monitors list_windows list_rules list_history presel cancel ratio pad focus shift swap push pull cycle nearest biggest circulate grab_pointer track_pointer ungrab_pointer toggle_fullscreen toggle_floating toggle_locked toggle_visibility close kill send_to drop_to send_to_monitor drop_to_monitor use use_monitor alternate alternate_desktop alternate_monitor add add_in rename_monitor rename cycle_monitor cycle_desktop layout cycle_layout rotate flip balance rule remove_rule put_status adopt_orphans restore_layout restore_history quit' + local messages='get set list list_desktops list_monitors list_windows list_rules list_history presel cancel ratio pad focus shift swap push pull cycle nearest biggest circulate grab_pointer track_pointer ungrab_pointer toggle_fullscreen toggle_floating toggle_locked toggle_visibility close kill send_to drop_to send_to_monitor drop_to_monitor use use_monitor alternate alternate_desktop alternate_monitor add add_in rename_monitor rename remove_desktop cycle_monitor cycle_desktop layout cycle_layout rotate flip balance rule remove_rule put_status adopt_orphans restore_layout restore_history quit' local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color urgent_border_color border_width window_gap split_ratio top_padding right_padding bottom_padding left_padding wm_name borderless_monocle gapless_monocle focus_follows_pointer adaptative_raise apply_shadow_property auto_alternate focus_by_distance' diff --git a/bspwm.1 b/bspwm.1 index b0d9c28..4b59c5a 100644 --- a/bspwm.1 +++ b/bspwm.1 @@ -222,6 +222,9 @@ Rename the monitor named CURRENT_NAME to NEW_NAME. .BI rename " CURRENT_NAME NEW_NAME" Rename the desktop named CURRENT_NAME to NEW_NAME. .TP +.BI remove_desktop " DESKTOP_NAME ..." +Remove the given desktops. +.TP .BI cycle_monitor " next|prev" Select the next or previous monitor. .TP diff --git a/messages.c b/messages.c index 03838a2..7f055d9 100644 --- a/messages.c +++ b/messages.c @@ -424,6 +424,17 @@ void process_message(char *msg, char *rsp) for (char *name = strtok(NULL, TOK_SEP); name != NULL; name = strtok(NULL, TOK_SEP)) add_desktop(mon, make_desktop(name)); return; + } else if (strcmp(cmd, "remove_desktop") == 0) { + for (char *name = strtok(NULL, TOK_SEP); name != NULL; name = strtok(NULL, TOK_SEP)) { + desktop_location_t loc; + if (locate_desktop(name, &loc)) { + if (loc.desktop->root == NULL && loc.monitor->desk_head != loc.monitor->desk_tail) + remove_desktop(loc.monitor, loc.desktop); + } + } + desktop_show(mon->desk); + update_current(); + return; } else if (strcmp(cmd, "focus") == 0) { if (mon->desk->focus == NULL || mon->desk->focus->client->fullscreen) return; diff --git a/rules.c b/rules.c index 5f9f81d..9845bac 100644 --- a/rules.c +++ b/rules.c @@ -40,6 +40,17 @@ void remove_rule_by_uid(unsigned int uid) remove_rule(find_rule(uid)); } +void prune_rules(desktop_t *d) +{ + rule_t *r = rule_head; + while (r != NULL) { + rule_t *next = r->next; + if (r->effect.desktop == d) + remove_rule(r); + r = next; + } +} + rule_t *find_rule(unsigned int uid) { for (rule_t *r = rule_head; r != NULL; r = r->next) diff --git a/rules.h b/rules.h index a003ecd..f057d4f 100644 --- a/rules.h +++ b/rules.h @@ -4,6 +4,7 @@ void add_rule(rule_t *); void remove_rule(rule_t *); void remove_rule_by_uid(unsigned int); +void prune_rules(desktop_t *); rule_t *find_rule(unsigned int); bool is_match(rule_t *, xcb_window_t); void handle_rules(xcb_window_t, monitor_t **, desktop_t **, bool *, bool *, bool *, bool *, bool *, bool *); diff --git a/tree.c b/tree.c index 036537a..8fb6ec5 100644 --- a/tree.c +++ b/tree.c @@ -779,11 +779,8 @@ void select_desktop(monitor_t *m, desktop_t *d) PRINTF("select desktop %s\n", d->name); if (visible) { - for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) - window_show(n->client->window); - - for (node_t *n = first_extrema(mon->desk->root); n != NULL; n = next_leaf(n, mon->desk->root)) - window_hide(n->client->window); + desktop_show(d); + desktop_hide(mon->desk); } mon->last_desk = mon->desk; diff --git a/types.c b/types.c index 0d7ebb7..f1569ff 100644 --- a/types.c +++ b/types.c @@ -4,6 +4,7 @@ #include #include "bspwm.h" #include "window.h" +#include "rules.h" #include "ewmh.h" #include "settings.h" #include "types.h" @@ -173,13 +174,13 @@ void unlink_desktop(monitor_t *m, desktop_t *d) m->last_desk = NULL; if (m->desk == d) m->desk = (m->last_desk == NULL ? m->desk_head : m->last_desk); - d->next = d->prev = NULL; } void remove_desktop(monitor_t *m, desktop_t *d) { PRINTF("remove desktop %s\n", d->name); + prune_rules(d); unlink_desktop(m, d); empty_desktop(d); free(d); diff --git a/window.c b/window.c index 7d22a08..63dabbd 100644 --- a/window.c +++ b/window.c @@ -557,6 +557,18 @@ void toggle_visibility(void) update_current(); } +void desktop_show(desktop_t *d) +{ + for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) + window_show(n->client->window); +} + +void desktop_hide(desktop_t *d) +{ + for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) + window_hide(n->client->window); +} + void enable_motion_recorder(void) { window_raise(motion_recorder); diff --git a/window.h b/window.h index fc47250..4a5bd1d 100644 --- a/window.h +++ b/window.h @@ -42,6 +42,8 @@ void window_set_visibility(xcb_window_t, bool); void window_hide(xcb_window_t); void window_show(xcb_window_t); void toggle_visibility(void); +void desktop_show(desktop_t *); +void desktop_hide(desktop_t *); void enable_motion_recorder(void); void disable_motion_recorder(void); void clear_input_focus(void);