X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=ca2a281be70c36cbb6c22db27e5fdcf51c2d86f6;hb=238662f0274ef1a90c168bedd4eb24281f278eaa;hp=8b59687522a9133b01b38d6ef7b6aa630eaec0f2;hpb=e5cdfa88418bbf02af8276c3918ddfd7c1fcba37;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 8b59687..ca2a281 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -90,6 +91,7 @@ #endif /* #define SWM_DEBUG */ +/* #define SWM_DEBUG */ #ifdef SWM_DEBUG #define DPRINTF(x...) do { if (swm_debug) fprintf(stderr, x); } while(0) #define DNPRINTF(n,x...) do { if (swm_debug & n) fprintf(stderr, x); } while(0) @@ -141,10 +143,16 @@ int cycle_visible = 0; double dialog_ratio = .6; /* status bar */ #define SWM_BAR_MAX (128) +char *bar_argv[] = { NULL, NULL }; +int bar_pipe[2]; +char bar_ext[SWM_BAR_MAX]; sig_atomic_t bar_alarm = 0; int bar_enabled = 1; +int bar_extra = 1; +int bar_extra_running = 0; int bar_verbose = 1; int bar_height = 0; +pid_t bar_pid; GC bar_gc; XGCValues bar_gcv; int bar_fidx = 0; @@ -155,12 +163,10 @@ char *bar_fonts[] = { NULL }; - - /* terminal + args */ -char *spawn_term[] = { "xterm", NULL }; -char *spawn_menu[] = { "dmenu_run", "-fn", NULL, - "-nb", NULL, "-nf", NULL, "-sb", NULL, "-sf", NULL, NULL }; +char *spawn_term[] = { "xterm", NULL }; +char *spawn_menu[] = { "dmenu_run", "-fn", NULL, + "-nb", NULL, "-nf", NULL, "-sb", NULL, "-sf", NULL, NULL }; #define SWM_MENU_FN (2) #define SWM_MENU_NB (4) @@ -189,7 +195,6 @@ struct swm_region { }; TAILQ_HEAD(swm_region_list, swm_region); - struct ws_win { TAILQ_ENTRY(ws_win) entry; Window id; @@ -245,7 +250,6 @@ struct workspace { } l_state; }; - enum { SWM_S_COLOR_BAR, SWM_S_COLOR_BAR_BORDER, SWM_S_COLOR_BAR_FONT, SWM_S_COLOR_FOCUS, SWM_S_COLOR_UNFOCUS, SWM_S_COLOR_MAX }; @@ -399,22 +403,24 @@ conf_load(char *filename) if (!strncmp(var, "bar_enabled", strlen("bar_enabled"))) bar_enabled = atoi(val); else if (!varmatch(var, "bar_border", &i)) - setscreencolor(var, i, SWM_S_COLOR_BAR_BORDER); + setscreencolor(val, i, SWM_S_COLOR_BAR_BORDER); else if (!varmatch(var, "bar_color", &i)) - setscreencolor(var, i, SWM_S_COLOR_BAR); + setscreencolor(val, i, SWM_S_COLOR_BAR); else if (!varmatch(var, "bar_font_color", &i)) - setscreencolor(var, i, SWM_S_COLOR_BAR_FONT); + setscreencolor(val, i, SWM_S_COLOR_BAR_FONT); else if (!strncmp(var, "bar_font", strlen("bar_font"))) asprintf(&bar_fonts[0], "%s", val); + else if (!strncmp(var, "bar_action", strlen("bar_action"))) + asprintf(&bar_argv[0], "%s", val); else goto bad; break; case 'c': if (!varmatch(var, "color_focus", &i)) - setscreencolor(var, i, SWM_S_COLOR_FOCUS); + setscreencolor(val, i, SWM_S_COLOR_FOCUS); else if (!varmatch(var, "color_unfocus", &i)) - setscreencolor(var, i, SWM_S_COLOR_UNFOCUS); + setscreencolor(val, i, SWM_S_COLOR_UNFOCUS); else if (!strncmp(var, "cycle_empty", strlen("cycle_empty"))) cycle_visible = atoi(val); else if (!strncmp(var, "cycle_visible", strlen("cycle_visible"))) @@ -451,6 +457,18 @@ bad: } void +socket_setnonblock(int fd) +{ + int flags; + + if ((flags = fcntl(fd, F_GETFL, 0)) == -1) + err(1, "fcntl F_GETFL"); + flags |= O_NONBLOCK; + if ((flags = fcntl(fd, F_SETFL, flags)) == -1) + err(1, "fcntl F_SETFL"); +} + +void bar_print(struct swm_region *r, char *s) { XClearWindow(display, r->bar_window); @@ -460,30 +478,63 @@ bar_print(struct swm_region *r, char *s) } void +bar_extra_stop(void) +{ + if (bar_pipe[0]) { + close(bar_pipe[0]); + bzero(bar_pipe, sizeof bar_pipe); + } + if (bar_pid) { + kill(bar_pid, SIGTERM); + bar_pid = 0; + } + strlcpy(bar_ext, "", sizeof bar_ext); + bar_extra = 0; +} + +void bar_update(void) { time_t tmt; struct tm tm; struct swm_region *r; int i, x; + size_t len; char s[SWM_BAR_MAX]; - char e[SWM_BAR_MAX]; - + char loc[SWM_BAR_MAX]; + char *b; + if (bar_enabled == 0) return; + if (bar_extra && bar_extra_running) { + /* ignore short reads; it'll correct itself */ + while ((b = fgetln(stdin, &len)) != NULL) + if (b && b[len - 1] == '\n') { + b[len - 1] = '\0'; + strlcpy(bar_ext, b, sizeof bar_ext); + } + if (b == NULL && errno != EAGAIN) { + fprintf(stderr, "bar_extra failed: errno: %d %s\n", + errno, strerror(errno)); + bar_extra_stop(); + } + } else + strlcpy(bar_ext, "", sizeof bar_ext); + time(&tmt); localtime_r(&tmt, &tm); strftime(s, sizeof s, "%a %b %d %R %Z %Y", &tm); for (i = 0; i < ScreenCount(display); i++) { x = 1; TAILQ_FOREACH(r, &screens[i].rl, entry) { - snprintf(e, sizeof e, "%s %d:%d", - s, x++, r->ws->idx + 1); - bar_print(r, e); + snprintf(loc, sizeof loc, "%s %d:%d %s", + s, x++, r->ws->idx + 1, bar_ext); + bar_print(r, loc); } } XSync(display, False); + alarm(60); } @@ -524,6 +575,55 @@ bar_toggle(struct swm_region *r, union arg *args) } void +bar_refresh(void) +{ + XSetWindowAttributes wa; + struct swm_region *r; + int i; + + /* do this here because the conf file is in memory */ + if (bar_extra && bar_extra_running == 0 && bar_argv[0]) { + /* launch external status app */ + bar_extra_running = 1; + if (pipe(bar_pipe) == -1) + err(1, "pipe error"); + socket_setnonblock(bar_pipe[0]); + socket_setnonblock(bar_pipe[1]); /* XXX hmmm, really? */ + if (dup2(bar_pipe[0], 0) == -1) + errx(1, "dup2"); + if (dup2(bar_pipe[1], 1) == -1) + errx(1, "dup2"); + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + err(1, "could not disable SIGPIPE"); + switch (bar_pid = fork()) { + case -1: + err(1, "cannot fork"); + break; + case 0: /* child */ + close(bar_pipe[0]); + execvp(bar_argv[0], bar_argv); + err(1, "%s external app failed", bar_argv[0]); + break; + default: /* parent */ + close(bar_pipe[1]); + break; + } + } + + bzero(&wa, sizeof wa); + for (i = 0; i < ScreenCount(display); i++) + TAILQ_FOREACH(r, &screens[i].rl, entry) { + wa.border_pixel = + screens[i].c[SWM_S_COLOR_BAR_BORDER].color; + wa.background_pixel = + screens[i].c[SWM_S_COLOR_BAR].color; + XChangeWindowAttributes(display, r->bar_window, + CWBackPixel | CWBorderPixel, &wa); + } + bar_update(); +} + +void bar_setup(struct swm_region *r) { int i; @@ -552,27 +652,7 @@ bar_setup(struct swm_region *r) if (signal(SIGALRM, bar_signal) == SIG_ERR) err(1, "could not install bar_signal"); - bar_update(); -} - -void -bar_refresh(void) -{ - XSetWindowAttributes wa; - struct swm_region *r; - int i; - - bzero(&wa, sizeof wa); - for (i = 0; i < ScreenCount(display); i++) - TAILQ_FOREACH(r, &screens[i].rl, entry) { - wa.border_pixel = - screens[i].c[SWM_S_COLOR_BAR_BORDER].color; - wa.background_pixel = - screens[i].c[SWM_S_COLOR_BAR].color; - XChangeWindowAttributes(display, r->bar_window, - CWBackPixel | CWBorderPixel, &wa); - } - bar_update(); + bar_refresh(); } void @@ -631,6 +711,8 @@ restart(struct swm_region *r, union arg *args) if (signal(SIGALRM, SIG_IGN) == SIG_ERR) errx(1, "can't disable alarm"); + bar_extra_stop(); + bar_extra = 1; XCloseDisplay(display); execvp(start_argv[0], start_argv); fprintf(stderr, "execvp failed\n"); @@ -704,7 +786,6 @@ spawn(struct swm_region *r, union arg *args) wait(0); } - void spawnmenu(struct swm_region *r, union arg *args) { @@ -1025,7 +1106,6 @@ stack_floater(struct ws_win *win, struct swm_region *r) XConfigureWindow(display, win->id, mask, &wc); } - void vertical_config(struct workspace *ws, int id) { @@ -1118,6 +1198,9 @@ vertical_stack(struct workspace *ws, struct swm_geometry *g) { win->g.h = wc.height = gg.h; mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; XConfigureWindow(display, win->id, mask, &wc); + /* + fprintf(stderr, "vertical_stack: win %d x %d y %d w %d h %d bw %d\n", win->id, win->g.x, win->g.y, win->g.w , win->g.h, wc.border_width); + */ } XMapRaised(display, win->id); @@ -1129,7 +1212,6 @@ vertical_stack(struct workspace *ws, struct swm_geometry *g) { focus_win(winfocus); /* has to be done outside of the loop */ } - void horizontal_config(struct workspace *ws, int id) { @@ -1312,6 +1394,14 @@ send_to_ws(struct swm_region *r, union arg *args) stack(); } +void +wkill(struct swm_region *r, union arg *args) +{ + DNPRINTF(SWM_D_MISC, "wkill\n"); + if(r->ws->focus != NULL) + XKillClient(display, r->ws->focus->id); +} + /* key definitions */ struct key { unsigned int mod; @@ -1361,6 +1451,7 @@ struct key { { MODKEY, XK_b, bar_toggle, {0} }, { MODKEY, XK_Tab, focus, {.id = SWM_ARG_ID_FOCUSNEXT} }, { MODKEY | ShiftMask, XK_Tab, focus, {.id = SWM_ARG_ID_FOCUSPREV} }, + { MODKEY | ShiftMask, XK_x, wkill, {0} }, }; void @@ -1555,7 +1646,9 @@ manage_window(Window id, struct workspace *ws) win->g.h = win->wa.height; win->g.x = win->wa.x; win->g.y = win->wa.y; - + /* + fprintf(stderr, "manage window: %d x %d y %d w %d h %d\n", win->id, win->g.x, win->g.y, win->g.w, win->g.h); + */ /* XXX make this a table */ bzero(&ch, sizeof ch); if (XGetClassHint(display, win->id, &ch)) { @@ -1582,7 +1675,7 @@ configurerequest(XEvent *e) { XConfigureRequestEvent *ev = &e->xconfigurerequest; struct ws_win *win; - int new = 1; + int new = 0; XWindowChanges wc; if ((win = find_window(ev->window)) == NULL) @@ -1591,6 +1684,10 @@ configurerequest(XEvent *e) if (new) { DNPRINTF(SWM_D_EVENT, "configurerequest: new window: %lu\n", ev->window); + /* + fprintf(stderr, "configurerequest: new window: %lu x %d y %d w %d h %d bw %d s %d sm %d\n", + ev->window, ev->x, ev->y, ev->width, ev->height, ev->border_width, ev->above, ev->detail); + */ bzero(&wc, sizeof wc); wc.x = ev->x; wc.y = ev->y; @@ -1601,6 +1698,10 @@ configurerequest(XEvent *e) wc.stack_mode = ev->detail; XConfigureWindow(display, ev->window, ev->value_mask, &wc); } else { + /* + fprintf(stderr, "configurerequest: change window: %lu\n", + ev->window); + */ DNPRINTF(SWM_D_EVENT, "configurerequest: change window: %lu\n", ev->window); if (win->floating) { @@ -1923,7 +2024,7 @@ setup_screens(void) else ncrtc = sr->ncrtc; - for (c = 0; c < ncrtc; c++) { + for (c = 0, ci = NULL; c < ncrtc; c++) { ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]); if (ci->noutput == 0) continue; @@ -1937,7 +2038,8 @@ setup_screens(void) ci->x, ci->y, ci->width, ci->height); w++; } - XRRFreeCrtcInfo(ci); + if (ci) + XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); #else new_region(&screens[i], &screens[i].ws[w], 0, 0,