+static void do_raise(GList *wins)
+{
+ GList *it;
+ GList *layer[OB_NUM_STACKING_LAYERS] = {NULL};
+ gint i;
+
+ for (it = wins; it; it = g_list_next(it)) {
+ ObStackingLayer l;
+
+ l = window_layer(it->data);
+ layer[l] = g_list_append(layer[l], it->data);
+ }
+
+ it = stacking_list;
+ for (i = OB_NUM_STACKING_LAYERS - 1; i >= 0; --i) {
+ if (layer[i]) {
+ for (; it; it = g_list_next(it)) {
+ /* look for the top of the layer */
+ if (window_layer(it->data) <= (ObStackingLayer) i)
+ break;
+ }
+ do_restack(layer[i], it);
+ g_list_free(layer[i]);
+ }
+ }
+}
+
+static void do_lower(GList *wins)
+{
+ GList *it;
+ GList *layer[OB_NUM_STACKING_LAYERS] = {NULL};
+ gint i;
+
+ for (it = wins; it; it = g_list_next(it)) {
+ ObStackingLayer l;
+
+ l = window_layer(it->data);
+ layer[l] = g_list_append(layer[l], it->data);
+ }
+
+ it = stacking_list;
+ for (i = OB_NUM_STACKING_LAYERS - 1; i >= 0; --i) {
+ if (layer[i]) {
+ for (; it; it = g_list_next(it)) {
+ /* look for the top of the next layer down */
+ if (window_layer(it->data) < (ObStackingLayer) i)
+ break;
+ }
+ do_restack(layer[i], it);
+ g_list_free(layer[i]);
+ }
+ }
+}
+
+static GList *pick_windows_recur(ObClient *top, ObClient *selected,
+ gboolean raise)
+{
+ GList *ret = NULL;
+ GList *it, *next, *prev;
+ GSList *sit;
+ gint i, n;
+ GList *modals = NULL;
+ GList *trans = NULL;
+ GList *modal_sel = NULL; /* the selected guys if modal */
+ GList *trans_sel = NULL; /* the selected guys if not */
+
+ /* remove first so we can't run into ourself */
+ if ((it = g_list_find(stacking_list, top)))
+ stacking_list = g_list_delete_link(stacking_list, it);
+ else
+ return NULL;
+
+ i = 0;
+ n = g_slist_length(top->transients);
+ for (it = stacking_list; i < n && it; it = next) {
+ prev = g_list_previous(it);
+ next = g_list_next(it);
+
+ if ((sit = g_slist_find(top->transients, it->data))) {
+ ObClient *c = sit->data;
+ gboolean sel_child;
+
+ ++i;
+
+ if (c == selected)
+ sel_child = TRUE;
+ else
+ sel_child = client_search_transient(c, selected) != NULL;
+
+ if (!c->modal) {
+ if (!sel_child) {
+ trans = g_list_concat
+ (trans, pick_windows_recur(c, selected, raise));
+ } else {
+ trans_sel = g_list_concat
+ (trans_sel, pick_windows_recur(c, selected, raise));
+ }
+ } else {
+ if (!sel_child) {
+ modals = g_list_concat
+ (modals, pick_windows_recur(c, selected, raise));
+ } else {
+ modal_sel = g_list_concat
+ (modal_sel, pick_windows_recur(c, selected, raise));
+ }
+ }
+ /* if we dont have a prev then start back at the beginning,
+ otherwise skip back to the prev's next */
+ next = prev ? g_list_next(prev) : stacking_list;
+ }
+ }
+
+ ret = g_list_concat((raise ? modal_sel : modals),
+ (raise ? modals : modal_sel));
+
+ ret = g_list_concat(ret, (raise ? trans_sel : trans));
+ ret = g_list_concat(ret, (raise ? trans : trans_sel));
+
+
+ /* add itself */
+ ret = g_list_append(ret, top);
+
+ return ret;
+}
+
+static GList *pick_group_windows_recur(ObClient *top, ObClient *selected,
+ gboolean raise, gboolean normal)
+{
+ GList *ret = NULL;
+ GList *it, *next, *prev;
+ GSList *sit;
+ gint i, n;
+
+ /* add group members in their stacking order */
+ if (top->group) {
+ i = 0;
+ n = g_slist_length(top->group->members) - 1;
+ for (it = stacking_list; i < n && it; it = next) {
+ prev = g_list_previous(it);
+ next = g_list_next(it);
+
+ if ((sit = g_slist_find(top->group->members, it->data))) {
+ ObClient *c;
+ ObClientType t;
+
+ ++i;
+ c = it->data;
+ t = c->type;
+
+ if ((c->desktop == selected->desktop ||
+ c->desktop == DESKTOP_ALL) &&
+ (t == OB_CLIENT_TYPE_TOOLBAR ||
+ t == OB_CLIENT_TYPE_MENU ||
+ t == OB_CLIENT_TYPE_UTILITY ||
+ (normal && t == OB_CLIENT_TYPE_NORMAL)))
+ {
+ ret = g_list_concat(ret,
+ pick_windows_recur(sit->data,
+ selected, raise));
+ /* if we dont have a prev then start back at the beginning,
+ otherwise skip back to the prev's next */
+ next = prev ? g_list_next(prev) : stacking_list;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+static GList *pick_windows(ObClient *selected, gboolean raise, gboolean group)