all repos — openbox @ db086ef336e01ee23c777f3dc6678568565d44ef

openbox fork - make it a bit more like ryudo

put focus_cycle into focus.c, use it there in the action. improved it as well to handle odd cases like modal windows. added functions to client.c which are needed by the focus cycling routine.
Dana Jansens danakj@orodu.net
commit

db086ef336e01ee23c777f3dc6678568565d44ef

parent

1f775fdd864715abb622070a9b4dd38341d6da79

5 files changed, 103 insertions(+), 70 deletions(-)

jump to
M openbox/action.copenbox/action.c

@@ -716,54 +716,7 @@ }

void action_cycle_windows(union ActionData *data) { - static Client *first = NULL; - static Client *t = NULL; - static GList *order = NULL; - GList *it, *start, *list; - - if (data->cycle.cancel) { - if (first) client_focus(first); - goto done_cycle; - } - if (!first) first = focus_client; - - if (data->cycle.linear) - list = client_list; - else { - if (!order) order = g_list_copy(focus_order[screen_desktop]); - list = order; - } - start = it = g_list_find(list, data->cycle.c); - if (!start) goto done_cycle; - - if (!data->cycle.final) { - t = NULL; - if (!start) /* switched desktops or something? */ - goto done_cycle; - - do { - if (data->cycle.forward) { - it = it->next; - if (it == NULL) it = list; - } else { - it = it->prev; - if (it == NULL) it = g_list_last(list); - } - if (client_focus(it->data)) { - t = it->data; - focus_ignore_in++; - break; - } - } while (it != start); - } else { - if (t) stacking_raise(t); - goto done_cycle; - } - return; - - done_cycle: - first = NULL; - g_list_free(order); - order = NULL; + focus_cycle(data->cycle.forward, data->cycle.linear, data->cycle.final, + data->cycle.cancel); }
M openbox/client.copenbox/client.c

@@ -1916,20 +1916,32 @@ client_calc_layer(self);

client_change_state(self); /* change the hint to relect these changes */ } -gboolean client_focus(Client *self) +Client *client_focus_target(Client *self) { - XEvent ev; Client *child; /* if we have a modal child, then focus it, not us */ child = client_find_modal_child(self); - if (child) - return client_focus(child); + if (child) return child; + return self; +} +gboolean client_focusable(Client *self) +{ /* won't try focus if the client doesn't want it, or if the window isn't visible on the screen */ - if (!(self->frame->visible && - (self->can_focus || self->focus_notify))) + return self->frame->visible && + (self->can_focus || self->focus_notify); +} + +gboolean client_focus(Client *self) +{ + XEvent ev; + + /* choose the correct target */ + self = client_focus_target(self); + + if (!client_focusable(self)) return FALSE; /* do a check to see if the window has already been unmapped or destroyed

@@ -1984,6 +1996,7 @@

void client_unfocus(Client *self) { g_assert(focus_client == self); + g_message("client_unfocus"); focus_fallback(FALSE); }
M openbox/client.hopenbox/client.h

@@ -410,6 +410,14 @@ process.

*/ void client_set_state(Client *self, Atom action, long data1, long data2); +/* Given a Client, find the client that focus would actually be sent to if + you wanted to give focus to the specified Client. Will return the same + Client passed to it or another Client if appropriate. */ +Client *client_focus_target(Client *self); + +/* Returns if a client can be focused or not */ +gboolean client_focusable(Client *self); + /*! Attempt to focus the client window */ gboolean client_focus(Client *self);
M openbox/focus.copenbox/focus.c

@@ -7,6 +7,7 @@ #include "prop.h"

#include "dispatch.h" #include "focus.h" #include "parse.h" +#include "engine.h" #include <X11/Xlib.h> #include <glib.h>

@@ -18,7 +19,8 @@

Window focus_backup = None; gboolean focus_new = TRUE; gboolean focus_follow = TRUE; -int focus_ignore_in = 0; + +static gboolean noreorder = 0; static void parse_assign(char *name, ParseToken *value) {

@@ -79,11 +81,21 @@ XSetInputFocus(ob_display, PointerRoot, RevertToPointerRoot,

event_lasttime); } +static void push_to_top(Client *client) +{ + guint desktop; + + desktop = client->desktop; + if (desktop == DESKTOP_ALL) desktop = screen_desktop; + focus_order[desktop] = g_list_remove(focus_order[desktop], client); + focus_order[desktop] = g_list_prepend(focus_order[desktop], client); + g_message("REORDERING"); +} + void focus_set_client(Client *client) { Window active; Client *old; - guint desktop; /* uninstall the old colormap, and install the new one */ screen_install_colormap(focus_client, FALSE);

@@ -100,15 +112,10 @@ old = focus_client;

focus_client = client; /* move to the top of the list */ - if (focus_ignore_in) { - g_assert(focus_ignore_in > 0); - --focus_ignore_in; - } else if (client != NULL) { - desktop = client->desktop; - if (desktop == DESKTOP_ALL) desktop = screen_desktop; - focus_order[desktop] = g_list_remove(focus_order[desktop], client); - focus_order[desktop] = g_list_prepend(focus_order[desktop], client); - } + if (noreorder) + --noreorder; + else if (client != NULL) + push_to_top(client); /* set the NET_ACTIVE_WINDOW hint */ active = client ? client->window : None;

@@ -171,3 +178,55 @@ if (it == NULL) /* nothing to focus */

focus_set_client(NULL); } } + +void focus_cycle(gboolean forward, gboolean linear, gboolean done, + gboolean cancel) +{ + static Client *first = NULL; + static Client *t = NULL; + static GList *order = NULL; + GList *it, *start, *list; + Client *ft; + + if (cancel) { + if (first) client_focus(first); + goto done_cycle; + } else if (done) { + if (focus_client) { + push_to_top(focus_client); /* move to top of focus_order */ + stacking_raise(focus_client); + } + goto done_cycle; + } + if (!first) first = focus_client; + + if (linear) list = client_list; + else list = focus_order[screen_desktop]; + + start = it = g_list_find(list, focus_client); + if (!start) goto done_cycle; /* switched desktops or something? */ + + do { + if (forward) { + it = it->next; + if (it == NULL) it = list; + } else { + it = it->prev; + if (it == NULL) it = g_list_last(list); + } + ft = client_focus_target(it->data); + if (ft == it->data && focus_client != ft && client_focusable(ft)) { + if (client_focus(ft)) { + noreorder++; /* avoid reordering the focus_order */ + break; + } + } + } while (it != start); + return; + +done_cycle: + t = NULL; + first = NULL; + g_list_free(order); + order = NULL; +}
M openbox/focus.hopenbox/focus.h

@@ -12,10 +12,6 @@

/*! The client which is currently focused */ extern struct Client *focus_client; -/* The number of FocusIn events which should be ignored for tracking the focus - order */ -extern int focus_ignore_in; - /*! The recent focus order on each desktop */ extern GList **focus_order;

@@ -33,5 +29,9 @@ void focus_set_client(struct Client *client);

/*! Call this when you need to focus something! */ void focus_fallback(gboolean switching_desks); + +/*! Cycle focus amongst windows */ +void focus_cycle(gboolean forward, gboolean linear, gboolean done, + gboolean cancel); #endif