/*! Pick a monitor to place a window on. */ static Rect* choose_monitor(ObClient *c, gboolean client_to_be_foregrounded, ObAppSettings *settings) { Rect *area; ObPlaceHead *choice; guint i; ObClient *p; GSList *it; choice = g_new(ObPlaceHead, screen_num_monitors); for (i = 0; i < screen_num_monitors; ++i) { choice[i].monitor = i; choice[i].flags = 0; } /* find monitors with group members */ if (c->group) { for (it = c->group->members; it; it = g_slist_next(it)) { ObClient *itc = it->data; if (itc != c) { guint m = client_monitor(itc); if (m < screen_num_monitors) { if (screen_compare_desktops(itc->desktop, c->desktop)) choice[m].flags |= HEAD_GROUP_DESK; else choice[m].flags |= HEAD_GROUP; } } } } i = screen_monitor_primary(FALSE); if (i < screen_num_monitors) { choice[i].flags |= HEAD_PRIMARY; if (config_place_monitor == OB_PLACE_MONITOR_PRIMARY) choice[i].flags |= HEAD_PLACED; if (settings && settings->monitor_type == OB_PLACE_MONITOR_PRIMARY) choice[i].flags |= HEAD_PERAPP; } i = screen_monitor_active(); if (i < screen_num_monitors) { if (config_place_monitor == OB_PLACE_MONITOR_ACTIVE) choice[i].flags |= HEAD_PLACED; if (settings && settings->monitor_type == OB_PLACE_MONITOR_ACTIVE) choice[i].flags |= HEAD_PERAPP; } i = screen_monitor_pointer(); if (i < screen_num_monitors) { if (config_place_monitor == OB_PLACE_MONITOR_MOUSE) choice[i].flags |= HEAD_PLACED; if (settings && settings->monitor_type == OB_PLACE_MONITOR_MOUSE) choice[i].flags |= HEAD_PERAPP; } if (settings) { i = settings->monitor - 1; if (i < screen_num_monitors) choice[i].flags |= HEAD_PERAPP; } /* direct parent takes highest precedence */ if ((p = client_direct_parent(c))) { i = client_monitor(p); if (i < screen_num_monitors) choice[i].flags |= HEAD_PARENT; } qsort(choice, screen_num_monitors, sizeof(ObPlaceHead), client_to_be_foregrounded ? cmp_foreground : cmp_background); /* save the areas of the monitors in order of their being chosen */ for (i = 0; i < screen_num_monitors; ++i) { ob_debug("placement choice %d is monitor %d", i, choice[i].monitor); if (choice[i].flags & HEAD_PARENT) ob_debug(" - parent on monitor"); if (choice[i].flags & HEAD_PLACED) ob_debug(" - placement choice"); if (choice[i].flags & HEAD_PRIMARY) ob_debug(" - primary monitor"); if (choice[i].flags & HEAD_GROUP_DESK) ob_debug(" - group on same desktop"); if (choice[i].flags & HEAD_GROUP) ob_debug(" - group on other desktop"); } area = screen_area(c->desktop, choice[0].monitor, NULL); g_free(choice); /* return the area for the chosen monitor */ return area; }
static void restack_windows(struct wm_client *selected, gboolean raise) { GList *it, *last, *below, *above, *next; GList *wins = NULL; GList *group_helpers = NULL; GList *group_modals = NULL; GList *group_trans = NULL; GList *modals = NULL; GList *trans = NULL; if(raise) { struct wm_client *p; while(selected->modal && (p = client_direct_parent(selected))) selected = p; } it = g_list_find(stacking_list, selected); g_assert(it); stacking_list = g_list_delete_link(stacking_list, it); if(raise) { for(it = g_list_last(stacking_list); it; it = next) { next = g_list_previous(it); if(WINDOW_IS_CLIENT(it->data)) { struct wm_client *ch = it->data; if(ch->layer == selected->layer && client_search_transient(selected, ch)) { if(client_is_direct_child(selected, ch)) { if(ch->modal) modals = g_list_prepend(modals, ch); else trans = g_list_prepend(trans, ch); } else if(client_helper(ch)) { if(selected->transient) { continue; } group_helpers = g_list_prepend(group_helpers, ch); } else { if(ch->modal) group_modals = g_list_prepend(group_modals, ch); else group_trans = g_list_prepend(group_trans, ch); } stacking_list = g_list_delete_link(stacking_list, it); } } } } wins = g_list_concat(modals, trans); wins = g_list_concat(wins, group_helpers); wins = g_list_append(wins, selected); if(selected->transient_for_group) { if(selected->modal) { wins = g_list_concat(wins, group_modals); group_modals = NULL; } wins = g_list_concat(wins, group_trans); group_trans = NULL; } last = NULL; for(it = g_list_last(stacking_list); it; it = g_list_previous(it)) { if(window_layer(it->data) < selected->layer) { last = it; continue; } if(!raise) break; if(window_layer(it->data) > selected->layer) break; last = it; } below = last; for(it = stacking_list; it; it = g_list_next(it)) { if(window_layer(it->data) > selected->layer) continue; if(window_layer(it->data) < selected->layer) break; if(WINDOW_IS_CLIENT(it->data)) { struct wm_client *c = it->data; if(c->group == selected->group) break; } if(it == below) break; } above = it ? g_list_previous(it) : g_list_last(stacking_list); if(below) it = g_list_previous(below); else it = g_list_last(stacking_list); for(; it != above; it = next) { next = g_list_previous(it); wins = g_list_prepend(wins, it->data); stacking_list = g_list_delete_link(stacking_list, it); } wins = g_list_concat(group_trans, wins); wins = g_list_concat(group_modals, wins); do_restack(wins, below); g_list_free(wins); if(!raise && selected->parents) { GSList *parents_copy, *sit; GSList *reorder = NULL; parents_copy = g_slist_copy(selected->parents); for(it = g_list_last(stacking_list); it && parents_copy; it = g_list_previous(it)) if((sit = g_slist_find(parents_copy, it->data))) { reorder = g_slist_prepend(reorder, sit->data); parents_copy = g_slist_delete_link(parents_copy, sit); } g_assert(parents_copy == NULL); for(sit = reorder; sit; sit = g_slist_next(sit)) restack_windows(sit->data, raise); } }