/* $scrotwm$ */
/*
- * Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2009-2010 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2009 Ryan McBride <mcbride@countersiege.com>
* Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
* Copyright (c) 2009 Pierre-Yves Ritschard <pyr@spootnik.org>
static const char *cvstag = "$scrotwm$";
-#define SWM_VERSION "0.9.25"
+#define SWM_VERSION "0.9.26"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <util.h>
#include <pwd.h>
+#include <paths.h>
#include <ctype.h>
#include <sys/types.h>
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 *);
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;
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;
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
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]);
}
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);
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
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);
+ }
+ 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);
}
- exit(0);
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ if (fd > 2)
+ close(fd);
+
+ execvp(args->argv[0], args->argv);
+
+ perror("execvp");
+ _exit(1);
}
}
return;
if (validate_ws(win->ws))
- abort();
+ abort(); /* XXX replace with return at some point */
if (win->ws->r == NULL)
return;
return;
if (validate_ws(win->ws))
- abort();
+ abort(); /* XXX replace with return at some point */
+
if (validate_win(win)) {
kill_refs(win);
return;
/* 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;
/* 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)
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);
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);
win_g.y += last_h + 2;
bzero(&wc, sizeof wc);
- wc.border_width = 1;
+ if (disable_border && bar_enabled == 0 && winno == 1){
+ wc.border_width = 0;
+ win_g.w += 2;
+ win_g.h += 2;
+ } else
+ wc.border_width = 1;
reconfigure = 0;
if (rot) {
if (win->g.x != win_g.y || win->g.y != win_g.x ||
if (win->g.x != gg.x || win->g.y != gg.y || win->g.w != gg.w ||
win->g.h != gg.h) {
bzero(&wc, sizeof wc);
- wc.border_width = 1;
win->g.x = wc.x = gg.x;
win->g.y = wc.y = gg.y;
- win->g.w = wc.width = gg.w;
- win->g.h = wc.height = gg.h;
+ if (bar_enabled){
+ wc.border_width = 1;
+ win->g.w = wc.width = gg.w;
+ win->g.h = wc.height = gg.h;
+ } else {
+ wc.border_width = 0;
+ win->g.w = wc.width = gg.w + 2;
+ win->g.h = wc.height = gg.h + 2;
+ }
mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
XConfigureWindow(display, win->id, mask, &wc);
configreq_win(win);
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
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;
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)
};
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 },
{ "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 },
};
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 */
r->ws = ws;
r->ws_prior = NULL;
ws->r = r;
+ outputs++;
TAILQ_INSERT_TAIL(&s->rl, r, entry);
}
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)
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,
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",
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);
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);
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) {