diff --git a/awesome.c b/awesome.c index 8c27e3e0..f02d7b5f 100644 --- a/awesome.c +++ b/awesome.c @@ -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) diff --git a/client.c b/client.c index 42059c9e..0856c73e 100644 --- a/client.c +++ b/client.c @@ -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); diff --git a/focus.c b/focus.c index 42ff7ded..3ee35a95 100644 --- a/focus.c +++ b/focus.c @@ -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) { diff --git a/focus.h b/focus.h index 2da6e6dc..66cf6338 100644 --- a/focus.h +++ b/focus.h @@ -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) diff --git a/layout.c b/layout.c index a5528641..0b0b4fcd 100644 --- a/layout.c +++ b/layout.c @@ -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); }