X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=44b614c5c3636470f14c13c09cc673624813852c;hb=726356b44efcb6e1d4d700bc8785c0966b95542f;hp=1575a43ad6d307f70f4d958ee3833972fdf870e1;hpb=63eea690871eadbb0998dd035cf8d2759f495016;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 1575a43..44b614c 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -207,12 +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_NAME_WORKSPACE, - SWM_SEARCH_SEARCH_WORKSPACE + SWM_SEARCH_SEARCH_WORKSPACE, + SWM_SEARCH_SEARCH_WINDOW }; /* dialog windows */ @@ -3309,6 +3320,86 @@ search_workspace(struct swm_region *r, union arg *args) } 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; @@ -3361,7 +3452,6 @@ search_resp_name_workspace(char *resp, unsigned long len) strerror(errno)); return; } - ws->name[len - 1] = '\0'; } } @@ -3381,7 +3471,6 @@ search_resp_search_workspace(char *resp, unsigned long len) strerror(errno)); return; } - q[len - 1] = '\0'; p = strchr(q, ':'); if (p != NULL) *p = '\0'; @@ -3397,6 +3486,39 @@ search_resp_search_workspace(char *resp, unsigned long len) 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 @@ -3422,6 +3544,12 @@ 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) { @@ -3434,9 +3562,15 @@ search_do_resp(void) 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); @@ -3893,6 +4027,7 @@ enum keyfuncid { kf_move_down, kf_name_workspace, kf_search_workspace, + kf_search_win, kf_dumpwins, /* MUST BE LAST */ kf_invalid }; @@ -3983,6 +4118,7 @@ struct keyfunc { { "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} }, }; @@ -4595,6 +4731,7 @@ setup_keys(void) 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