#define SH_INC_H(w) ((w)->sh.height_inc)
#define SWM_MAX_FONT_STEPS (3)
#define WINID(w) ((w) ? (w)->id : XCB_WINDOW_NONE)
+#define ACCEPTS_FOCUS(w) (!((w)->hints.flags & XCB_ICCCM_WM_HINT_INPUT) \
+ || ((w)->hints.input))
#define WS_FOCUSED(ws) ((ws)->r && (ws)->r->s->r_focus == (ws)->r)
#define YESNO(x) ((x) ? "yes" : "no")
#define ICONIC(w) ((w)->ewmh_flags & EWMH_F_HIDDEN)
xcb_window_t transient;
struct ws_win *focus_child; /* focus on child transient */
struct swm_geometry g; /* current geometry */
+ struct swm_geometry g_prev; /* prev configured geometry */
struct swm_geometry g_float; /* region coordinates */
bool g_floatvalid; /* g_float geometry validity */
bool mapped;
void focus_pointer(struct binding *, struct swm_region *, union arg *);
void focus_region(struct swm_region *);
void focus_win(struct ws_win *);
-#ifdef SWM_DEBUG
void focusin(xcb_focus_in_event_t *);
+#ifdef SWM_DEBUG
void focusout(xcb_focus_out_event_t *);
#endif
void focusrg(struct binding *, struct swm_region *, union arg *);
#endif
int32_t get_swm_ws(xcb_window_t);
bool get_urgent(struct ws_win *);
+#ifdef SWM_DEBUG
+char *get_win_input_model(struct ws_win *);
+#endif
char *get_win_name(xcb_window_t);
uint8_t get_win_state(xcb_window_t);
void get_wm_protocols(struct ws_win *);
void priorws(struct binding *, struct swm_region *, union arg *);
#ifdef SWM_DEBUG
void print_win_geom(xcb_window_t);
-void print_win_input_model(struct ws_win *);
#endif
void propertynotify(xcb_property_notify_event_t *);
void put_back_event(xcb_generic_event_t *);
break;
}
- if (asprintf(&s, "%#x wl:%d s:%d", win->id, widx, sidx) == -1)
+ if (asprintf(&s, "%#x f:%#x wl:%d s:%d im:%s", win->id,
+ win->frame, widx, sidx, get_win_input_model(win)) == -1)
return;
len = strlen(s);
int i, j, num_screens;
xcb_query_tree_reply_t *qtr;
+ DNPRINTF(SWM_D_MISC, "find_window: id: %#x\n", id);
+
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++)
for (j = 0; j < workspace_limit; j++)
{
struct ws_win *cfw = NULL, *parent = NULL, *w, *tmpw;
struct workspace *ws;
- xcb_get_input_focus_reply_t *gifr;
+ xcb_get_input_focus_reply_t *gifr = NULL;
+ xcb_get_window_attributes_reply_t *war = NULL;
DNPRINTF(SWM_D_FOCUS, "focus_win: win %#x\n", WINID(win));
gifr->focus);
cfw = find_window(gifr->focus);
- if (cfw != NULL && cfw != win) {
- if (cfw->ws != ws && cfw->ws->r != NULL &&
- cfw->frame != XCB_WINDOW_NONE) {
- draw_frame(cfw);
- } else {
- unfocus_win(cfw);
+ if (cfw) {
+ if (cfw != win) {
+ if (cfw->ws != ws && cfw->ws->r != NULL &&
+ cfw->frame != XCB_WINDOW_NONE) {
+ draw_frame(cfw);
+ } else {
+ unfocus_win(cfw);
+ }
+ }
+ } else {
+ war = xcb_get_window_attributes_reply(conn,
+ xcb_get_window_attributes(conn, gifr->focus), NULL);
+ if (war && war->override_redirect && ws->focus == win) {
+ DNPRINTF(SWM_D_FOCUS, "focus_win: skip refocus "
+ "from override_redirect.\n");
+ goto out;
}
}
- free(gifr);
}
if (ws->focus != win) {
if (ws->r) {
/* Set input focus if no input hint, or indicated by hint. */
- if (!(win->hints.flags & XCB_ICCCM_WM_HINT_INPUT) ||
- win->hints.input) {
+ if (ACCEPTS_FOCUS(win)) {
DNPRINTF(SWM_D_FOCUS, "focus_win: set_input_focus: %#x,"
" revert-to: parent, time: %#x\n", win->id,
last_event_time);
}
out:
+ free(gifr);
+ free(war);
DNPRINTF(SWM_D_FOCUS, "focus_win: done.\n");
}
"(%d,%d) %d x %d, bordered: %s\n", win->id, wc[0], wc[1], wc[2],
wc[3], YESNO(win->bordered));
xcb_configure_window(conn, win->id, mask, wc);
- config_win(win, NULL);
+
+ /* ICCCM 4.2.3 Synthetic ConfigureNotify when moved and not resized. */
+ if ((X(win) != win->g_prev.x || Y(win) != win->g_prev.y) &&
+ (win->java || (WIDTH(win) == win->g_prev.w &&
+ HEIGHT(win) == win->g_prev.h))) {
+ /* Java has special needs when moved together with a resize. */
+ config_win(win, NULL);
+ }
+
+ win->g_prev = win->g;
}
struct event {
#ifdef SWM_DEBUG
/* Must be after getting WM_HINTS and WM_PROTOCOLS. */
- print_win_input_model(win);
+ DNPRINTF(SWM_D_FOCUS, "manage_window: input_model: %s\n",
+ get_win_input_model(win));
#endif
/* Set initial quirks based on EWMH. */
DNPRINTF(SWM_D_EVENT, "expose: done\n");
}
-#ifdef SWM_DEBUG
void
focusin(xcb_focus_in_event_t *e)
{
+ struct ws_win *win;
+
DNPRINTF(SWM_D_EVENT, "focusin: win %#x, mode: %s(%u), "
"detail: %s(%u)\n", e->event, get_notify_mode_label(e->mode),
e->mode, get_notify_detail_label(e->detail), e->detail);
+ if ((win = find_window(e->event)) && win != win->ws->focus &&
+ win != win->ws->focus_pending &&
+ e->mode == XCB_NOTIFY_MODE_NORMAL) {
+ win->ws->focus_prev = win->ws->focus;
+ win->ws->focus = win;
+ win->ws->focus_pending = NULL;
+
+ if (win->ws->focus_prev)
+ draw_frame(win->ws->focus_prev);
+ draw_frame(win);
+ raise_window(win);
+ }
}
+#ifdef SWM_DEBUG
void
focusout(xcb_focus_out_event_t *e)
{
void
buttonpress(xcb_button_press_event_t *e)
{
- struct ws_win *win = NULL;
+ struct ws_win *win = NULL, *newf;
struct swm_region *r, *old_r;
struct action *ap;
struct binding *bp;
win = find_window(e->event);
}
- if (win)
- focus_win(get_focus_magic(win));
+ if (win) {
+ newf = get_focus_magic(win);
+ if (win->ws->focus == newf && newf != win) {
+ if (win->focus_child == win)
+ win->focus_child = NULL;
+ newf = win;
+ }
+ focus_win(newf);
+ }
/* Handle any bound action. */
bp = binding_lookup(CLEANMASK(e->state), BTNBIND, e->detail);
}
#ifdef SWM_DEBUG
-void
-print_win_input_model(struct ws_win *win)
+char *
+get_win_input_model(struct ws_win *win)
{
char *inputmodel;
/*
* Globally Active False Present
*/
- if (!(win->hints.flags & XCB_ICCCM_WM_HINT_INPUT) || win->hints.input)
+ if (ACCEPTS_FOCUS(win))
inputmodel = (win->take_focus) ? "Locally Active" : "Passive";
else
inputmodel = (win->take_focus) ? "Globally Active" : "No Input";
- DNPRINTF(SWM_D_FOCUS, "print_win_input_model: win %#x, model: %s\n",
- win->id, inputmodel);
+ return inputmodel;
}
void
maprequest(xcb_map_request_event_t *e)
{
struct ws_win *win, *w = NULL;
- xcb_get_window_attributes_reply_t *war;
DNPRINTF(SWM_D_EVENT, "maprequest: win %#x\n",
e->window);
- war = xcb_get_window_attributes_reply(conn,
- xcb_get_window_attributes(conn, e->window),
- NULL);
- if (war == NULL) {
- DNPRINTF(SWM_D_EVENT, "maprequest: window lost.\n");
- goto out;
- }
-
- if (war->override_redirect) {
- DNPRINTF(SWM_D_EVENT, "maprequest: override_redirect; "
- "skipping.\n");
- goto out;
- }
-
win = manage_window(e->window, spawn_position, true);
if (win == NULL)
goto out;
/* The new window should get focus; prepare. */
if (focus_mode != SWM_FOCUS_FOLLOW &&
- !(win->quirks & SWM_Q_NOFOCUSONMAP) &&
- (!(win->hints.flags & XCB_ICCCM_WM_HINT_INPUT) ||
- (win->hints.flags & XCB_ICCCM_WM_HINT_INPUT &&
- win->hints.input))) {
+ !(win->quirks & SWM_Q_NOFOCUSONMAP) && ACCEPTS_FOCUS(win)) {
if (win->quirks & SWM_Q_FOCUSONMAP_SINGLE) {
/* See if other wins of same type are already mapped. */
TAILQ_FOREACH(w, &win->ws->winlist, entry) {
if (focus_mode == SWM_FOCUS_DEFAULT)
event_drain(XCB_ENTER_NOTIFY);
out:
- free(war);
DNPRINTF(SWM_D_EVENT, "maprequest: done.\n");
}
EVENT(XCB_DESTROY_NOTIFY, destroynotify);
EVENT(XCB_ENTER_NOTIFY, enternotify);
EVENT(XCB_EXPOSE, expose);
-#ifdef SWM_DEBUG
EVENT(XCB_FOCUS_IN, focusin);
+#ifdef SWM_DEBUG
EVENT(XCB_FOCUS_OUT, focusout);
#endif
/*EVENT(XCB_GRAPHICS_EXPOSURE, );*/