X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=b0c116d2770b3c4e23cbbd1862af3ef772d0c620;hb=a8c625928eca5ad3c8af0f22fb25f4aa85ddaf8c;hp=ac9b894f82d8be414c9c8a0145b05bb1a361b49d;hpb=1bded57c6463157c2616bf26986489e245a97f79;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index ac9b894..b0c116d 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -207,10 +207,23 @@ pid_t searchpid; volatile sig_atomic_t search_resp; int search_resp_action; +struct search_window { + TAILQ_ENTRY(search_window) entry; + int idx; + struct ws_win *win; + Window indicator; +}; +TAILQ_HEAD(search_winlist, search_window); + +struct search_winlist search_wl; + /* search actions */ enum { SWM_SEARCH_NONE, - SWM_SEARCH_UNICONIFY + SWM_SEARCH_UNICONIFY, + SWM_SEARCH_NAME_WORKSPACE, + SWM_SEARCH_SEARCH_WORKSPACE, + SWM_SEARCH_SEARCH_WINDOW }; /* dialog windows */ @@ -369,6 +382,7 @@ struct layout { /* 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 */ @@ -1359,6 +1373,7 @@ bar_update(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]; @@ -1394,16 +1409,20 @@ bar_update(void) 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); } } @@ -1926,12 +1945,12 @@ validate_win(struct ws_win *testwin) struct ws_win *win; struct workspace *ws; struct swm_region *r; - int i, x, foundit = 0; + int i, x; if (testwin == NULL) return (0); - for (i = 0, foundit = 0; i < ScreenCount(display); i++) + for (i = 0; i < ScreenCount(display); i++) TAILQ_FOREACH(r, &screens[i].rl, entry) for (x = 0; x < SWM_WS_MAX; x++) { ws = &r->s->ws[x]; @@ -1947,10 +1966,10 @@ validate_ws(struct workspace *testws) { struct swm_region *r; struct workspace *ws; - int foundit, i, x; + int i, x; /* validate all ws */ - for (i = 0, foundit = 0; i < ScreenCount(display); i++) + for (i = 0; i < ScreenCount(display); i++) TAILQ_FOREACH(r, &screens[i].rl, entry) for (x = 0; x < SWM_WS_MAX; x++) { ws = &r->s->ws[x]; @@ -2504,13 +2523,10 @@ void cycle_layout(struct swm_region *r, union arg *args) { struct workspace *ws = r->ws; - struct ws_win *winfocus; union arg a; DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx); - winfocus = ws->focus; - ws->cur_layout++; if (ws->cur_layout->l_stack == NULL) ws->cur_layout = &layouts[0]; @@ -3245,6 +3261,139 @@ uniconify(struct swm_region *r, union arg *args) } void +name_workspace(struct swm_region *r, union arg *args) +{ + FILE *lfile; + + DNPRINTF(SWM_D_MISC, "name_workspace\n"); + + if (r == NULL) + 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_workspace(struct swm_region *r, union arg *args) +{ + int i; + struct workspace *ws; + FILE *lfile; + + DNPRINTF(SWM_D_MISC, "search_workspace\n"); + + if (r == NULL) + return; + + search_r = r; + search_resp_action = SWM_SEARCH_SEARCH_WORKSPACE; + + 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 : "")); + } + + fclose(lfile); +} + +void +search_win_cleanup(void) +{ + struct search_window *sw = NULL; + + while ((sw = TAILQ_FIRST(&search_wl)) != NULL) { + XDestroyWindow(display, sw->indicator); + TAILQ_REMOVE(&search_wl, sw, entry); + free(sw); + } +} + +void +search_win(struct swm_region *r, union arg *args) +{ + struct ws_win *win = NULL; + struct search_window *sw = NULL; + Window w; + GC gc; + XGCValues gcv; + int i; + char s[8]; + FILE *lfile; + size_t len; + int textwidth; + + DNPRINTF(SWM_D_MISC, "search_win\n"); + + search_r = r; + search_resp_action = SWM_SEARCH_SEARCH_WINDOW; + + spawn_select(r, args, "search", &searchpid); + + if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL) + return; + + TAILQ_INIT(&search_wl); + + i = 1; + TAILQ_FOREACH(win, &r->ws->winlist, entry) { + if (win->iconic == 1) + continue; + + sw = calloc(1, sizeof(struct search_window)); + if (sw == NULL) { + fprintf(stderr, "search_win: calloc: %s", strerror(errno)); + fclose(lfile); + search_win_cleanup(); + return; + } + sw->idx = i; + sw->win = win; + + snprintf(s, sizeof s, "%d", i); + len = strlen(s); + textwidth = XTextWidth(bar_fs, s, len); + + w = XCreateSimpleWindow(display, + win->id, 0, 0, textwidth + 12, + bar_fs->ascent + bar_fs->descent + 4, 1, + r->s->c[SWM_S_COLOR_UNFOCUS].color, + r->s->c[SWM_S_COLOR_FOCUS].color); + + sw->indicator = w; + TAILQ_INSERT_TAIL(&search_wl, sw, entry); + + gc = XCreateGC(display, w, 0, &gcv); + XSetFont(display, gc, bar_fs->fid); + XMapRaised(display, w); + XSetForeground(display, gc, r->s->c[SWM_S_COLOR_BAR].color); + + XDrawString(display, w, gc, 6, bar_fs->ascent + 2, s, len); + + fprintf(lfile, "%d\n", i); + i++; + } + + fclose(lfile); +} + +void search_resp_uniconify(char *resp, unsigned long len) { unsigned char *name; @@ -3274,6 +3423,96 @@ search_resp_uniconify(char *resp, unsigned long len) } } +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; + } + } +} + +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; + } + 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); +} + +void +search_resp_search_window(char *resp, unsigned long len) +{ + char *s; + int idx; + const char *errstr; + struct search_window *sw; + + DNPRINTF(SWM_D_MISC, "search_resp_search_window: resp %s\n", resp); + + s = strdup(resp); + if (!s) { + DNPRINTF(SWM_D_MISC, "search_resp_search_window: strdup: %s", + strerror(errno)); + return; + } + + idx = strtonum(s, 1, INT_MAX, &errstr); + if (errstr) { + DNPRINTF(SWM_D_MISC, "window idx is %s: %s", + errstr, s); + free(s); + return; + } + free(s); + + TAILQ_FOREACH(sw, &search_wl, entry) + if (idx == sw->idx) { + focus_win(sw->win); + break; + } +} + #define MAX_RESP_LEN 1024 void @@ -3299,15 +3538,33 @@ search_do_resp(void) goto done; } resp[rbytes] = '\0'; + + /* XXX: + * Older versions of dmenu (Atleast pre 4.4.1) do not send a + * newline, so work around that by sanitizing the resp now. + */ + resp[strcspn(resp, "\n")] = '\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; + case SWM_SEARCH_SEARCH_WINDOW: + search_resp_search_window(resp, len); + break; } done: + if (search_resp_action == SWM_SEARCH_SEARCH_WINDOW) + search_win_cleanup(); + search_resp_action = SWM_SEARCH_NONE; close(select_resp_pipe[0]); free(resp); @@ -3557,9 +3814,7 @@ move_window(struct ws_win *win) { unsigned int mask; XWindowChanges wc; - struct swm_region *r; - r = root_to_region(win->wa.root); bzero(&wc, sizeof wc); mask = CWX | CWY; wc.x = win->g.x; @@ -3762,6 +4017,9 @@ enum keyfuncid { kf_move_right, kf_move_up, kf_move_down, + kf_name_workspace, + kf_search_workspace, + kf_search_win, kf_dumpwins, /* MUST BE LAST */ kf_invalid }; @@ -3850,6 +4108,9 @@ struct keyfunc { { "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} }, + { "search_win", search_win, {0} }, { "dumpwins", dumpwins, {0} }, /* MUST BE LAST */ { "invalid key func", NULL, {0} }, }; @@ -4189,6 +4450,13 @@ setup_spawn(void) " -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 */ @@ -4453,6 +4721,9 @@ setup_keys(void) 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); + setkeybinding(MODKEY, XK_f, kf_search_win, NULL); #ifdef SWM_DEBUG setkeybinding(MODKEY|ShiftMask, XK_d, kf_dumpwins, NULL); #endif @@ -6322,6 +6593,7 @@ setup_screens(void) 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;