char *bar_fonts;
XftColor bar_font_color;
struct passwd *pwd;
+char *startup_exception;
+unsigned int nr_exceptions = 0;
/* layout manager data */
struct swm_geometry {
void wkill(struct swm_region *, union arg *);
void workaround(void);
void xft_init(struct swm_region *);
+void _add_startup_exception(const char *, va_list);
+void add_startup_exception(const char *, ...);
RB_PROTOTYPE(key_tree, key, entry, key_cmp);
RB_GENERATE(key_tree, key, entry, key_cmp);
continue;
}
- bar_fmt(fmtexp, fmtnew, r, sizeof fmtnew);
- bar_replace(fmtnew, fmtrep, r, sizeof fmtrep);
+ if (startup_exception)
+ snprintf(fmtrep, sizeof fmtrep, "total "
+ "exceptions: %d, first exception: %s",
+ nr_exceptions,
+ startup_exception);
+ else {
+ bar_fmt(fmtexp, fmtnew, r, sizeof fmtnew);
+ bar_replace(fmtnew, fmtrep, r, sizeof fmtrep);
+ }
if (bar_font_legacy)
bar_print_legacy(r, fmtrep);
else
r->bar->id = xcb_generate_id(conn);
wa[0] = r->s->c[SWM_S_COLOR_BAR].pixel;
wa[1] = r->s->c[SWM_S_COLOR_BAR_BORDER_UNFOCUS].pixel;
- wa[2] = XCB_EVENT_MASK_EXPOSURE;
+ wa[2] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION |
+ XCB_EVENT_MASK_POINTER_MOTION_HINT;
xcb_create_window(conn, XCB_COPY_FROM_PARENT, r->bar->id, r->s->root,
X(r->bar), Y(r->bar), WIDTH(r->bar), HEIGHT(r->bar),
{
struct swm_geometry gg = *g;
struct ws_win *w, *win = NULL, *parent = NULL;
- int winno, num_screens;
+ int winno;
DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
DNPRINTF(SWM_D_STACK, "max_stack: win: 0x%x\n", win->id);
/* maximize all top level windows */
- num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
TAILQ_FOREACH(w, &ws->winlist, entry) {
if (w->transient || w->iconic)
continue;
+ if (!w->mapped && w != win)
+ map_window(w);
+
if (w->floating && !w->floatmaxed) {
/*
* retain geometry for retrieval on exit from
update_window(w);
}
-
- /* Unmap unwanted windows if not multi-screen. */
- if (num_screens <= 1 && outputs <= 1 && w != win &&
- w != parent && w->transient != win->id)
- unmap_window(w);
}
- /* If a parent exists, map it first. */
+ /* If a parent exists, map/raise it first. */
if (parent) {
map_window(parent);
}
}
- /* Map focused window. */
+ /* Map/raise focused window. */
map_window(win);
- /* Finally, map children of focus window. */
+ /* Finally, map/raise children of focus window. */
TAILQ_FOREACH(w, &ws->winlist, entry)
if (w->transient == win->id && !w->iconic) {
stack_floater(w, ws->r);
free(r);
/* Use WM_NAME instead; no UTF-8. */
c = xcb_get_property(conn, 0, win, XCB_ATOM_WM_NAME,
- XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
+ XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
r = xcb_get_property_reply(conn, c, NULL);
if (!r)
}
if (r->length > 0)
name = strndup(xcb_get_property_value(r),
- xcb_get_property_value_length(r));
+ xcb_get_property_value_length(r));
free(r);
}
int
setconfspawn(char *selector, char *value, int flags)
{
- char *args;
-
- /* suppress unused warning since var is needed */
- (void)flags;
+ char *args;
+ char which[PATH_MAX];
+ size_t i;
args = expand_tilde(value);
DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, args);
+ /* verify we have the goods */
+ snprintf(which, sizeof which, "which %s", value);
+ for (i = strlen("which "); i < strlen(which); i++)
+ if (which[i] == ' ') {
+ which[i] = '\0';
+ break;
+ }
+ if (flags == 0 && system(which) != 0)
+ add_startup_exception("could not find %s",
+ &which[strlen("which ")]);
+
setspawn(selector, args);
free(args);
{
setconfspawn("term", "xterm", 0);
setconfspawn("spawn_term", "xterm", 0);
- setconfspawn("screenshot_all", "screenshot.sh full", 0);
- setconfspawn("screenshot_wind", "screenshot.sh window", 0);
- setconfspawn("lock", "xlock", 0);
- setconfspawn("initscr", "initscreen.sh", 0);
setconfspawn("menu", "dmenu_run"
" -fn $bar_font"
" -nb $bar_color"
" -nf $bar_font_color"
" -sb $bar_border"
" -sf $bar_color", 0);
+
+ /* these are not verified for existence */
+ setconfspawn("lock", "xlock", 1);
+ setconfspawn("screenshot_all", "screenshot.sh full", 1);
+ setconfspawn("screenshot_wind", "screenshot.sh window", 1);
+ setconfspawn("initscr", "initscreen.sh", 1);
}
/* key bindings */
{ "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT },
};
+void
+_add_startup_exception(const char *fmt, va_list ap)
+{
+ if (vasprintf(&startup_exception, fmt, ap) == -1)
+ warn("%s: asprintf", __func__);
+}
+
+void
+add_startup_exception(const char *fmt, ...)
+{
+ va_list ap;
+
+ nr_exceptions++;
+
+ if (startup_exception)
+ return;
+
+ /* force bar to be enabled due to exception */
+ bar_enabled = 1;
+
+ va_start(ap, fmt);
+ _add_startup_exception(fmt, ap);
+ va_end(ap);
+}
+
int
conf_load(const char *filename, int keymapping)
{
FILE *config;
- char *line, *cp, *optsub, *optval;
+ char *line = NULL, *cp, *optsub, *optval;
size_t linelen, lineno = 0;
int wordlen, i, optidx;
struct config_option *opt = NULL;
}
while (!feof(config)) {
+ if (line)
+ free(line);
+
if ((line = fparseln(config, &linelen, &lineno, NULL, 0))
== NULL) {
if (ferror(config))
cp += strspn(cp, " \t\n"); /* eat whitespace */
if (cp[0] == '\0') {
/* empty line */
- free(line);
continue;
}
/* get config option */
wordlen = strcspn(cp, "=[ \t\n");
if (wordlen == 0) {
- warnx("%s: line %zd: no option found",
+ add_startup_exception("%s: line %zd: no option found",
filename, lineno);
- goto out;
+ continue;
}
optidx = -1;
for (i = 0; i < LENGTH(configopt); i++) {
}
}
if (optidx == -1) {
- warnx("%s: line %zd: unknown option %.*s",
- filename, lineno, wordlen, cp);
- goto out;
+ add_startup_exception("%s: line %zd: unknown option "
+ "%.*s", filename, lineno, wordlen, cp);
+ continue;
}
if (keymapping && opt && strcmp(opt->optname, "bind")) {
- warnx("%s: line %zd: invalid option %.*s",
- filename, lineno, wordlen, cp);
- goto out;
+ add_startup_exception("%s: line %zd: invalid option "
+ "%.*s", filename, lineno, wordlen, cp);
+ continue;
}
cp += wordlen;
cp += strspn(cp, " \t\n"); /* eat whitespace */
+
+ /* from here on out we call goto invalid to continue */
+
/* get [selector] if any */
optsub = NULL;
if (*cp == '[') {
wordlen = strcspn(cp, "]");
if (*cp != ']') {
if (wordlen == 0) {
- warnx("%s: line %zd: syntax error",
- filename, lineno);
- goto out;
+ add_startup_exception("%s: line %zd: "
+ "syntax error", filename, lineno);
+ goto invalid;
}
if (asprintf(&optsub, "%.*s", wordlen, cp) ==
-1) {
- warnx("%s: line %zd: unable to allocate"
- "memory for selector", filename,
- lineno);
- goto out;
+ add_startup_exception("%s: line %zd: "
+ "unable to allocatememory for "
+ "selector", filename, lineno);
+ goto invalid;
}
}
cp += wordlen;
cp += strspn(cp, "= \t\n"); /* eat trailing */
/* get RHS value */
optval = strdup(cp);
+ if (strlen(optval) == 0) {
+ add_startup_exception("%s: line %zd: must supply value "
+ "to %s", filename, lineno,
+ configopt[optidx].optname);
+ goto invalid;
+ }
/* call function to deal with it all */
if (configopt[optidx].func(optsub, optval,
- configopt[optidx].funcflags) != 0)
- errx(1, "%s: line %zd: invalid data for %s",
- filename, lineno, configopt[optidx].optname);
- free(optval);
- free(optsub);
- free(line);
+ configopt[optidx].funcflags) != 0) {
+ add_startup_exception("%s: line %zd: invalid data for "
+ "%s", filename, lineno, configopt[optidx].optname);
+ goto invalid;
+ }
+invalid:
+ if (optval) {
+ free(optval);
+ optval = NULL;
+ }
+ if (optsub) {
+ free(optsub);
+ optsub = NULL;
+ }
}
+ if (line)
+ free(line);
fclose(config);
DNPRINTF(SWM_D_CONF, "conf_load: end\n");
return (0);
-
-out:
- free(line);
- fclose(config);
- DNPRINTF(SWM_D_CONF, "conf_load: end with error.\n");
-
- return (1);
}
void
int ncrtc = 0;
#endif /* SWM_XRR_HAS_CRTC */
struct swm_region *r;
+ struct ws_win *win;
int num_screens;
xcb_randr_get_screen_resources_current_cookie_t src;
xcb_randr_get_screen_resources_current_reply_t *srr;
screen->height_in_pixels);
out:
+ /* Cleanup unused previously visible workspaces. */
+ TAILQ_FOREACH(r, &screens[i].orl, entry) {
+ TAILQ_FOREACH(win, &r->ws->winlist, entry)
+ unmap_window(win);
+
+ /* The screen shouldn't focus on an unused region. */
+ if (screens[i].r_focus == r)
+ screens[i].r_focus = NULL;
+ }
+
DNPRINTF(SWM_D_MISC, "scan_xrandr: done.\n");
}
print_win_geom(e->root);
#endif
/* add bars to all regions */
- for (i = 0; i < num_screens; i++)
+ for (i = 0; i < num_screens; i++) {
TAILQ_FOREACH(r, &screens[i].rl, entry)
bar_setup(r);
+ }
+
stack();
+
+ /* Make sure a region has focus on each screen. */
+ for (i = 0; i < num_screens; i++) {
+ if (screens[i].r_focus == NULL) {
+ r = TAILQ_FIRST(&screens[i].rl);
+ if (r != NULL)
+ focus_region(r);
+ }
+ }
+
bar_draw();
focus_flush();
}