Skip to content

Commit

Permalink
Add new configurable status bar workspace list indicator.
Browse files Browse the repository at this point in the history
Enable by adding +L to bar_format.

Add new bar_format character sequence: +L

Add new conf option: workspace_indicator

Closes #113 and closes #170
  • Loading branch information
LordReg committed Sep 7, 2018
1 parent d781d4e commit 6331a29
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
31 changes: 31 additions & 0 deletions spectrwm.1
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ It may contain the following character sequences:
.It Li "+D" Ta "Workspace name" .It Li "+D" Ta "Workspace name"
.It Li "+F" Ta "Floating indicator" .It Li "+F" Ta "Floating indicator"
.It Li "+I" Ta "Workspace index" .It Li "+I" Ta "Workspace index"
.It Li "+L" Ta "Workspace list indicator"
.It Li "+M" Ta "Number of iconic (minimized) windows in workspace" .It Li "+M" Ta "Number of iconic (minimized) windows in workspace"
.It Li "+N" Ta "Screen number" .It Li "+N" Ta "Screen number"
.It Li "+P" Ta "Window class and instance separated by a colon" .It Li "+P" Ta "Window class and instance separated by a colon"
Expand Down Expand Up @@ -517,6 +518,36 @@ Enable by setting to 1.
Centers the pointer on the focused window when using bindings to change focus, Centers the pointer on the focused window when using bindings to change focus,
switch workspaces, change regions, etc. switch workspaces, change regions, etc.
Enable by setting to 1. Enable by setting to 1.
.It Ic workspace_indicator
Configure the status bar workspace indicator.
One or more of the following options may be specified in a comma-separated
list:
.Pp
.Bl -tag -width "markcurrentXXX" -offset indent -compact
.It Ar listcurrent
Include the current workspace.
.It Ar listactive
Include workspaces with windows.
.It Ar listempty
Include empty workspaces.
.It Ar listnamed
Include named workspaces.
.It Ar listurgent
Include workspaces with urgent window(s).
.It Ar listall
Include all workspaces.
.It Ar hidecurrent
Always exclude the current workspace from the list.
.It Ar markcurrent
Indicate the current workspace if it is in the list.
.It Ar markurgent
Indicate workspaces in the list that contain urgent window(s).
.It Ar printnames
Display the names of named workspaces in the list.
.El
.Pp
The default is
.Ar listcurrent , Ns Ar listactive , Ns Ar markcurrent , Ns Ar printnames
.It Ic workspace_limit .It Ic workspace_limit
Set the total number of workspaces available. Set the total number of workspaces available.
Minimum is 1, maximum is 22, default is 10. Minimum is 1, maximum is 22, default is 10.
Expand Down
144 changes: 144 additions & 0 deletions spectrwm.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -271,6 +271,19 @@ uint32_t swm_debug = 0
#define SWM_CK_FALLBACK (0x4) #define SWM_CK_FALLBACK (0x4)
#define SWM_CK_REGION (0x8) #define SWM_CK_REGION (0x8)


#define SWM_WSI_LISTCURRENT (0x001)
#define SWM_WSI_LISTACTIVE (0x002)
#define SWM_WSI_LISTEMPTY (0x004)
#define SWM_WSI_LISTNAMED (0x008)
#define SWM_WSI_LISTURGENT (0x010)
#define SWM_WSI_LISTALL (0x0ff)
#define SWM_WSI_HIDECURRENT (0x100)
#define SWM_WSI_MARKCURRENT (0x200)
#define SWM_WSI_MARKURGENT (0x400)
#define SWM_WSI_PRINTNAMES (0x800)
#define SWM_WSI_DEFAULT (SWM_WSI_LISTCURRENT | SWM_WSI_LISTACTIVE | \
SWM_WSI_MARKCURRENT | SWM_WSI_PRINTNAMES)

#define SWM_CONF_DEFAULT (0) #define SWM_CONF_DEFAULT (0)
#define SWM_CONF_KEYMAPPING (1) #define SWM_CONF_KEYMAPPING (1)


