Bugfix: Respect WM_HINTS.input for WM_TAKE_FOCUS clients
This fixes problems with Qt apps (like Quassel) and apparently Eclipse since the last commit.
This commit is contained in:
parent
e2b97a6fda
commit
2d14ced024
|
@ -2,7 +2,7 @@
|
|||
* vim:ts=4:sw=4:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
* © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
*
|
||||
* include/data.h: This file defines all data structures used by i3
|
||||
*
|
||||
|
@ -293,6 +293,10 @@ struct Window {
|
|||
/** Whether the application needs to receive WM_TAKE_FOCUS */
|
||||
bool needs_take_focus;
|
||||
|
||||
/** Whether this window accepts focus. We store this inverted so that the
|
||||
* default will be 'accepts focus'. */
|
||||
bool doesnt_accept_focus;
|
||||
|
||||
/** Whether the window says it is a dock window */
|
||||
enum { W_NODOCK = 0, W_DOCK_TOP = 1, W_DOCK_BOTTOM = 2 } dock;
|
||||
|
||||
|
|
|
@ -57,4 +57,10 @@ void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop);
|
|||
*/
|
||||
void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt);
|
||||
|
||||
/**
|
||||
* Updates the WM_HINTS (we only care about the input focus handling part).
|
||||
*
|
||||
*/
|
||||
void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -855,18 +855,16 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
|
|||
|
||||
xcb_icccm_wm_hints_t hints;
|
||||
|
||||
if (reply != NULL) {
|
||||
if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
|
||||
if (reply == NULL)
|
||||
if (!(reply = xcb_get_property_reply(conn, xcb_icccm_get_wm_hints(conn, window), NULL)))
|
||||
return false;
|
||||
} else {
|
||||
if (!xcb_icccm_get_wm_hints_reply(conn, xcb_icccm_get_wm_hints_unchecked(conn, con->window->id), &hints, NULL))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
|
||||
return false;
|
||||
|
||||
if (!con->urgent && focused == con) {
|
||||
DLOG("Ignoring urgency flag for current client\n");
|
||||
FREE(reply);
|
||||
return true;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Update the flag on the client directly */
|
||||
|
@ -882,17 +880,10 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
|
|||
|
||||
tree_render();
|
||||
|
||||
#if 0
|
||||
/* If the workspace this client is on is not visible, we need to redraw
|
||||
* the workspace bar */
|
||||
if (!workspace_is_visible(client->workspace)) {
|
||||
Output *output = client->workspace->output;
|
||||
render_workspace(conn, output, output->current_workspace);
|
||||
xcb_flush(conn);
|
||||
}
|
||||
#endif
|
||||
|
||||
FREE(reply);
|
||||
end:
|
||||
if (con->window)
|
||||
window_update_hints(con->window, reply);
|
||||
else free(reply);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
|||
xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
|
||||
utf8_title_cookie, title_cookie,
|
||||
class_cookie, leader_cookie, transient_cookie,
|
||||
role_cookie, startup_id_cookie;
|
||||
role_cookie, startup_id_cookie, wm_hints_cookie;
|
||||
|
||||
|
||||
geomc = xcb_get_geometry(conn, d);
|
||||
|
@ -142,6 +142,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
|
|||
class_cookie = GET_PROPERTY(XCB_ATOM_WM_CLASS, 128);
|
||||
role_cookie = GET_PROPERTY(A_WM_WINDOW_ROLE, 128);
|
||||
startup_id_cookie = GET_PROPERTY(A__NET_STARTUP_ID, 512);
|
||||
wm_hints_cookie = xcb_icccm_get_wm_hints(conn, window);
|
||||
/* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
|
||||
|
||||
DLOG("Managing window 0x%08x\n", window);
|
||||
|
@ -169,6 +170,7 @@ 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));
|
||||
window_update_role(cwindow, xcb_get_property_reply(conn, role_cookie, NULL), true);
|
||||
window_update_hints(cwindow, xcb_get_property_reply(conn, wm_hints_cookie, NULL));
|
||||
|
||||
xcb_get_property_reply_t *startup_id_reply;
|
||||
startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL);
|
||||
|
|
27
src/window.c
27
src/window.c
|
@ -2,7 +2,7 @@
|
|||
* vim:ts=4:sw=4:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
* © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
*
|
||||
* window.c: Updates window attributes (X11 hints/properties).
|
||||
*
|
||||
|
@ -251,3 +251,28 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo
|
|||
|
||||
free(prop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the WM_HINTS (we only care about the input focus handling part).
|
||||
*
|
||||
*/
|
||||
void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop) {
|
||||
if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
|
||||
DLOG("WM_HINTS not set.\n");
|
||||
FREE(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
xcb_icccm_wm_hints_t hints;
|
||||
|
||||
if (!xcb_icccm_get_wm_hints_from_reply(&hints, prop)) {
|
||||
DLOG("Could not get WM_HINTS\n");
|
||||
free(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
win->doesnt_accept_focus = !hints.input;
|
||||
LOG("WM_HINTS.input changed to \"%d\"\n", hints.input);
|
||||
|
||||
free(prop);
|
||||
}
|
||||
|
|
11
src/x.c
11
src/x.c
|
@ -2,7 +2,7 @@
|
|||
* vim:ts=4:sw=4:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
* © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
*
|
||||
* x.c: Interface to X11, transfers our in-memory state to X11 (see also
|
||||
* render.c). Basically a big state machine.
|
||||
|
@ -849,12 +849,17 @@ void x_push_changes(Con *con) {
|
|||
/* Invalidate focused_id to correctly focus new windows with the same ID */
|
||||
focused_id = XCB_NONE;
|
||||
} else {
|
||||
bool set_focus = true;
|
||||
if (focused->window != NULL &&
|
||||
focused->window->needs_take_focus) {
|
||||
DLOG("Updating focus by sending WM_TAKE_FOCUS to window 0x%08x only (focused: %p / %s)\n",
|
||||
DLOG("Updating focus by sending WM_TAKE_FOCUS to window 0x%08x (focused: %p / %s)\n",
|
||||
to_focus, focused, focused->name);
|
||||
send_take_focus(to_focus);
|
||||
} else {
|
||||
set_focus = !focused->window->doesnt_accept_focus;
|
||||
DLOG("set_focus = %d\n", set_focus);
|
||||
}
|
||||
|
||||
if (set_focus) {
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue