#include <stdlib.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <locale.h>
#include <unistd.h>
#include <time.h>
#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)
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;
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)
};
TAILQ_HEAD(swm_region_list, swm_region);
-
struct ws_win {
TAILQ_ENTRY(ws_win) entry;
Window id;
} 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 };
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")))
}
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);
}
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);
}
}
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;
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
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");
wait(0);
}
-
void
spawnmenu(struct swm_region *r, union arg *args)
{
XConfigureWindow(display, win->id, mask, &wc);
}
-
void
vertical_config(struct workspace *ws, int id)
{
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);
focus_win(winfocus); /* has to be done outside of the loop */
}
-
void
horizontal_config(struct workspace *ws, int id)
{
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;
{ 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
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)) {
{
XConfigureRequestEvent *ev = &e->xconfigurerequest;
struct ws_win *win;
- int new = 1;
+ int new = 0;
XWindowChanges wc;
if ((win = find_window(ev->window)) == NULL)
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;
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) {
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;
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,