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:
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;
- }
}
}
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;
+ }
}
}