Expand Down Expand Up @@ -386,6 +399,7 @@ char *clock_format = NULL;
bool window_class_enabled = false; bool window_class_enabled = false;
bool window_instance_enabled = false; bool window_instance_enabled = false;
bool window_name_enabled = false; bool window_name_enabled = false;
uint32_t workspace_indicator = SWM_WSI_DEFAULT;
int focus_mode = SWM_FOCUS_DEFAULT; int focus_mode = SWM_FOCUS_DEFAULT;
int focus_close = SWM_STACK_BELOW; int focus_close = SWM_STACK_BELOW;
bool focus_close_wrap = true; bool focus_close_wrap = true;
Expand Down Expand Up @@ -1007,6 +1021,7 @@ void bar_window_float(char *, size_t, struct swm_region *);
void bar_window_instance(char *, size_t, struct swm_region *); void bar_window_instance(char *, size_t, struct swm_region *);
void bar_window_name(char *, size_t, struct swm_region *); void bar_window_name(char *, size_t, struct swm_region *);
void bar_window_state(char *, size_t, struct swm_region *); void bar_window_state(char *, size_t, struct swm_region *);
void bar_workspace_indicator(char *, size_t, struct swm_region *);
void bar_workspace_name(char *, size_t, struct swm_region *); void bar_workspace_name(char *, size_t, struct swm_region *);
int binding_cmp(struct binding *, struct binding *); int binding_cmp(struct binding *, struct binding *);
void binding_insert(uint16_t, enum binding_type, uint32_t, enum actionid, void binding_insert(uint16_t, enum binding_type, uint32_t, enum actionid,
Expand Down Expand Up @@ -1146,6 +1161,7 @@ int parse_rgb(const char *, uint16_t *, uint16_t *, uint16_t *);
int parsebinding(const char *, uint16_t *, enum binding_type *, uint32_t *, int parsebinding(const char *, uint16_t *, enum binding_type *, uint32_t *,
uint32_t *); uint32_t *);
int parsequirks(const char *, uint32_t *, int *); int parsequirks(const char *, uint32_t *, int *);
int parse_workspace_indicator(const char *, uint32_t *);
void pressbutton(struct binding *, struct swm_region *, union arg *); void pressbutton(struct binding *, struct swm_region *, union arg *);
void priorws(struct binding *, struct swm_region *, union arg *); void priorws(struct binding *, struct swm_region *, union arg *);
#ifdef SWM_DEBUG #ifdef SWM_DEBUG
Expand Down Expand Up @@ -2437,6 +2453,69 @@ bar_urgent(char *s, size_t sz)
s[strlen(s) - 1] = 0; s[strlen(s) - 1] = 0;
} }


void
bar_workspace_indicator(char *s, size_t sz, struct swm_region *r)
{
struct ws_win *w;
struct workspace *ws;
int i, count = 0;
char tmp[SWM_BAR_MAX], *mark;
bool current, active, named, urgent, collapse;

if (r == NULL)
return;

for (i = 0; i < workspace_limit; i++) {
ws = &r->s->ws[i];

current = (ws == r->ws);
named = (ws->name != NULL);
urgent = false;
active = false;
TAILQ_FOREACH(w, &ws->winlist, entry) {
active = true;
/* Only get urgent if needed. */
if (!(workspace_indicator & SWM_WSI_LISTURGENT ||
workspace_indicator & SWM_WSI_MARKURGENT) ||
(urgent = get_urgent(w)))
break;
}

collapse = !(workspace_indicator & SWM_WSI_MARKCURRENT ||
workspace_indicator & SWM_WSI_MARKURGENT);

if (!(current && workspace_indicator & SWM_WSI_HIDECURRENT) &&
((current && workspace_indicator & SWM_WSI_LISTCURRENT) ||
(active && workspace_indicator & SWM_WSI_LISTACTIVE) ||
(!active && workspace_indicator & SWM_WSI_LISTEMPTY) ||
(urgent && workspace_indicator & SWM_WSI_LISTURGENT) ||
(named && workspace_indicator & SWM_WSI_LISTNAMED))) {
if (count > 0)
strlcat(s, " ", sz);

if (current &&
workspace_indicator & SWM_WSI_MARKCURRENT)
mark = "*";
else if (urgent && workspace_indicator &
SWM_WSI_MARKURGENT)
mark = "!";
else if (!collapse)
mark = " ";
else
mark = "";
strlcat(s, mark, sz);

if (named && workspace_indicator & SWM_WSI_PRINTNAMES)
snprintf(tmp, sizeof tmp, "%d:%s", ws->idx + 1,
ws->name);
else
snprintf(tmp, sizeof tmp, "%d", ws->idx + 1);
strlcat(s, tmp, sz);
count++;
}
}
}

void void
bar_workspace_name(char *s, size_t sz, struct swm_region *r) bar_workspace_name(char *s, size_t sz, struct swm_region *r)
{ {
Expand Down Expand Up @@ -2581,6 +2660,9 @@ bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep,
case 'I': case 'I':
snprintf(tmp, sizeof tmp, "%d", r->ws->idx + 1); snprintf(tmp, sizeof tmp, "%d", r->ws->idx + 1);
break; break;
case 'L':
bar_workspace_indicator(tmp, sizeof tmp, r);
break;
case 'M': case 'M':
count = 0; count = 0;
TAILQ_FOREACH(w, &r->ws->winlist, entry) TAILQ_FOREACH(w, &r->ws->winlist, entry)
Expand Down Expand Up @@ -8650,6 +8732,62 @@ grabbuttons(void)
DNPRINTF(SWM_D_MOUSE, "done\n"); DNPRINTF(SWM_D_MOUSE, "done\n");
} }


