diff --git a/include/i3.h b/include/i3.h index bf9d4b81..9b20e2a9 100644 --- a/include/i3.h +++ b/include/i3.h @@ -21,7 +21,7 @@ #ifndef _I3_H #define _I3_H -#define NUM_ATOMS 21 +#define NUM_ATOMS 22 extern xcb_connection_t *global_conn; extern xcb_key_symbols_t *keysyms; diff --git a/include/util.h b/include/util.h index d1384962..7d942766 100644 --- a/include/util.h +++ b/include/util.h @@ -126,6 +126,12 @@ char *convert_utf8_to_ucs2(char *input, int *real_strlen); Client *get_last_focused_client(xcb_connection_t *conn, Container *container, Client *exclude); +/** + * Sends WM_TAKE_FOCUS to the client + * + */ +void take_focus(xcb_connection_t *conn, Client *client); + /** * Sets the given client as focused by updating the data structures correctly, * updating the X input focus and finally re-decorating both windows (to diff --git a/include/xcb.h b/include/xcb.h index 78e1373a..8d867553 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -64,7 +64,8 @@ enum { _NET_SUPPORTED = 0, WM_CLIENT_LEADER, _NET_CURRENT_DESKTOP, _NET_ACTIVE_WINDOW, - _NET_WORKAREA + _NET_WORKAREA, + WM_TAKE_FOCUS }; extern unsigned int xcb_numlock_mask; diff --git a/src/mainx.c b/src/mainx.c index b0ae40b9..be4713e6 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -326,6 +326,7 @@ int main(int argc, char *argv[], char *env[]) { REQUEST_ATOM(_NET_CURRENT_DESKTOP); REQUEST_ATOM(_NET_ACTIVE_WINDOW); REQUEST_ATOM(_NET_WORKAREA); + REQUEST_ATOM(WM_TAKE_FOCUS); /* TODO: this has to be more beautiful somewhen */ int major, minor, error; @@ -491,6 +492,7 @@ int main(int argc, char *argv[], char *env[]) { GET_ATOM(_NET_CURRENT_DESKTOP); GET_ATOM(_NET_ACTIVE_WINDOW); GET_ATOM(_NET_WORKAREA); + GET_ATOM(WM_TAKE_FOCUS); xcb_property_set_handler(&prophs, atoms[_NET_WM_WINDOW_TYPE], UINT_MAX, handle_window_type, NULL); /* TODO: In order to comply with EWMH, we have to watch _NET_WM_STRUT_PARTIAL */ diff --git a/src/manage.c b/src/manage.c index 06f4e664..089d62cb 100644 --- a/src/manage.c +++ b/src/manage.c @@ -512,6 +512,7 @@ map: } if (new->container == CUR_CELL || client_is_floating(new)) { xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, new->child, XCB_CURRENT_TIME); + take_focus(conn, new); ewmh_update_active_window(new->child); } } diff --git a/src/util.c b/src/util.c index cb37d30a..d119b35a 100644 --- a/src/util.c +++ b/src/util.c @@ -222,6 +222,25 @@ Client *get_last_focused_client(xcb_connection_t *conn, Container *container, Cl return NULL; } +/* + * Sends WM_TAKE_FOCUS to the client + * + */ +void take_focus(xcb_connection_t *conn, Client *client) { + xcb_client_message_event_t ev; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.window = client->child; + ev.type = atoms[WM_PROTOCOLS]; + ev.format = 32; + ev.data.data32[0] = atoms[WM_TAKE_FOCUS]; + ev.data.data32[1] = XCB_CURRENT_TIME; + + DLOG("Sending WM_TAKE_FOCUS to the client\n"); + xcb_send_event(conn, false, client->child, XCB_EVENT_MASK_NO_EVENT, (char*)&ev); +} /* * Sets the given client as focused by updating the data structures correctly, @@ -261,6 +280,7 @@ void set_focus(xcb_connection_t *conn, Client *client, bool set_anyways) { CLIENT_LOG(client); /* Set focus to the entered window, and flush xcb buffer immediately */ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, client->child, XCB_CURRENT_TIME); + take_focus(conn, client); ewmh_update_active_window(client->child); //xcb_warp_pointer(conn, XCB_NONE, client->child, 0, 0, 0, 0, 10, 10);