/*
- * Copyright (c) 2009-2012 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2009-2015 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2009-2011 Ryan McBride <mcbride@countersiege.com>
* Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
* Copyright (c) 2009 Pierre-Yves Ritschard <pyr@spootnik.org>
* Copyright (c) 2010 Tuukka Kataja <stuge@xor.fi>
* Copyright (c) 2011 Jason L. Wright <jason@thought.net>
- * Copyright (c) 2011-2014 Reginald Kennedy <rk@rejii.com>
+ * Copyright (c) 2011-2015 Reginald Kennedy <rk@rejii.com>
* Copyright (c) 2011-2012 Lawrence Teo <lteo@lteo.net>
* Copyright (c) 2011-2012 Tiago Cunha <tcunha@gmx.com>
- * Copyright (c) 2012-2013 David Hill <dhill@mindcry.org>
+ * Copyright (c) 2012-2015 David Hill <dhill@mindcry.org>
+ * Copyright (c) 2014-2015 Yuri D'Elia <yuri.delia@eurac.edu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <poll.h>
#include <fcntl.h>
#include <locale.h>
#include <paths.h>
int term_width = 0;
int font_adjusted = 0;
unsigned int mod_key = MODKEY;
+bool warp_focus = false;
bool warp_pointer = false;
+bool workspace_clamp = false;
/* dmenu search */
struct swm_region *search_r;
bool bar_extra = false;
int bar_height = 0;
int bar_justify = SWM_BAR_JUSTIFY_LEFT;
-char *bar_format = NULL;
+char *bar_format = NULL;
bool stack_enabled = true;
bool clock_enabled = true;
bool iconic_enabled = false;
+bool maximize_hide_bar = false;
bool urgent_enabled = false;
bool urgent_collapse = false;
char *clock_format = NULL;
time_t time_started;
#endif
pid_t bar_pid;
-XFontSet bar_fs;
+XFontSet bar_fs = NULL;
XFontSetExtents *bar_fs_extents;
-XftFont *bar_font;
+XftFont *bar_font = NULL;
bool bar_font_legacy = true;
-char *bar_fonts;
+char *bar_fonts = NULL;
XftColor bar_font_color;
XftColor search_font_color;
-struct passwd *pwd;
-char *startup_exception;
+char *startup_exception = NULL;
unsigned int nr_exceptions = 0;
/* layout manager data */
#define SWM_ARG_ID_FLIPLAYOUT (24)
#define SWM_ARG_ID_STACKRESET (30)
#define SWM_ARG_ID_STACKINIT (31)
+#define SWM_ARG_ID_STACKBALANCE (32)
#define SWM_ARG_ID_CYCLEWS_UP (40)
#define SWM_ARG_ID_CYCLEWS_DOWN (41)
#define SWM_ARG_ID_CYCLERG_UP (42)
#define SWM_ARG_ID_LOWER (106)
#define SWM_ARG_ID_BAR_TOGGLE (110)
#define SWM_ARG_ID_BAR_TOGGLE_WS (111)
+#define SWM_ARG_ID_CYCLERG_MOVE_UP (112)
+#define SWM_ARG_ID_CYCLERG_MOVE_DOWN (113)
char **argv;
};
regex_t regex_name;
uint32_t quirk;
int ws; /* Initial workspace. */
-#define SWM_Q_FLOAT (1<<0) /* float this window */
-#define SWM_Q_TRANSSZ (1<<1) /* transiend window size too small */
-#define SWM_Q_ANYWHERE (1<<2) /* don't position this window */
-#define SWM_Q_XTERM_FONTADJ (1<<3) /* adjust xterm fonts when resizing */
-#define SWM_Q_FULLSCREEN (1<<4) /* remove border */
-#define SWM_Q_FOCUSPREV (1<<5) /* focus on caller */
+#define SWM_Q_FLOAT (1<<0) /* Float this window. */
+#define SWM_Q_TRANSSZ (1<<1) /* Transient window size too small. */
+#define SWM_Q_ANYWHERE (1<<2) /* Don't position this window */
+#define SWM_Q_XTERM_FONTADJ (1<<3) /* Adjust xterm fonts when resizing. */
+#define SWM_Q_FULLSCREEN (1<<4) /* Remove border when fullscreen. */
+#define SWM_Q_FOCUSPREV (1<<5) /* Focus on caller. */
#define SWM_Q_NOFOCUSONMAP (1<<6) /* Don't focus on window when mapped. */
#define SWM_Q_FOCUSONMAP_SINGLE (1<<7) /* Only focus if single win of type. */
#define SWM_Q_OBEYAPPFOCUSREQ (1<<8) /* Focus when applications ask. */
#define SWM_Q_IGNOREPID (1<<9) /* Ignore PID when determining ws. */
#define SWM_Q_IGNORESPAWNWS (1<<10) /* Ignore _SWM_WS when managing win. */
+#define SWM_Q_NOFOCUSCYCLE (1<<11) /* Remove from normal focus cycle. */
+#define SWM_Q_MINIMALBORDER (1<<12) /* No border when floating/unfocused. */
};
TAILQ_HEAD(quirk_list, quirk);
struct quirk_list quirks = TAILQ_HEAD_INITIALIZER(quirks);
KF_RG_7,
KF_RG_8,
KF_RG_9,
+ KF_RG_MOVE_NEXT,
+ KF_RG_MOVE_PREV,
KF_RG_NEXT,
KF_RG_PREV,
KF_SCREEN_NEXT,
KF_SEARCH_WIN,
KF_SEARCH_WORKSPACE,
KF_SPAWN_CUSTOM,
+ KF_STACK_BALANCE,
KF_STACK_INC,
KF_STACK_DEC,
KF_STACK_RESET,
void check_conn(void);
void clear_keys(void);
int clear_maximized(struct workspace *);
+void clear_quirks(void);
+void clear_spawns(void);
void clientmessage(xcb_client_message_event_t *);
void client_msg(struct ws_win *, xcb_atom_t, xcb_timestamp_t);
int conf_load(const char *, int);
for (i = 0; i < num_screens; i++)
for (j = 0; j < workspace_limit; j++)
TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
- urgent[j] = get_urgent(win);
+ if (get_urgent(win))
+ urgent[j] = true;
for (i = 0; i < workspace_limit; i++) {
if (urgent[i]) {
strlcat(s, "- ", sz);
}
}
+ if(urgent_collapse && s[0])
+ s[strlen(s) - 1] = 0;
}
void
/* bar_urgent already adds the space before the last asterisk */
if (urgent_enabled)
- strlcat(fmtnew, "* +U*+4<", sz);
+ strlcat(fmtnew, (urgent_collapse ? "*+U*+4<" : "* +U*+4<"), sz);
if (window_class_enabled) {
strlcat(fmtnew, "+C", sz);
void
xft_init(struct swm_region *r)
{
- char *font, *d, *search;
+ char *font, *str, *search;
XRenderColor color;
if (bar_font == NULL) {
- if ((d = strdup(bar_fonts)) == NULL)
+ if ((search = str = strdup(bar_fonts)) == NULL)
errx(1, "insufficient memory.");
- search = d;
+
while ((font = strsep(&search, ",")) != NULL) {
if (*font == '\0')
continue;
break;
}
}
- free(d);
+ free(str);
}
if (bar_font == NULL)
uint16_t data[2] = { state, XCB_ATOM_NONE };
DNPRINTF(SWM_D_EVENT, "set_win_state: win %#x, state: %u\n",
- win->id, state);
+ WINID(win), state);
if (win == NULL)
return;
struct ws_win *target = NULL;
struct workspace *ws;
+ DNPRINTF(SWM_D_EVENT, "lower_window: win %#x\n", WINID(win));
+
if (win == NULL)
return;
ws = win->ws;
- DNPRINTF(SWM_D_EVENT, "lower_window: win %#x\n", win->id);
-
TAILQ_FOREACH(target, &ws->stack, stack_entry) {
if (target == win || ICONIC(target))
continue;
struct ws_win *target = NULL;
struct workspace *ws;
+ DNPRINTF(SWM_D_EVENT, "raise_window: win %#x\n", WINID(win));
+
if (win == NULL)
return;
- ws = win->ws;
- DNPRINTF(SWM_D_EVENT, "raise_window: win %#x\n", win->id);
+ ws = win->ws;
TAILQ_FOREACH(target, &ws->stack, stack_entry) {
if (target == win || ICONIC(target))
void
kill_refs(struct ws_win *win)
{
- int i, x, num_screens;
- struct swm_region *r;
struct workspace *ws;
+ struct ws_win *w;
+ int i, j, num_screens;
if (win == NULL)
return;
num_screens = get_screen_count();
- for (i = 0; i < num_screens; i++)
- TAILQ_FOREACH(r, &screens[i].rl, entry)
- for (x = 0; x < workspace_limit; x++) {
- ws = &r->s->ws[x];
- if (win == ws->focus)
- ws->focus = NULL;
- if (win == ws->focus_prev)
- ws->focus_prev = NULL;
- }
+ for (i = 0; i < num_screens; i++) {
+ for (j = 0; j < workspace_limit; j++) {
+ ws = &screens[i].ws[j];
+
+ if (win == ws->focus)
+ ws->focus = NULL;
+ if (win == ws->focus_prev)
+ ws->focus_prev = NULL;
+
+ if (TRANS(win))
+ TAILQ_FOREACH(w, &ws->winlist, entry)
+ if (win == w->focus_child)
+ w->focus_child = NULL;
+ }
+ }
}
int
if (win->ws->always_raise)
raise_window(win);
+ /* Update border width */
+ if (win->bordered && (win->quirks & SWM_Q_MINIMALBORDER) &&
+ FLOATING(win)) {
+ win->bordered = 0;
+ X(win) += border_width;
+ Y(win) += border_width;
+ update_window(win);
+ }
+
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1, &none);
&cfw->s->c[(MAXIMIZED(cfw) ?
SWM_S_COLOR_UNFOCUS_MAXIMIZED :
SWM_S_COLOR_UNFOCUS)].pixel);
+
+ /* Update border width */
+ if (cfw->bordered &&
+ (cfw->quirks & SWM_Q_MINIMALBORDER) &&
+ FLOATING(cfw)) {
+ cfw->bordered = 0;
+ X(cfw) += border_width;
+ Y(cfw) += border_width;
+ update_window(cfw);
+ }
} else {
unfocus_win(cfw);
}
ws->focus = win;
}
- /* If this window directs focus to a child window, then clear. */
- if (win->focus_child)
- win->focus_child = NULL;
+ /* Clear focus child redirect. */
+ win->focus_child = NULL;
/* If transient, adjust parent's focus child for focus_magic. */
if (TRANS(win)) {
&win->id);
}
- if (cfw != win)
+ if (cfw != win) {
/* Update window border even if workspace is hidden. */
update_window_color(win);
+ /* Update border width */
+ if (!win->bordered && WS_FOCUSED(win->ws) &&
+ (win->quirks & SWM_Q_MINIMALBORDER) && FLOATING(win)) {
+ win->bordered = 1;
+ X(win) -= border_width;
+ Y(win) -= border_width;
+ update_window(win);
+ }
+ }
+
out:
bar_draw();
if (new_ws == old_ws)
return;
+ other_r = new_ws->r;
+ if (other_r && workspace_clamp) {
+ DNPRINTF(SWM_D_WS, "switchws: ws clamped.\n");
+
+ if (warp_focus) {
+ DNPRINTF(SWM_D_WS, "switchws: warping focus to region "
+ "with ws %d.\n", wsid);
+ focus_region(other_r);
+ center_pointer(other_r);
+ focus_flush();
+ }
+ return;
+ }
+
if ((win = old_ws->focus) != NULL) {
update_window_color(win);
&none);
}
- other_r = new_ws->r;
- if (other_r == NULL) {
- /* the other workspace is hidden, hide this one */
- old_ws->r = NULL;
- unmap_old = true;
- } else {
+ if (other_r) {
/* the other ws is visible in another region, exchange them */
other_r->ws_prior = new_ws;
other_r->ws = old_ws;
old_ws->r = other_r;
+ } else {
+ /* the other workspace is hidden, hide this one */
+ old_ws->r = NULL;
+ unmap_old = true;
}
+
this_r->ws_prior = old_ws;
this_r->ws = new_ws;
new_ws->r = this_r;
void
cyclerg(struct swm_region *r, union arg *args)
{
+ union arg a;
struct swm_region *rr = NULL;
int i, num_screens;
switch (args->id) {
case SWM_ARG_ID_CYCLERG_UP:
+ case SWM_ARG_ID_CYCLERG_MOVE_UP:
rr = TAILQ_NEXT(r, entry);
if (rr == NULL)
rr = TAILQ_FIRST(&screens[i].rl);
break;
case SWM_ARG_ID_CYCLERG_DOWN:
+ case SWM_ARG_ID_CYCLERG_MOVE_DOWN:
rr = TAILQ_PREV(r, swm_region_list, entry);
if (rr == NULL)
rr = TAILQ_LAST(&screens[i].rl, swm_region_list);
if (rr == NULL)
return;
- focus_region(rr);
- center_pointer(rr);
- focus_flush();
+ switch (args->id) {
+ case SWM_ARG_ID_CYCLERG_UP:
+ case SWM_ARG_ID_CYCLERG_DOWN:
+ focus_region(rr);
+ center_pointer(rr);
+ focus_flush();
+ break;
+ case SWM_ARG_ID_CYCLERG_MOVE_UP:
+ case SWM_ARG_ID_CYCLERG_MOVE_DOWN:
+ a.id = rr->ws->idx;
+ switchws(r, &a);
+ break;
+ default:
+ return;
+ };
+
DNPRINTF(SWM_D_FOCUS, "cyclerg: done\n");
}
} while (winfocus && (ICONIC(winfocus) ||
winfocus->id == cur_focus->transient ||
(cur_focus->transient != XCB_WINDOW_NONE &&
- winfocus->transient == cur_focus->transient)));
+ winfocus->transient == cur_focus->transient) ||
+ (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
break;
case SWM_ARG_ID_FOCUSNEXT:
if (cur_focus == NULL)
} while (winfocus && (ICONIC(winfocus) ||
winfocus->id == cur_focus->transient ||
(cur_focus->transient != XCB_WINDOW_NONE &&
- winfocus->transient == cur_focus->transient)));
+ winfocus->transient == cur_focus->transient) ||
+ (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
break;
case SWM_ARG_ID_FOCUSMAIN:
if (cur_focus == NULL)
struct workspace *ws;
struct swm_region *r;
+ DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", WINID(win));
+
if (win == NULL)
return;
if ((r = ws->r) == NULL)
return;
- DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", win->id);
-
win->bordered = true;
if (FULLSCREEN(win)) {
win->g = r->g;
- if (bar_enabled && ws->bar_enabled) {
+ if (bar_enabled && ws->bar_enabled && !maximize_hide_bar) {
if (!bar_at_bottom)
Y(win) += bar_height;
HEIGHT(win) -= bar_height;
if (r != ws->old_r)
load_float_geom(win);
- if ((win->quirks & SWM_Q_FULLSCREEN) &&
- WIDTH(win) >= WIDTH(r) && HEIGHT(win) >= HEIGHT(r)) {
- /* Remove border for FULLSCREEN quirk. */
+ if (((win->quirks & SWM_Q_FULLSCREEN) &&
+ WIDTH(win) >= WIDTH(r) && HEIGHT(win) >= HEIGHT(r)) ||
+ ((!WS_FOCUSED(win->ws) || win->ws->focus != win) &&
+ (win->quirks & SWM_Q_MINIMALBORDER))) {
+ /* Remove border */
win->bordered = false;
} else if (!MANUAL(win)) {
if (TRANS(win) && (win->quirks & SWM_Q_TRANSSZ)) {
if (ws->l_state.vertical_mwin > 0)
ws->l_state.vertical_mwin--;
break;
+ case SWM_ARG_ID_STACKBALANCE:
+ ws->l_state.vertical_msize = SWM_V_SLICE / (ws->l_state.vertical_stacks + 1);
+ break;
case SWM_ARG_ID_STACKINC:
ws->l_state.vertical_stacks++;
break;
if (ws->l_state.horizontal_mwin > 0)
ws->l_state.horizontal_mwin--;
break;
+ case SWM_ARG_ID_STACKBALANCE:
+ ws->l_state.horizontal_msize = SWM_H_SLICE / (ws->l_state.horizontal_stacks + 1);
+ break;
case SWM_ARG_ID_STACKINC:
ws->l_state.horizontal_stacks++;
break;
int num_screens, i;
num_screens = get_screen_count();
- for (i = 0; i < num_screens; ++i)
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
- screens[i].root, ewmh[_NET_CURRENT_DESKTOP].atom,
- XCB_ATOM_CARDINAL, 32, 1, &screens[i].r_focus->ws->idx);
+ for (i = 0; i < num_screens; ++i) {
+ if (screens[i].r_focus)
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_CURRENT_DESKTOP].atom,
+ XCB_ATOM_CARDINAL, 32, 1,
+ &screens[i].r_focus->ws->idx);
+ }
}
void
{ "rg_7", focusrg, {.id = 6} },
{ "rg_8", focusrg, {.id = 7} },
{ "rg_9", focusrg, {.id = 8} },
+ { "rg_move_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_MOVE_UP} },
+ { "rg_move_prev", cyclerg, {.id = SWM_ARG_ID_CYCLERG_MOVE_DOWN} },
{ "rg_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_UP} },
{ "rg_prev", cyclerg, {.id = SWM_ARG_ID_CYCLERG_DOWN} },
{ "screen_next", cyclerg, {.id = SWM_ARG_ID_CYCLERG_UP} },
{ "search_win", search_win, {0} },
{ "search_workspace", search_workspace, {0} },
{ "spawn_custom", NULL, {0} },
+ { "stack_balance", stack_config, {.id = SWM_ARG_ID_STACKBALANCE} },
{ "stack_inc", stack_config, {.id = SWM_ARG_ID_STACKINC} },
{ "stack_dec", stack_config, {.id = SWM_ARG_ID_STACKDEC} },
{ "stack_reset", stack_config, {.id = SWM_ARG_ID_STACKRESET} },
DNPRINTF(SWM_D_SPAWN, "spawn_remove: leave\n");
}
+void
+clear_spawns(void)
+{
+ struct spawn_prog *sp;
+
+ while ((sp = TAILQ_FIRST(&spawns)) != NULL) {
+ spawn_remove(sp);
+ }
+}
+
struct spawn_prog*
spawn_find(const char *name)
{
*mod |= XCB_MOD_MASK_3;
else if (strncmp(name, "Mod4", SWM_MODNAME_SIZE) == 0)
*mod |= XCB_MOD_MASK_4;
+ else if (strncmp(name, "Mod5", SWM_MODNAME_SIZE) == 0)
+ *mod |= XCB_MOD_MASK_5;
else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0)
*mod |= XCB_MOD_MASK_SHIFT;
else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0)
"OBEYAPPFOCUSREQ",
"IGNOREPID",
"IGNORESPAWNWS",
+ "NOFOCUSCYCLE",
+ "MINIMALBORDER",
};
/* SWM_Q_DELIM: retain '|' for back compat for now (2009-08-11) */
if (quirk == NULL || qstr == NULL)
return (1);
- if ((str = strdup(qstr)) == NULL)
+ if ((cp = str = strdup(qstr)) == NULL)
err(1, "parsequirks: strdup");
- cp = str;
*quirk = 0;
while ((name = strsep(&cp, SWM_Q_DELIM)) != NULL) {
if (cp)
free(qp);
}
+void
+clear_quirks(void)
+{
+ struct quirk *qp;
+
+ while ((qp = TAILQ_FIRST(&quirks)) != NULL) {
+ quirk_remove(qp);
+ }
+}
+
void
quirk_replace(struct quirk *qp, const char *class, const char *instance,
const char *name, uint32_t quirk, int ws)
SWM_S_FOCUS_MODE,
SWM_S_ICONIC_ENABLED,
SWM_S_JAVA_WORKAROUND,
+ SWM_S_MAXIMIZE_HIDE_BAR,
SWM_S_REGION_PADDING,
SWM_S_SPAWN_ORDER,
SWM_S_SPAWN_TERM,
SWM_S_URGENT_COLLAPSE,
SWM_S_URGENT_ENABLED,
SWM_S_VERBOSE_LAYOUT,
+ SWM_S_WARP_FOCUS,
SWM_S_WARP_POINTER,
SWM_S_WINDOW_CLASS_ENABLED,
SWM_S_WINDOW_INSTANCE_ENABLED,
SWM_S_WINDOW_NAME_ENABLED,
+ SWM_S_WORKSPACE_CLAMP,
SWM_S_WORKSPACE_LIMIT,
SWM_S_WORKSPACE_NAME,
};
{
struct workspace *ws;
int i, ws_id, num_screens;
- char *b, *str, s[1024];
+ char *b, *str, *sp, s[1024];
switch (flags) {
case SWM_S_BAR_ACTION:
if (!bar_font_legacy)
break;
- if ((str = strdup(value)) == NULL)
+ if ((sp = str = strdup(value)) == NULL)
err(1, "setconfvalue: strdup");
/* If there are any non-XLFD entries, switch to Xft mode. */
- while ((b = strsep(&str, ",")) != NULL) {
+ while ((b = strsep(&sp, ",")) != NULL) {
if (*b == '\0')
continue;
if (!isxlfd(b)) {
case SWM_S_JAVA_WORKAROUND:
java_workaround = (atoi(value) != 0);
break;
+ case SWM_S_MAXIMIZE_HIDE_BAR:
+ maximize_hide_bar = atoi(value);
+ break;
case SWM_S_REGION_PADDING:
region_padding = atoi(value);
if (region_padding < 0)
layouts[i].l_string = plain_stacker;
}
break;
+ case SWM_S_WARP_FOCUS:
+ warp_focus = (atoi(value) != 0);
+ break;
case SWM_S_WARP_POINTER:
warp_pointer = (atoi(value) != 0);
break;
case SWM_S_WINDOW_NAME_ENABLED:
window_name_enabled = (atoi(value) != 0);
break;
+ case SWM_S_WORKSPACE_CLAMP:
+ workspace_clamp = (atoi(value) != 0);
+ break;
case SWM_S_WORKSPACE_LIMIT:
workspace_limit = atoi(value);
if (workspace_limit > SWM_WS_MAX)
update_modkey(XCB_MOD_MASK_3);
else if (strncasecmp(value, "Mod4", strlen("Mod4")) == 0)
update_modkey(XCB_MOD_MASK_4);
+ else if (strncasecmp(value, "Mod5", strlen("Mod5")) == 0)
+ update_modkey(XCB_MOD_MASK_5);
else
return (1);
return (0);
{
int ws_id;
char s[1024];
- char *ap, *sp;
+ char *ap, *sp, *str;
union arg a;
int argc = 0;
pid_t pid;
if (ws_id < 0 || ws_id >= workspace_limit)
errx(1, "autorun: invalid workspace %d", ws_id + 1);
- sp = expand_tilde((char *)&s);
+ sp = str = expand_tilde((char *)&s);
/*
* This is a little intricate
err(1, "setautorun: realloc");
a.argv[argc - 1] = ap;
}
- free(sp);
+ free(str);
if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL)
err(1, "setautorun: realloc");
{ "java_workaround", setconfvalue, SWM_S_JAVA_WORKAROUND },
{ "keyboard_mapping", setkeymapping, 0 },
{ "layout", setlayout, 0 },
+ { "maximize_hide_bar", setconfvalue, SWM_S_MAXIMIZE_HIDE_BAR },
{ "modkey", setconfmodkey, 0 },
{ "program", setconfspawn, 0 },
{ "quirk", setconfquirk, 0 },
{ "urgent_collapse", setconfvalue, SWM_S_URGENT_COLLAPSE },
{ "urgent_enabled", setconfvalue, SWM_S_URGENT_ENABLED },
{ "verbose_layout", setconfvalue, SWM_S_VERBOSE_LAYOUT },
+ { "warp_focus", setconfvalue, SWM_S_WARP_FOCUS },
{ "warp_pointer", setconfvalue, SWM_S_WARP_POINTER },
{ "window_class_enabled", setconfvalue, SWM_S_WINDOW_CLASS_ENABLED },
{ "window_instance_enabled", setconfvalue, SWM_S_WINDOW_INSTANCE_ENABLED },
{ "window_name_enabled", setconfvalue, SWM_S_WINDOW_NAME_ENABLED },
+ { "workspace_clamp", setconfvalue, SWM_S_WORKSPACE_CLAMP },
{ "workspace_limit", setconfvalue, SWM_S_WORKSPACE_LIMIT },
{ "name", setconfvalue, SWM_S_WORKSPACE_NAME },
};
void
free_window(struct ws_win *win)
{
- DNPRINTF(SWM_D_MISC, "free_window: win %#x\n", win->id);
+ DNPRINTF(SWM_D_MISC, "free_window: win %#x\n", WINID(win));
if (win == NULL)
return;
- TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
-
xcb_icccm_get_wm_class_reply_wipe(&win->ch);
- kill_refs(win);
-
/* paint memory */
memset(win, 0xff, sizeof *win); /* XXX kill later */
{
struct ws_win *parent;
+ DNPRINTF(SWM_D_MISC, "unmanage_window: win %#x\n", WINID(win));
+
if (win == NULL)
return;
- DNPRINTF(SWM_D_MISC, "unmanage_window: win %#x\n", win->id);
-
if (TRANS(win)) {
parent = find_window(win->transient);
if (parent)
DNPRINTF(SWM_D_EVENT, "destroynotify: win %#x\n", e->window);
- if ((win = find_window(e->window)) == NULL) {
- if ((win = find_unmanaged_window(e->window)) == NULL)
- return;
- free_window(win);
- return;
- }
-
- if (focus_mode != SWM_FOCUS_FOLLOW) {
- /* If we were focused, make sure we focus on something else. */
- if (win == win->ws->focus)
- win->ws->focus_pending = get_focus_prev(win);
- }
+ if ((win = find_window(e->window))) {
+ /* Managed window cleanup. */
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ /* If focused, focus on something else. */
+ if (win == win->ws->focus)
+ win->ws->focus_pending = get_focus_prev(win);
+ }
- unmanage_window(win);
- stack();
+ unmanage_window(win);
+ stack();
- if (focus_mode != SWM_FOCUS_FOLLOW && WS_FOCUSED(win->ws)) {
- if (win->ws->focus_pending) {
- focus_win(win->ws->focus_pending);
- win->ws->focus_pending = NULL;
- } else if (win == win->ws->focus) {
- xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT,
- win->ws->r->id, XCB_CURRENT_TIME);
+ if (focus_mode != SWM_FOCUS_FOLLOW && WS_FOCUSED(win->ws)) {
+ if (win->ws->focus_pending) {
+ focus_win(win->ws->focus_pending);
+ win->ws->focus_pending = NULL;
+ } else if (win == win->ws->focus) {
+ xcb_set_input_focus(conn,
+ XCB_INPUT_FOCUS_PARENT, win->ws->r->id,
+ XCB_CURRENT_TIME);
+ }
}
+
+ kill_refs(win);
+ focus_flush();
+ } else {
+ win = find_unmanaged_window(e->window);
}
- free_window(win);
+ if (win) {
+ /* unmanage_window() puts win into unmanaged list. */
+ TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
+ free_window(win);
+ }
- focus_flush();
+ DNPRINTF(SWM_D_EVENT, "destroynotify: done.\n");
}
#ifdef SWM_DEBUG
return;
}
+ if (focus_mode != SWM_FOCUS_FOLLOW &&
+ e->mode == XCB_NOTIFY_MODE_UNGRAB) {
+ DNPRINTF(SWM_D_EVENT, "enternotify: ungrab; ignoring.\n");
+ return;
+ }
+
last_event_time = e->time;
if ((win = find_window(e->event)) == NULL) {
xcb_randr_query_version_reply_t *r;
num_screens = get_screen_count();
- if ((screens = calloc(num_screens,
- sizeof(struct swm_screen))) == NULL)
+ if ((screens = calloc(num_screens, sizeof(struct swm_screen))) == NULL)
err(1, "setup_screens: calloc: failed to allocate memory for "
"screens");
void
shutdown_cleanup(void)
{
+ struct swm_region *r;
+ struct ws_win *w;
+ struct workspace *ws;
int i, num_screens;
/* disable alarm because the following code may not be interrupted */
cursors_cleanup();
+ clear_quirks();
+ clear_spawns();
+ clear_keys();
+
teardown_ewmh();
num_screens = get_screen_count();
for (i = 0; i < num_screens; ++i) {
+ int j;
+
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT,
screens[i].root, XCB_CURRENT_TIME);
XftColorFree(display, DefaultVisual(display, i),
DefaultColormap(display, i), &search_font_color);
}
+
+ for (j = 0; j < SWM_S_COLOR_MAX; ++j) {
+ free(screens[i].c[j].name);
+ }
+
+ /* Free window memory. */
+ for (j = 0; j < SWM_WS_MAX; ++j) {
+ ws = &screens[i].ws[j];
+ free(ws->name);
+
+ while ((w = TAILQ_FIRST(&ws->winlist)) != NULL) {
+ TAILQ_REMOVE(&ws->winlist, w, entry);
+ free_window(w);
+ }
+
+ while ((w = TAILQ_FIRST(&ws->unmanagedlist)) != NULL) {
+ TAILQ_REMOVE(&ws->unmanagedlist, w, entry);
+ free_window(w);
+ }
+ }
+
+ /* Free region memory. */
+ while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) {
+ TAILQ_REMOVE(&screens[i].rl, r, entry);
+ free(r->bar);
+ free(r);
+ }
+
+ while ((r = TAILQ_FIRST(&screens[i].orl)) != NULL) {
+ TAILQ_REMOVE(&screens[i].rl, r, entry);
+ free(r->bar);
+ free(r);
+ }
}
+ free(screens);
- if (bar_font_legacy)
+ free(bar_format);
+ free(bar_fonts);
+ free(clock_format);
+ free(startup_exception);
+
+ if (bar_fs)
XFreeFontSet(display, bar_fs);
- else {
+ if (bar_font)
XftFontClose(display, bar_font);
- }
xcb_key_symbols_free(syms);
xcb_flush(conn);
int
main(int argc, char *argv[])
{
- struct swm_region *r;
- char conf[PATH_MAX], *cfile = NULL;
- struct stat sb;
- int xfd, i, num_screens;
+ struct pollfd pfd[2];
struct sigaction sact;
+ struct stat sb;
+ struct passwd *pwd;
+ struct swm_region *r;
xcb_generic_event_t *evt;
- struct timeval tv;
- fd_set rd;
- int rd_max;
- int num_readable;
+ int xfd, i, num_screens, num_readable;
+ char conf[PATH_MAX], *cfile = NULL;
bool stdin_ready = false, startup = true;
/* suppress unused warning since var is needed */
TAILQ_FOREACH(r, &screens[i].rl, entry)
r->ws->state = SWM_WS_STATE_MAPPED;
- rd_max = xfd > STDIN_FILENO ? xfd : STDIN_FILENO;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd[0].fd = xfd;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = STDIN_FILENO;
+ pfd[1].events = POLLIN;
while (running) {
while ((evt = xcb_poll_for_event(conn))) {
}
}
- FD_ZERO(&rd);
-
- if (bar_extra)
- FD_SET(STDIN_FILENO, &rd);
-
- FD_SET(xfd, &rd);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- num_readable = select(rd_max + 1, &rd, NULL, NULL, &tv);
- if (num_readable == -1 && errno != EINTR) {
- DNPRINTF(SWM_D_MISC, "select failed");
- } else if (num_readable > 0 && FD_ISSET(STDIN_FILENO, &rd)) {
+ num_readable = poll(pfd, bar_extra ? 2 : 1, 1000);
+ if (num_readable == -1) {
+ DNPRINTF(SWM_D_MISC, "poll failed: %s",
+ strerror(errno));
+ } else if (num_readable > 0 && bar_extra &&
+ pfd[1].revents & POLLIN) {
stdin_ready = true;
}