uint8_t state, xcb_window_t window,
xcb_atom_t name, xcb_get_property_reply_t *prop);
+int handle_focus_in(void *data, xcb_connection_t *conn, xcb_focus_in_event_t *event);
#endif
#ifndef _X_H
#define _X_H
+/** Stores the X11 window ID of the currently focused window */
+extern xcb_window_t focused_id;
+
/**
* Initializes the X11 part for the given container. Called exactly once for
* every container from con_new().
*
* i3 - an improved dynamic tiling window manager
*
- * (c) 2009 Michael Stapelberg and contributors
+ * © 2009-2011 Michael Stapelberg and contributors
*
* See file LICENSE for license information.
*
while rendering the layout) */
/** The XCB_CW_EVENT_MASK for the child (= real window) */
#define CHILD_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY)
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
+ XCB_EVENT_MASK_FOCUS_CHANGE)
/** The XCB_CW_EVENT_MASK for its frame */
#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | /* …mouse is pressed/released */ \
handle_mapping_notify(NULL, conn, (xcb_mapping_notify_event_t*)event);
break;
+ case XCB_FOCUS_IN:
+ handle_focus_in(NULL, conn, (xcb_focus_in_event_t*)event);
+ break;
+
case XCB_PROPERTY_NOTIFY:
DLOG("Property notify\n");
xcb_property_notify_event_t *e = (xcb_property_notify_event_t*)event;
return 1;
}
+
+/*
+ * Handles FocusIn events which are generated by clients (i3’s focus changes
+ * don’t generate FocusIn events due to a different EventMask) and updates the
+ * decorations accordingly.
+ *
+ */
+int handle_focus_in(void *data, xcb_connection_t *conn, xcb_focus_in_event_t *event) {
+ DLOG("focus change in, for window 0x%08x\n", event->event);
+ Con *con;
+ if ((con = con_by_window_id(event->event)) == NULL || con->window == NULL)
+ return 1;
+ DLOG("That is con %p / %s\n", con, con->name);
+
+ if (event->detail == XCB_NOTIFY_DETAIL_POINTER) {
+ DLOG("notify detail is pointer, ignoring this event\n");
+ return 1;
+ }
+
+ if (focused_id == event->event) {
+ DLOG("focus matches the currently focused window, not doing anything\n");
+ return 1;
+ }
+
+ DLOG("focus is different, updating decorations\n");
+ con_focus(con);
+ /* We update focused_id because we don’t need to set focus again */
+ focused_id = event->event;
+ x_push_changes(croot);
+ return 1;
+}
#include "all.h"
/* Stores the X11 window ID of the currently focused window */
-static xcb_window_t focused_id = XCB_NONE;
+xcb_window_t focused_id = XCB_NONE;
/*
* Describes the X11 state we may modify (map state, position, window stack).
focused_id = XCB_NONE;
} else {
DLOG("Updating focus (focused: %p / %s)\n", focused, focused->name);
+ /* We remove XCB_EVENT_MASK_FOCUS_CHANGE from the event mask to get
+ * no focus change events for our own focus changes. We only want
+ * these generated by the clients. */
+ if (focused->window != NULL) {
+ values[0] = CHILD_EVENT_MASK & ~(XCB_EVENT_MASK_FOCUS_CHANGE);
+ xcb_change_window_attributes(conn, focused->window->id, XCB_CW_EVENT_MASK, values);
+ }
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, to_focus, XCB_CURRENT_TIME);
+ if (focused->window != NULL) {
+ values[0] = CHILD_EVENT_MASK;
+ xcb_change_window_attributes(conn, focused->window->id, XCB_CW_EVENT_MASK, values);
+ }
if (focused->window != NULL &&
focused->window->needs_take_focus) {
CIRCLEQ_FOREACH(state, &old_state_head, old_state) {
DLOG("old stack: 0x%08x\n", state->id);
}
+
+ xcb_flush(conn);
}
/*