#include <X11/Xcursor/Xcursor.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib-xcb.h>
+#include <xcb/xcb.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h>
#define MAXIMIZED(w) (MAXIMIZED_VERT(w) || MAXIMIZED_HORZ(w))
#define MANUAL(w) ((w)->ewmh_flags & SWM_F_MANUAL)
#define TRANS(w) ((w)->transient != XCB_WINDOW_NONE)
-#define FLOATING(w) (ABOVE(w) || TRANS(w) || FULLSCREEN(w) || \
+#define FLOATING(w) (ABOVE(w) || TRANS(w))
+#define FLOATINGFULLMAX(w) (ABOVE(w) || TRANS(w) || FULLSCREEN(w) || \
MAXIMIZED(w))
/* Constrain Window flags */
int tile_gap = 0;
bool java_workaround = true;
bool verbose_layout = false;
+bool track_pid_ws = true;
#ifdef SWM_DEBUG
bool debug_enabled;
time_t time_started;
void horizontal_config(struct workspace *, int);
void horizontal_stack(struct workspace *, struct swm_geometry *);
void max_stack(struct workspace *, struct swm_geometry *);
+void max_config(struct workspace *, int);
void plain_stacker(struct workspace *);
void fancy_stacker(struct workspace *);
/* stack, configure */
{ vertical_stack, vertical_config, 0, plain_stacker },
{ horizontal_stack, horizontal_config, 0, plain_stacker },
- { max_stack, NULL,
+ { max_stack, max_config,
SWM_L_MAPONFOCUS | SWM_L_FOCUSPREV, plain_stacker },
{ NULL, NULL, 0, NULL },
};
};
struct swm_screen *screens;
+struct layout_config {
+ bool configured;
+ int layout;
+ int master_grow;
+ int master_add;
+ int stack_inc;
+ int always_raise;
+ bool apply_flip;
+} initial_layouts[SWM_WS_MAX];
+
/* args to functions */
union arg {
int id;
#define SWM_ARG_ID_MASTERADD (22)
#define SWM_ARG_ID_MASTERDEL (23)
#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)
_NET_WM_STATE_SKIP_PAGER,
_NET_WM_STATE_SKIP_TASKBAR,
_NET_WM_WINDOW_TYPE,
+ _NET_WM_WINDOW_TYPE_DESKTOP,
_NET_WM_WINDOW_TYPE_DIALOG,
_NET_WM_WINDOW_TYPE_DOCK,
_NET_WM_WINDOW_TYPE_NORMAL,
{"_NET_WM_STATE_SKIP_PAGER", XCB_ATOM_NONE},
{"_NET_WM_STATE_SKIP_TASKBAR", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE", XCB_ATOM_NONE},
+ {"_NET_WM_WINDOW_TYPE_DESKTOP", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE_DIALOG", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE_DOCK", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE_NORMAL", XCB_ATOM_NONE},
FN_STACK_BALANCE,
FN_STACK_INC,
FN_STACK_DEC,
- FN_STACK_RESET,
+ FN_STACK_INIT,
FN_SWAP_MAIN,
FN_SWAP_NEXT,
FN_SWAP_PREV,
void bar_urgent(char *, size_t);
void bar_window_class(char *, size_t, struct swm_region *);
void bar_window_class_instance(char *, size_t, struct swm_region *);
-void bar_window_float(char *, size_t, struct swm_region *);
+void bar_window_index_count(char *, size_t, struct swm_region *);
void bar_window_instance(char *, size_t, struct swm_region *);
void bar_window_name(char *, size_t, struct swm_region *);
void bar_window_state(char *, size_t, struct swm_region *);
void bar_workspace_name(char *, size_t, struct swm_region *);
+void bar_workspace_state(char *, size_t, struct swm_region *);
int binding_cmp(struct binding *, struct binding *);
void binding_insert(uint16_t, enum binding_type, uint32_t, enum actionid,
uint32_t, const char *);
void ewmh_autoquirk(struct ws_win *);
void ewmh_get_desktop_names(void);
void ewmh_get_wm_state(struct ws_win *);
+int ewmh_handle_special_types(xcb_window_t, struct swm_region *);
void ewmh_update_actions(struct ws_win *);
void ewmh_update_client_list(void);
void ewmh_update_current_desktop(void);
void grabbuttons(void);
void grabkeys(void);
void iconify(struct binding *, struct swm_region *, union arg *);
+void initlayout(struct workspace *);
bool isxlfd(char *);
bool keybindreleased(struct binding *, xcb_key_release_event_t *);
void keypress(xcb_key_press_event_t *);
}
}
+int
+ewmh_handle_special_types(xcb_window_t id, struct swm_region *region)
+{
+ xcb_get_property_reply_t *r;
+ xcb_get_property_cookie_t c;
+ xcb_atom_t *type;
+ int i, n;
+ uint16_t configure_mask = 0;
+ uint32_t wa[2];
+
+ c = xcb_get_property(conn, 0, id,
+ ewmh[_NET_WM_WINDOW_TYPE].atom, XCB_ATOM_ATOM, 0, UINT32_MAX);
+ r = xcb_get_property_reply(conn, c, NULL);
+ if (r == NULL)
+ return 0;
+
+ type = xcb_get_property_value(r);
+ n = xcb_get_property_value_length(r) / sizeof(xcb_atom_t);
+
+ for (i = 0; i < n; i++) {
+ if (type[i] == ewmh[_NET_WM_WINDOW_TYPE_DESKTOP].atom) {
+ configure_mask = XCB_CONFIG_WINDOW_STACK_MODE |
+ XCB_CONFIG_WINDOW_SIBLING;
+ wa[0] = region->id;
+ wa[1] = XCB_STACK_MODE_ABOVE;
+ break;
+ }
+
+ if (type[i] == ewmh[_NET_WM_WINDOW_TYPE_DOCK].atom) {
+ configure_mask = XCB_CONFIG_WINDOW_STACK_MODE;
+ wa[0] = XCB_STACK_MODE_ABOVE;
+ break;
+ }
+ }
+ free(r);
+
+ if (configure_mask != 0) {
+ xcb_map_window(conn, id);
+ xcb_configure_window (conn, id, configure_mask, wa);
+ return 1;
+ }
+
+ return 0;
+}
+
void
ewmh_autoquirk(struct ws_win *win)
{
for (i = 0; i < n; i++) {
if (type[i] == ewmh[_NET_WM_WINDOW_TYPE_NORMAL].atom)
break;
- if (type[i] == ewmh[_NET_WM_WINDOW_TYPE_DOCK].atom ||
- type[i] == ewmh[_NET_WM_WINDOW_TYPE_TOOLBAR].atom ||
+ if (type[i] == ewmh[_NET_WM_WINDOW_TYPE_TOOLBAR].atom ||
type[i] == ewmh[_NET_WM_WINDOW_TYPE_UTILITY].atom) {
win->quirks = SWM_Q_FLOAT | SWM_Q_ANYWHERE;
break;
}
}
free(r);
+
+
+ c = xcb_get_property(conn, 0, win->id,
+ ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 0, UINT32_MAX);
+ r = xcb_get_property_reply(conn, c, NULL);
+ if (r == NULL)
+ return;
+
+ type = xcb_get_property_value(r);
+ n = xcb_get_property_value_length(r) / sizeof(xcb_atom_t);
+
+ for (i = 0; i < n; i++) {
+ if (type[i] == ewmh[_NET_WM_STATE_SKIP_PAGER].atom ||
+ type[i] == ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom) {
+ win->quirks = SWM_Q_FLOAT | SWM_Q_ANYWHERE;
+ break;
+ }
+ }
+ free(r);
}
void
bar_window_instance(s, sz, r);
}
+void
+bar_window_index_count(char *s, size_t sz, struct swm_region *r)
+{
+ struct ws_win *w;
+ int count, index;
+
+ if (r == NULL || r->ws == NULL || r->ws->focus == NULL) {
+ strlcat(s, "0/0", sz);
+ return;
+ }
+
+ count = 0;
+ index = 0;
+
+ TAILQ_FOREACH(w, &r->ws->winlist, entry) {
+ ++count;
+ if (w->id == r->ws->focus->id) {
+ index = count;
+ }
+ }
+
+ snprintf(s, sz, "%d/%d", index, count);
+}
+
void
bar_window_state(char *s, size_t sz, struct swm_region *r)
{
strlcat(s, r->ws->name, sz);
}
+void
+bar_workspace_state(char *s, size_t sz, struct swm_region *r)
+{
+ struct ws_win *win;
+ int i, j, num_screens;
+ bool used_workspaces[SWM_WS_MAX];
+ char tmp[8];
+ int first = 1;
+ char *fmt;
+
+ if (r == NULL || r->ws == NULL)
+ return;
+
+ for (i = 0; i < SWM_WS_MAX; ++i)
+ used_workspaces[i] = false;
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; i++)
+ for (j = 0; j < workspace_limit; j++)
+ TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+ ++used_workspaces[win->ws->idx];
+
+ for (i = 0; i < SWM_WS_MAX; ++i) {
+ fmt = NULL;
+ if (i == r->ws->idx) {
+ fmt = " [%d]";
+ } else if (used_workspaces[i]) {
+ fmt = " %d";
+ }
+ if (fmt) {
+ fmt = fmt + first;
+ first = 0;
+ snprintf(tmp, sizeof tmp, fmt, i + 1);
+ strlcat(s, tmp, sz);
+ }
+ }
+}
+
/* build the default bar format according to the defined enabled options */
void
bar_fmt(const char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz)
case 'I':
snprintf(tmp, sizeof tmp, "%d", r->ws->idx + 1);
break;
+ case 'i':
+ bar_workspace_state(tmp, sizeof tmp, r);
+ break;
case 'M':
count = 0;
TAILQ_FOREACH(w, &r->ws->winlist, entry)
case 'N':
snprintf(tmp, sizeof tmp, "%d", r->s->idx + 1);
break;
+ case 'p':
+ bar_window_index_count(tmp, sizeof tmp, r);
+ break;
case 'P':
bar_window_class_instance(tmp, sizeof tmp, r);
break;
}
int
-count_win(struct workspace *ws, bool count_transient)
+count_win(struct workspace *ws, bool count_floating)
{
struct ws_win *win;
int count = 0;
TAILQ_FOREACH(win, &ws->winlist, entry) {
- if (!count_transient && FLOATING(win))
+ if (!count_floating && FLOATING(win))
continue;
if (ICONIC(win))
continue;
void
update_win_stacking(struct ws_win *win)
{
- struct ws_win *sibling;
#ifdef SWM_DEBUG
struct ws_win *w;
#endif
struct swm_region *r;
+ uint16_t configure_mask;
uint32_t val[2];
if (win == NULL || (r = win->ws->r) == NULL)
return;
}
- sibling = TAILQ_NEXT(win, stack_entry);
- if (sibling != NULL && (FLOATING(win) == FLOATING(sibling) ||
- (win->ws->always_raise && win->ws->focus == win)))
- val[0] = sibling->frame;
- else if (FLOATING(win) || (win->ws->always_raise &&
- win->ws->focus == win))
- val[0] = r->bar->id;
- else
- val[0] = r->id;
+ if (FLOATINGFULLMAX(win) || (win->ws->always_raise &&
+ win->ws->focus == win)) {
+ configure_mask = XCB_CONFIG_WINDOW_STACK_MODE;
+ val[0] = XCB_STACK_MODE_ABOVE;
+ val[1] = 0;
- DNPRINTF(SWM_D_EVENT, "update_win_stacking: win %#x (%#x), "
- "sibling %#x\n", win->frame, win->id, val[0]);
+ DNPRINTF(SWM_D_EVENT, "update_win_stacking: to very top "
+ "win %#x (%#x), ", win->frame, win->id);
+ } else {
+ configure_mask = XCB_CONFIG_WINDOW_STACK_MODE |
+ XCB_CONFIG_WINDOW_SIBLING;
+ val[0] = r->bar->id;
+ val[1] = XCB_STACK_MODE_BELOW;
- val[1] = XCB_STACK_MODE_ABOVE;
+ DNPRINTF(SWM_D_EVENT, "update_win_stacking: to tile top "
+ "win %#x (%#x), ", win->frame, win->id);
+ }
- xcb_configure_window(conn, win->frame, XCB_CONFIG_WINDOW_SIBLING |
- XCB_CONFIG_WINDOW_STACK_MODE, val);
+ xcb_configure_window(conn, win->frame, configure_mask, val);
#ifdef SWM_DEBUG
TAILQ_FOREACH(w, &win->ws->winlist, entry)
close(xcb_get_file_descriptor(conn));
- if ((ret = getenv("LD_PRELOAD"))) {
- if (asprintf(&ret, "%s:%s", SWM_LIB, ret) == -1) {
- warn("spawn: asprintf LD_PRELOAD");
+ if (track_pid_ws) {
+ if ((ret = getenv("LD_PRELOAD"))) {
+ if (asprintf(&ret, "%s:%s", SWM_LIB, ret) == -1) {
+ warn("spawn: asprintf LD_PRELOAD");
+ _exit(1);
+ }
+ setenv("LD_PRELOAD", ret, 1);
+ free(ret);
+ } else {
+ setenv("LD_PRELOAD", SWM_LIB, 1);
+ }
+
+ if (asprintf(&ret, "%d", ws_idx) == -1) {
+ warn("spawn: asprintf SWM_WS");
_exit(1);
}
- setenv("LD_PRELOAD", ret, 1);
+ setenv("_SWM_WS", ret, 1);
free(ret);
- } else {
- setenv("LD_PRELOAD", SWM_LIB, 1);
- }
-
- if (asprintf(&ret, "%d", ws_idx) == -1) {
- warn("spawn: asprintf SWM_WS");
- _exit(1);
- }
- setenv("_SWM_WS", ret, 1);
- free(ret);
- ret = NULL;
+ ret = NULL;
- if (asprintf(&ret, "%d", getpid()) == -1) {
- warn("spawn: asprintf _SWM_PID");
- _exit(1);
+ if (asprintf(&ret, "%d", getpid()) == -1) {
+ warn("spawn: asprintf _SWM_PID");
+ _exit(1);
+ }
+ setenv("_SWM_PID", ret, 1);
+ free(ret);
+ ret = NULL;
}
- setenv("_SWM_PID", ret, 1);
- free(ret);
- ret = NULL;
if (setsid() == -1) {
warn("spawn: setsid");
r->s->r_focus = r;
+ /* Update the focus window frame on the now unfocused region. */
+ if (rf && rf->ws->focus)
+ draw_frame(rf->ws->focus);
+
ewmh_update_current_desktop();
}
DNPRINTF(SWM_D_STACK, "stack_config: id: %d workspace: %d\n",
args->id, ws->idx);
- if (clear_maximized(ws) > 0)
- stack(r);
-
- if (ws->cur_layout->l_config != NULL)
+ if (args->id == SWM_ARG_ID_STACKINIT) {
+ initlayout(ws);
+ } else {
ws->cur_layout->l_config(ws, args->id);
+ }
+
+ clear_maximized(ws);
+ stack(r);
- if (args->id != SWM_ARG_ID_STACKINIT)
- stack(r);
bar_draw(r->bar);
center_pointer(r);
if (ICONIC(win))
continue;
- if (FLOATING(win)) {
+ if (FLOATINGFULLMAX(win)) {
update_floater(win);
continue;
}
id, ws->idx);
switch (id) {
- case SWM_ARG_ID_STACKRESET:
case SWM_ARG_ID_STACKINIT:
ws->l_state.vertical_msize = SWM_V_SLICE / 2;
ws->l_state.vertical_mwin = 1;
DNPRINTF(SWM_D_STACK, "horizontal_config: workspace: %d\n", ws->idx);
switch (id) {
- case SWM_ARG_ID_STACKRESET:
case SWM_ARG_ID_STACKINIT:
ws->l_state.horizontal_mwin = 1;
ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
{
struct swm_geometry gg = *g;
struct ws_win *w, *win = NULL, *parent = NULL, *tmpw;
- int winno;
DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
if (ws == NULL)
return;
- winno = count_win(ws, false);
- if (winno == 0 && count_win(ws, true) == 0)
+ if (count_win(ws, true) == 0)
return;
/* Figure out which top level window should be visible. */
/* Set maximized flag for all maxed windows. */
if (!MAXIMIZED(w)) {
- /* Preserve floating geometry. */
- if (ABOVE(w))
- store_float_geom(w);
-
ewmh_apply_flags(w, w->ewmh_flags | EWMH_F_MAXIMIZED);
ewmh_update_wm_state(w);
}
map_window(w);
}
+void
+max_config(struct workspace *ws, int id)
+{
+ /* suppress unused warning since vars are needed */
+ (void)ws;
+ (void)id;
+
+ DNPRINTF(SWM_D_STACK, "max_config: workspace: %d (noop)\n", ws->idx);
+}
+
void
send_to_rg(struct binding *bp, struct swm_region *r, union arg *args)
{
{ "stack_balance", stack_config, 0, {.id = SWM_ARG_ID_STACKBALANCE} },
{ "stack_inc", stack_config, 0, {.id = SWM_ARG_ID_STACKINC} },
{ "stack_dec", stack_config, 0, {.id = SWM_ARG_ID_STACKDEC} },
- { "stack_reset", stack_config, 0, {.id = SWM_ARG_ID_STACKRESET} },
+ { "stack_reset", stack_config, 0, {.id = SWM_ARG_ID_STACKINIT} },
{ "swap_main", swapwin, 0, {.id = SWM_ARG_ID_SWAPMAIN} },
{ "swap_next", swapwin, 0, {.id = SWM_ARG_ID_SWAPNEXT} },
{ "swap_prev", swapwin, 0, {.id = SWM_ARG_ID_SWAPPREV} },
BINDKEYSPAWN(MODSHIFT, XK_Return, "term");
BINDKEY(MODSHIFT, XK_comma, FN_STACK_INC);
BINDKEY(MODSHIFT, XK_period, FN_STACK_DEC);
- BINDKEY(MODSHIFT, XK_space, FN_STACK_RESET);
+ BINDKEY(MODSHIFT, XK_space, FN_STACK_INIT);
BINDKEY(MODKEY, XK_Return, FN_SWAP_MAIN);
BINDKEY(MODSHIFT, XK_j, FN_SWAP_NEXT);
BINDKEY(MODSHIFT, XK_k, FN_SWAP_PREV);
SWM_S_STACK_ENABLED,
SWM_S_TERM_WIDTH,
SWM_S_TILE_GAP,
+ SWM_S_TRACK_PID_WS,
SWM_S_URGENT_COLLAPSE,
SWM_S_URGENT_ENABLED,
SWM_S_VERBOSE_LAYOUT,
case SWM_S_TILE_GAP:
tile_gap = atoi(value);
break;
+ case SWM_S_TRACK_PID_WS:
+ track_pid_ws = atoi(value);
+ break;
case SWM_S_URGENT_COLLAPSE:
urgent_collapse = (atoi(value) != 0);
break;
setlayout(const char *selector, const char *value, int flags)
{
struct workspace *ws;
- int ws_id, i, x, mg, ma, si, ar;
+ int ws_id, i, mg, ma, si, ar;
int st = SWM_V_STACK, num_screens;
char s[1024];
bool f = false;
(void)selector;
(void)flags;
- if (getenv("SWM_STARTED"))
- return (0);
-
bzero(s, sizeof s);
if (sscanf(value, "ws[%d]:%d:%d:%d:%d:%1023c",
&ws_id, &mg, &ma, &si, &ar, s) != 6)
f = true;
} else if (strcasecmp(s, "fullscreen") == 0)
st = SWM_MAX_STACK;
- else
+ else {
errx(1, "invalid layout entry, should be 'ws[<idx>]:"
"<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
"<type>'");
+ return 0;
+ }
+
+ initial_layouts[ws_id].configured = true;
+ initial_layouts[ws_id].layout = st;
+ initial_layouts[ws_id].master_grow = mg;
+ initial_layouts[ws_id].master_add = ma;
+ initial_layouts[ws_id].stack_inc = si;
+ initial_layouts[ws_id].always_raise = ar;
+ initial_layouts[ws_id].apply_flip = f;
num_screens = get_screen_count();
- for (i = 0; i < num_screens; i++) {
- ws = (struct workspace *)&screens[i].ws;
- ws[ws_id].cur_layout = &layouts[st];
+ for (i = 0; i < num_screens; ++i) {
+ ws = &screens[i].ws[ws_id];
+ initlayout(ws);
+ }
- ws[ws_id].always_raise = (ar != 0);
- if (st == SWM_MAX_STACK)
- continue;
+ return 0;
+}
- /* master grow */
- for (x = 0; x < abs(mg); x++) {
- ws[ws_id].cur_layout->l_config(&ws[ws_id],
- mg >= 0 ? SWM_ARG_ID_MASTERGROW :
- SWM_ARG_ID_MASTERSHRINK);
- }
- /* master add */
- for (x = 0; x < abs(ma); x++) {
- ws[ws_id].cur_layout->l_config(&ws[ws_id],
- ma >= 0 ? SWM_ARG_ID_MASTERADD :
- SWM_ARG_ID_MASTERDEL);
- }
- /* stack inc */
- for (x = 0; x < abs(si); x++) {
- ws[ws_id].cur_layout->l_config(&ws[ws_id],
- si >= 0 ? SWM_ARG_ID_STACKINC :
- SWM_ARG_ID_STACKDEC);
- }
- /* Apply flip */
- if (f) {
- ws[ws_id].cur_layout->l_config(&ws[ws_id],
- SWM_ARG_ID_FLIPLAYOUT);
- }
- }
+void
+initlayout(struct workspace *ws)
+{
+ int i, ws_id;
- return (0);
+ ws_id = ws->idx;
+
+ if (!initial_layouts[ws_id].configured)
+ return;
+
+ ws->cur_layout = &layouts[initial_layouts[ws_id].layout];
+
+ ws->cur_layout->l_config(ws, SWM_ARG_ID_STACKINIT);
+
+ ws->always_raise = (initial_layouts[ws_id].always_raise != 0);
+
+ /* master grow */
+ for (i = 0; i < abs(initial_layouts[ws_id].master_grow); i++) {
+ ws->cur_layout->l_config(ws,
+ initial_layouts[ws_id].master_grow >= 0 ? SWM_ARG_ID_MASTERGROW :
+ SWM_ARG_ID_MASTERSHRINK);
+ }
+ /* master add */
+ for (i = 0; i < abs(initial_layouts[ws_id].master_add); i++) {
+ ws->cur_layout->l_config(ws,
+ initial_layouts[ws_id].master_add >= 0 ? SWM_ARG_ID_MASTERADD :
+ SWM_ARG_ID_MASTERDEL);
+ }
+ /* stack inc */
+ for (i = 0; i < abs(initial_layouts[ws_id].stack_inc); i++) {
+ ws->cur_layout->l_config(ws,
+ initial_layouts[ws_id].stack_inc >= 0 ? SWM_ARG_ID_STACKINC :
+ SWM_ARG_ID_STACKDEC);
+ }
+ /* Apply flip */
+ if (initial_layouts[ws_id].apply_flip) {
+ ws->cur_layout->l_config(ws,
+ SWM_ARG_ID_FLIPLAYOUT);
+ }
}
/* config options */
{ "tile_gap", setconfvalue, SWM_S_TILE_GAP },
{ "title_class_enabled", setconfvalue, SWM_S_WINDOW_CLASS_ENABLED }, /* For backwards compat. */
{ "title_name_enabled", setconfvalue, SWM_S_WINDOW_INSTANCE_ENABLED }, /* For backwards compat. */
+ { "track_pid_ws", setconfvalue, SWM_S_TRACK_PID_WS },
{ "urgent_collapse", setconfvalue, SWM_S_URGENT_COLLAPSE },
{ "urgent_enabled", setconfvalue, SWM_S_URGENT_ENABLED },
{ "verbose_layout", setconfvalue, SWM_S_VERBOSE_LAYOUT },
configopt[optidx].optname);
continue;
}
+ /* trim trailing spaces */
+ ce = optval + strlen(optval) - 1;
+ while (ce > optval && isspace(*ce)) --ce;
+ *(ce + 1) = '\0';
/* call function to deal with it all */
if (configopt[optidx].func(optsub, optval,
configopt[optidx].funcflags) != 0) {
DNPRINTF(SWM_D_MISC, "manage_window: win %#x found on "
"unmanaged list.\n", id);
TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
-
- if (TRANS(win))
- set_child_transient(win, &trans);
-
- goto remanage;
} else {
DNPRINTF(SWM_D_MISC, "manage_window: win %#x is new.\n", id);
}
goto out;
}
- /* Create and initialize ws_win object. */
- if ((win = calloc(1, sizeof(struct ws_win))) == NULL)
- err(1, "manage_window: calloc: failed to allocate memory for "
- "new window");
+ /* Figure out which region the window belongs to. */
+ r = root_to_region(gr->root, SWM_CK_ALL);
- win->id = id;
+ /* Handle special windows with special _NET_WM_WINDOW_TYPE */
+ if (ewmh_handle_special_types(id, r)) {
+ DNPRINTF(SWM_D_EVENT, "manage_window: "
+ "unmanaged ewmh window type\n");
+ goto out;
+ }
- /* Figureout which region the window belongs to. */
- r = root_to_region(gr->root, SWM_CK_ALL);
+ if (!win) {
+ /* Create and initialize ws_win object. */
+ if ((win = calloc(1, sizeof(struct ws_win))) == NULL)
+ err(1, "manage_window: calloc: failed to allocate "
+ "memory for new window");
+
+ win->id = id;
+ }
/* Ignore window border if there is one. */
WIDTH(win) = gr->width;
update_window(win);
}
-remanage:
/* Figure out where to insert the window in the workspace list. */
if (trans && (ww = find_window(trans)))
TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
if (win->state == SWM_WIN_STATE_REPARENTING) {
win->state = SWM_WIN_STATE_REPARENTED;
- if (win->ws->r)
+ if (win->ws->r && !ICONIC(win))
map_window(win);
else
unmap_window(win);
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. */
+ /* The screen shouldn't focus on unused regions. */
TAILQ_FOREACH(r, &screens[idx].orl, entry) {
- TAILQ_FOREACH(win, &r->ws->winlist, entry)
- unmap_window(win);
- r->ws->state = SWM_WS_STATE_HIDDEN;
-
- /* The screen shouldn't focus on an unused region. */
if (screens[idx].r_focus == r)
screens[idx].r_focus = NULL;
}
screenchange(xcb_randr_screen_change_notify_event_t *e)
{
struct swm_region *r;
- int i, num_screens;
+ struct workspace *ws;
+ struct ws_win *win;
+ int i, j, num_screens;
DNPRINTF(SWM_D_EVENT, "screenchange: root: %#x\n", e->root);
focus_region(r);
}
+ /* Cleanup unused previously visible workspaces. */
+ for (j = 0; j < workspace_limit; j++) {
+ ws = &screens[i].ws[j];
+ if (ws->r == NULL && ws->state != SWM_WS_STATE_HIDDEN) {
+ TAILQ_FOREACH(win, &ws->winlist, entry)
+ unmap_window(win);
+ ws->state = SWM_WS_STATE_HIDDEN;
+ }
+ }
+
focus_flush();
/* Update workspace state and bar on all regions. */
TAILQ_INIT(&ws->unmanagedlist);
for (k = 0; layouts[k].l_stack != NULL; k++)
- if (layouts[k].l_config != NULL)
- layouts[k].l_config(ws,
- SWM_ARG_ID_STACKINIT);
+ layouts[k].l_config(ws, SWM_ARG_ID_STACKINIT);
ws->cur_layout = &layouts[0];
ws->cur_layout->l_string(ws);
}