int select_resp_pipe[2];
pid_t searchpid;
volatile sig_atomic_t search_resp;
+int search_resp_action;
+
+/* search actions */
+enum {
+ SWM_SEARCH_NONE,
+ SWM_SEARCH_UNICONIFY,
+ SWM_SEARCH_NAME_WORKSPACE,
+ SWM_SEARCH_SEARCH_WORKSPACE
+};
/* dialog windows */
double dialog_ratio = .6;
/* status bar */
-#define SWM_BAR_MAX (256)
+#define SWM_BAR_MAX (256)
+#define SWM_BAR_JUSTIFY_LEFT (0)
+#define SWM_BAR_JUSTIFY_CENTER (1)
+#define SWM_BAR_JUSTIFY_RIGHT (2)
+#define SWM_BAR_OFFSET (4)
char *bar_argv[] = { NULL, NULL };
int bar_pipe[2];
char bar_ext[SWM_BAR_MAX];
int bar_extra_running = 0;
int bar_verbose = 1;
int bar_height = 0;
+int bar_justify = SWM_BAR_JUSTIFY_LEFT;
int stack_enabled = 1;
int clock_enabled = 1;
int urgent_enabled = 0;
/* define work spaces */
struct workspace {
int idx; /* workspace index */
+ char *name; /* workspace name */
int always_raise; /* raise windows on focus */
struct layout *cur_layout; /* current layout handlers */
struct ws_win *focus; /* may be NULL */
#define SWM_ARG_ID_CYCLEWS_DOWN (41)
#define SWM_ARG_ID_CYCLESC_UP (42)
#define SWM_ARG_ID_CYCLESC_DOWN (43)
+#define SWM_ARG_ID_CYCLEWS_UP_ALL (44)
+#define SWM_ARG_ID_CYCLEWS_DOWN_ALL (45)
#define SWM_ARG_ID_STACKINC (50)
#define SWM_ARG_ID_STACKDEC (51)
#define SWM_ARG_ID_SS_ALL (60)
void
bar_print(struct swm_region *r, char *s)
{
+ int textwidth, x;
+ size_t len;
+
XClearWindow(display, r->bar_window);
XSetForeground(display, bar_gc, r->s->c[SWM_S_COLOR_BAR_FONT].color);
- XDrawString(display, r->bar_window, bar_gc, 4, bar_fs->ascent, s,
- strlen(s));
+
+ len = strlen(s);
+ textwidth = XTextWidth(bar_fs, s, len);
+
+ switch (bar_justify) {
+ case SWM_BAR_JUSTIFY_LEFT:
+ x = SWM_BAR_OFFSET;
+ break;
+ case SWM_BAR_JUSTIFY_CENTER:
+ x = (WIDTH(r) - textwidth) / 2;
+ break;
+ case SWM_BAR_JUSTIFY_RIGHT:
+ x = WIDTH(r) - textwidth - SWM_BAR_OFFSET;
+ break;
+ }
+
+ if (x < SWM_BAR_OFFSET)
+ x = SWM_BAR_OFFSET;
+
+ XDrawString(display, r->bar_window, bar_gc, x, bar_fs->ascent, s, len);
}
void
struct swm_region *r;
int i, x;
size_t len;
+ char ws[SWM_BAR_MAX];
char s[SWM_BAR_MAX];
char cn[SWM_BAR_MAX];
char loc[SWM_BAR_MAX];
x = 1;
TAILQ_FOREACH(r, &screens[i].rl, entry) {
strlcpy(cn, "", sizeof cn);
+ strlcpy(ws, "", sizeof ws);
if (r && r->ws) {
bar_urgent(cn, sizeof cn);
bar_class_name(cn, sizeof cn, r->ws->focus);
bar_window_name(cn, sizeof cn, r->ws->focus);
+ if (r->ws->name)
+ snprintf(ws, sizeof ws, "<%s>", r->ws->name);
}
if (stack_enabled)
stack = r->ws->stacker;
- snprintf(loc, sizeof loc, "%d:%d %s %s%s %s %s",
- x++, r->ws->idx + 1, stack, s, cn, bar_ext, bar_vertext);
+ snprintf(loc, sizeof loc, "%d:%d %s %s %s%s %s %s",
+ x++, r->ws->idx + 1, stack, ws, s, cn, bar_ext,
+ bar_vertext);
bar_print(r, loc);
}
}
{
union arg a;
struct swm_screen *s = r->s;
+ int cycle_all = 0;
DNPRINTF(SWM_D_WS, "cyclews id %d "
"in screen[%d]:%dx%d+%d+%d ws %d\n", args->id,
a.id = r->ws->idx;
do {
switch (args->id) {
+ case SWM_ARG_ID_CYCLEWS_UP_ALL:
+ cycle_all = 1;
+ /* FALLTHROUGH */
case SWM_ARG_ID_CYCLEWS_UP:
if (a.id < SWM_WS_MAX - 1)
a.id++;
else
a.id = 0;
break;
+ case SWM_ARG_ID_CYCLEWS_DOWN_ALL:
+ cycle_all = 1;
+ /* FALLTHROUGH */
case SWM_ARG_ID_CYCLEWS_DOWN:
if (a.id > 0)
a.id--;
return;
};
- if (cycle_empty == 0 && TAILQ_EMPTY(&s->ws[a.id].winlist))
+ if (!cycle_all &&
+ (cycle_empty == 0 && TAILQ_EMPTY(&s->ws[a.id].winlist)))
continue;
if (cycle_visible == 0 && s->ws[a.id].r != NULL)
continue;
return;
search_r = r;
+ search_resp_action = SWM_SEARCH_UNICONIFY;
- spawn_select(r, args, "uniconify", &searchpid);
+ spawn_select(r, args, "search", &searchpid);
if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
return;
fclose(lfile);
}
-#define MAX_RESP_LEN 1024
+void
+name_workspace(struct swm_region *r, union arg *args)
+{
+ struct workspace *ws;
+ FILE *lfile;
+
+ DNPRINTF(SWM_D_MISC, "name_workspace\n");
+
+ if (r && r->ws)
+ ws = r->ws;
+ else
+ return;
+
+ search_r = r;
+ search_resp_action = SWM_SEARCH_NAME_WORKSPACE;
+
+ spawn_select(r, args, "name_workspace", &searchpid);
+
+ if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+ return;
+
+ fprintf(lfile, "%s", "");
+ fclose(lfile);
+}
void
-search_do_resp(void)
+search_workspace(struct swm_region *r, union arg *args)
{
- ssize_t rbytes;
- struct ws_win *win;
- unsigned char *name;
- char *resp, *s;
- unsigned long len;
+ int i;
+ struct workspace *ws;
+ FILE *lfile;
- DNPRINTF(SWM_D_MISC, "search_do_resp:\n");
+ DNPRINTF(SWM_D_MISC, "search_workspace\n");
- search_resp = 0;
- searchpid = 0;
+ if (r == NULL)
+ return;
- if ((resp = calloc(1, MAX_RESP_LEN + 1)) == NULL) {
- fprintf(stderr, "search: calloc\n");
- goto done;
- }
+ search_r = r;
+ search_resp_action = SWM_SEARCH_SEARCH_WORKSPACE;
- rbytes = read(select_resp_pipe[0], resp, MAX_RESP_LEN);
- if (rbytes <= 0) {
- fprintf(stderr, "search: read error: %s\n", strerror(errno));
- goto done;
+ spawn_select(r, args, "search", &searchpid);
+
+ if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+ return;
+
+ for (i = 0; i < SWM_WS_MAX; i++) {
+ ws = &r->s->ws[i];
+ if (ws == NULL)
+ continue;
+ fprintf(lfile, "%d%s%s\n", ws->idx + 1,
+ (ws->name ? ":" : ""), (ws->name ? ws->name : ""));
}
- resp[rbytes] = '\0';
- len = strlen(resp);
- DNPRINTF(SWM_D_MISC, "search_do_resp: resp %s\n", resp);
+ fclose(lfile);
+}
+
+void
+search_resp_uniconify(char *resp, unsigned long len)
+{
+ unsigned char *name;
+ struct ws_win *win;
+ char *s;
+
+ DNPRINTF(SWM_D_MISC, "search_resp_uniconify: resp %s\n", resp);
+
TAILQ_FOREACH(win, &search_r->ws->winlist, entry) {
if (win->iconic == 0)
continue;
}
free(s);
}
+}
+
+void
+search_resp_name_workspace(char *resp, unsigned long len)
+{
+ struct workspace *ws;
+
+ DNPRINTF(SWM_D_MISC, "search_resp_name_workspace: resp %s\n", resp);
+
+ if (search_r->ws == NULL)
+ return;
+ ws = search_r->ws;
+
+ if (ws->name) {
+ free(search_r->ws->name);
+ search_r->ws->name = NULL;
+ }
+
+ if (len > 1) {
+ ws->name = strdup(resp);
+ if (ws->name == NULL) {
+ DNPRINTF(SWM_D_MISC, "search_resp_name_workspace: strdup: %s",
+ strerror(errno));
+ return;
+ }
+ ws->name[len - 1] = '\0';
+ }
+}
+
+void
+search_resp_search_workspace(char *resp, unsigned long len)
+{
+ char *p, *q;
+ int ws_idx;
+ const char *errstr;
+ union arg a;
+
+ DNPRINTF(SWM_D_MISC, "search_resp_search_workspace: resp %s\n", resp);
+
+ q = strdup(resp);
+ if (!q) {
+ DNPRINTF(SWM_D_MISC, "search_resp_search_workspace: strdup: %s",
+ strerror(errno));
+ return;
+ }
+ q[len - 1] = '\0';
+ p = strchr(q, ':');
+ if (p != NULL)
+ *p = '\0';
+ ws_idx = strtonum(q, 1, SWM_WS_MAX, &errstr);
+ if (errstr) {
+ DNPRINTF(SWM_D_MISC, "workspace idx is %s: %s",
+ errstr, q);
+ free(q);
+ return;
+ }
+ free(q);
+ a.id = ws_idx - 1;
+ switchws(search_r, &a);
+}
+
+#define MAX_RESP_LEN 1024
+
+void
+search_do_resp(void)
+{
+ ssize_t rbytes;
+ char *resp;
+ unsigned long len;
+
+ DNPRINTF(SWM_D_MISC, "search_do_resp:\n");
+
+ search_resp = 0;
+ searchpid = 0;
+
+ if ((resp = calloc(1, MAX_RESP_LEN + 1)) == NULL) {
+ fprintf(stderr, "search: calloc\n");
+ goto done;
+ }
+
+ rbytes = read(select_resp_pipe[0], resp, MAX_RESP_LEN);
+ if (rbytes <= 0) {
+ fprintf(stderr, "search: read error: %s\n", strerror(errno));
+ goto done;
+ }
+ resp[rbytes] = '\0';
+ len = strlen(resp);
+
+ switch (search_resp_action) {
+ case SWM_SEARCH_UNICONIFY:
+ search_resp_uniconify(resp, len);
+ break;
+ case SWM_SEARCH_NAME_WORKSPACE:
+ search_resp_name_workspace(resp, len);
+ break;
+ case SWM_SEARCH_SEARCH_WORKSPACE:
+ search_resp_search_workspace(resp, len);
+ break;
+ }
+
done:
+ search_resp_action = SWM_SEARCH_NONE;
close(select_resp_pipe[0]);
free(resp);
}
kf_ws_10,
kf_ws_next,
kf_ws_prev,
+ kf_ws_next_all,
+ kf_ws_prev_all,
kf_ws_prior,
kf_screen_next,
kf_screen_prev,
kf_move_right,
kf_move_up,
kf_move_down,
+ kf_name_workspace,
+ kf_search_workspace,
kf_dumpwins, /* MUST BE LAST */
kf_invalid
};
{ "ws_10", switchws, {.id = 9} },
{ "ws_next", cyclews, {.id = SWM_ARG_ID_CYCLEWS_UP} },
{ "ws_prev", cyclews, {.id = SWM_ARG_ID_CYCLEWS_DOWN} },
+ { "ws_next_all", cyclews, {.id = SWM_ARG_ID_CYCLEWS_UP_ALL} },
+ { "ws_prev_all", cyclews, {.id = SWM_ARG_ID_CYCLEWS_DOWN_ALL} },
{ "ws_prior", priorws, {0} },
{ "screen_next", cyclescr, {.id = SWM_ARG_ID_CYCLESC_UP} },
{ "screen_prev", cyclescr, {.id = SWM_ARG_ID_CYCLESC_DOWN} },
{ "move_right", move_step, {.id = SWM_ARG_ID_MOVERIGHT} },
{ "move_up", move_step, {.id = SWM_ARG_ID_MOVEUP} },
{ "move_down", move_step, {.id = SWM_ARG_ID_MOVEDOWN} },
+ { "name_workspace", name_workspace, {0} },
+ { "search_workspace", search_workspace, {0} },
{ "dumpwins", dumpwins, {0} }, /* MUST BE LAST */
{ "invalid key func", NULL, {0} },
};
" -nf $bar_font_color"
" -sb $bar_border"
" -sf $bar_color", 0);
- setconfspawn("uniconify", "dmenu"
+ setconfspawn("search", "dmenu"
" -i"
" -fn $bar_font"
" -nb $bar_color"
" -nf $bar_font_color"
" -sb $bar_border"
" -sf $bar_color", 0);
+ setconfspawn("name_workspace", "dmenu"
+ " -p Workspace"
+ " -fn $bar_font"
+ " -nb $bar_color"
+ " -nf $bar_font_color"
+ " -sb $bar_border"
+ " -sf $bar_color", 0);
}
/* key bindings */
setkeybinding(MODKEY, XK_0, kf_ws_10, NULL);
setkeybinding(MODKEY, XK_Right, kf_ws_next, NULL);
setkeybinding(MODKEY, XK_Left, kf_ws_prev, NULL);
+ setkeybinding(MODKEY, XK_Up, kf_ws_next_all, NULL);
+ setkeybinding(MODKEY, XK_Down, kf_ws_prev_all, NULL);
setkeybinding(MODKEY, XK_a, kf_ws_prior, NULL);
setkeybinding(MODKEY|ShiftMask, XK_Right, kf_screen_next, NULL);
setkeybinding(MODKEY|ShiftMask, XK_Left, kf_screen_prev, NULL);
setkeybinding(MODKEY, XK_bracketright,kf_move_right, NULL);
setkeybinding(MODKEY|ShiftMask, XK_bracketleft, kf_move_up, NULL);
setkeybinding(MODKEY|ShiftMask, XK_bracketright,kf_move_down, NULL);
+ setkeybinding(MODKEY|ShiftMask, XK_slash, kf_name_workspace,NULL);
+ setkeybinding(MODKEY, XK_slash, kf_search_workspace,NULL);
#ifdef SWM_DEBUG
setkeybinding(MODKEY|ShiftMask, XK_d, kf_dumpwins, NULL);
#endif
SWM_S_FOCUS_MODE, SWM_S_DISABLE_BORDER, SWM_S_BORDER_WIDTH,
SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM,
SWM_S_SS_APP, SWM_S_DIALOG_RATIO, SWM_S_BAR_AT_BOTTOM,
- SWM_S_VERBOSE_LAYOUT
+ SWM_S_VERBOSE_LAYOUT, SWM_S_BAR_JUSTIFY
};
int
case SWM_S_BAR_AT_BOTTOM:
bar_at_bottom = atoi(value);
break;
+ case SWM_S_BAR_JUSTIFY:
+ if (!strcmp(value, "left"))
+ bar_justify = SWM_BAR_JUSTIFY_LEFT;
+ else if (!strcmp(value, "center"))
+ bar_justify = SWM_BAR_JUSTIFY_CENTER;
+ else if (!strcmp(value, "right"))
+ bar_justify = SWM_BAR_JUSTIFY_RIGHT;
+ else
+ errx(1, "invalid bar_justify");
+ break;
case SWM_S_STACK_ENABLED:
stack_enabled = atoi(value);
break;
{ "bar_font", setconfvalue, SWM_S_BAR_FONT },
{ "bar_action", setconfvalue, SWM_S_BAR_ACTION },
{ "bar_delay", setconfvalue, SWM_S_BAR_DELAY },
+ { "bar_justify", setconfvalue, SWM_S_BAR_JUSTIFY },
{ "keyboard_mapping", setkeymapping, 0 },
{ "bind", setconfbinding, 0 },
{ "stack_enabled", setconfvalue, SWM_S_STACK_ENABLED },
for (j = 0; j < SWM_WS_MAX; j++) {
ws = &screens[i].ws[j];
ws->idx = j;
+ ws->name = NULL;
ws->focus = NULL;
ws->r = NULL;
ws->old_r = NULL;