* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Much code and ideas taken from dwm under the following license:
- * MIT/X Consortium License
- *
- * 2006-2008 Anselm R Garbe <garbeam at gmail dot com>
- * 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
- * 2006-2007 Jukka Salmi <jukka at salmi dot ch>
- * 2007 Premysl Hruby <dfenze at gmail dot com>
- * 2007 Szabolcs Nagy <nszabolcs at gmail dot com>
- * 2007 Christof Musik <christof at sendfax dot de>
- * 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
- * 2007-2008 Peter Hartlich <sgkkr at hartlich dot com>
- * 2008 Martin Hurton <martin dot hurton at gmail dot com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
/* kernel includes */
#include <sys/types.h>
#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 MOUSEMASK (BUTTONMASK|XCB_EVENT_MASK_POINTER_MOTION)
#define SWM_PROPLEN (16)
#define SWM_FUNCNAME_LEN (32)
-#define SWM_KEYS_LEN (255)
#define SWM_QUIRK_LEN (64)
#define X(r) ((r)->g.x)
#define Y(r) ((r)->g.y)
#define SWM_FOCUS_FOLLOW (1)
#define SWM_FOCUS_MANUAL (2)
-#define SWM_CK_NONE (0)
#define SWM_CK_ALL (0xf)
#define SWM_CK_FOCUS (0x1)
#define SWM_CK_POINTER (0x2)
#define SWM_CK_FALLBACK (0x4)
#define SWM_CK_REGION (0x8)
-#define SWM_G_ALL (0xf)
-#define SWM_G_SIZE (0x1)
-#define SWM_G_POS (0x2)
-
#define SWM_CONF_DEFAULT (0)
#define SWM_CONF_KEYMAPPING (1)
struct ws_win *focus; /* may be NULL */
struct ws_win *focus_prev; /* may be NULL */
struct ws_win *focus_pending; /* may be NULL */
+ struct ws_win *focus_raise; /* may be NULL */
struct swm_region *r; /* may be NULL */
struct swm_region *old_r; /* may be NULL */
struct ws_win_list winlist; /* list of windows in ws */
#define SWM_ARG_ID_CYCLEWS_MOVE_DOWN (47)
#define SWM_ARG_ID_STACKINC (50)
#define SWM_ARG_ID_STACKDEC (51)
-#define SWM_ARG_ID_SS_ALL (60)
-#define SWM_ARG_ID_SS_WINDOW (61)
#define SWM_ARG_ID_DONTCENTER (70)
#define SWM_ARG_ID_CENTER (71)
#define SWM_ARG_ID_KILLWINDOW (80)
#define SWM_ARG_ID_MOVEDOWN (101)
#define SWM_ARG_ID_MOVELEFT (102)
#define SWM_ARG_ID_MOVERIGHT (103)
-#define SWM_ARG_ID_RAISE (105)
-#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)
_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_FOCUS_NEXT,
FN_FOCUS_PREV,
FN_FOCUS_URGENT,
+ FN_FULLSCREEN_TOGGLE,
FN_MAXIMIZE_TOGGLE,
FN_HEIGHT_GROW,
FN_HEIGHT_SHRINK,
FN_MVRG_7,
FN_MVRG_8,
FN_MVRG_9,
+ KF_MVRG_NEXT,
+ KF_MVRG_PREV,
FN_MVWS_1,
FN_MVWS_2,
FN_MVWS_3,
FN_MVWS_22,
FN_NAME_WORKSPACE,
FN_QUIT,
+ FN_RAISE,
FN_RAISE_TOGGLE,
FN_RESIZE,
FN_RESIZE_CENTERED,
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 focusrg(struct binding *, struct swm_region *, union arg *);
void fontset_init(void);
void free_window(struct ws_win *);
+void fullscreen_toggle(struct binding *, struct swm_region *, union arg *);
xcb_atom_t get_atom_from_string(const char *);
#ifdef SWM_DEBUG
char *get_atom_name(xcb_atom_t);
void quirk_replace(struct quirk *, const char *, const char *, const char *,
uint32_t, int);
void quit(struct binding *, struct swm_region *, union arg *);
+void raise_focus(struct binding *, struct swm_region *, union arg *);
void raise_toggle(struct binding *, struct swm_region *, union arg *);
void raise_window(struct ws_win *);
void region_containment(struct ws_win *, struct swm_region *, int);
void search_win_cleanup(void);
void search_workspace(struct binding *, struct swm_region *, union arg *);
void send_to_rg(struct binding *, struct swm_region *, union arg *);
+void send_to_rg_relative(struct binding *, struct swm_region *, union arg *);
void send_to_ws(struct binding *, struct swm_region *, union arg *);
void set_region(struct swm_region *);
int setautorun(const char *, const char *, int);
}
}
+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;
strlcat(s, "- ", sz);
}
}
- if(urgent_collapse && s[0])
+ if (urgent_collapse && s[0])
s[strlen(s) - 1] = 0;
}
sibling = TAILQ_NEXT(win, stack_entry);
if (sibling != NULL && (FLOATING(win) == FLOATING(sibling) ||
- (win->ws->always_raise && win->ws->focus == win)))
+ (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[1] = XCB_STACK_MODE_ABOVE;
+ } else if (FLOATING(win) || (win->ws->always_raise &&
+ win->ws->focus == win)) {
val[0] = r->bar->id;
- else
- val[0] = r->id;
+ val[1] = XCB_STACK_MODE_ABOVE;
+ } else {
+ val[0] = r->bar->id;
+ val[1] = XCB_STACK_MODE_BELOW;
+ }
DNPRINTF(SWM_D_EVENT, "update_win_stacking: win %#x (%#x), "
- "sibling %#x\n", win->frame, win->id, val[0]);
-
- val[1] = XCB_STACK_MODE_ABOVE;
+ "sibling %#x mode %#x\n", win->frame, win->id, val[0], val[1]);
xcb_configure_window(conn, win->frame, XCB_CONFIG_WINDOW_SIBLING |
XCB_CONFIG_WINDOW_STACK_MODE, val);
struct ws_win *
find_window(xcb_window_t id)
{
- struct ws_win *win;
+ struct ws_win *win = NULL;
int i, j, num_screens;
xcb_query_tree_reply_t *qtr;
if (id == win->id || id == win->frame)
return (win);
- /* win NULL */
/* If window isn't top-level, try to find managed ancestor. */
qtr = xcb_query_tree_reply(conn, xcb_query_tree(conn, id), NULL);
close(xcb_get_file_descriptor(conn));
- setenv("LD_PRELOAD", SWM_LIB, 1);
+ 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");
ws->focus_prev = NULL;
if (win == ws->focus_pending)
ws->focus_pending = NULL;
+ if (win == ws->focus_raise)
+ ws->focus_raise = NULL;
if (TRANS(win))
TAILQ_FOREACH(w, &ws->winlist, entry)
if (win->ws->focus == win) {
win->ws->focus = NULL;
win->ws->focus_prev = win;
+ if (win->ws->focus_raise == win && !FLOATING(win)) {
+ update_win_stacking(win);
+ }
}
if (validate_win(win->ws->focus)) {
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();
}
int wsid = args->id;
bool unmap_old = false;
- (void)bp;
-
if (!(r && r->s))
return;
return;
other_r = new_ws->r;
- if (other_r && workspace_clamp) {
+ if (other_r && workspace_clamp &&
+ bp->action != FN_RG_MOVE_NEXT && bp->action != FN_RG_MOVE_PREV) {
DNPRINTF(SWM_D_WS, "switchws: ws clamped.\n");
if (warp_focus) {
DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d, rot: %s, "
"flip: %s\n", ws->idx, YESNO(rot), YESNO(flip));
+ memset(&cell, 0, sizeof(cell));
+
/* Prepare tiling variables, if needed. */
if ((winno = count_win(ws, false)) > 0) {
/* Find first tiled window. */
focus_flush();
}
+/* Transfer focused window to region-relative workspace and focus. */
+void
+send_to_rg_relative(struct binding *bp, struct swm_region *r, union arg *args)
+{
+ union arg args_abs;
+ struct swm_region *r_other;
+
+ if (args->id == 1) {
+ r_other = TAILQ_NEXT(r, entry);
+ if (r_other == NULL)
+ r_other = TAILQ_FIRST(&r->s->rl);
+ } else {
+ r_other = TAILQ_PREV(r, swm_region_list, entry);
+ if (r_other == NULL)
+ r_other = TAILQ_LAST(&r->s->rl, swm_region_list);
+ }
+
+ /* Map relative to absolute */
+ args_abs = *args;
+ args_abs.id = r_other->ws->idx;
+
+ send_to_ws(bp, r, &args_abs);
+}
+
void
win_to_ws(struct ws_win *win, int wsid, bool unfocus)
{
XCB_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
}
+void
+raise_focus(struct binding *bp, struct swm_region *r, union arg *args)
+{
+ struct ws_win *win;
+ uint32_t val;
+
+ /* Suppress warning. */
+ (void)bp;
+ (void)args;
+
+ if (r == NULL || r->ws == NULL || r->ws->focus == NULL)
+ return;
+
+ win = r->ws->focus;
+ r->ws->focus_raise = win;
+ raise_window(win);
+
+ /* Temporarily override stacking order also in the stack */
+ if (!FLOATING(win)) {
+ val = XCB_STACK_MODE_ABOVE;
+ xcb_configure_window(conn, win->frame,
+ XCB_CONFIG_WINDOW_STACK_MODE, &val);
+ }
+}
+
void
raise_toggle(struct binding *bp, struct swm_region *r, union arg *args)
{
++len;
}
- if((name_list = calloc(len, sizeof(char))) == NULL)
+ if ((name_list = calloc(len, sizeof(char))) == NULL)
err(1, "update_desktop_names: calloc: failed to "
"allocate memory.");
DNPRINTF(SWM_D_MISC, "floating_toggle: done\n");
}
+void
+fullscreen_toggle(struct binding *bp, struct swm_region *r, union arg *args)
+{
+ struct ws_win *w = r->ws->focus;
+
+ /* suppress unused warning since var is needed */
+ (void)bp;
+ (void)args;
+
+ if (w == NULL)
+ return;
+
+ DNPRINTF(SWM_D_MISC, "fullscreen_toggle: win %#x\n", w->id);
+
+ ewmh_apply_flags(w, w->ewmh_flags ^ EWMH_F_FULLSCREEN);
+ ewmh_update_wm_state(w);
+
+ stack(r);
+
+ if (w == w->ws->focus)
+ focus_win(w);
+
+ center_pointer(r);
+ focus_flush();
+ DNPRINTF(SWM_D_MISC, "fullscreen_toggle: done\n");
+}
void
region_containment(struct ws_win *win, struct swm_region *r, int opts)
{
SIMPLEQ_HEAD(event_queue, event) events = SIMPLEQ_HEAD_INITIALIZER(events);
xcb_generic_event_t *
-get_next_event(bool wait)
+get_next_event(bool dowait)
{
struct event *ep;
xcb_generic_event_t *evt;
evt = ep->ev;
SIMPLEQ_REMOVE_HEAD(&events, entry);
free(ep);
- } else if (wait)
+ } else if (dowait)
evt = xcb_wait_for_event(conn);
else
evt = xcb_poll_for_event(conn);
{ "focus_next", focus, 0, {.id = SWM_ARG_ID_FOCUSNEXT} },
{ "focus_prev", focus, 0, {.id = SWM_ARG_ID_FOCUSPREV} },
{ "focus_urgent", focus, 0, {.id = SWM_ARG_ID_FOCUSURGENT} },
+ { "fullscreen_toggle", fullscreen_toggle, 0, {0} },
{ "maximize_toggle", maximize_toggle,0, {0} },
{ "height_grow", resize, 0, {.id = SWM_ARG_ID_HEIGHTGROW} },
{ "height_shrink", resize, 0, {.id = SWM_ARG_ID_HEIGHTSHRINK} },
{ "mvrg_7", send_to_rg, 0, {.id = 6} },
{ "mvrg_8", send_to_rg, 0, {.id = 7} },
{ "mvrg_9", send_to_rg, 0, {.id = 8} },
+ { "mvrg_next", send_to_rg_relative, 0, {.id = 1} },
+ { "mvrg_prev", send_to_rg_relative, 0, {.id = -1} },
{ "mvws_1", send_to_ws, 0, {.id = 0} },
{ "mvws_2", send_to_ws, 0, {.id = 1} },
{ "mvws_3", send_to_ws, 0, {.id = 2} },
{ "mvws_22", send_to_ws, 0, {.id = 21} },
{ "name_workspace", name_workspace, 0, {0} },
{ "quit", quit, 0, {0} },
+ { "raise", raise_focus, 0, {0} },
{ "raise_toggle", raise_toggle, 0, {0} },
{ "resize", resize, FN_F_NOREPLAY, {.id = SWM_ARG_ID_DONTCENTER} },
{ "resize_centered", resize, FN_F_NOREPLAY, {.id = SWM_ARG_ID_CENTER} },
BINDKEY(MODKEY, XK_k, FN_FOCUS_PREV);
BINDKEY(MODSHIFT, XK_Tab, FN_FOCUS_PREV);
BINDKEY(MODKEY, XK_u, FN_FOCUS_URGENT);
+ BINDKEY(MODSHIFT, XK_e, FN_FULLSCREEN_TOGGLE);
BINDKEY(MODKEY, XK_e, FN_MAXIMIZE_TOGGLE);
BINDKEY(MODSHIFT, XK_equal, FN_HEIGHT_GROW);
BINDKEY(MODSHIFT, XK_minus, FN_HEIGHT_SHRINK);
BINDKEY(MODSHIFT, XK_F12, FN_MVWS_22);
BINDKEY(MODSHIFT, XK_slash, FN_NAME_WORKSPACE);
BINDKEY(MODSHIFT, XK_q, FN_QUIT);
+ BINDKEY(MODKEY, XK_r, FN_RAISE);
BINDKEY(MODSHIFT, XK_r, FN_RAISE_TOGGLE);
BINDKEY(MODKEY, XK_q, FN_RESTART);
BINDKEY(MODKEY, XK_KP_End, FN_RG_1);
struct ws_win *
manage_window(xcb_window_t id, int spawn_pos, bool mapping)
{
- struct ws_win *win, *ww;
+ struct ws_win *win = NULL, *ww;
struct swm_region *r;
struct pid_e *p;
struct quirk *qp;
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);
{
char *name;
- switch(mode) {
+ switch (mode) {
case XCB_STACK_MODE_ABOVE:
name = "Above";
break;
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);
print_win_geom(e->root);
#endif
/* add bars to all regions */
- for (i = 0; i < num_screens; i++) {
- TAILQ_FOREACH(r, &screens[i].rl, entry)
- bar_setup(r);
- }
+ TAILQ_FOREACH(r, &screens[i].rl, entry)
+ bar_setup(r);
/* Stack all regions. */
TAILQ_FOREACH(r, &screens[i].rl, entry)
stack(r);
- /* 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);
+ /* Make sure a region has focus. */
+ if (screens[i].r_focus == NULL) {
+ r = TAILQ_FIRST(&screens[i].rl);
+ if (r != NULL)
+ 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. */
- for (i = 0; i < num_screens; i++)
- TAILQ_FOREACH(r, &screens[i].rl, entry) {
- r->ws->state = SWM_WS_STATE_MAPPED;
- bar_draw(r->bar);
- }
+ TAILQ_FOREACH(r, &screens[i].rl, entry) {
+ r->ws->state = SWM_WS_STATE_MAPPED;
+ bar_draw(r->bar);
+ }
}
void
ws->focus = NULL;
ws->focus_prev = NULL;
ws->focus_pending = NULL;
+ ws->focus_raise = NULL;
ws->r = NULL;
ws->old_r = NULL;
ws->state = SWM_WS_STATE_HIDDEN;