[focus] Rewrite focus handling on arrange.

Also add some documentation.

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-05-23 22:40:17 +02:00
parent e710cff383
commit 495b99f1c5
5 changed files with 64 additions and 15 deletions

View File

@ -386,7 +386,7 @@ main(int argc, char **argv)
/* init screens struct */
globalconf.screens_info = screensinfo_new(globalconf.connection);
globalconf.screens = p_new(VirtScreen, globalconf.screens_info->nscreen);
focus_add_client(NULL);
focus_client_push(NULL);
/* parse config */
if(!confpath)

View File

@ -204,7 +204,7 @@ client_unfocus(client_t *c)
luaA_settype(globalconf.L, "client");
luaA_dofunction(globalconf.L, globalconf.hooks.unfocus, 1);
focus_add_client(NULL);
focus_client_push(NULL);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
titlebar_draw(c);
}
@ -254,7 +254,7 @@ client_focus(client_t *c, int screen, bool raise)
/* unban the client before focusing or it will fail */
client_unban(c);
/* save sel in focus history */
focus_add_client(c);
focus_client_push(c);
titlebar_draw(c);
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT,
c->win, XCB_CURRENT_TIME);
@ -421,7 +421,10 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
window_setshape(c->win, c->phys_screen);
}
/* Push client in client list */
client_list_push(&globalconf.clients, c);
/* Append client in history: it'll be last. */
focus_client_append(c);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
ewmh_update_net_client_list(c->phys_screen);
@ -643,7 +646,7 @@ client_unmanage(client_t *c)
/* remove client everywhere */
client_list_detach(&globalconf.clients, c);
focus_delete_client(c);
focus_client_delete(c);
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
untag_client(c, tag);

41
focus.c
View File

@ -25,6 +25,10 @@
extern AwesomeConf globalconf;
/** Get the client's node focus.
* \param c The client.
* \return The client node focus.
*/
static client_node_t *
focus_get_node_by_client(client_t *c)
{
@ -37,8 +41,12 @@ focus_get_node_by_client(client_t *c)
return NULL;
}
void
focus_add_client(client_t *c)
/** Create a client node for focus.
* \param c The client
* \return The client focus node.
*/
static client_node_t *
focus_client_add(client_t *c)
{
client_node_t *node;
@ -51,11 +59,34 @@ focus_add_client(client_t *c)
else /* if we've got a node, detach it */
client_node_list_detach(&globalconf.focus, node);
return node;
}
/** Push the client at the beginning of the client focus history stack.
* \param c The client to push.
*/
void
focus_client_push(client_t *c)
{
client_node_t *node = focus_client_add(c);
client_node_list_push(&globalconf.focus, node);
}
/** Append the client at the end of the client focus history stack.
* \param c The client to append.
*/
void
focus_delete_client(client_t *c)
focus_client_append(client_t *c)
{
client_node_t *node = focus_client_add(c);
client_node_list_append(&globalconf.focus, node);
}
/** Remove a client from focus history.
* \param c The client.
*/
void
focus_client_delete(client_t *c)
{
client_node_t *node = focus_get_node_by_client(c);
@ -87,6 +118,10 @@ focus_get_latest_client_for_tags(tag_t **t, int nindex)
return NULL;
}
/** Get the latest focused client on a screen.
* \param screen The virtual screen number.
* \return A pointer to an existing client.
*/
client_t *
focus_get_current_client(int screen)
{

View File

@ -24,8 +24,9 @@
#include "structs.h"
void focus_add_client(client_t *);
void focus_delete_client(client_t *);
void focus_client_push(client_t *);
void focus_client_append(client_t *);
void focus_client_delete(client_t *);
client_t * focus_get_current_client(int);
DO_SLIST(client_node_t, client_node, p_delete)

View File

@ -44,7 +44,7 @@ arrange(int screen)
{
client_t *c;
layout_t *curlay = layout_get_current(screen);
int phys_screen = screen_virttophys(screen);
int fscreen, phys_screen = screen_virttophys(screen);
xcb_query_pointer_cookie_t qp_c;
xcb_query_pointer_reply_t *qp_r;
@ -67,11 +67,6 @@ arrange(int screen)
client_unban(c);
}
/* if we have a valid client that could be focused but currently no window
* are focused, then set the focus on this window */
if((c = focus_get_current_client(screen)) && !globalconf.focus->client)
client_focus(c, screen, true);
qp_c = xcb_query_pointer_unchecked(globalconf.connection,
xcb_aux_get_screen(globalconf.connection,
phys_screen)->root);
@ -84,6 +79,21 @@ arrange(int screen)
globalconf.pointer_x = qp_r->root_x;
globalconf.pointer_y = qp_r->root_y;
/* no window have focus, let's try to see if mouse is on
* the screen we just rearranged */
if(!globalconf.focus->client)
{
fscreen = screen_get_bycoord(globalconf.screens_info,
screen,
qp_r->root_x, qp_r->root_y);
/* if the mouse in on the same screen we just rearranged, and no
* client are currently focused, pick the first one in history */
if(fscreen == screen
&& (c = focus_get_current_client(screen)))
client_focus(c, screen, true);
}
p_delete(&qp_r);
}