X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fstacking.c;h=34064db7d3a9b5df8df5e78fd6d2572726fd88a6;hb=62a39c4c70b0ed8e153b0cccac853cc6fded99ba;hp=2a57e1a3bab546eaabe4f6eb87bc45e8ecab01ea;hpb=da226cdeff0072cf24afc8ff1e84d6cf7a3052ba;p=chaz%2Fopenbox diff --git a/openbox/stacking.c b/openbox/stacking.c index 2a57e1a3..34064db7 100644 --- a/openbox/stacking.c +++ b/openbox/stacking.c @@ -1,6 +1,7 @@ /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- stacking.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson Copyright (c) 2003 Ben Jansens This program is free software; you can redistribute it and/or modify @@ -41,7 +42,7 @@ void stacking_set_list() /* create an array of the window ids (from bottom to top, reverse order!) */ if (stacking_list) { - windows = g_new(Window, g_list_length(stacking_list)); + windows = g_new(Window, g_list_length(stacking_list)); for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) { if (WINDOW_IS_CLIENT(it->data)) windows[i++] = WINDOW_AS_CLIENT(it->data)->window; @@ -49,18 +50,19 @@ void stacking_set_list() } PROP_SETA32(RootWindow(ob_display, ob_screen), - net_client_list_stacking, window, (guint32*)windows, i); + net_client_list_stacking, window, (gulong*)windows, i); g_free(windows); } static void do_restack(GList *wins, GList *before) { - GList *it, *next; + GList *it; Window *win; - int i; + gint i; #ifdef DEBUG + GList *next; /* pls only restack stuff in the same layer at a time */ for (it = wins; it; it = next) { next = g_list_next(it); @@ -106,7 +108,7 @@ static void do_raise(GList *wins) { GList *it; GList *layer[OB_NUM_STACKING_LAYERS] = {NULL}; - int i; + gint i; for (it = wins; it; it = g_list_next(it)) { ObStackingLayer l; @@ -133,7 +135,7 @@ static void do_lower(GList *wins) { GList *it; GList *layer[OB_NUM_STACKING_LAYERS] = {NULL}; - int i; + gint i; for (it = wins; it; it = g_list_next(it)) { ObStackingLayer l; @@ -156,12 +158,13 @@ static void do_lower(GList *wins) } } -static GList *pick_windows(ObClient *top, ObClient *selected, gboolean raise) +static GList *pick_windows_recur(ObClient *top, ObClient *selected, + gboolean raise) { GList *ret = NULL; GList *it, *next, *prev; GSList *sit; - int i, n; + gint i, n; GList *modals = NULL; GList *trans = NULL; GList *modal_sel = NULL; /* the selected guys if modal */ @@ -192,21 +195,19 @@ static GList *pick_windows(ObClient *top, ObClient *selected, gboolean raise) if (!c->modal) { if (!sel_child) { - trans = g_list_concat(trans, - pick_windows(c, selected, raise)); + trans = g_list_concat + (trans, pick_windows_recur(c, selected, raise)); } else { - trans_sel = g_list_concat(trans_sel, - pick_windows(c, selected, - raise)); + trans_sel = g_list_concat + (trans_sel, pick_windows_recur(c, selected, raise)); } } else { if (!sel_child) { - modals = g_list_concat(modals, - pick_windows(c, selected, raise)); + modals = g_list_concat + (modals, pick_windows_recur(c, selected, raise)); } else { - modal_sel = g_list_concat(modal_sel, - pick_windows(c, selected, - raise)); + 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, @@ -228,13 +229,13 @@ static GList *pick_windows(ObClient *top, ObClient *selected, gboolean raise) return ret; } -static GList *pick_group_windows(ObClient *top, ObClient *selected, - gboolean raise) +static GList *pick_group_windows_recur(ObClient *top, ObClient *selected, + gboolean raise, gboolean normal) { GList *ret = NULL; GList *it, *next, *prev; GSList *sit; - int i, n; + gint i, n; /* add group members in their stacking order */ if (top->group) { @@ -245,19 +246,23 @@ static GList *pick_group_windows(ObClient *top, ObClient *selected, next = g_list_next(it); if ((sit = g_slist_find(top->group->members, it->data))) { + ObClient *c; ObClientType t; ++i; - - t = ((ObClient*)it->data)->type; - - if (t == OB_CLIENT_TYPE_TOOLBAR || - t == OB_CLIENT_TYPE_MENU || - t == OB_CLIENT_TYPE_UTILITY) + 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(sit->data, - selected, raise)); + 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; @@ -268,17 +273,43 @@ static GList *pick_group_windows(ObClient *top, ObClient *selected, return ret; } -void stacking_raise(ObWindow *window) +static GList *pick_windows(ObClient *selected, gboolean raise, gboolean group) +{ + GList *it; + GSList *top, *top_it; + GSList *top_reorder = NULL; + GList *ret = NULL; + + top = client_search_top_transients(selected); + + /* go thru stacking list backwords so we can use g_slist_prepend */ + for (it = g_list_last(stacking_list); it && top; + it = g_list_previous(it)) + if ((top_it = g_slist_find(top, it->data))) { + top_reorder = g_slist_prepend(top_reorder, top_it->data); + top = g_slist_delete_link(top, top_it); + } + g_assert(top == NULL); + + for (top_it = top_reorder; top_it; top_it = g_slist_next(top_it)) + ret = g_list_concat(ret, + pick_windows_recur(top_it->data, selected, raise)); + + for (top_it = top_reorder; top_it; top_it = g_slist_next(top_it)) + ret = g_list_concat(ret, + pick_group_windows_recur(top_it->data, + selected, raise, group)); + return ret; +} + +void stacking_raise(ObWindow *window, gboolean group) { GList *wins; if (WINDOW_IS_CLIENT(window)) { - ObClient *c; ObClient *selected; selected = WINDOW_AS_CLIENT(window); - c = client_search_top_transient(selected); - wins = pick_windows(c, selected, TRUE); - wins = g_list_concat(wins, pick_group_windows(c, selected, TRUE)); + wins = pick_windows(selected, TRUE, group); } else { wins = g_list_append(NULL, window); stacking_list = g_list_remove(stacking_list, window); @@ -287,17 +318,14 @@ void stacking_raise(ObWindow *window) g_list_free(wins); } -void stacking_lower(ObWindow *window) +void stacking_lower(ObWindow *window, gboolean group) { GList *wins; if (WINDOW_IS_CLIENT(window)) { - ObClient *c; ObClient *selected; selected = WINDOW_AS_CLIENT(window); - c = client_search_top_transient(selected); - wins = pick_windows(c, selected, FALSE); - wins = g_list_concat(pick_group_windows(c, selected, FALSE), wins); + wins = pick_windows(selected, FALSE, group); } else { wins = g_list_append(NULL, window); stacking_list = g_list_remove(stacking_list, window); @@ -322,24 +350,18 @@ void stacking_below(ObWindow *window, ObWindow *below) void stacking_add(ObWindow *win) { - ObStackingLayer l; - GList *wins; - g_assert(screen_support_win != None); /* make sure I dont break this in the - future */ - - l = window_layer(win); - wins = g_list_append(NULL, win); /* list of 1 element */ + future */ stacking_list = g_list_append(stacking_list, win); - stacking_raise(win); + stacking_raise(win, FALSE); } void stacking_add_nonintrusive(ObWindow *win) { ObClient *client; ObClient *parent = NULL; - GList *it_before = NULL; + GList *it_below = NULL; if (!WINDOW_IS_CLIENT(win)) { stacking_add(win); /* no special rules for others */ @@ -357,10 +379,11 @@ void stacking_add_nonintrusive(ObWindow *win) GList *it; if (client->group) - for (it = stacking_list; !parent && it; it = it->next) { + for (it = stacking_list; !parent && it; it = g_list_next(it)) { if ((sit = g_slist_find(client->group->members, it->data))) for (sit = client->group->members; !parent && sit; - sit = sit->next) { + sit = g_slist_next(sit)) + { ObClient *c = sit->data; /* checking transient_for prevents infinate loops! */ if (sit->data == it->data && !c->transient_for) @@ -370,20 +393,38 @@ void stacking_add_nonintrusive(ObWindow *win) } } - if (!(it_before = g_list_find(stacking_list, parent))) { + if (!(it_below = g_list_find(stacking_list, parent))) { /* no parent to put above, try find the focused client to go under */ if (focus_client && focus_client->layer == client->layer) { - if ((it_before = g_list_find(stacking_list, focus_client))) - it_before = it_before->next; + if ((it_below = g_list_find(stacking_list, focus_client))) + it_below = it_below->next; } } - if (!it_before) { + if (!it_below) { /* out of ideas, just add it normally... */ stacking_add(win); } else { + /* make sure it's not in the wrong layer though ! */ + for (; it_below; it_below = g_list_next(it_below)) + { + /* stop when the window is not in a higher layer than the window + it is going above (it_below) */ + if (client->layer >= window_layer(it_below->data)) + break; + } + for (; it_below != stacking_list; + it_below = g_list_previous(it_below)) + { + /* stop when the window is not in a lower layer than the + window it is going under (it_above) */ + GList *it_above = g_list_previous(it_below); + if (client->layer <= window_layer(it_above->data)) + break; + } + GList *wins = g_list_append(NULL, win); - do_restack(wins, it_before); + do_restack(wins, it_below); g_list_free(wins); } }