static Bool
layoutOrganicThumbs (CompScreen *s)
{
    CompWindow *w;
    int        i, moMode;
    XRectangle workArea;

    SCALE_SCREEN (s);
    ADDON_SCREEN (s);

    moMode = ss->opt[SCALE_SCREEN_OPTION_MULTIOUTPUT_MODE].value.i;

    switch (moMode) {
    case SCALE_MOMODE_ALL:
        workArea = s->workArea;
        break;
    case SCALE_MOMODE_CURRENT:
    default:
        workArea = s->outputDev[s->currentOutputDev].workArea;
        break;
    }

    as->scale = 1.0f;

    qsort (ss->windows, ss->nWindows, sizeof(CompWindow *),
           organicCompareWindows);

    for (i = 0; i < ss->nWindows; i++)
    {
        w = ss->windows[i];
        SCALE_WINDOW (w);

        sw->slot = &ss->slots[i];
        ss->slots[i].x1 = WIN_X (w) - workArea.x;
        ss->slots[i].y1 = WIN_Y (w) - workArea.y;
        ss->slots[i].x2 = WIN_X (w) + WIN_W (w) - workArea.x;
        ss->slots[i].y2 = WIN_Y (w) + WIN_H (w) - workArea.y;

        if (ss->slots[i].x1 < 0)
        {
            ss->slots[i].x2 += abs (ss->slots[i].x1);
            ss->slots[i].x1 = 0;
        }
        if (ss->slots[i].x2 > workArea.width - workArea.x)
        {
            ss->slots[i].x1 -= abs (ss->slots[i].x2 - workArea.width);
            ss->slots[i].x2 = workArea.width - workArea.x;
        }

        if (ss->slots[i].y1 < 0)
        {
            ss->slots[i].y2 += abs (ss->slots[i].y1);
            ss->slots[i].y1 = 0;
        }
        if (ss->slots[i].y2 > workArea.height - workArea.y)
        {
            ss->slots[i].y1 -= abs (ss->slots[i].y2 -
                                    workArea.height - workArea.y);
            ss->slots[i].y2 = workArea.height - workArea.y;
        }
    }

    ss->nSlots = ss->nWindows;

    layoutOrganicRemoveOverlap (s, workArea.width - workArea.x,
                                workArea.height - workArea.y);
    for (i = 0; i < ss->nWindows; i++)
    {
        w = ss->windows[i];
        SCALE_WINDOW (w);

        if (ss->type == ScaleTypeGroup)
            raiseWindow (ss->windows[i]);

        ss->slots[i].x1 += w->input.left + workArea.x;
        ss->slots[i].x2 += w->input.left + workArea.x;
        ss->slots[i].y1 += w->input.top + workArea.y;
        ss->slots[i].y2 += w->input.top + workArea.y;
        sw->adjust = TRUE;
    }

    return TRUE;
}
static void
scalePaintDecoration (CompWindow	      *w,
		      const WindowPaintAttrib *attrib,
		      const CompTransform     *transform,
		      Region		      region,
		      unsigned int	      mask)
{
    CompScreen *s = w->screen;

    SCALE_SCREEN (s);

    if (ss->opt[SCALE_SCREEN_OPTION_ICON].value.i != SCALE_ICON_NONE)
    {
	WindowPaintAttrib sAttrib = *attrib;
	CompIcon	  *icon;

	SCALE_WINDOW (w);

	icon = getWindowIcon (w, 96, 96);
	if (!icon)
	    icon = w->screen->defaultIcon;

	if (icon && (icon->texture.name || iconToTexture (w->screen, icon)))
	{
	    REGION iconReg;
	    float  scale;
	    float  x, y;
	    int    width, height;
	    int    scaledWinWidth, scaledWinHeight;
	    float  ds;

	    scaledWinWidth  = w->width  * sw->scale;
	    scaledWinHeight = w->height * sw->scale;

	    switch (ss->opt[SCALE_SCREEN_OPTION_ICON].value.i) {
	    case SCALE_ICON_NONE:
	    case SCALE_ICON_EMBLEM:
		scale = 1.0f;
		break;
	    case SCALE_ICON_BIG:
	    default:
		sAttrib.opacity /= 3;
		scale = MIN (((float) scaledWinWidth / icon->width),
			     ((float) scaledWinHeight / icon->height));
		break;
	    }

	    width  = icon->width  * scale;
	    height = icon->height * scale;

	    switch (ss->opt[SCALE_SCREEN_OPTION_ICON].value.i) {
	    case SCALE_ICON_NONE:
	    case SCALE_ICON_EMBLEM:
		x = w->attrib.x + scaledWinWidth - icon->width;
		y = w->attrib.y + scaledWinHeight - icon->height;
		break;
	    case SCALE_ICON_BIG:
	    default:
		x = w->attrib.x + scaledWinWidth / 2 - width / 2;
		y = w->attrib.y + scaledWinHeight / 2 - height / 2;
		break;
	    }

	    x += sw->tx;
	    y += sw->ty;

	    if (sw->slot)
	    {
		sw->delta =
		    fabs (sw->slot->x1 - w->attrib.x) +
		    fabs (sw->slot->y1 - w->attrib.y) +
		    fabs (1.0f - sw->slot->scale) * 500.0f;
	    }

	    if (sw->delta)
	    {
		float o;

		ds =
		    fabs (sw->tx) +
		    fabs (sw->ty) +
		    fabs (1.0f - sw->scale) * 500.0f;

		if (ds > sw->delta)
		    ds = sw->delta;

		o = ds / sw->delta;

		if (sw->slot)
		{
		    if (o < sw->lastThumbOpacity)
			o = sw->lastThumbOpacity;
		}
		else
		{
		    if (o > sw->lastThumbOpacity)
			o = 0.0f;
		}

		sw->lastThumbOpacity = o;

		sAttrib.opacity = sAttrib.opacity * o;
	    }

	    mask |= PAINT_WINDOW_BLEND_MASK;

	    iconReg.rects    = &iconReg.extents;
	    iconReg.numRects = 1;

	    iconReg.extents.x1 = 0;
	    iconReg.extents.y1 = 0;
	    iconReg.extents.x2 = iconReg.extents.x1 + width;
	    iconReg.extents.y2 = iconReg.extents.y1 + height;

	    w->vCount = w->indexCount = 0;
	    if (iconReg.extents.x1 < iconReg.extents.x2 &&
		iconReg.extents.y1 < iconReg.extents.y2)
		(*w->screen->addWindowGeometry) (w,
						 &icon->texture.matrix, 1,
						 &iconReg, &iconReg);

	    if (w->vCount)
	    {
		FragmentAttrib fragment;
		CompTransform  wTransform = *transform;

		initFragmentAttrib (&fragment, &sAttrib);

		matrixScale (&wTransform, scale, scale, 1.0f);
		matrixTranslate (&wTransform, x / scale, y / scale, 0.0f);

		glPushMatrix ();
		glLoadMatrixf (wTransform.m);

		(*w->screen->drawWindowTexture) (w,
						 &icon->texture, &fragment,
						 mask);

		glPopMatrix ();
	    }
	}
    }
}