struct wsi_flag {
char *name;
uint32_t mask;
} wsiflags[] = {
{"listcurrent", SWM_WSI_LISTCURRENT},
{"listactive", SWM_WSI_LISTACTIVE},
{"listempty", SWM_WSI_LISTEMPTY},
{"listnamed", SWM_WSI_LISTNAMED},
{"listurgent", SWM_WSI_LISTURGENT},
{"listall", SWM_WSI_LISTALL},
{"hidecurrent", SWM_WSI_HIDECURRENT},
{"markcurrent", SWM_WSI_MARKCURRENT},
{"markurgent", SWM_WSI_MARKURGENT},
{"printnames", SWM_WSI_PRINTNAMES},
};

#define SWM_FLAGS_DELIM ","
#define SWM_FLAGS_WHITESPACE " \t\n"
int
parse_workspace_indicator(const char *str, uint32_t *mode)
{
char *tmp, *cp, *name;
size_t len;
int i;

if (str == NULL || mode == NULL)
return (1);

if ((cp = tmp = strdup(str)) == NULL)
err(1, "parse_workspace_indicator: strdup");

*mode = 0;
while ((name = strsep(&cp, SWM_FLAGS_DELIM)) != NULL) {
if (cp)
cp += (long)strspn(cp, SWM_FLAGS_WHITESPACE);
name += strspn(name, SWM_FLAGS_WHITESPACE);
len = strcspn(name, SWM_FLAGS_WHITESPACE);

for (i = 0; i < LENGTH(wsiflags); i++) {
if (strncasecmp(name, wsiflags[i].name, len) == 0) {
DNPRINTF(SWM_D_CONF, "flag: [%s]\n", name);
*mode |= wsiflags[i].mask;
break;
}
}
if (i >= LENGTH(wsiflags)) {
DNPRINTF(SWM_D_CONF, "invalid flag: [%s]\n", name);
free(tmp);
return (1);
}
}

free(tmp);
return (0);
}

const char *quirkname[] = { const char *quirkname[] = {
"NONE", /* config string for "no value" */ "NONE", /* config string for "no value" */
"FLOAT", "FLOAT",
Expand Down Expand Up @@ -9001,6 +9139,7 @@ enum {
SWM_S_WINDOW_NAME_ENABLED, SWM_S_WINDOW_NAME_ENABLED,
SWM_S_WORKSPACE_CLAMP, SWM_S_WORKSPACE_CLAMP,
SWM_S_WORKSPACE_LIMIT, SWM_S_WORKSPACE_LIMIT,
SWM_S_WORKSPACE_INDICATOR,
SWM_S_WORKSPACE_NAME, SWM_S_WORKSPACE_NAME,
}; };


Expand Down Expand Up @@ -9229,6 +9368,10 @@ setconfvalue(const char *selector, const char *value, int flags)


ewmh_update_desktops(); ewmh_update_desktops();
break; break;
case SWM_S_WORKSPACE_INDICATOR:
if (parse_workspace_indicator(value, &workspace_indicator))
errx(1, "invalid workspace_indicator");
break;
case SWM_S_WORKSPACE_NAME: case SWM_S_WORKSPACE_NAME:
if (getenv("SWM_STARTED") != NULL) if (getenv("SWM_STARTED") != NULL)
return (0); return (0);
Expand Down Expand Up @@ -9576,6 +9719,7 @@ struct config_option configopt[] = {
{ "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED }, { "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED },
{ "workspace_clamp", setconfvalue, SWM_S_WORKSPACE_CLAMP }, { "workspace_clamp", setconfvalue, SWM_S_WORKSPACE_CLAMP },
{ "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT }, { "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT },
{ "workspace_indicator", setconfvalue, SWM_S_WORKSPACE_INDICATOR },
{ "name", setconfvalue, SWM_S_WORKSPACE_NAME }, { "name", setconfvalue, SWM_S_WORKSPACE_NAME },
}; };


Expand Down
1 change: 1 addition & 0 deletions spectrwm.conf
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
# bar_action = baraction.sh # bar_action = baraction.sh
# bar_justify = left # bar_justify = left
# bar_format = +N:+I +S <+D>+4<%a %b %d %R %Z %Y+8<+A+4<+V # bar_format = +N:+I +S <+D>+4<%a %b %d %R %Z %Y+8<+A+4<+V
# workspace_indicator = listcurrent,listactive,markcurrent,printnames
# bar_at_bottom = 1 # bar_at_bottom = 1
# stack_enabled = 1 # stack_enabled = 1
# clock_enabled = 1 # clock_enabled = 1
Expand Down

0 comments on commit 6331a29

Please sign in to comment.