/*! 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;
}
Exemple #2
0
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);
	}
}