From 82e286ed7c20f269e1a225c2ce082cf6a33a140b Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 18 Mar 2011 17:07:56 +0100 Subject: [PATCH] Only send WM_TAKE_FOCUS when the client supports it in the protocols atom Fixes opening xterm, for example --- include/data.h | 3 +++ include/x.h | 6 ++++++ include/xcb.h | 6 ++++++ src/manage.c | 3 +++ src/x.c | 19 +++++-------------- src/xcb.c | 20 ++++++++++++++++++++ 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/include/data.h b/include/data.h index 8beb91ab..088561c4 100644 --- a/include/data.h +++ b/include/data.h @@ -246,6 +246,9 @@ struct Window { /** Whether the application used _NET_WM_NAME */ bool uses_net_wm_name; + /** Whether the application needs to receive WM_TAKE_FOCUS */ + bool needs_take_focus; + /** Whether the window says it is a dock window */ enum { W_NODOCK = 0, W_DOCK_TOP = 1, W_DOCK_BOTTOM = 2 } dock; diff --git a/include/x.h b/include/x.h index 43b0814b..da4147cc 100644 --- a/include/x.h +++ b/include/x.h @@ -39,6 +39,12 @@ void x_reinit(Con *con); */ void x_con_kill(Con *con); +/** + * Returns true if the client supports the given protocol atom (like WM_DELETE_WINDOW) + * + */ +bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom); + /** * Kills the given X11 window using WM_DELETE_WINDOW (if supported). * diff --git a/include/xcb.h b/include/xcb.h index bec06b06..4a09766f 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -116,6 +116,12 @@ void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window); */ void fake_absolute_configure_notify(Con *con); +/** + * Sends the WM_TAKE_FOCUS ClientMessage to the given window + * + */ +void send_take_focus(xcb_window_t window); + /** * Finds out which modifier mask is the one for numlock, as the user may * change this. diff --git a/src/manage.c b/src/manage.c index 4821e28f..ac199468 100644 --- a/src/manage.c +++ b/src/manage.c @@ -156,6 +156,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki window_update_transient_for(cwindow, xcb_get_property_reply(conn, transient_cookie, NULL)); window_update_strut_partial(cwindow, xcb_get_property_reply(conn, strut_cookie, NULL)); + /* check if the window needs WM_TAKE_FOCUS */ + cwindow->needs_take_focus = window_supports_protocol(cwindow->id, A_WM_TAKE_FOCUS); + /* Where to start searching for a container that swallows the new one? */ Con *search_at = croot; diff --git a/src/x.c b/src/x.c index 374fd162..21e9b14e 100644 --- a/src/x.c +++ b/src/x.c @@ -178,7 +178,7 @@ void x_con_kill(Con *con) { * Returns true if the client supports the given protocol atom (like WM_DELETE_WINDOW) * */ -static bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom) { +bool window_supports_protocol(xcb_window_t window, xcb_atom_t atom) { xcb_get_property_cookie_t cookie; xcb_icccm_get_wm_protocols_reply_t protocols; bool result = false; @@ -618,19 +618,10 @@ void x_push_changes(Con *con) { xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, to_focus, XCB_CURRENT_TIME); /* TODO: check if that client acccepts WM_TAKE_FOCUS at all */ - xcb_client_message_event_t ev; - - memset(&ev, 0, sizeof(xcb_client_message_event_t)); - - ev.response_type = XCB_CLIENT_MESSAGE; - ev.window = to_focus; - ev.type = A_WM_PROTOCOLS; - ev.format = 32; - ev.data.data32[0] = A_WM_TAKE_FOCUS; - ev.data.data32[1] = XCB_CURRENT_TIME; - - DLOG("Sending WM_TAKE_FOCUS to the client\n"); - xcb_send_event(conn, false, to_focus, XCB_EVENT_MASK_NO_EVENT, (char*)&ev); + if (focused->window != NULL && + focused->window->needs_take_focus) { + send_take_focus(to_focus); + } ewmh_update_active_window(to_focus); focused_id = to_focus; diff --git a/src/xcb.c b/src/xcb.c index aaad590d..7382cc61 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -206,6 +206,26 @@ void fake_absolute_configure_notify(Con *con) { fake_configure_notify(conn, absolute, con->window->id); } +/* + * Sends the WM_TAKE_FOCUS ClientMessage to the given window + * + */ +void send_take_focus(xcb_window_t window) { + xcb_client_message_event_t ev; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.window = window; + ev.type = A_WM_PROTOCOLS; + ev.format = 32; + ev.data.data32[0] = A_WM_TAKE_FOCUS; + ev.data.data32[1] = XCB_CURRENT_TIME; + + DLOG("Sending WM_TAKE_FOCUS to the client\n"); + xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char*)&ev); +} + /* * Finds out which modifier mask is the one for numlock, as the user may change this. *