Lazyle set the input focus (FS#804)

Instead of immediately setting the X11 input focus when client.focus is assigned
something, we now just remember that we'll have to do something later. The focus
is then set in the next prepare call by libev (= after the current main loop run
is done).

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2010-10-10 14:50:35 +02:00
parent f931af7ce1
commit 3dbf89c990
4 changed files with 30 additions and 20 deletions

View File

@ -29,6 +29,7 @@ awesome_refresh(void)
{ {
banning_refresh(); banning_refresh();
stack_refresh(); stack_refresh();
client_focus_refresh();
return xcb_flush(globalconf.connection); return xcb_flush(globalconf.connection);
} }

View File

@ -85,6 +85,8 @@ typedef struct
{ {
/** Focused client */ /** Focused client */
client_t *client; client_t *client;
/** Is there a focus change pending? */
bool need_update;
} focus; } focus;
/** Drawins */ /** Drawins */
drawin_array_t drawins; drawin_array_t drawins;

View File

@ -188,6 +188,7 @@ static void
client_unfocus_update(client_t *c) client_unfocus_update(client_t *c)
{ {
globalconf.focus.client = NULL; globalconf.focus.client = NULL;
globalconf.focus.need_update = true;
luaA_object_push(globalconf.L, c); luaA_object_push(globalconf.L, c);
luaA_object_emit_signal(globalconf.L, -1, "unfocus", 0); luaA_object_emit_signal(globalconf.L, -1, "unfocus", 0);
@ -200,15 +201,6 @@ client_unfocus_update(client_t *c)
static void static void
client_unfocus(client_t *c) client_unfocus(client_t *c)
{ {
xcb_window_t root_win = globalconf.screen->root;
/* Set focus on root window, so no events leak to the current window.
* This kind of inlines client_set_focus(), but a root window will never have
* the WM_TAKE_FOCUS protocol.
*/
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT,
root_win, globalconf.timestamp);
client_unfocus_update(c); client_unfocus_update(c);
} }
@ -329,19 +321,33 @@ client_focus(client_t *c)
if(!client_maybevisible(c, c->screen)) if(!client_maybevisible(c, c->screen))
return; return;
/* X11 doesn't let you focus a window that isn't viewable */ client_focus_update(c);
client_unban(c); globalconf.focus.need_update = true;
}
/* Sets focus on window - using xcb_set_input_focus or WM_TAKE_FOCUS */ void
if(!c->nofocus) client_focus_refresh(void)
{
client_t *c = globalconf.focus.client;
if(!globalconf.focus.need_update)
return;
globalconf.focus.need_update = false;
if(c)
{
/* Sets focus on window - using xcb_set_input_focus or WM_TAKE_FOCUS */
if(!c->nofocus)
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT,
c->window, globalconf.timestamp);
if(client_hasproto(c, WM_TAKE_FOCUS))
xwindow_takefocus(c->window);
}
else
/* Nothing has the focus, set the focus to the root window */
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT, xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT,
c->window, globalconf.timestamp); globalconf.screen->root, globalconf.timestamp);
if(client_hasproto(c, WM_TAKE_FOCUS))
xwindow_takefocus(c->window);
if (!c->nofocus)
client_focus_update(c);
} }
static void static void

View File

@ -145,6 +145,7 @@ void client_set_icon(lua_State *, int, int);
void client_set_skip_taskbar(lua_State *, int, bool); void client_set_skip_taskbar(lua_State *, int, bool);
void client_focus(client_t *); void client_focus(client_t *);
void client_focus_update(client_t *); void client_focus_update(client_t *);
void client_focus_refresh(void);
bool client_hasproto(client_t *, xcb_atom_t); bool client_hasproto(client_t *, xcb_atom_t);
void client_ignore_enterleave_events(void); void client_ignore_enterleave_events(void);
void client_restore_enterleave_events(void); void client_restore_enterleave_events(void);