From 13bcf0b6150c7948b1889d110340468a0ba4e3c1 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 27 Jun 2010 09:35:56 -0400 Subject: [PATCH] Watch stacking changes on managed windows also, as this can change the "above" relationship for unmanaged windows --- openbox/event.c | 23 +++---- openbox/stacking.c | 149 +++++++++++++++++++++++++++++---------------- openbox/stacking.h | 2 +- 3 files changed, 106 insertions(+), 68 deletions(-) diff --git a/openbox/event.c b/openbox/event.c index bf404d37..2a233708 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -1809,28 +1809,26 @@ static void event_handle_window(ObWindow *wi, XEvent *e) RECT_SET(wi->area, x, y, w, h); } - /* set the top window's area/border */ if (e->xconfigure.window == window_top(wi)) { + /* set the top window's area/border */ XConfigureEvent const *xe = &e->xconfigure; RECT_SET(wi->toparea, xe->x, xe->y, xe->width, xe->height); wi->topborder = xe->border_width; + + /* fix the stacking order */ + if (e->xconfigure.above != wi->above) { + stacking_above_notify(wi, e->xconfigure.above); + wi->above = e->xconfigure.above; + } } break; case CreateNotify: if (e->xcreatewindow.parent == obt_root(ob_screen)) - /* we actually only care about tracking above for unmanaged - windows, and they are only created by create or reparent - events, at which time they become the top-most, so we don't - bother tracking above for all windows in this function */ wi->above = window_top(stacking_topmost_window()); break; case ReparentNotify: if (e->xreparent.parent == obt_root(ob_screen)) - /* we actually only care about tracking above for unmanaged - windows, and they are only created by create or reparent - events, at which time they become the top-most, so we don't - bother tracking above for all windows in this function */ wi->above = window_top(stacking_topmost_window()); break; case MapNotify: @@ -1914,13 +1912,6 @@ static void event_handle_unmanaged(ObUnmanaged *um, XEvent *e) e->xconfigurerequest.value_mask, &xwc); obt_display_ignore_errors(FALSE); break; - case ConfigureNotify: - if (e->xconfigure.above != UNMANAGED_AS_WINDOW(um)->above) { - ob_debug("ConfigureNotify changed stacking order for " - "unmanaged 0x%lx", window_top(um)); - stacking_unmanaged_above_notify(um, e->xconfigure.above); - UNMANAGED_AS_WINDOW(um)->above = e->xconfigure.above; - } } } diff --git a/openbox/stacking.c b/openbox/stacking.c index 6e9e8e81..17583449 100644 --- a/openbox/stacking.c +++ b/openbox/stacking.c @@ -807,64 +807,111 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling, return ret; } -void stacking_unmanaged_above_notify(ObUnmanaged *win, Window above) +void stacking_above_notify(ObWindow *win, Window above) { GList *aboveit, *winit, *uit, *mit; ObUNode *un, *an; + gboolean last; + + if (!WINDOW_IS_UNMANAGED(win)) { + GList *belowme; + /* a managed window moved, so any unmanaged that were above it before + no longer are. + on the other hand, the unmanaged that were above @above before + are now above this window */ + winit = g_hash_table_lookup(stacking_map, &window_top(win)); + belowme = winit->next; + + /* find the unmanaged windows that were above me */ + for (uit = stacking_ulist; uit; uit = g_list_next(uit)) + if (((ObUNode*)uit->data)->belowme == winit) break; + /* change them to be above what i used to be above */ + while (uit && ((ObUNode*)uit->data)->belowme == winit) { + ((ObUNode*)uit->data)->belowme = belowme; + uit = g_list_next(uit); + } - g_assert(WINDOW_IS_UNMANAGED(win)); - - winit = g_hash_table_lookup(stacking_umap, &window_top(win)); - - if (!above) { - /* at the very bottom of the stacking order */ - stacking_ulist = g_list_remove_link(stacking_ulist, winit); - stacking_ulist = list_insert_link_before(stacking_ulist, NULL, winit); - un = winit->data; - un->belowme = NULL; - } - else if ((aboveit = g_hash_table_lookup(stacking_map, &above))) { - /* directly above a managed window, so put it at the bottom of - any siblings which are also above it */ - - stacking_ulist = g_list_remove_link(stacking_ulist, winit); - un = winit->data; - un->belowme = aboveit; - - /* go through the managed windows in the stacking list from top to - bottom. - follow along in the list of unmanaged windows, until we come to the - managed window @winit is now above. then keep moving through the - unmanaged windows until we find something above a different - managed window, and insert @winit into the unmanaged list before it. - */ - mit = stacking_list; - uit = stacking_ulist; - for (; mit; mit = g_list_next(mit)) { - /* skip thru the unmanged windows above 'mit' */ - while (uit && ((ObUNode*)uit->data)->belowme == mit) - uit = g_list_next(uit); - if (mit == aboveit) { - /* @win is above 'mit', so stick it in the unmanaged list - before 'uit' (the first window above something lower in the - managed stacking list */ - stacking_ulist = list_insert_link_before(stacking_ulist, - uit, winit); - break; /* done */ + /* find who i am now above and tell them so */ + if (!above) { + /* unmanaged that used to be above nothing */ + uit = g_list_last(stacking_ulist); + while (uit && ((ObUNode*)uit->data)->belowme == NULL) { + ((ObUNode*)uit->data)->belowme = winit; + uit = g_list_previous(uit); + } + } + else if ((aboveit = g_hash_table_lookup(stacking_map, &above))) { + /* find unmanaged windows above managed 'aboveit' */ + for (uit = stacking_ulist; uit; uit = g_list_next(uit)) + if (((ObUNode*)uit->data)->belowme == aboveit) break; + while (uit && ((ObUNode*)uit->data)->belowme == aboveit) + ((ObUNode*)uit->data)->belowme = winit; + } + else if ((uit = g_hash_table_lookup(stacking_umap, &above))) { + /* change unmanaged windows above unmanaged 'uit' */ + aboveit = ((ObUNode*)uit->data)->belowme; + uit = g_list_previous(uit); + while (uit && ((ObUNode*)uit->data)->belowme == aboveit) { + ((ObUNode*)uit->data)->belowme = winit; + uit = g_list_previous(uit); } } } - else if ((aboveit = g_hash_table_lookup(stacking_umap, &above))) { - /* directly above another unmanaged window, put it in that position - in the stacking_ulist */ - - stacking_ulist = g_list_remove_link(stacking_ulist, winit); - stacking_ulist = list_insert_link_before(stacking_ulist, - aboveit, winit); - /* we share the same neighbour in stacking_list */ - un = winit->data; - an = aboveit->data; - un->belowme = an->belowme; + else { + winit = g_hash_table_lookup(stacking_umap, &window_top(win)); + + if (!above) { + /* at the very bottom of the stacking order */ + stacking_ulist = g_list_remove_link(stacking_ulist, winit); + stacking_ulist = list_insert_link_before(stacking_ulist, + NULL, winit); + un = winit->data; + un->belowme = NULL; + } + else if ((aboveit = g_hash_table_lookup(stacking_map, &above))) { + /* directly above a managed window, so put it at the bottom of + any siblings which are also above it */ + + stacking_ulist = g_list_remove_link(stacking_ulist, winit); + un = winit->data; + un->belowme = aboveit; + + /* go through the managed windows in the stacking list from top to + bottom. + follow along in the list of unmanaged windows, until we come to + the managed window @winit is now above. then keep moving + through the unmanaged windows until we find something above a + different managed window, and insert @winit into the unmanaged + list before it. + */ + mit = stacking_list; + uit = stacking_ulist; + for (; mit; mit = g_list_next(mit)) { + /* skip thru the unmanged windows above 'mit' */ + while (uit && ((ObUNode*)uit->data)->belowme == mit) + uit = g_list_next(uit); + if (mit == aboveit) { + /* @win is above 'mit', so stick it in the unmanaged list + before 'uit' (the first window above something lower in + the managed stacking list */ + stacking_ulist = list_insert_link_before(stacking_ulist, + uit, winit); + break; /* done */ + } + } + } + else if ((aboveit = g_hash_table_lookup(stacking_umap, &above))) { + /* directly above another unmanaged window, put it in that position + in the stacking_ulist */ + + stacking_ulist = g_list_remove_link(stacking_ulist, winit); + stacking_ulist = list_insert_link_before(stacking_ulist, + aboveit, winit); + /* we share the same neighbour in stacking_list */ + un = winit->data; + an = aboveit->data; + un->belowme = an->belowme; + } } } diff --git a/openbox/stacking.h b/openbox/stacking.h index 6058786d..1c0ace22 100644 --- a/openbox/stacking.h +++ b/openbox/stacking.h @@ -90,7 +90,7 @@ gboolean stacking_restack_request(struct _ObClient *client, struct _ObClient *sibling, gint detail); -void stacking_unmanaged_above_notify(struct _ObUnmanaged *win, Window above); +void stacking_above_notify(struct _ObWindow *win, Window above); ObStackingIter* stacking_iter_head(void); ObStackingIter* stacking_iter_tail(void); -- 2.34.1