#include <util.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xrandr.h>
+#include <X11/Xcursor/Xcursor.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb_atom.h>
#define SWM_FOCUS_FOLLOW (1)
#define SWM_FOCUS_MANUAL (2)
+#define SWM_CK_NONE 0
+#define SWM_CK_ALL 0x7
+#define SWM_CK_FOCUS 0x1
+#define SWM_CK_POINTER 0x2
+#define SWM_CK_FALLBACK 0x4
+
#define SWM_CONF_DEFAULT (0)
#define SWM_CONF_KEYMAPPING (1)
{"_SWM_WM_STATE_MANUAL", XCB_ATOM_NONE},
};
+/* Cursors */
+enum {
+ XC_FLEUR,
+ XC_LEFT_PTR,
+ XC_BOTTOM_LEFT_CORNER,
+ XC_BOTTOM_RIGHT_CORNER,
+ XC_SIZING,
+ XC_TOP_LEFT_CORNER,
+ XC_TOP_RIGHT_CORNER,
+ XC_MAX
+};
+
+struct cursors {
+ char *name; /* Name used by Xcursor .*/
+ uint8_t cf_char; /* cursorfont index. */
+ xcb_cursor_t cid;
+} cursors[XC_MAX] = {
+ {"fleur", XC_fleur, XCB_CURSOR_NONE},
+ {"left_ptr", XC_left_ptr, XCB_CURSOR_NONE},
+ {"bottom_left_corner", XC_bottom_left_corner, XCB_CURSOR_NONE},
+ {"bottom_right_corner", XC_bottom_right_corner, XCB_CURSOR_NONE},
+ {"sizing", XC_sizing, XCB_CURSOR_NONE},
+ {"top_left_corner", XC_top_left_corner, XCB_CURSOR_NONE},
+ {"top_right_corner", XC_top_right_corner, XCB_CURSOR_NONE},
+};
+
/* function prototypes */
void buttonpress(xcb_button_press_event_t *);
void check_conn(void);
char *get_notify_detail_label(uint8_t);
char *get_notify_mode_label(uint8_t);
#endif
+struct ws_win *get_pointer_win(xcb_window_t);
struct ws_win *get_region_focus(struct swm_region *);
xcb_screen_t *get_screen(int);
char *get_win_name(xcb_window_t);
void update_window(struct ws_win *);
/*void visibilitynotify(xcb_visibility_notify_event_t *);*/
+void
+cursors_load(void)
+{
+ xcb_font_t cf = XCB_NONE;
+ int i;
+
+ for (i = 0; i < LENGTH(cursors); ++i) {
+ /* try to load Xcursor first. */
+ cursors[i].cid = XcursorLibraryLoadCursor(display,
+ cursors[i].name);
+
+ /* fallback to cursorfont. */
+ if (cursors[i].cid == XCB_CURSOR_NONE) {
+ if (cf == XCB_NONE) {
+ cf = xcb_generate_id(conn);
+ xcb_open_font(conn, cf, strlen("cursor"),
+ "cursor");
+ }
+
+ cursors[i].cid = xcb_generate_id(conn);
+ xcb_create_glyph_cursor(conn, cursors[i].cid, cf, cf,
+ cursors[i].cf_char, cursors[i].cf_char + 1, 0, 0, 0,
+ 0xffff, 0xffff, 0xffff);
+
+ }
+ }
+
+ if (cf != XCB_NONE)
+ xcb_close_font(conn, cf);
+}
+
+void
+cursors_cleanup(void)
+{
+ int i;
+ for (i = 0; i < LENGTH(cursors); ++i)
+ xcb_free_cursor(conn, cursors[i].cid);
+}
+
char *
expand_tilde(char *s)
{
s = &s[i];
ppwd = strlen(user) == 0 ? getpwuid(getuid()) : getpwnam(user);
+ free(user);
+
if (ppwd == NULL)
result = strdup(sc);
else
}
void
-update_iconic(struct ws_win *win, int newv)
+set_swm_iconic(struct ws_win *win, int newv)
{
int32_t v = newv;
if (title_class_enabled) {
strlcat(fmtnew, "+C", sz);
- if (title_name_enabled == 0)
+ if (!title_name_enabled)
strlcat(fmtnew, "+4<", sz);
}
size_t len;
char *b;
- if (bar_enabled == 0)
+ if (!bar_enabled)
return;
if (bar_extra && bar_extra_running) {
/* ignore short reads; it'll correct itself */
int i, num_screens;
/* do this here because the conf file is in memory */
- if (bar_extra && bar_extra_running == 0 && bar_argv[0]) {
+ if (bar_extra && !bar_extra_running && bar_argv[0]) {
/* launch external status app */
bar_extra_running = 1;
if (pipe(bar_pipe) == -1)
int count = 0;
TAILQ_FOREACH(win, &ws->winlist, entry) {
- if (count_transient == 0 && win->floating)
+ if (!count_transient && win->floating)
continue;
- if (count_transient == 0 && win->transient)
+ if (!count_transient && win->transient)
continue;
if (win->iconic)
continue;
quit(NULL, NULL);
}
+struct ws_win *
+get_pointer_win(xcb_window_t root)
+{
+ struct ws_win *win = NULL;
+ xcb_query_pointer_reply_t *r;
+
+ DNPRINTF(SWM_D_EVENT, "get_pointer_win: root: 0x%x.\n", root);
+
+ r = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, root), NULL);
+ if (r) {
+ win = find_window(r->child);
+ if (win) {
+ DNPRINTF(SWM_D_EVENT, "get_pointer_win: 0x%x.\n",
+ win->id);
+ } else {
+ DNPRINTF(SWM_D_EVENT, "get_pointer_win: none.\n");
+ }
+ }
+
+ return win;
+}
+
struct swm_region *
-root_to_region(xcb_window_t root)
+root_to_region(xcb_window_t root, int check)
{
+ struct ws_win *cfw;
struct swm_region *r = NULL;
int i, num_screens;
xcb_query_pointer_reply_t *qpr;
+ xcb_get_input_focus_reply_t *gifr;
DNPRINTF(SWM_D_MISC, "root_to_region: window: 0x%x\n", root);
if (screens[i].root == root)
break;
- qpr = xcb_query_pointer_reply(conn, xcb_query_pointer(conn,
- screens[i].root), NULL);
+ if (check & SWM_CK_FOCUS) {
+ /* Try to find an actively focused window */
+ gifr = xcb_get_input_focus_reply(conn,
+ xcb_get_input_focus(conn), NULL);
+ if (gifr) {
+ cfw = find_window(gifr->focus);
+ if (cfw && cfw->ws->r)
+ r = cfw->ws->r;
- if (qpr) {
- DNPRINTF(SWM_D_MISC, "root_to_region: pointer: (%d,%d)\n",
- qpr->root_x, qpr->root_y);
- /* choose a region based on pointer location */
- TAILQ_FOREACH(r, &screens[i].rl, entry)
- if (X(r) <= qpr->root_x && qpr->root_x < MAX_X(r) &&
- Y(r) <= qpr->root_y && qpr->root_y < MAX_Y(r))
- break;
- free(qpr);
+ free(gifr);
+ }
}
- if (r == NULL)
+ if (r == NULL && check & SWM_CK_POINTER) {
+ /* No region with an active focus; try to use pointer. */
+ qpr = xcb_query_pointer_reply(conn, xcb_query_pointer(conn,
+ screens[i].root), NULL);
+
+ if (qpr) {
+ DNPRINTF(SWM_D_MISC, "root_to_region: pointer: "
+ "(%d,%d)\n", qpr->root_x, qpr->root_y);
+ TAILQ_FOREACH(r, &screens[i].rl, entry)
+ if (X(r) <= qpr->root_x &&
+ qpr->root_x < MAX_X(r) &&
+ Y(r) <= qpr->root_y &&
+ qpr->root_y < MAX_Y(r))
+ break;
+ free(qpr);
+ }
+ }
+
+ /* Last resort. */
+ if (r == NULL && check & SWM_CK_FALLBACK)
r = TAILQ_FIRST(&screens[i].rl);
return (r);
void
focus_win(struct ws_win *win)
{
- struct ws_win *cfw = NULL;
+ struct ws_win *cfw = NULL, *parent = NULL, *w;
+ struct workspace *ws;
xcb_get_input_focus_reply_t *r;
DNPRINTF(SWM_D_FOCUS, "focus_win: window: 0x%x\n", WINID(win));
if (win->ws == NULL)
goto out;
- if (validate_ws(win->ws))
+ ws = win->ws;
+
+ if (validate_ws(ws))
goto out;
if (validate_win(win)) {
free(r);
}
- if (win->ws->focus != win) {
- if (win->ws->focus && win->ws->focus != cfw)
- unfocus_win(win->ws->focus);
- win->ws->focus = win;
+ if (ws->focus != win) {
+ if (ws->focus && ws->focus != cfw)
+ unfocus_win(ws->focus);
+ ws->focus = win;
+ }
+
+ /* If this window directs focus to a child window, then clear. */
+ if (win->focus_child)
+ win->focus_child = NULL;
+
+ /* If transient, adjust parent's focus child for focus_magic. */
+ if (win->transient) {
+ parent = find_window(win->transient);
+ if (parent && parent->focus_child != win)
+ parent->focus_child = win;
}
- if (cfw != win && win->ws->r != NULL) {
+ if (cfw != win && ws->r != NULL) {
/* Set input focus if no input hint, or indicated by hint. */
if (!(win->hints.flags & XCB_ICCCM_WM_HINT_INPUT) ||
(win->hints.flags & XCB_ICCCM_WM_HINT_INPUT &&
if (win->take_focus) {
/* java is special; always tell parent */
if (win->transient && win->java)
- client_msg(find_window(win->transient),
- a_takefocus, last_event_time);
+ client_msg(parent, a_takefocus,
+ last_event_time);
else
client_msg(win, a_takefocus, last_event_time);
}
xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
- &win->ws->r->s->c[SWM_S_COLOR_FOCUS].pixel);
+ &ws->r->s->c[SWM_S_COLOR_FOCUS].pixel);
+
+ if (ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
+ ws->always_raise) {
+ /* If a parent exists, map it first. */
+ if (parent) {
+ map_window(parent);
+
+ /* Map siblings next. */
+ TAILQ_FOREACH(w, &ws->winlist, entry)
+ if (w != win && !w->iconic &&
+ w->transient == parent->id)
+ map_window(w);
+ }
- if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
- win->ws->always_raise)
+ /* Map focused window. */
map_window(win);
+ /* Finally, map children of focus window. */
+ TAILQ_FOREACH(w, &ws->winlist, entry)
+ if (w->transient == win->id && !w->iconic)
+ map_window(w);
+
+ }
+
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1,
&win->id);
get_focus_magic(struct ws_win *win)
{
struct ws_win *parent = NULL;
+ struct ws_win *child = NULL;
DNPRINTF(SWM_D_FOCUS, "get_focus_magic: window: 0x%x\n", WINID(win));
if (win == NULL)
if (win->transient) {
parent = find_window(win->transient);
- /* If parent prefers focus elsewhere, then do so. */
- if (parent && parent->focus_child) {
- if (validate_win(parent->focus_child) == 0)
- win = parent->focus_child;
+ /* If parent prefers focus elsewhere, then try to do so. */
+ if (parent && (child = parent->focus_child)) {
+ if (validate_win(child) == 0 && child->mapped)
+ win = child;
else
parent->focus_child = NULL;
}
}
- /* If this window prefers focus elsewhere, then do so. */
- if (win->focus_child) {
- if (validate_win(win->focus_child) == 0)
- win = win->focus_child;
+ /* If this window prefers focus elsewhere, then try to do so. */
+ if ((child = win->focus_child)) {
+ if (validate_win(child) == 0 && child->mapped)
+ win = child;
else
win->focus_child = NULL;
}
this_r->ws = new_ws;
new_ws->r = this_r;
+ /* Set focus_pending before stacking. */
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ new_ws->focus_pending = get_region_focus(new_ws->r);
+
stack();
/* unmap old windows */
TAILQ_FOREACH(win, &old_ws->winlist, entry)
unmap_window(win);
- new_ws->focus_pending = get_region_focus(new_ws->r);
+ /* if workspaces were swapped, then don't wait to set focus */
+ if (old_ws->r && focus_mode != SWM_FOCUS_FOLLOW) {
+ if (new_ws->focus_pending) {
+ focus_win(new_ws->focus_pending);
+ } else {
+ /* Empty region, focus on root. */
+ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT,
+ new_ws->r->s[new_ws->r->s->idx].root,
+ XCB_CURRENT_TIME);
+ }
+ }
- if (new_ws->focus_pending) {
- /* if workspaces were swapped, then don't wait to set focus */
- if (old_ws->r)
- focus_win(new_ws->focus);
- } else {
- /* make sure bar gets updated if ws is empty */
+ /* Clear bar if new ws is empty. */
+ if (new_ws->focus_pending == NULL)
bar_update();
- }
focus_flush();
};
if (!cycle_all &&
- (cycle_empty == 0 && TAILQ_EMPTY(&s->ws[a.id].winlist)))
+ (!cycle_empty && TAILQ_EMPTY(&s->ws[a.id].winlist)))
continue;
- if (cycle_visible == 0 && s->ws[a.id].r != NULL)
+ if (!cycle_visible && s->ws[a.id].r != NULL)
continue;
switchws(r, &a);
void
cyclescr(struct swm_region *r, union arg *args)
{
+ struct ws_win *nfw;
struct swm_region *rr = NULL;
- int i, x, y, num_screens;
+ int i, num_screens;
num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
/* do nothing if we don't have more than one screen */
if (rr == NULL)
return;
- /* move mouse to region */
- x = X(rr) + 1;
- y = Y(rr) + 1 + (bar_enabled ? bar_height : 0);
- xcb_warp_pointer(conn, XCB_WINDOW_NONE, rr->s[i].root, 0, 0, 0, 0,
- x, y);
-
- rr->ws->focus = get_region_focus(rr);
+ nfw = get_region_focus(rr);
+ if (nfw) {
+ focus_win(nfw);
+ } else {
+ /* New region is empty; unfocus old region and warp pointer. */
+ unfocus_win(r->ws->focus);
+ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT,
+ rr->s[i].root, XCB_CURRENT_TIME);
- if (rr->ws->focus) {
- /* move to focus window */
- x = X(rr->ws->focus) + 1;
- y = Y(rr->ws->focus) + 1;
- xcb_warp_pointer(conn, XCB_WINDOW_NONE, rr->s[i].root, 0, 0, 0,
- 0, x, y);
+ /* Clear bar since empty. */
+ bar_update();
}
focus_flush();
/* make sure there is at least one uniconified window */
all_iconics = 1;
TAILQ_FOREACH(winfocus, wl, entry)
- if (winfocus->iconic == 0) {
+ if (!winfocus->iconic) {
all_iconics = 0;
break;
}
while (winfocus != cur_focus) {
if (winfocus == NULL)
winfocus = TAILQ_LAST(wl, ws_win_list);
- if (winfocus->iconic == 0)
+ if (!winfocus->iconic)
break;
winfocus = TAILQ_PREV(winfocus, ws_win_list,
entry);
while (winfocus != cur_focus) {
if (winfocus == NULL)
winfocus = TAILQ_FIRST(wl);
- if (winfocus->iconic == 0)
+ if (!winfocus->iconic)
break;
winfocus = TAILQ_NEXT(winfocus, entry);
}
focus_win(get_focus_magic(winfocus));
- xcb_flush(conn);
+ focus_flush();
}
void
return;
TAILQ_FOREACH(win, &ws->winlist, entry)
- if (win->transient == 0 && win->floating == 0
- && win->iconic == 0)
+ if (!win->transient && !win->floating && !win->iconic)
break;
if (win == NULL)
/* stack all the tiled windows */
i = j = 0, s = stacks;
TAILQ_FOREACH(win, &ws->winlist, entry) {
- if (win->transient != 0 || win->floating != 0)
+ if (win->transient || win->floating)
continue;
- if (win->iconic != 0)
+ if (win->iconic)
continue;
if (win->ewmh_flags & EWMH_F_FULLSCREEN) {
else
win_g.y += last_h + 2 * border_width;
- if (disable_border && bar_enabled == 0 && winno == 1){
+ if (disable_border && !bar_enabled && winno == 1){
bordered = 0;
win_g.w += 2 * border_width;
win_g.h += 2 * border_width;
notiles:
/* now, stack all the floaters and transients */
TAILQ_FOREACH(win, &ws->winlist, entry) {
- if (win->transient == 0 && win->floating == 0)
+ if (!win->transient && !win->floating)
continue;
- if (win->iconic == 1)
+ if (win->iconic)
continue;
if (win->ewmh_flags & EWMH_F_FULLSCREEN) {
fs_win = win;
map_window(win);
}
+ /* Make sure fs_win is stacked last so it's on top. */
if (fs_win) {
stack_floater(fs_win, ws->r);
map_window(fs_win);
max_stack(struct workspace *ws, struct swm_geometry *g)
{
struct swm_geometry gg = *g;
- struct ws_win *win, *wintrans = NULL, *parent = NULL;
+ struct ws_win *w, *win = NULL, *parent = NULL;
int winno, num_screens;
DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
if (winno == 0 && count_win(ws, 1) == 0)
return;
+ /* Figure out which top level window should be visible. */
+ if (ws->focus_pending)
+ win = ws->focus_pending;
+ else if (ws->focus)
+ win = ws->focus;
+ else
+ win = TAILQ_FIRST(&ws->winlist);
+
+ if (win->transient)
+ parent = find_window(win->transient);
+
+ 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(win, &ws->winlist, entry) {
- if (win->transient) {
- wintrans = win;
- parent = find_window(win->transient);
+ TAILQ_FOREACH(w, &ws->winlist, entry) {
+ if (w->transient || w->iconic)
continue;
- }
- if (win->floating && win->floatmaxed == 0 ) {
+ if (w->floating && !w->floatmaxed) {
/*
* retain geometry for retrieval on exit from
* max_stack mode
*/
- store_float_geom(win, ws->r);
- win->floatmaxed = 1;
+ store_float_geom(w, ws->r);
+ w->floatmaxed = 1;
}
/* only reconfigure if necessary */
- if (X(win) != gg.x || Y(win) != gg.y || WIDTH(win) != gg.w ||
- HEIGHT(win) != gg.h) {
- win->g = gg;
+ if (X(w) != gg.x || Y(w) != gg.y || WIDTH(w) != gg.w ||
+ HEIGHT(w) != gg.h) {
+ w->g = gg;
if (bar_enabled){
- win->bordered = 1;
+ w->bordered = 1;
} else {
- win->bordered = 0;
- WIDTH(win) += 2 * border_width;
- HEIGHT(win) += 2 * border_width;
+ w->bordered = 0;
+ WIDTH(w) += 2 * border_width;
+ HEIGHT(w) += 2 * border_width;
}
- update_window(win);
+ update_window(w);
}
- /* unmap only if we don't have multi screen */
- if (win != ws->focus)
- if (!(num_screens > 1 || outputs > 1))
- unmap_window(win);
+
+ /* Unmap unwanted windows if not multi-screen. */
+ if (!(num_screens > 1 || outputs > 1) && (w != win ||
+ w != parent || w->transient != win->id))
+ unmap_window(w);
}
- /* put the last transient on top */
- if (wintrans) {
- if (parent)
- map_window(parent);
- stack_floater(wintrans, ws->r);
- ws->focus = get_focus_magic(wintrans);
+ /* If a parent exists, map it first. */
+ if (parent) {
+ map_window(parent);
+
+ /* Map siblings next. */
+ TAILQ_FOREACH(w, &ws->winlist, entry)
+ if (w != win && !w->iconic &&
+ w->transient == parent->id) {
+ stack_floater(w, ws->r);
+ map_window(w);
+ }
}
+
+ /* Map focused window. */
+ map_window(win);
+
+ /* Finally, map children of focus window. */
+ TAILQ_FOREACH(w, &ws->winlist, entry)
+ if (w->transient == win->id && !w->iconic) {
+ stack_floater(w, ws->r);
+ map_window(w);
+ }
}
void
{
int wsid = args->id;
struct ws_win *win = NULL, *parent;
- struct workspace *ws, *nws;
+ struct workspace *ws, *nws, *pws;
char ws_idx_str[SWM_PROPLEN];
- union arg a;
if (wsid >= workspace_limit)
return;
win = r->ws->focus;
else
return;
- if (win == NULL)
- return;
+
if (win->ws->idx == wsid)
return;
- DNPRINTF(SWM_D_MOVE, "send_to_ws: window: 0x%x\n", win->id);
+ DNPRINTF(SWM_D_MOVE, "send_to_ws: win 0x%x, ws %d -> %d\n", win->id,
+ win->ws->idx, wsid);
ws = win->ws;
nws = &win->s->ws[wsid];
- a.id = SWM_ARG_ID_FOCUSPREV;
- focus(r, &a);
- if (win->transient) {
- parent = find_window(win->transient);
- if (parent) {
- unmap_window(parent);
- TAILQ_REMOVE(&ws->winlist, parent, entry);
- TAILQ_INSERT_TAIL(&nws->winlist, parent, entry);
- parent->ws = nws;
+ /* Update the window's workspace property: _SWM_WS */
+ if (snprintf(ws_idx_str, SWM_PROPLEN, "%d", nws->idx) < SWM_PROPLEN) {
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ ws->focus_pending = get_focus_prev(win);
+
+ /* Move the parent if this is a transient window. */
+ if (win->transient) {
+ parent = find_window(win->transient);
+ if (parent) {
+ pws = parent->ws;
+ /* Set new focus in parent's ws if needed. */
+ if (pws->focus == parent) {
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ pws->focus_pending =
+ get_focus_prev(parent);
+
+ unfocus_win(parent);
+
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ pws->focus = pws->focus_pending;
+
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ pws->focus_pending = NULL;
+ }
+
+ /* Don't unmap parent if new ws is visible */
+ if (nws->r == NULL)
+ unmap_window(parent);
+
+ /* Transfer */
+ TAILQ_REMOVE(&ws->winlist, parent, entry);
+ TAILQ_INSERT_TAIL(&nws->winlist, parent, entry);
+ parent->ws = nws;
+
+ DNPRINTF(SWM_D_PROP, "send_to_ws: set "
+ "property: _SWM_WS: %s\n", ws_idx_str);
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ parent->id, a_swm_ws, XCB_ATOM_STRING, 8,
+ strlen(ws_idx_str), ws_idx_str);
+ }
}
- }
- unmap_window(win);
- TAILQ_REMOVE(&ws->winlist, win, entry);
- TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
- if (TAILQ_EMPTY(&ws->winlist))
- r->ws->focus = NULL;
- win->ws = nws;
- /* Try to update the window's workspace property */
- if (snprintf(ws_idx_str, SWM_PROPLEN, "%d", nws->idx) < SWM_PROPLEN) {
+ unfocus_win(win);
+
+ /* Don't unmap if new ws is visible */
+ if (nws->r == NULL)
+ unmap_window(win);
+
+ /* Transfer */
+ TAILQ_REMOVE(&ws->winlist, win, entry);
+ TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
+ win->ws = nws;
+
+ /* Set focus on new ws. */
+ unfocus_win(nws->focus);
+ nws->focus = win;
+
DNPRINTF(SWM_D_PROP, "send_to_ws: set property: _SWM_WS: %s\n",
ws_idx_str);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
a_swm_ws, XCB_ATOM_STRING, 8, strlen(ws_idx_str),
ws_idx_str);
- }
- stack();
- bar_update();
+ /* Restack and set new focus. */
+ stack();
- focus_flush();
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ focus_win(ws->focus_pending);
+ ws->focus_pending = NULL;
+ }
+
+ focus_flush();
+ }
+
+ DNPRINTF(SWM_D_MOVE, "send_to_ws: done.\n");
}
void
r->ws->always_raise = !r->ws->always_raise;
/* bring floaters back to top */
- if (r->ws->always_raise == 0)
+ if (!r->ws->always_raise)
stack();
focus_flush();
if (r->ws->focus == NULL)
return;
- update_iconic(r->ws->focus, 1);
+ set_swm_iconic(r->ws->focus, 1);
xcb_flush(conn);
}
TAILQ_FOREACH(win, &r->ws->winlist, entry) {
if (win->ws == NULL)
continue; /* should never happen */
- if (win->iconic == 0)
+ if (!win->iconic)
continue;
count++;
}
TAILQ_FOREACH(win, &r->ws->winlist, entry) {
if (win->ws == NULL)
continue; /* should never happen */
- if (win->iconic == 0)
+ if (!win->iconic)
continue;
name = get_win_name(win->id);
i = 1;
TAILQ_FOREACH(win, &r->ws->winlist, entry) {
- if (win->iconic == 1)
+ if (win->iconic)
continue;
sw = calloc(1, sizeof(struct search_window));
DNPRINTF(SWM_D_MISC, "search_resp_uniconify: resp: %s\n", resp);
TAILQ_FOREACH(win, &search_r->ws->winlist, entry) {
- if (win->iconic == 0)
+ if (!win->iconic)
continue;
name = get_win_name(win->id);
if (name == NULL)
free(name);
if (strncmp(s, resp, len) == 0) {
/* XXX this should be a callback to generalize */
- update_iconic(win, 0);
- xcb_flush(conn);
+ set_swm_iconic(win, 0);
free(s);
break;
}
if (r->ws->focus->can_delete)
client_msg(r->ws->focus, a_delete, 0);
- xcb_flush(conn);
+ focus_flush();
}
int
struct swm_geometry g;
int top = 0, left = 0, resizing;
int dx, dy;
- unsigned int shape; /* cursor style */
- xcb_cursor_t cursor;
- xcb_font_t cursor_font;
+ xcb_cursor_t cursor;
xcb_query_pointer_reply_t *xpr;
xcb_generic_event_t *evt;
xcb_motion_notify_event_t *mne;
"transient: 0x%x\n", win->id, YESNO(win->floating),
win->transient);
- if (!(win->transient != 0 || win->floating != 0))
+ if (!win->transient && !win->floating)
return;
/* reject resizes in max mode for floaters (transient ok) */
top = 1;
if (args->id == SWM_ARG_ID_CENTER)
- shape = XC_sizing;
+ cursor = cursors[XC_SIZING].cid;
else if (top)
- shape = (left) ? XC_top_left_corner : XC_top_right_corner;
+ cursor = cursors[left ? XC_TOP_LEFT_CORNER :
+ XC_TOP_RIGHT_CORNER].cid;
else
- shape = (left) ? XC_bottom_left_corner : XC_bottom_right_corner;
-
- cursor_font = xcb_generate_id(conn);
- xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
-
- cursor = xcb_generate_id(conn);
- xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
- shape, shape + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff);
+ cursor = cursors[left ? XC_BOTTOM_LEFT_CORNER :
+ XC_BOTTOM_RIGHT_CORNER].cid;
xcb_grab_pointer(conn, 0, win->id, MOUSEMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, cursor,
store_float_geom(win,r);
xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
- xcb_free_cursor(conn, cursor);
- xcb_close_font(conn, cursor_font);
free(xpr);
DNPRINTF(SWM_D_EVENT, "resize: done.\n");
}
return;
resize(win, args);
+ focus_flush();
}
#define SWM_MOVE_STEPS (50)
xcb_timestamp_t timestamp = 0;
int move_step = 0, moving;
struct swm_region *r = NULL;
- xcb_font_t cursor_font;
- xcb_cursor_t cursor;
xcb_query_pointer_reply_t *qpr;
xcb_generic_event_t *evt;
xcb_motion_notify_event_t *mne;
return;
win->manual = 1;
- if (win->floating == 0 && !win->transient) {
+ if (!win->floating && !win->transient) {
store_float_geom(win, r);
ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
_NET_WM_STATE_ADD);
return;
}
- cursor_font = xcb_generate_id(conn);
- xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
-
- cursor = xcb_generate_id(conn);
- xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
- XC_fleur, XC_fleur + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff);
-
xcb_grab_pointer(conn, 0, win->id, MOUSEMASK,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
- XCB_WINDOW_NONE, cursor, XCB_CURRENT_TIME);
+ XCB_WINDOW_NONE, cursors[XC_FLEUR].cid, XCB_CURRENT_TIME);
/* get cursor offset from window root */
qpr = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, win->id),
NULL);
if (!qpr) {
xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
- xcb_free_cursor(conn, cursor);
- xcb_close_font(conn, cursor_font);
return;
}
}
store_float_geom(win, r);
free(qpr);
- xcb_free_cursor(conn, cursor);
- xcb_close_font(conn, cursor_font);
xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
DNPRINTF(SWM_D_EVENT, "move: done.\n");
}
else
return;
- if (!(win->transient != 0 || win->floating != 0))
+ if (!win->transient && !win->floating)
return;
move(win, args);
+ focus_flush();
}
/* user/key callable function IDs */
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
XCB_WINDOW_NONE, XCB_CURSOR_NONE,
buttons[i].button, buttons[i].mask);
-
- /* click to focus */
- xcb_grab_button(conn, 0, win->id, BUTTONMASK, XCB_GRAB_MODE_SYNC,
- XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE, XCB_CURSOR_NONE,
- XCB_BUTTON_INDEX_1, XCB_BUTTON_MASK_ANY);
}
const char *quirkname[] = {
case SWM_S_FOCUS_MODE:
if (!strcmp(value, "default"))
focus_mode = SWM_FOCUS_DEFAULT;
- else if (!strcmp(value, "follow_cursor"))
+ else if (!strcmp(value, "follow") ||
+ !strcmp(value, "follow_cursor"))
focus_mode = SWM_FOCUS_FOLLOW;
else if (!strcmp(value, "manual"))
focus_mode = SWM_FOCUS_MANUAL;
DNPRINTF(SWM_D_MISC, "set_child_transient: parent doesn't exist"
" for 0x%x trans 0x%x\n", win->id, win->transient);
- r = root_to_region(win->wa->root);
+ r = root_to_region(win->wa->root, SWM_CK_ALL);
ws = r->ws;
/* parent doen't exist in our window list */
TAILQ_FOREACH(w, &ws->winlist, entry) {
NULL);
/* Figure out which region the window belongs to. */
- r = root_to_region(win->wa->root);
+ r = root_to_region(win->wa->root, SWM_CK_ALL);
/* Ignore window border if there is one. */
WIDTH(win) = win->wa->width;
free(p);
p = NULL;
} else if ((ws_idx = get_ws_idx(win->id)) != -1 &&
- win->transient == 0) {
+ !win->transient) {
/* _SWM_WS is set; use that. */
win->ws = &r->s->ws[ws_idx];
} else if (trans && (ww = find_window(trans)) != NULL) {
last_event_time = e->time;
if (kp->funcid == KF_SPAWN_CUSTOM)
- spawn_custom(root_to_region(e->root),
+ spawn_custom(root_to_region(e->root, SWM_CK_ALL),
&(keyfuncs[kp->funcid].args), kp->spawn_name);
else if (keyfuncs[kp->funcid].func)
- keyfuncs[kp->funcid].func(root_to_region(e->root),
+ keyfuncs[kp->funcid].func(root_to_region(e->root, SWM_CK_ALL),
&(keyfuncs[kp->funcid].args));
}
void
buttonpress(xcb_button_press_event_t *e)
{
- struct ws_win *win;
+ struct ws_win *win = NULL;
+ struct swm_region *r, *old_r;
int i;
int handled = 0;
- DNPRINTF(SWM_D_EVENT, "buttonpress: window 0x%x, detail: %u\n",
- e->event, e->detail);
+ DNPRINTF(SWM_D_EVENT, "buttonpress: win (x,y): 0x%x (%d,%d), "
+ "detail: %u, time: %u, root (x,y): 0x%x (%d,%d), child: 0x%x, "
+ "state: %u, same_screen: %s\n", e->event, e->event_x, e->event_y,
+ e->detail, e->time, e->root, e->root_x, e->root_y, e->child,
+ e->state, YESNO(e->same_screen));
+
+ if (e->event == e->root) {
+ if (e->child != 0) {
+ win = find_window(e->child);
+ /* Pass ButtonPress to window if it isn't managed. */
+ if (win == NULL)
+ goto out;
+ } else {
+ /* Focus on empty region */
+ /* If no windows on region if its empty. */
+ r = root_to_region(e->root, SWM_CK_POINTER);
+ if (r && TAILQ_EMPTY(&r->ws->winlist)) {
+ old_r = root_to_region(e->root, SWM_CK_FOCUS);
+ if (old_r && old_r != r)
+ unfocus_win(old_r->ws->focus);
+
+ xcb_set_input_focus(conn,
+ XCB_INPUT_FOCUS_PARENT, e->root, e->time);
+
+ /* Clear bar since empty. */
+ bar_update();
- if ((win = find_window(e->event)) == NULL)
+ handled = 1;
+ goto out;
+ }
+ }
+ } else {
+ win = find_window(e->event);
+ }
+
+ if (win == NULL)
return;
last_event_time = e->time;
handled = 1;
}
+out:
if (!handled) {
DNPRINTF(SWM_D_EVENT, "buttonpress: passing to window.\n");
+ /* Replay event to event window */
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, e->time);
} else {
DNPRINTF(SWM_D_EVENT, "buttonpress: handled.\n");
+ /* Unfreeze grab events. */
+ xcb_allow_events(conn, XCB_ALLOW_SYNC_POINTER, e->time);
}
xcb_flush(conn);
wc[i++] = e->stack_mode;
}
- if (mask != 0)
+ if (mask != 0) {
xcb_configure_window(conn, e->window, mask, wc);
+ xcb_flush(conn);
+ }
} else if ((!win->manual || win->quirks & SWM_Q_ANYWHERE) &&
!(win->ewmh_flags & EWMH_F_FULLSCREEN)) {
if (win->ws->r)
win->g_floatvalid = 1;
- if (win->floating && r) {
+ if (win->floating && r && (win->transient ||
+ win->ws->cur_layout != &layouts[SWM_MAX_STACK])) {
WIDTH(win) = win->g_float.w;
HEIGHT(win) = win->g_float.h;
config_win(win, e);
xcb_flush(conn);
}
+
+ DNPRINTF(SWM_D_EVENT, "configurerequest: done.\n");
}
void
{
struct ws_win *win;
- DNPRINTF(SWM_D_EVENT, "configurenotify: window: 0x%x\n",
- e->window);
+ DNPRINTF(SWM_D_EVENT, "configurenotify: win 0x%x, event win: 0x%x, "
+ "(x,y) WxH: (%d,%d) %ux%u, border: %u, above_sibling: 0x%x, "
+ "override_redirect: %s\n", e->window, e->event, e->x, e->y,
+ e->width, e->height, e->border_width, e->above_sibling,
+ YESNO(e->override_redirect));
win = find_window(e->window);
if (win) {
return;
}
- /* 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 (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);
+ }
unmanage_window(win);
stack();
- if (win->ws->focus_pending) {
- focus_win(win->ws->focus_pending);
- win->ws->focus_pending = NULL;
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ if (win->ws->focus_pending) {
+ focus_win(win->ws->focus_pending);
+ win->ws->focus_pending = NULL;
+ }
}
free_window(win);
enternotify(xcb_enter_notify_event_t *e)
{
struct ws_win *win;
+ struct swm_region *old_r, *r;
DNPRINTF(SWM_D_FOCUS, "enternotify: time: %u, win (x,y): 0x%x "
"(%d,%d), mode: %s(%d), detail: %s(%d), root (x,y): 0x%x (%d,%d), "
return;
}
+ last_event_time = e->time;
+
if ((win = find_window(e->event)) == NULL) {
- DNPRINTF(SWM_D_EVENT, "enternotify: window is NULL; ignoring\n");
+ if (e->event == e->root) {
+ /* If no windows on pointer region, then focus root. */
+ r = root_to_region(e->root, SWM_CK_POINTER);
+ if (TAILQ_EMPTY(&r->ws->winlist)) {
+ old_r = root_to_region(e->root, SWM_CK_FOCUS);
+ if (old_r && old_r != r)
+ unfocus_win(old_r->ws->focus);
+
+ xcb_set_input_focus(conn,
+ XCB_INPUT_FOCUS_PARENT, e->root, e->time);
+
+ /* Clear bar since empty. */
+ bar_update();
+
+ focus_flush();
+ }
+ } else {
+ DNPRINTF(SWM_D_EVENT, "enternotify: window is NULL; "
+ "ignoring\n");
+ }
return;
}
- last_event_time = e->time;
-
focus_win(get_focus_magic(win));
xcb_flush(conn);
win->mapped = 1;
set_win_state(win, XCB_ICCCM_WM_STATE_NORMAL);
- if (win->ws->focus_pending == win) {
- focus_win(win);
- win->ws->focus_pending = NULL;
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ if (win->ws->focus_pending == win) {
+ focus_win(win);
+ win->ws->focus_pending = NULL;
+ focus_flush();
+ }
}
xcb_flush(conn);
win = manage_window(e->window,
(war->map_state == XCB_MAP_STATE_VIEWABLE));
+ /* The new window should get focus; prepare. */
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ win->ws->focus_pending = get_focus_magic(win);
+
/* All windows need to be mapped if they are in the current workspace.*/
if (win->ws->r)
stack();
- /* The new window should get focus. */
- win->ws->focus_pending = get_focus_magic(win);
-
/* Ignore EnterNotify to handle the mapnotify without interference. */
if (focus_mode == SWM_FOCUS_DEFAULT)
event_drain(XCB_ENTER_NOTIFY);
name = get_atom_name(e->atom);
DNPRINTF(SWM_D_EVENT, "propertynotify: window: 0x%x, atom: %s(%u), "
- "time: %#x\n", e->window, name, e->atom, e->time);
+ "time: %#x, state: %u\n", e->window, name, e->atom, e->time,
+ e->state);
free(name);
#endif
win = find_window(e->window);
last_event_time = e->time;
if (e->atom == a_swm_iconic) {
- if (e->state == XCB_PROPERTY_DELETE) {
- /* The window is no longer iconic, restack ws. */
- win->ws->focus_pending = get_focus_magic(win);
- stack();
+ if (e->state == XCB_PROPERTY_NEW_VALUE) {
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ win->ws->focus_pending = get_focus_prev(win);
- /* Flush EnterNotify for mapnotify, if needed. */
- focus_flush();
- return;
- } else if (e->state == XCB_PROPERTY_NEW_VALUE) {
- win->ws->focus_pending = get_focus_prev(win);
unfocus_win(win);
unmap_window(win);
if (win->ws->r) {
stack();
- focus_win(win->ws->focus_pending);
- win->ws->focus_pending = NULL;
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ focus_win(win->ws->focus_pending);
+ win->ws->focus_pending = NULL;
+ }
focus_flush();
}
+ } else if (e->state == XCB_PROPERTY_DELETE) {
+ /* The window is no longer iconic, restack ws. */
+ if (focus_mode != SWM_FOCUS_FOLLOW)
+ win->ws->focus_pending = get_focus_magic(win);
+
+ stack();
+
+ /* Flush EnterNotify for mapnotify, if needed. */
+ focus_flush();
}
- } else if (e->atom == a_state && e->state == XCB_PROPERTY_NEW_VALUE) {
+ } else if (e->atom == a_state) {
/* State just changed, make sure it gets focused if mapped. */
- if (win->mapped && win->ws->focus_pending == win) {
- win->ws->focus_pending = NULL;
- focus_win(win);
+ if (e->state == XCB_PROPERTY_NEW_VALUE) {
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ if (win->mapped &&
+ win->ws->focus_pending == win) {
+ focus_win(win->ws->focus_pending);
+ win->ws->focus_pending = NULL;
+ }
+ }
}
- }
-
- switch (e->atom) {
- case XCB_ATOM_WM_CLASS:
- case XCB_ATOM_WM_NAME:
+ } else if (e->atom == XCB_ATOM_WM_CLASS ||
+ e->atom == XCB_ATOM_WM_NAME) {
bar_update();
- break;
- default:
- break;
}
xcb_flush(conn);
unmapnotify(xcb_unmap_notify_event_t *e)
{
struct ws_win *win;
+ struct workspace *ws;
DNPRINTF(SWM_D_EVENT, "unmapnotify: window: 0x%x\n", e->window);
- /* determine if we need to help unmanage this window */
+ /* If we aren't managing the window, then ignore. */
win = find_window(e->window);
if (win == NULL)
return;
- if (getstate(e->window) == XCB_ICCCM_WM_STATE_NORMAL) {
- /* If we were focused, make sure we focus on something else. */
- if (win == win->ws->focus)
- win->ws->focus_pending = get_focus_prev(win);
+ ws = win->ws;
- win->mapped = 0;
+ if (getstate(e->window) != XCB_ICCCM_WM_STATE_ICONIC)
set_win_state(win, XCB_ICCCM_WM_STATE_ICONIC);
- unmanage_window(win);
- stack();
+ if (win->mapped) {
+ /* window unmapped itself */
+ /* do unmap/unfocus/restack and unmanage */
+ win->mapped = 0;
- if (win->ws->focus_pending) {
- focus_win(win->ws->focus_pending);
- win->ws->focus_pending = NULL;
+ /* If win was focused, make sure to focus on something else. */
+ if (win == ws->focus) {
+ if (focus_mode != SWM_FOCUS_FOLLOW) {
+ ws->focus_pending = get_focus_prev(win);
+ DNPRINTF(SWM_D_EVENT, "unmapnotify: "
+ "focus_pending: 0x%x\n",
+ WINID(ws->focus_pending));
+ }
+
+ unfocus_win(win);
}
- focus_flush();
+ unmanage_window(win);
+
+ if (ws->r)
+ stack();
+
+ if (focus_mode == SWM_FOCUS_FOLLOW) {
+ if (ws->r)
+ focus_win(get_pointer_win(ws->r->s->root));
+ } else {
+ if (ws->focus_pending) {
+ focus_win(ws->focus_pending);
+ ws->focus_pending = NULL;
+ }
+ }
}
+
+ if (getstate(e->window) == XCB_ICCCM_WM_STATE_NORMAL)
+ set_win_state(win, XCB_ICCCM_WM_STATE_ICONIC);
+
+ focus_flush();
}
#if 0
if (win == NULL) {
if (e->type == ewmh[_NET_ACTIVE_WINDOW].atom) {
+ /* Manage the window with maprequest. */
DNPRINTF(SWM_D_EVENT, "clientmessage: request focus on "
"unmanaged window.\n");
mre.window = e->window;
stack();
}
- xcb_flush(conn);
+ focus_flush();
}
void
enable_wm(void)
{
int num_screens, i;
- const uint32_t val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
+ const uint32_t val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
+ XCB_EVENT_MASK_ENTER_WINDOW;
xcb_screen_t *sc;
xcb_void_cookie_t wac;
xcb_generic_error_t *error;
free(error);
return 1;
}
+
+ /* click to focus on empty region */
+ xcb_grab_button(conn, 1, sc->root, BUTTONMASK,
+ XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE,
+ XCB_CURSOR_NONE, XCB_BUTTON_INDEX_1, XCB_BUTTON_MASK_ANY);
}
return 0;
void
grab_windows(void)
{
- xcb_window_t *wins = NULL;
+ xcb_window_t *wins = NULL, trans;
int no;
int i, j, num_screens;
uint16_t state, manage, mapped;
no = xcb_query_tree_children_length(qtr);
/* attach windows to a region */
/* normal windows */
+ DNPRINTF(SWM_D_INIT, "grab_windows: grab top level windows.\n");
for (j = 0; j < no; j++) {
c = xcb_get_window_attributes(conn, wins[j]);
r = xcb_get_window_attributes_reply(conn, c, NULL);
- if (!r)
+ if (!r) {
+ DNPRINTF(SWM_D_INIT, "grab_windows: skip %#x; "
+ "doesn't exist.\n", wins[j]);
continue;
+ }
if (r->override_redirect) {
+ DNPRINTF(SWM_D_INIT, "grab_windows: skip %#x; "
+ "override_redirect set.\n", wins[j]);
free(r);
continue;
}
pc = xcb_icccm_get_wm_transient_for(conn, wins[j]);
if (xcb_icccm_get_wm_transient_for_reply(conn, pc,
- &wins[j], NULL)) {
+ &trans, NULL)) {
+ DNPRINTF(SWM_D_INIT, "grab_windows: skip %#x; "
+ "is transient for %#x.\n", wins[j], trans);
free(r);
continue;
}
state = getstate(wins[j]);
- manage = state == XCB_ICCCM_WM_STATE_ICONIC;
+ manage = state != XCB_ICCCM_WM_STATE_WITHDRAWN;
mapped = r->map_state != XCB_MAP_STATE_UNMAPPED;
if (mapped || manage)
manage_window(wins[j], mapped);
free(r);
}
/* transient windows */
+ DNPRINTF(SWM_D_INIT, "grab_windows: grab transient windows.\n");
for (j = 0; j < no; j++) {
c = xcb_get_window_attributes(conn, wins[j]);
r = xcb_get_window_attributes_reply(conn, c, NULL);
- if (!r)
+ if (!r) {
+ DNPRINTF(SWM_D_INIT, "grab_windows: skip %#x; "
+ "doesn't exist.\n", wins[j]);
continue;
+ }
if (r->override_redirect) {
+ DNPRINTF(SWM_D_INIT, "grab_windows: skip %#x; "
+ "override_redirect set.\n", wins[j]);
free(r);
continue;
}
- free(r);
state = getstate(wins[j]);
- manage = state == XCB_ICCCM_WM_STATE_ICONIC;
+ manage = state != XCB_ICCCM_WM_STATE_WITHDRAWN;
mapped = r->map_state != XCB_MAP_STATE_UNMAPPED;
pc = xcb_icccm_get_wm_transient_for(conn, wins[j]);
if (xcb_icccm_get_wm_transient_for_reply(conn, pc,
- &wins[j], NULL) && manage)
+ &trans, NULL) && manage)
manage_window(wins[j], mapped);
+ free(r);
}
free(qtr);
}
uint32_t gcv[1], wa[1];
const xcb_query_extension_reply_t *qep;
xcb_screen_t *screen;
- xcb_cursor_t cursor;
- xcb_font_t cursor_font;
xcb_randr_query_version_cookie_t c;
xcb_randr_query_version_reply_t *r;
}
}
- cursor_font = xcb_generate_id(conn);
- xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
-
- cursor = xcb_generate_id(conn);
- xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
- XC_left_ptr, XC_left_ptr + 1, 0, 0, 0, 0xffff, 0xffff, 0xffff);
- wa[0] = cursor;
+ wa[0] = cursors[XC_LEFT_PTR].cid;
/* map physical screens */
for (i = 0; i < num_screens; i++) {
xcb_randr_select_input(conn, screens[i].root,
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
}
- xcb_free_cursor(conn, cursor);
- xcb_close_font(conn, cursor_font);
}
void
bar_extra = 1;
unmap_all();
+ cursors_cleanup();
+
teardown_ewmh();
num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
if (enable_wm() != 0)
errx(1, "another window manager is currently running");
+ /* Load Xcursors and/or cursorfont glyph cursors. */
+ cursors_load();
+
xcb_aux_sync(conn);
setup_globals();
while (running) {
while ((evt = xcb_poll_for_event(conn))) {
- if (running == 0)
+ if (!running)
goto done;
event_handle(evt);
free(evt);
}
- /* if we are being restarted go focus on first window */
- if (winfocus) {
+ /* If just (re)started, set default focus if needed. */
+ if (winfocus && focus_mode != SWM_FOCUS_FOLLOW) {
rr = winfocus->ws->r;
if (rr == NULL) {
/* not a visible window */
winfocus = NULL;
continue;
}
- /* move pointer to first screen if multi screen */
- if (num_screens > 1 || outputs > 1)
- xcb_warp_pointer(conn, XCB_WINDOW_NONE,
- rr->s[0].root, 0, 0, 0, 0, X(rr),
- Y(rr) + (bar_enabled ? bar_height : 0));
focus_win(get_region_focus(rr));
focus_flush();
if (errno != EINTR) {
DNPRINTF(SWM_D_MISC, "select failed");
}
- if (restart_wm == 1)
+ if (restart_wm)
restart(NULL, NULL);
- if (search_resp == 1)
+ if (search_resp)
search_do_resp();
- if (running == 0)
+ if (!running)
goto done;
if (bar_alarm) {
bar_alarm = 0;