void meta_stack_tracker_record_lower (MetaStackTracker *tracker, Window window, gulong serial) { meta_stack_tracker_record_raise_above (tracker, window, None, serial); }
/* * This function is used to avoid raising a window above popup * menus and other such things. * * The key to the operation of this function is that we are expecting * at most one window to be added at a time. If xwindow is newly added, * then its own stack position will be too high (the frame window * is created at the top of the stack), but if we ignore xwindow, * then the *next* managed window in the stack will be a window that * we've already stacked. * * We could generalize this and remove the assumption that windows * are added one at a time by keeping an explicit ->stacked flag in * MetaWindow. * * An alternate approach would be to reverse the stacking algorithm to * work by placing each window above the others, and start by lowering * a window to the bottom (instead of the current way, which works by * placing each window below another and starting with a raise) */ static void raise_window_relative_to_managed_windows (MetaScreen *screen, Window xwindow) { Window *children; int n_children; int i; meta_stack_tracker_get_stack (screen->stack_tracker, &children, &n_children); /* Children are in order from bottom to top. We want to * find the topmost managed child, then configure * our window to be above it. */ i = n_children - 1; while (i >= 0) { if (children[i] == xwindow) { /* Do nothing. This means we're already the topmost managed * window, but it DOES NOT mean we are already just above * the topmost managed window. This is important because if * an override redirect window is up, and we map a new * managed window, the new window is probably above the old * popup by default, and we want to push it below that * popup. So keep looking for a sibling managed window * to be moved below. */ } else { MetaWindow *other = meta_display_lookup_x_window (screen->display, children[i]); if (other != NULL && !other->override_redirect && !other->unmanaging) { XWindowChanges changes; /* children[i] is the topmost managed child */ meta_topic (META_DEBUG_STACK, "Moving 0x%lx above topmost managed child window 0x%lx\n", xwindow, children[i]); changes.sibling = children[i]; changes.stack_mode = Above; meta_error_trap_push (screen->display); meta_stack_tracker_record_raise_above (screen->stack_tracker, xwindow, children[i], XNextRequest (screen->display->xdisplay)); XConfigureWindow (screen->display->xdisplay, xwindow, CWSibling | CWStackMode, &changes); meta_error_trap_pop (screen->display); break; } } --i; } if (i < 0) { /* No sibling to use, just lower ourselves to the bottom * to be sure we're below any override redirect windows. */ meta_error_trap_push (screen->display); meta_stack_tracker_record_lower (screen->stack_tracker, xwindow, XNextRequest (screen->display->xdisplay)); XLowerWindow (screen->display->xdisplay, xwindow); meta_error_trap_pop (screen->display); } }