X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=71451089735c23e87c1cb992f5e04a4b5ae9b20b;hb=8e288840b3294c3d4f46a7205b8f3c8df3607e21;hp=9f6d7ff8a57e7b4277ce7b8c38db7a413d8fe4d9;hpb=63f6779ee0a5d8458a290284c233767788892448;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 9f6d7ff..7145108 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -1,6 +1,6 @@ /* $scrotwm$ */ /* - * Copyright (c) 2009 Marco Peereboom + * Copyright (c) 2009-2010 Marco Peereboom * Copyright (c) 2009 Ryan McBride * Copyright (c) 2009 Darrin Chandler * Copyright (c) 2009 Pierre-Yves Ritschard @@ -52,7 +52,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "0.9.25" +#define SWM_VERSION "0.9.26" #include #include @@ -66,6 +66,7 @@ static const char *cvstag = "$scrotwm$"; #include #include #include +#include #include #include @@ -168,6 +169,7 @@ Atom aprot; Atom adelete; Atom takefocus; volatile sig_atomic_t running = 1; +volatile sig_atomic_t restart_wm = 0; int outputs = 0; int last_focus_event = FocusOut; int (*xerrorxlib)(Display *, XErrorEvent *); @@ -196,6 +198,7 @@ int bar_version = 0; sig_atomic_t bar_alarm = 0; int bar_delay = 30; int bar_enabled = 1; +int bar_at_bottom = 0; int bar_extra = 1; int bar_extra_running = 0; int bar_verbose = 1; @@ -206,6 +209,7 @@ char *clock_format = NULL; int title_name_enabled = 0; int title_class_enabled = 0; int focus_mode = SWM_FOCUS_DEFAULT; +int disable_border = 0; pid_t bar_pid; GC bar_gc; XGCValues bar_gcv; @@ -597,35 +601,47 @@ void (*handler[LASTEvent])(XEvent *) = { void sighdlr(int sig) { + int saved_errno, status; pid_t pid; + saved_errno = errno; + switch (sig) { case SIGCHLD: - while ((pid = waitpid(WAIT_ANY, NULL, WNOHANG)) != -1) { - DNPRINTF(SWM_D_MISC, "reaping: %d\n", pid); - if (pid <= 0) + while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) != 0) { + if (pid == -1) { + if (errno == EINTR) + continue; +#ifdef SWM_DEBUG + if (errno != ECHILD) + warn("sighdlr: waitpid"); +#endif /* SWM_DEBUG */ break; + } + +#ifdef SWM_DEBUG + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + warnx("sighdlr: child exit status: %d", + WEXITSTATUS(status)); + } else + warnx("sighdlr: child is terminated " + "abnormally"); +#endif /* SWM_DEBUG */ } break; + + case SIGHUP: + restart_wm = 1; + break; case SIGINT: case SIGTERM: - case SIGHUP: case SIGQUIT: running = 0; break; } -} -void -installsignal(int sig, char *name) -{ - struct sigaction sa; - - sa.sa_handler = sighdlr; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(sig, &sa, NULL) == -1) - err(1, "could not install %s handler", name); + errno = saved_errno; } unsigned long @@ -906,7 +922,12 @@ bar_refresh(void) void bar_setup(struct swm_region *r) { - int i; + int i, x, y; + + if (bar_fs) { + XFreeFont(display, bar_fs); + bar_fs = NULL; + } for (i = 0; bar_fonts[i] != NULL; i++) { bar_fs = XLoadQueryFont(display, bar_fonts[i]); @@ -917,10 +938,15 @@ bar_setup(struct swm_region *r) } if (bar_fonts[i] == NULL) errx(1, "couldn't load font"); + if (bar_fs == NULL) + errx(1, "couldn't create font structure"); + bar_height = bar_fs->ascent + bar_fs->descent + 3; + x = X(r); + y = bar_at_bottom ? (Y(r) + HEIGHT(r) - bar_height) : Y(r); r->bar_window = XCreateSimpleWindow(display, - r->s->root, X(r), Y(r), WIDTH(r) - 2, bar_height - 2, + r->s->root, x, y, WIDTH(r) - 2, bar_height - 2, 1, r->s->c[SWM_S_COLOR_BAR_BORDER].color, r->s->c[SWM_S_COLOR_BAR].color); bar_gc = XCreateGC(display, r->bar_window, 0, &bar_gcv); @@ -1083,9 +1109,8 @@ unmap_window(struct ws_win *win) set_win_state(win, IconicState); XUnmapWindow(display, win->id); - if (win->ws->r) - XSetWindowBorder(display, win->id, - win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color); + XSetWindowBorder(display, win->id, + win->s->c[SWM_S_COLOR_UNFOCUS].color); } void @@ -1229,39 +1254,56 @@ find_window(Window id) void spawn(struct swm_region *r, union arg *args) { - char *ret; - int si; + int fd; + char *ret = NULL; DNPRINTF(SWM_D_MISC, "spawn: %s\n", args->argv[0]); - /* - * The double-fork construct avoids zombie processes and keeps the code - * clean from stupid signal handlers. - */ + if (fork() == 0) { - if (fork() == 0) { - if (display) - close(ConnectionNumber(display)); - setenv("LD_PRELOAD", SWM_LIB, 1); - if (asprintf(&ret, "%d", r->ws->idx)) { - setenv("_SWM_WS", ret, 1); - free(ret); - } - if (asprintf(&ret, "%d", getpid())) { - setenv("_SWM_PID", ret, 1); - free(ret); - } - setsid(); - /* kill stdin, mplayer, ssh-add etc. need that */ - si = open("/dev/null", O_RDONLY, 0); - if (si == -1) - err(1, "open /dev/null"); - if (dup2(si, 0) == -1) - err(1, "dup2 /dev/null"); - execvp(args->argv[0], args->argv); - fprintf(stderr, "execvp failed\n"); - perror(" failed"); + if (display) + close(ConnectionNumber(display)); + + setenv("LD_PRELOAD", SWM_LIB, 1); + + if (asprintf(&ret, "%d", r->ws->idx) == -1) { + perror("_SWM_WS"); + _exit(1); + } + setenv("_SWM_WS", ret, 1); + free(ret); + ret = NULL; + + if (asprintf(&ret, "%d", getpid()) == -1) { + perror("_SWM_PID"); + _exit(1); } - exit(0); + setenv("_SWM_PID", ret, 1); + free(ret); + ret = NULL; + + if (setsid() == -1) { + perror("setsid"); + _exit(1); + } + + /* + * close stdin and stdout to prevent interaction between apps + * and the baraction script + * leave stderr open to record errors + */ + if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) { + perror("open"); + _exit(1); + } + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + if (fd > 2) + close(fd); + + execvp(args->argv[0], args->argv); + + perror("execvp"); + _exit(1); } } @@ -1349,7 +1391,7 @@ unfocus_win(struct ws_win *win) return; if (validate_ws(win->ws)) - abort(); + abort(); /* XXX replace with return at some point */ if (win->ws->r == NULL) return; @@ -1414,7 +1456,8 @@ focus_win(struct ws_win *win) return; if (validate_ws(win->ws)) - abort(); + abort(); /* XXX replace with return at some point */ + if (validate_win(win)) { kill_refs(win); return; @@ -1583,7 +1626,7 @@ cyclescr(struct swm_region *r, union arg *args) /* move mouse to region */ x = rr->g.x + 1; - y = rr->g.y + 1 + bar_enabled ? bar_height : 0; + y = rr->g.y + 1 + (bar_enabled ? bar_height : 0); XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, x, y); a.id = SWM_ARG_ID_FOCUSCUR; @@ -1700,10 +1743,10 @@ focus_prev(struct ws_win *win) /* if in max_stack try harder */ if (ws->cur_layout->flags & SWM_L_FOCUSPREV) { - if (cur_focus != ws->focus_prev) - winfocus = ws->focus_prev; - else if (cur_focus != ws->focus) - winfocus = ws->focus; + if (cur_focus != ws->focus_prev) + winfocus = ws->focus_prev; + else if (cur_focus != ws->focus) + winfocus = ws->focus; else winfocus = TAILQ_PREV(win, ws_win_list, entry); if (winfocus) @@ -1757,7 +1800,7 @@ focus(struct swm_region *r, union arg *args) winlostfocus = cur_focus; switch (args->id) { - case SWM_ARG_ID_FOCUSPREV: + case SWM_ARG_ID_FOCUSPREV: winfocus = TAILQ_PREV(cur_focus, ws_win_list, entry); if (winfocus == NULL) winfocus = TAILQ_LAST(wl, ws_win_list); @@ -1840,7 +1883,8 @@ stack(void) { g.w -= 2; g.h -= 2; if (bar_enabled) { - g.y += bar_height; + if (!bar_at_bottom) + g.y += bar_height; g.h -= bar_height; } r->ws->cur_layout->l_stack(r->ws, &g); @@ -2113,7 +2157,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) win_g.y += last_h + 2; bzero(&wc, sizeof wc); - if (bar_enabled == 0 && winno == 1){ + if (disable_border && bar_enabled == 0 && winno == 1){ wc.border_width = 0; win_g.w += 2; win_g.h += 2; @@ -3514,8 +3558,9 @@ enum { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_STACK_ENABLED, SWM_S_CLOCK_ENABLED, SWM_S_CLOCK_FORMAT, SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, SWM_S_SS_ENABLED, SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED, SWM_S_TITLE_NAME_ENABLED, - SWM_S_FOCUS_MODE, SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM, - SWM_S_SS_APP, SWM_S_DIALOG_RATIO + SWM_S_FOCUS_MODE, SWM_S_DISABLE_BORDER, 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 }; int @@ -3528,6 +3573,9 @@ setconfvalue(char *selector, char *value, int flags) case SWM_S_BAR_ENABLED: bar_enabled = atoi(value); break; + case SWM_S_BAR_AT_BOTTOM: + bar_at_bottom = atoi(value); + break; case SWM_S_STACK_ENABLED: stack_enabled = atoi(value); break; @@ -3569,6 +3617,9 @@ setconfvalue(char *selector, char *value, int flags) else err(1, "focus_mode"); break; + case SWM_S_DISABLE_BORDER: + disable_border = atoi(value); + break; case SWM_S_BAR_FONT: free(bar_fonts[0]); if ((bar_fonts[0] = strdup(value)) == NULL) @@ -3635,6 +3686,7 @@ struct config_option { }; struct config_option configopt[] = { { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, + { "bar_at_bottom", setconfvalue, SWM_S_BAR_AT_BOTTOM }, { "bar_border", setconfcolor, SWM_S_COLOR_BAR_BORDER }, { "bar_color", setconfcolor, SWM_S_COLOR_BAR }, { "bar_font_color", setconfcolor, SWM_S_COLOR_BAR_FONT }, @@ -3661,6 +3713,7 @@ struct config_option configopt[] = { { "title_class_enabled", setconfvalue, SWM_S_TITLE_CLASS_ENABLED }, { "title_name_enabled", setconfvalue, SWM_S_TITLE_NAME_ENABLED }, { "focus_mode", setconfvalue, SWM_S_FOCUS_MODE }, + { "disable_border", setconfvalue, SWM_S_DISABLE_BORDER }, }; @@ -4018,9 +4071,17 @@ focus_magic(struct ws_win *win, int do_trans) if (win->child_trans->take_focus) client_msg(win, takefocus); } else { - focus_win(win->child_trans); - if (win->child_trans->take_focus) - client_msg(win->child_trans, takefocus); + /* make sure transient hasn't dissapeared */ + if (validate_win(win->child_trans) == 0) { + focus_win(win->child_trans); + if (win->child_trans->take_focus) + client_msg(win->child_trans, takefocus); + } else { + win->child_trans = NULL; + focus_win(win); + if (win->take_focus) + client_msg(win, takefocus); + } } } else { /* regular focus */ @@ -4553,6 +4614,7 @@ new_region(struct swm_screen *s, int x, int y, int w, int h) r->ws = ws; r->ws_prior = NULL; ws->r = r; + outputs++; TAILQ_INSERT_TAIL(&s->rl, r, entry); } @@ -4578,10 +4640,10 @@ scan_xrandr(int i) TAILQ_REMOVE(&screens[i].rl, r, entry); TAILQ_INSERT_TAIL(&screens[i].orl, r, entry); } + outputs = 0; /* map virtual screens onto physical screens */ #ifdef SWM_XRR_HAS_CRTC - outputs = 0; if (xrandr_support) { sr = XRRGetScreenResources(display, screens[i].root); if (sr == NULL) @@ -4595,7 +4657,6 @@ scan_xrandr(int i) ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]); if (ci->noutput == 0) continue; - outputs++; if (ci != NULL && ci->mode == None) new_region(&screens[i], 0, 0, @@ -4798,6 +4859,7 @@ main(int argc, char *argv[]) XEvent e; int xfd, i; fd_set rd; + struct sigaction sact; start_argv = argv; fprintf(stderr, "Welcome to scrotwm V%s cvs tag: %s\n", @@ -4811,12 +4873,19 @@ main(int argc, char *argv[]) if (active_wm()) errx(1, "other wm running"); - /* handle some signale */ - installsignal(SIGINT, "INT"); - installsignal(SIGHUP, "HUP"); - installsignal(SIGQUIT, "QUIT"); - installsignal(SIGTERM, "TERM"); - installsignal(SIGCHLD, "CHLD"); + /* handle some signals */ + bzero(&sact, sizeof(sact)); + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; + sact.sa_handler = sighdlr; + sigaction(SIGINT, &sact, NULL); + sigaction(SIGQUIT, &sact, NULL); + sigaction(SIGTERM, &sact, NULL); + sigaction(SIGHUP, &sact, NULL); + + sact.sa_handler = sighdlr; + sact.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &sact, NULL); astate = XInternAtom(display, "WM_STATE", False); aprot = XInternAtom(display, "WM_PROTOCOLS", False); @@ -4904,7 +4973,7 @@ main(int argc, char *argv[]) if (ScreenCount(display) > 1 || outputs > 1) XWarpPointer(display, None, rr->s[0].root, 0, 0, 0, 0, rr->g.x, - rr->g.y + bar_enabled ? bar_height : 0); + rr->g.y + (bar_enabled ? bar_height : 0)); a.id = SWM_ARG_ID_FOCUSCUR; focus(rr, &a); @@ -4919,6 +4988,8 @@ main(int argc, char *argv[]) if (select(xfd + 1, &rd, NULL, NULL, &tv) == -1) if (errno != EINTR) DNPRINTF(SWM_D_MISC, "select failed"); + if (restart_wm == 1) + restart(NULL, NULL); if (running == 0) goto done; if (bar_alarm) {