Beispiel #1
0
/*
 * groupDragHoverTimeout
 *
 * Description:
 * Activates a window after a certain time a slot has been dragged over it.
 *
 */
static Bool
groupDragHoverTimeout (void* closure)
{
	CompWindow *w = (CompWindow *) closure;
	if (!w)
		return FALSE;

	GROUP_SCREEN (w->screen);
	GROUP_WINDOW (w);

	const BananaValue *
	option_bar_animations = bananaGetOption (bananaIndex,
	                                         "bar_animations",
	                                         w->screen->screenNum);

	const BananaValue *
	option_pulse_time = bananaGetOption (bananaIndex,
	                                     "pulse_time",
	                                     w->screen->screenNum);

	if (option_bar_animations->b)
	{
		GroupTabBar *bar = gw->group->tabBar;

		bar->bgAnimation = AnimationPulse;
		bar->bgAnimationTime = option_pulse_time->f * 1000;
	}

	(*w->screen->activateWindow) (w);
	gs->dragHoverTimeoutHandle = 0;

	return FALSE;
}
Beispiel #2
0
/*
 * groupWindowResizeNotify
 *
 */
void
groupWindowResizeNotify (CompWindow *w,
                         int        dx,
                         int        dy,
                         int        dwidth,
                         int        dheight)
{
	CompScreen *s = w->screen;

	GROUP_SCREEN (s);
	GROUP_WINDOW (w);

	if (gw->resizeGeometry)
	{
		free (gw->resizeGeometry);
		gw->resizeGeometry = NULL;
	}

	UNWRAP (gs, s, windowResizeNotify);
	(*s->windowResizeNotify)(w, dx, dy, dwidth, dheight);
	WRAP (gs, s, windowResizeNotify, groupWindowResizeNotify);

	if (gw->glowQuads)
		groupComputeGlowQuads (w, &gs->glowTexture.matrix);

	if (gw->group && gw->group->tabBar && IS_TOP_TAB (w, gw->group))
	{
		if (gw->group->tabBar->state != PaintOff)
		{
			groupRecalcTabBarPos (gw->group, pointerX,
			                      WIN_X (w), WIN_X (w) + WIN_WIDTH (w));
		}
	}
}
void
groupEnqueueUngrabNotify (CompWindow *w)
{
    GroupPendingUngrabs *ungrab;

    GROUP_SCREEN (w->screen);

    ungrab = malloc (sizeof (GroupPendingUngrabs));

    if (!ungrab)
	return;

    ungrab->w    = w;
    ungrab->next = NULL;

    if (gs->pendingUngrabs)
    {
	GroupPendingUngrabs *temp;
	for (temp = gs->pendingUngrabs; temp->next; temp = temp->next);

	temp->next = ungrab;
    }
    else
	gs->pendingUngrabs = ungrab;

    if (!gs->dequeueTimeoutHandle)
    {
	gs->dequeueTimeoutHandle =
	    compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen);
    }
}
Beispiel #4
0
void
GroupWindow::enqueueUngrabNotify ()
{
    GroupWindow::PendingUngrabs *ungrab;

    GROUP_SCREEN (screen);

    ungrab = new GroupWindow::PendingUngrabs;

    if (!ungrab)
	return;

    ungrab->w    = window;
    ungrab->next = NULL;

    if (gs->mPendingUngrabs)
    {
	GroupWindow::PendingUngrabs *temp;
	for (temp = gs->mPendingUngrabs; temp->next; temp = temp->next);

	temp->next = ungrab;
    }
    else
	gs->mPendingUngrabs = ungrab;

    if (!gs->mDequeueTimeoutHandle.active ())
    {
	gs->mDequeueTimeoutHandle.start ();
    }
}
Beispiel #5
0
/*
 * groupApplyInitialActions
 *
 * timer callback for stuff that needs to be called after all
 * screens and windows are initialized
 *
 */
static Bool
groupApplyInitialActions (void *closure)
{
    CompScreen *s = (CompScreen *) closure;
    CompWindow *w;

    GROUP_SCREEN (s);

    gs->initialActionsTimeoutHandle = 0;

    /* we need to do it from top to buttom of the stack to avoid problems
       with a reload of Compiz and tabbed static groups. (topTab will always
       be above the other windows in the group) */
    for (w = s->reverseWindows; w; w = w->prev)
    {
        Bool tabbed;
        long int id;
        GLushort color[3];

        GROUP_WINDOW (w);

        /* read window property to see if window was grouped
           before - if it was, regroup */
        if (groupCheckWindowProperty (w, &id, &tabbed, color))
        {
            GroupSelection *group;

            for (group = gs->groups; group; group = group->next)
                if (group->identifier == id)
                    break;

            groupAddWindowToGroup (w, group, id);
            if (tabbed)
                groupTabGroup (w);

            gw->group->color[0] = color[0];
            gw->group->color[1] = color[1];
            gw->group->color[2] = color[2];

            groupRenderTopTabHighlight (gw->group);
            damageScreen (w->screen);
        }

        const BananaValue *
        option_autotab_create = bananaGetOption (bananaIndex,
                                "autotab_create",
                                s->screenNum);

        if (option_autotab_create->b && groupIsGroupWindow (w))
        {
            if (!gw->group && (gw->windowState == WindowNormal))
            {
                groupAddWindowToGroup (w, NULL, 0);
                groupTabGroup (w);
            }
        }
    }

    return FALSE;
}
Beispiel #6
0
/*
 * groupPreparePaintScreen
 *
 */
void
groupPreparePaintScreen (CompScreen *s,
                         int        msSinceLastPaint)
{
	GroupSelection *group, *next;

	GROUP_SCREEN (s);

	UNWRAP (gs, s, preparePaintScreen);
	(*s->preparePaintScreen)(s, msSinceLastPaint);
	WRAP (gs, s, preparePaintScreen, groupPreparePaintScreen);

	group = gs->groups;
	while (group)
	{
		GroupTabBar *bar = group->tabBar;

		if (bar)
		{
			groupApplyForces (s, bar, (gs->dragged) ? gs->draggedSlot : NULL);
			groupApplySpeeds (s, group, msSinceLastPaint);

			if ((bar->state != PaintOff) && HAS_TOP_WIN (group))
				groupHandleHoverDetection (group);

			if (bar->state == PaintFadeIn || bar->state == PaintFadeOut)
				groupHandleTabBarFade (group, msSinceLastPaint);

			if (bar->textLayer)
				groupHandleTextFade (group, msSinceLastPaint);

			if (bar->bgAnimation)
				groupHandleTabBarAnimation (group, msSinceLastPaint);
		}

		if (group->changeState != NoTabChange)
		{
			group->changeAnimationTime -= msSinceLastPaint;
			if (group->changeAnimationTime <= 0)
				groupHandleAnimation (group);
		}

		/* groupDrawTabAnimation may delete the group, so better
		   save the pointer to the next chain element */
		next = group->next;

		if (group->tabbingState != NoTabbing)
			groupDrawTabAnimation (group, msSinceLastPaint);

		group = next;
	}
}
Beispiel #7
0
/*
 * groupInitWindow
 *
 */
static Bool
groupInitWindow (CompPlugin *p,
                 CompWindow *w)
{
    GroupWindow *gw;

    GROUP_SCREEN (w->screen);

    gw = malloc (sizeof (GroupWindow));
    if (!gw)
        return FALSE;

    gw->group        = NULL;
    gw->slot         = NULL;
    gw->glowQuads    = NULL;
    gw->inSelection  = FALSE;
    gw->needsPosSync = FALSE;
    gw->readOnlyProperty = FALSE;

    /* for tab */
    gw->animateState = 0;

    gw->tx        = 0.0f;
    gw->ty        = 0.0f;
    gw->xVelocity = 0.0f;
    gw->yVelocity = 0.0f;

    gw->orgPos.x        = 0;
    gw->orgPos.y        = 0;
    gw->mainTabOffset.x = 0;
    gw->mainTabOffset.y = 0;
    gw->destination.x   = 0;
    gw->destination.y   = 0;

    gw->windowHideInfo = NULL;
    gw->resizeGeometry = NULL;

    if (w->minimized)
        gw->windowState = WindowMinimized;
    else if (w->shaded)
        gw->windowState = WindowShaded;
    else
        gw->windowState = WindowNormal;

    w->privates[gs->windowPrivateIndex].ptr = gw;

    groupComputeGlowQuads (w, &gs->glowTexture.matrix);

    return TRUE;
}
static Bool
groupDequeueTimer (void *closure)
{
    CompScreen *s = (CompScreen *) closure;

    GROUP_SCREEN (s);

    groupDequeueMoveNotifies (s);
    groupDequeueGrabNotifies (s);
    groupDequeueUngrabNotifies (s);

    gs->dequeueTimeoutHandle = 0;

    return FALSE;
}
Beispiel #9
0
void
groupActivateWindow (CompWindow *w)
{
	CompScreen *s = w->screen;

	GROUP_SCREEN (s);
	GROUP_WINDOW (w);

	if (gw->group && gw->group->tabBar && !IS_TOP_TAB (w, gw->group))
		groupChangeTab (gw->slot, RotateUncertain);

	UNWRAP (gs, s, activateWindow);
	(*s->activateWindow)(w);
	WRAP (gs, s, activateWindow, groupActivateWindow);
}
Beispiel #10
0
/*
 * groupDonePaintScreen
 *
 */
void
groupDonePaintScreen (CompScreen *s)
{
	GroupSelection *group;

	GROUP_SCREEN (s);

	UNWRAP (gs, s, donePaintScreen);
	(*s->donePaintScreen)(s);
	WRAP (gs, s, donePaintScreen, groupDonePaintScreen);

	for (group = gs->groups; group; group = group->next)
	{
		if (group->tabbingState != NoTabbing)
			damageScreen (s);
		else if (group->changeState != NoTabChange)
			damageScreen (s);
		else if (group->tabBar)
		{
			Bool needDamage = FALSE;

			if ((group->tabBar->state == PaintFadeIn) ||
			    (group->tabBar->state == PaintFadeOut))
			{
				needDamage = TRUE;
			}

			if (group->tabBar->textLayer)
			{
				if ((group->tabBar->textLayer->state == PaintFadeIn) ||
				    (group->tabBar->textLayer->state == PaintFadeOut))
				{
					needDamage = TRUE;
				}
			}

			if (group->tabBar->bgAnimation)
				needDamage = TRUE;

			if (gs->draggedSlot)
				needDamage = TRUE;

			if (needDamage)
				groupDamageTabBarRegion (group);
		}
	}
}
Beispiel #11
0
/*
 * groupIsGroupWindow
 *
 */
Bool
groupIsGroupWindow (CompWindow *w)
{
	GROUP_SCREEN (w->screen);

	if (w->attrib.override_redirect)
		return FALSE;

	if (w->type & CompWindowTypeDesktopMask)
		return FALSE;

	if (w->invisible)
		return FALSE;

	if (!matchEval (&gs->window_match, w))
		return FALSE;

	return TRUE;
}
Beispiel #12
0
/*
 * groupGetOutputExtentsForWindow
 *
 */
void
groupGetOutputExtentsForWindow (CompWindow        *w,
                                CompWindowExtents *output)
{
	GROUP_SCREEN (w->screen);
	GROUP_WINDOW (w);

	UNWRAP (gs, w->screen, getOutputExtentsForWindow);
	(*w->screen->getOutputExtentsForWindow)(w, output);
	WRAP (gs, w->screen, getOutputExtentsForWindow,
	      groupGetOutputExtentsForWindow);

	if (gw->group && gw->group->nWins > 1)
	{
		GROUP_DISPLAY (&display);

		const BananaValue *
		option_glow_size = bananaGetOption (bananaIndex,
		                                    "glow_size",
		                                    w->screen->screenNum);

		const BananaValue *
		option_glow_type = bananaGetOption (bananaIndex,
		                                    "glow_type",
		                                    w->screen->screenNum);

		int glowSize = option_glow_size->i;
		int glowType = option_glow_type->i;
		int glowTextureSize = gd->glowTextureProperties[glowType].textureSize;
		int glowOffset = gd->glowTextureProperties[glowType].glowOffset;

		glowSize = glowSize * (glowTextureSize - glowOffset) / glowTextureSize;

		/* glowSize is the size of the glow outside the window decoration
		 * (w->input), while w->output includes the size of w->input
		 * this is why we have to add w->input here */
		output->left   = MAX (output->left, glowSize + w->input.left);
		output->right  = MAX (output->right, glowSize + w->input.right);
		output->top    = MAX (output->top, glowSize + w->input.top);
		output->bottom = MAX (output->bottom, glowSize + w->input.bottom);
	}
}
static void
groupDequeueUngrabNotifies (CompScreen *s)
{
    GroupPendingUngrabs *ungrab;

    GROUP_SCREEN (s);

    gs->queued = TRUE;

    while (gs->pendingUngrabs)
    {
	ungrab = gs->pendingUngrabs;
	gs->pendingUngrabs = gs->pendingUngrabs->next;

	(*(ungrab->w)->screen->windowUngrabNotify) (ungrab->w);

	free (ungrab);
    }

    gs->queued = FALSE;
}
void
groupEnqueueMoveNotify (CompWindow *w,
			int        dx,
			int        dy,
			Bool       immediate,
			Bool       sync)
{
    GroupPendingMoves *move;

    GROUP_SCREEN (w->screen);

    move = malloc (sizeof (GroupPendingMoves));
    if (!move)
	return;

    move->w  = w;
    move->dx = dx;
    move->dy = dy;

    move->immediate = immediate;
    move->sync      = sync;
    move->next      = NULL;

    if (gs->pendingMoves)
    {
	GroupPendingMoves *temp;
	for (temp = gs->pendingMoves; temp->next; temp = temp->next);

	temp->next = move;
    }
    else
	gs->pendingMoves = move;

    if (!gs->dequeueTimeoutHandle)
    {
	gs->dequeueTimeoutHandle =
	    compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen);
    }
}
Beispiel #15
0
void
groupWindowStateChangeNotify (CompWindow   *w,
                              unsigned int lastState)
{
	CompScreen *s = w->screen;

	GROUP_DISPLAY (&display);
	GROUP_SCREEN (s);
	GROUP_WINDOW (w);

	if (gw->group && !gd->ignoreMode)
	{
		const BananaValue *
		option_maximize_unmaximize_all = bananaGetOption (bananaIndex,
		                                            "maximize_unmaximize_all",
		                                            s->screenNum);

		if (((lastState & MAXIMIZE_STATE) != (w->state & MAXIMIZE_STATE)) &&
		    option_maximize_unmaximize_all->b)
		{
			int i;
			for (i = 0; i < gw->group->nWins; i++)
			{
				CompWindow *cw = gw->group->windows[i];
				if (!cw)
					continue;

				if (cw->id == w->id)
					continue;

				maximizeWindow (cw, w->state & MAXIMIZE_STATE);
			}
		}
	}

	UNWRAP (gs, s, windowStateChangeNotify);
	(*s->windowStateChangeNotify)(w, lastState);
	WRAP (gs, s, windowStateChangeNotify, groupWindowStateChangeNotify);
}
void
groupEnqueueGrabNotify (CompWindow   *w,
			int          x,
			int          y,
			unsigned int state,
			unsigned int mask)
{
    GroupPendingGrabs *grab;

    GROUP_SCREEN (w->screen);

    grab = malloc (sizeof (GroupPendingGrabs));
    if (!grab)
	return;

    grab->w = w;
    grab->x = x;
    grab->y = y;

    grab->state = state;
    grab->mask  = mask;
    grab->next  = NULL;

    if (gs->pendingGrabs)
    {
	GroupPendingGrabs *temp;
	for (temp = gs->pendingGrabs; temp->next; temp = temp->next);

	temp->next = grab;
    }
    else
	gs->pendingGrabs = grab;

    if (!gs->dequeueTimeoutHandle)
    {
	gs->dequeueTimeoutHandle =
	    compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen);
    }
}
Beispiel #17
0
/*
 * groupaintTransformedOutput
 *
 */
void
groupPaintTransformedOutput (CompScreen              *s,
                             const ScreenPaintAttrib *sa,
                             const CompTransform     *transform,
                             Region                  region,
                             CompOutput              *output,
                             unsigned int            mask)
{
	GROUP_SCREEN (s);

	UNWRAP (gs, s, paintTransformedOutput);
	(*s->paintTransformedOutput)(s, sa, transform, region, output, mask);
	WRAP (gs, s, paintTransformedOutput, groupPaintTransformedOutput);

	if ((gs->vpX == s->x) && (gs->vpY == s->y))
	{
		gs->painted = TRUE;

		if ((gs->grabState == ScreenGrabTabDrag) &&
		    gs->draggedSlot && gs->dragged)
		{
			CompTransform wTransform = *transform;

			(*s->applyScreenTransform)(s, sa, output, &wTransform);
			transformToScreenSpace (s, output, -sa->zTranslate, &wTransform);
			glPushMatrix ();
			glLoadMatrixf (wTransform.m);

			groupPaintThumb (NULL, gs->draggedSlot, &wTransform, OPAQUE);

			glPopMatrix ();
		}
		else if (gs->grabState == ScreenGrabSelect)
		{
			groupPaintSelectionOutline (s, sa, transform, output, TRUE);
		}
	}
}
Beispiel #18
0
/*
 * groupGrabScreen
 *
 */
void
groupGrabScreen (CompScreen           *s,
                 GroupScreenGrabState newState)
{
	GROUP_SCREEN (s);

	if ((gs->grabState != newState) && gs->grabIndex)
	{
		removeScreenGrab (s, gs->grabIndex, NULL);
		gs->grabIndex = 0;
	}

	if (newState == ScreenGrabSelect)
	{
		gs->grabIndex = pushScreenGrab (s, None, "group");
	}
	else if (newState == ScreenGrabTabDrag)
	{
		gs->grabIndex = pushScreenGrab (s, None, "group-drag");
	}

	gs->grabState = newState;
}
static void
groupDequeueGrabNotifies (CompScreen *s)
{
    GroupPendingGrabs *grab;

    GROUP_SCREEN (s);

    gs->queued = TRUE;

    while (gs->pendingGrabs)
    {
	grab = gs->pendingGrabs;
	gs->pendingGrabs = gs->pendingGrabs->next;

	(*(grab->w)->screen->windowGrabNotify) (grab->w,
						grab->x, grab->y,
						grab->state, grab->mask);

	free (grab);
    }

    gs->queued = FALSE;
}
Beispiel #20
0
void
GroupWindow::enqueueMoveNotify (int  dx,
				     int  dy,
				     bool immediate,
				     bool sync)
{
    GroupWindow::PendingMoves *move;

    GROUP_SCREEN (screen);

    move = new GroupWindow::PendingMoves;
    if (!move)
	return;

    move->w  = window;
    move->dx = dx;
    move->dy = dy;

    move->immediate = immediate;
    move->sync      = sync;
    move->next      = NULL;

    if (gs->mPendingMoves)
    {
	GroupWindow::PendingMoves *temp;
	for (temp = gs->mPendingMoves; temp->next; temp = temp->next);

	temp->next = move;
    }
    else
	gs->mPendingMoves = move;

    if (!gs->mDequeueTimeoutHandle.active ())
    {
	gs->mDequeueTimeoutHandle.start ();
    }
}
Beispiel #21
0
void
GroupWindow::enqueueGrabNotify (int          x,
				     int          y,
				     unsigned int state,
				     unsigned int mask)
{
    GroupWindow::PendingGrabs *grab;
    
    GROUP_SCREEN (screen);

    grab = new GroupWindow::PendingGrabs;
    if (!grab)
	return;

    grab->w = window;
    grab->x = x;
    grab->y = y;

    grab->state = state;
    grab->mask  = mask;
    grab->next  = NULL;

    if (gs->mPendingGrabs)
    {
	GroupWindow::PendingGrabs *temp;
	for (temp = gs->mPendingGrabs; temp->next; temp = temp->next);

	temp->next = grab;
    }
    else
	gs->mPendingGrabs = grab;

    if (!gs->mDequeueTimeoutHandle.active ())
    {
	gs->mDequeueTimeoutHandle.start ();
    }
}
void
groupDequeueMoveNotifies (CompScreen *s)
{
    GroupPendingMoves *move;
    GroupPendingSyncs *syncs = NULL, *sync;

    GROUP_SCREEN (s);

    gs->queued = TRUE;

    while (gs->pendingMoves)
    {
	move = gs->pendingMoves;
	gs->pendingMoves = move->next;

	moveWindow (move->w, move->dx, move->dy, TRUE, move->immediate);
	if (move->sync)
	{
	    sync = malloc (sizeof (GroupPendingSyncs));
	    if (sync)
	    {
		GROUP_WINDOW (move->w);

		gw->needsPosSync = TRUE;
		sync->w          = move->w;
		sync->next       = syncs;
		syncs            = sync;
	    }
	}
	free (move);
    }

    if (syncs)
	groupDequeueSyncs (syncs);

    gs->queued = FALSE;
}
Beispiel #23
0
static void
groupChangeNotify (const char        *optionName,
                   BananaType        optionType,
                   const BananaValue *optionValue,
                   int               screenNum)
{
    GROUP_DISPLAY (&display);

    if (strcasecmp (optionName, "window_match") == 0)
    {
        CompScreen *s = getScreenFromScreenNum (screenNum);
        GROUP_SCREEN (s);

        matchFini (&gs->window_match);
        matchInit (&gs->window_match);
        matchAddFromString (&gs->window_match, optionValue->s);
        matchUpdate (&gs->window_match);
    }
    else if (strcasecmp (optionName, "tab_base_color") == 0 ||
             strcasecmp (optionName, "tab_highlight_color") == 0 ||
             strcasecmp (optionName, "tab_border_color") == 0 ||
             strcasecmp (optionName, "tab_style") == 0 ||
             strcasecmp (optionName, "border_radius") == 0 ||
             strcasecmp (optionName, "border_width") == 0)
    {
        GroupSelection *group;

        CompScreen *s = getScreenFromScreenNum (screenNum);
        GROUP_SCREEN (s);

        for (group = gs->groups; group; group = group->next)
            if (group->tabBar)
                groupRenderTabBarBackground (group);
    }
    else if (strcasecmp (optionName, "tabbar_font_size") == 0 ||
             strcasecmp (optionName, "tabbar_font_color") == 0)
    {
        GroupSelection *group;

        CompScreen *s = getScreenFromScreenNum (screenNum);
        GROUP_SCREEN (s);

        for (group = gs->groups; group; group = group->next)
            groupRenderWindowTitle (group);
    }
    else if (strcasecmp (optionName, "thumb_size") == 0 ||
             strcasecmp (optionName, "thumb_space") == 0)
    {
        GroupSelection *group;

        CompScreen *s = getScreenFromScreenNum (screenNum);
        GROUP_SCREEN (s);

        for (group = gs->groups; group; group = group->next)
            if (group->tabBar)
            {
                BoxPtr box = &group->tabBar->region->extents;
                groupRecalcTabBarPos (group, (box->x1 + box->x2 ) / 2,
                                      box->x1, box->x2);
            }
    }
    else if (strcasecmp (optionName, "glow") == 0 ||
             strcasecmp (optionName, "glow_size") == 0)
    {
        CompScreen *s = getScreenFromScreenNum (screenNum);
        GROUP_SCREEN (s);

        CompWindow *w;

        for (w = s->windows; w; w = w->next)
        {
            GROUP_WINDOW (w);

            groupComputeGlowQuads (w, &gs->glowTexture.matrix);
            if (gw->glowQuads)
            {
                damageWindowOutputExtents (w);
                updateWindowOutputExtents (w);
                damageWindowOutputExtents (w);
            }
        }
    }
    else if (strcasecmp (optionName, "glow_type") == 0)
    {
        CompScreen *s = getScreenFromScreenNum (screenNum);
        GROUP_SCREEN (s);

        int glowType;
        GlowTextureProperties *glowProperty;

        GROUP_DISPLAY (&display);

        const BananaValue *
        option_glow_type = bananaGetOption (bananaIndex,
                                            "glow_type",
                                            s->screenNum);

        glowType = option_glow_type->i;
        glowProperty = &gd->glowTextureProperties[glowType];

        finiTexture (s, &gs->glowTexture);
        initTexture (s, &gs->glowTexture);

        imageDataToTexture (s, &gs->glowTexture,
                            glowProperty->textureData,
                            glowProperty->textureSize,
                            glowProperty->textureSize,
                            GL_RGBA, GL_UNSIGNED_BYTE);

        const BananaValue *
        option_glow = bananaGetOption (bananaIndex,
                                       "glow",
                                       s->screenNum);

        if (option_glow->b && gs->groups)
        {
            CompWindow *w;

            for (w = s->windows; w; w = w->next)
                groupComputeGlowQuads (w, &gs->glowTexture.matrix);

            damageScreen (s);
        }
    }
    else if (strcasecmp (optionName, "select_button") == 0)
        updateButton (optionValue->s, &gd->select_button);
    else if (strcasecmp (optionName, "select_single_key") == 0)
        updateKey (optionValue->s, &gd->select_single_key);
    else if (strcasecmp (optionName, "group_key") == 0)
        updateKey (optionValue->s, &gd->group_key);
    else if (strcasecmp (optionName, "ungroup_key") == 0)
        updateKey (optionValue->s, &gd->ungroup_key);
    else if (strcasecmp (optionName, "remove_key") == 0)
        updateKey (optionValue->s, &gd->remove_key);
    else if (strcasecmp (optionName, "close_key") == 0)
        updateKey (optionValue->s, &gd->close_key);
    else if (strcasecmp (optionName, "ignore_key") == 0)
        updateKey (optionValue->s, &gd->ignore_key);
    else if (strcasecmp (optionName, "tabmode_key") == 0)
        updateKey (optionValue->s, &gd->tabmode_key);
    else if (strcasecmp (optionName, "change_tab_left_key") == 0)
        updateKey (optionValue->s, &gd->change_tab_left_key);
    else if (strcasecmp (optionName, "change_tab_right_key") == 0)
        updateKey (optionValue->s, &gd->change_tab_right_key);
    else if (strcasecmp (optionName, "change_color_key") == 0)
        updateKey (optionValue->s, &gd->change_color_key);
    else if (strcasecmp (optionName, "autotab_windows") == 0)
    {
        CompScreen *s = getScreenFromScreenNum (screenNum);

        GROUP_SCREEN (s);

        int i;
        if (gs->autotab && gs->autotabCount != 0)
        {
            for (i = 0; i <= gs->autotabCount - 1; i++)
                matchFini (&gs->autotab[i]);

            free (gs->autotab);
        }

        gs->autotabCount = optionValue->list.nItem;
        gs->autotab = malloc (gs->autotabCount * sizeof (CompMatch));

        for (i = 0; i <= gs->autotabCount - 1; i++)
        {
            matchInit (&gs->autotab[i]);
            matchAddFromString (&gs->autotab[i], optionValue->list.item[i].s);
            matchUpdate (&gs->autotab[i]);
        }
    }
}
Beispiel #24
0
/*
 * TextLayer::render
 *
 * Renders some text without a background, without automatically
 * binding the text pixmap to a texture (since we need to bind it later)
 *
 */
void
TextLayer::render ()
{
    int             twidth, theight;
    Pixmap          pixmap = None;

    GROUP_SCREEN (screen);

    if (!HAS_TOP_WIN (mGroup))
	return;

    /* Maximum text width is the tab bar width */
    twidth = mGroup->mTabBar->mRegion.boundingRect ().width ();
    theight = mGroup->mTabBar->mRegion.boundingRect ().height ();

    if (mGroup->mTabBar->mTextSlot &&
        mGroup->mTabBar->mTextSlot->mWindow && gTextAvailable)
    {
	CompText::Attrib  textAttrib;

	textAttrib.family = "Sans";
	textAttrib.size   = gs->optionGetTabbarFontSize ();

	/* Bold text, ellipsize if there is not enough room and do not
	 * automatically bind pixmap to texture */
	textAttrib.flags = CompText::StyleBold | CompText::Ellipsized |
	                   CompText::NoAutoBinding;

	textAttrib.color[0] = gs->optionGetTabbarFontColorRed ();
	textAttrib.color[1] = gs->optionGetTabbarFontColorGreen ();
	textAttrib.color[2] = gs->optionGetTabbarFontColorBlue ();
	textAttrib.color[3] = gs->optionGetTabbarFontColorAlpha ();

	textAttrib.maxWidth = twidth;
	textAttrib.maxHeight = theight;

	/* Render title of the top window */
	if (gs->mText.renderWindowTitle (
		             mGroup->mTabBar->mTextSlot->mWindow->id (),
						     false, textAttrib))
	{
	    pixmap = gs->mText.getPixmap ();
	    twidth = gs->mText.getWidth ();
	    theight = gs->mText.getHeight ();
	}
    }

    if (!pixmap)
    {
	/* getting the pixmap failed, so create an empty one */
	pixmap = XCreatePixmap (screen->dpy (), screen->root (), twidth,
							   theight, 32);

	if (pixmap)
	{
	    XGCValues gcv;
	    GC        gc;

	    gcv.foreground = 0x00000000;
	    gcv.plane_mask = 0xffffffff;

	    gc = XCreateGC (screen->dpy (), pixmap, GCForeground, &gcv);
	    XFillRectangle (screen->dpy (), pixmap, gc, 0, 0, twidth,
							       theight);
	    XFreeGC (screen->dpy (), gc);
	}
    }

    setWidth  (twidth);
    setHeight (theight);

    if (pixmap)
    {
	mTexture.clear ();
	mPixmap = pixmap;
	/* Text layer's texture is bound here, this can be re used
	 * in TextureLayer::paint
	 */
	mTexture = GLTexture::bindPixmapToTexture (mPixmap,
						   width (), height (),
						   32);
    }
}
Beispiel #25
0
/*
 * groupPaintTabBar
 *
 */
static void
groupPaintTabBar (GroupSelection          *group,
                  const WindowPaintAttrib *wAttrib,
                  const CompTransform     *transform,
                  unsigned int            mask,
                  Region                  clipRegion)
{
	CompWindow      *topTab;
	CompScreen      *s = group->screen;
	GroupTabBar     *bar = group->tabBar;
	int count;
	REGION box;

	GROUP_SCREEN (s);

	if (HAS_TOP_WIN (group))
		topTab = TOP_TAB (group);
	else
		topTab = PREV_TOP_TAB (group);

#define PAINT_BG     0
#define PAINT_SEL    1
#define PAINT_THUMBS 2
#define PAINT_TEXT   3
#define PAINT_MAX    4

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

	const BananaValue *
	option_fade_time = bananaGetOption (bananaIndex,
	                                    "fade_time",
	                                    s->screenNum);

	const BananaValue *
	option_mipmaps = bananaGetOption (bananaIndex,
	                                  "mipmaps",
	                                  s->screenNum);

	const BananaValue *
	option_fade_text_time = bananaGetOption (bananaIndex,
	                                         "fade_text_time",
	                                         s->screenNum);

	for (count = 0; count < PAINT_MAX; count++)
	{
		int alpha = OPAQUE;
		float wScale = 1.0f, hScale = 1.0f;
		GroupCairoLayer *layer = NULL;

		if (bar->state == PaintFadeIn)
			alpha -= alpha * bar->animationTime / (option_fade_time->f * 1000);
		else if (bar->state == PaintFadeOut)
			alpha = alpha * bar->animationTime / (option_fade_time->f * 1000);

		switch (count) {
		case PAINT_BG:
		{
			int newWidth;

			layer = bar->bgLayer;

			/* handle the repaint of the background */
			newWidth = bar->region->extents.x2 - bar->region->extents.x1;
			if (layer && (newWidth > layer->texWidth))
				newWidth = layer->texWidth;

			wScale = (double) (bar->region->extents.x2 -
			                   bar->region->extents.x1) / (double) newWidth;

			/* FIXME: maybe move this over to groupResizeTabBarRegion -
			   the only problem is that we would have 2 redraws if
			   there is an animation */
			if (newWidth != bar->oldWidth || bar->bgAnimation)
				groupRenderTabBarBackground (group);

			bar->oldWidth = newWidth;
			box.extents = bar->region->extents;
		}
		break;

		case PAINT_SEL:
			if (group->topTab != gs->draggedSlot)
			{
				layer = bar->selectionLayer;
				box.extents = group->topTab->region->extents;
			}
			break;

		case PAINT_THUMBS:
		{
			GLenum oldTextureFilter;
			GroupTabBarSlot *slot;

			oldTextureFilter = display.textureFilter;

			if (option_mipmaps->b)
				display.textureFilter = GL_LINEAR_MIPMAP_LINEAR;

			for (slot = bar->slots; slot; slot = slot->next)
			{
				if (slot != gs->draggedSlot || !gs->dragged)
					groupPaintThumb (group, slot, transform,
					                 wAttrib->opacity);
			}

			display.textureFilter = oldTextureFilter;
		}
		break;

		case PAINT_TEXT:
			if (bar->textLayer && (bar->textLayer->state != PaintOff))
			{
				layer = bar->textLayer;

				box.extents.x1 = bar->region->extents.x1 + 5;
				box.extents.x2 = bar->region->extents.x1 +
				                 bar->textLayer->texWidth + 5;
				box.extents.y1 = bar->region->extents.y2 -
				                 bar->textLayer->texHeight - 5;
				box.extents.y2 = bar->region->extents.y2 - 5;

				if (box.extents.x2 > bar->region->extents.x2)
					box.extents.x2 = bar->region->extents.x2;

				/* recalculate the alpha again for text fade... */
				if (layer->state == PaintFadeIn)
					alpha -= alpha * layer->animationTime /
					         (option_fade_text_time->f * 1000);
				else if (layer->state == PaintFadeOut)
					alpha = alpha * layer->animationTime /
					        (option_fade_text_time->f * 1000);
			}
			break;
		}

		if (layer)
		{
			CompMatrix matrix = layer->texture.matrix;

			/* remove the old x1 and y1 so we have a relative value */
			box.extents.x2 -= box.extents.x1;
			box.extents.y2 -= box.extents.y1;
			box.extents.x1 = (box.extents.x1 - topTab->attrib.x) / wScale +
			                 topTab->attrib.x;
			box.extents.y1 = (box.extents.y1 - topTab->attrib.y) / hScale +
			                 topTab->attrib.y;

			/* now add the new x1 and y1 so we have a absolute value again,
			   also we don't want to stretch the texture... */
			if (box.extents.x2 * wScale < layer->texWidth)
				box.extents.x2 += box.extents.x1;
			else
				box.extents.x2 = box.extents.x1 + layer->texWidth;

			if (box.extents.y2 * hScale < layer->texHeight)
				box.extents.y2 += box.extents.y1;
			else
				box.extents.y2 = box.extents.y1 + layer->texHeight;

			matrix.x0 -= box.extents.x1 * matrix.xx;
			matrix.y0 -= box.extents.y1 * matrix.yy;
			topTab->vCount = topTab->indexCount = 0;

			addWindowGeometry (topTab, &matrix, 1, &box, clipRegion);

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

				matrixTranslate (&wTransform,
				                 WIN_X (topTab), WIN_Y (topTab), 0.0f);
				matrixScale (&wTransform, wScale, hScale, 1.0f);
				matrixTranslate (&wTransform,
				                 wAttrib->xTranslate / wScale - WIN_X (topTab),
				                 wAttrib->yTranslate / hScale - WIN_Y (topTab),
				                 0.0f);

				glPushMatrix ();
				glLoadMatrixf (wTransform.m);

				alpha = alpha * ((float)wAttrib->opacity / OPAQUE);

				initFragmentAttrib (&fragment, wAttrib);
				fragment.opacity = alpha;

				(*s->drawWindowTexture)(topTab, &layer->texture,
				                        &fragment, mask |
				                        PAINT_WINDOW_BLEND_MASK |
				                        PAINT_WINDOW_TRANSFORMED_MASK |
				                        PAINT_WINDOW_TRANSLUCENT_MASK);

				glPopMatrix ();
			}
		}
	}
}
Beispiel #26
0
/*
 * groupFiniScreen
 *
 */
static void
groupFiniScreen (CompPlugin *p,
                 CompScreen *s)
{
    GROUP_SCREEN (s);

    if (gs->groups)
    {
        GroupSelection *group, *nextGroup;

        for (group = gs->groups; group; )
        {
            if (group->tabBar)
            {
                GroupTabBarSlot *slot, *nextSlot;

                for (slot = group->tabBar->slots; slot; )
                {
                    if (slot->region)
                        XDestroyRegion (slot->region);

                    nextSlot = slot->next;
                    free (slot);
                    slot = nextSlot;
                }

                groupDestroyCairoLayer (s, group->tabBar->textLayer);
                groupDestroyCairoLayer (s, group->tabBar->bgLayer);
                groupDestroyCairoLayer (s, group->tabBar->selectionLayer);

                if (group->inputPrevention)
                    XDestroyWindow (display.display,
                                    group->inputPrevention);

                if (group->tabBar->region)
                    XDestroyRegion (group->tabBar->region);

                if (group->tabBar->timeoutHandle)
                    compRemoveTimeout (group->tabBar->timeoutHandle);

                free (group->tabBar);
            }

            nextGroup = group->next;
            free (group);
            group = nextGroup;
        }
    }

    if (gs->tmpSel.windows)
        free (gs->tmpSel.windows);

    if (gs->grabIndex)
        groupGrabScreen (s, ScreenGrabNone);

    if (gs->dragHoverTimeoutHandle)
        compRemoveTimeout (gs->dragHoverTimeoutHandle);

    if (gs->showDelayTimeoutHandle)
        compRemoveTimeout (gs->showDelayTimeoutHandle);

    if (gs->dequeueTimeoutHandle)
        compRemoveTimeout (gs->dequeueTimeoutHandle);

    if (gs->initialActionsTimeoutHandle)
        compRemoveTimeout (gs->initialActionsTimeoutHandle);

    freeWindowPrivateIndex (s, gs->windowPrivateIndex);

    matchFini (&gs->window_match);

    UNWRAP (gs, s, windowMoveNotify);
    UNWRAP (gs, s, windowResizeNotify);
    UNWRAP (gs, s, getOutputExtentsForWindow);
    UNWRAP (gs, s, preparePaintScreen);
    UNWRAP (gs, s, paintOutput);
    UNWRAP (gs, s, drawWindow);
    UNWRAP (gs, s, paintWindow);
    UNWRAP (gs, s, paintTransformedOutput);
    UNWRAP (gs, s, donePaintScreen);
    UNWRAP (gs, s, windowGrabNotify);
    UNWRAP (gs, s, windowUngrabNotify);
    UNWRAP (gs, s, damageWindowRect);
    UNWRAP (gs, s, windowStateChangeNotify);
    UNWRAP (gs, s, activateWindow);

    finiTexture (s, &gs->glowTexture);
    free (gs);
}
Beispiel #27
0
/*
 * groupPaintSelectionOutline
 *
 */
static void
groupPaintSelectionOutline (CompScreen              *s,
                            const ScreenPaintAttrib *sa,
                            const CompTransform     *transform,
                            CompOutput              *output,
                            Bool                    transformed)
{
	int x1, x2, y1, y2;

	GROUP_SCREEN (s);

	x1 = MIN (gs->x1, gs->x2);
	y1 = MIN (gs->y1, gs->y2);
	x2 = MAX (gs->x1, gs->x2);
	y2 = MAX (gs->y1, gs->y2);

	const BananaValue *
	option_fill_color = bananaGetOption (bananaIndex,
	                                     "fill_color",
	                                     s->screenNum);

	const BananaValue *
	option_line_color = bananaGetOption (bananaIndex,
	                                     "line_color",
	                                     s->screenNum);

	unsigned short fill_color[] = { 0, 0, 0, 0 };

	unsigned short line_color[] = { 0, 0, 0, 0 };

	stringToColor (option_fill_color->s, fill_color);
	stringToColor (option_line_color->s, line_color);

	if (gs->grabState == ScreenGrabSelect)
	{
		CompTransform sTransform = *transform;

		if (transformed)
		{
			(*s->applyScreenTransform)(s, sa, output, &sTransform);
			transformToScreenSpace (s, output, -sa->zTranslate, &sTransform);
		} else
			transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform);

		glPushMatrix ();
		glLoadMatrixf (sTransform.m);

		glDisableClientState (GL_TEXTURE_COORD_ARRAY);
		glEnable (GL_BLEND);

		glColor4usv (fill_color);
		glRecti (x1, y2, x2, y1);

		glColor4usv (line_color);
		glBegin (GL_LINE_LOOP);
		glVertex2i (x1, y1);
		glVertex2i (x2, y1);
		glVertex2i (x2, y2);
		glVertex2i (x1, y2);
		glEnd ();

		glColor4usv (defaultColor);
		glDisable (GL_BLEND);
		glEnableClientState (GL_TEXTURE_COORD_ARRAY);
		glPopMatrix ();
	}
}
Beispiel #28
0
/*
 * groupPaintOutput
 *
 */
Bool
groupPaintOutput (CompScreen              *s,
                  const ScreenPaintAttrib *sAttrib,
                  const CompTransform     *transform,
                  Region                  region,
                  CompOutput              *output,
                  unsigned int            mask)
{
	GroupSelection *group;
	Bool status;

	GROUP_SCREEN (s);
	GROUP_DISPLAY (&display);

	gs->painted = FALSE;
	gs->vpX = s->x;
	gs->vpY = s->y;

	if (gd->resizeInfo)
	{
		mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
	}
	else
	{
		for (group = gs->groups; group; group = group->next)
		{
			if (group->changeState != NoTabChange ||
			    group->tabbingState != NoTabbing)
			{
				mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
			}
			else if (group->tabBar && (group->tabBar->state != PaintOff))
			{
				mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
			}
		}
	}

	UNWRAP (gs, s, paintOutput);
	status = (*s->paintOutput)(s, sAttrib, transform, region, output, mask);
	WRAP (gs, s, paintOutput, groupPaintOutput);

	if (status && !gs->painted)
	{
		if ((gs->grabState == ScreenGrabTabDrag) && gs->draggedSlot)
		{
			CompTransform wTransform = *transform;
			PaintState state;

			GROUP_WINDOW (gs->draggedSlot->window);

			transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &wTransform);

			glPushMatrix ();
			glLoadMatrixf (wTransform.m);

			/* prevent tab bar drawing.. */
			state = gw->group->tabBar->state;
			gw->group->tabBar->state = PaintOff;
			groupPaintThumb (NULL, gs->draggedSlot, &wTransform, OPAQUE);
			gw->group->tabBar->state = state;

			glPopMatrix ();
		}
		else if (gs->grabState == ScreenGrabSelect)
		{
			groupPaintSelectionOutline (s, sAttrib, transform, output, FALSE);
		}
	}

	return status;
}
Beispiel #29
0
/*
 * groupDrawWindow
 *
 */
Bool
groupDrawWindow (CompWindow           *w,
                 const CompTransform  *transform,
                 const FragmentAttrib *attrib,
                 Region               region,
                 unsigned int         mask)
{
	Bool status;
	CompScreen *s = w->screen;

	GROUP_WINDOW (w);
	GROUP_SCREEN (s);

	if (gw->group && (gw->group->nWins > 1) && gw->glowQuads)
	{
		if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
			region = &infiniteRegion;

		if (region->numRects)
		{
			REGION box;
			int i;

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

			w->vCount = w->indexCount = 0;

			for (i = 0; i < NUM_GLOWQUADS; i++)
			{
				box.extents = gw->glowQuads[i].box;

				if (box.extents.x1 < box.extents.x2 &&
				    box.extents.y1 < box.extents.y2)
				{
					(*s->addWindowGeometry)(w, &gw->glowQuads[i].matrix,
					                        1, &box, region);
				}
			}

			if (w->vCount)
			{
				FragmentAttrib fAttrib = *attrib;
				GLushort average;
				GLushort color[3] = {gw->group->color[0],
					             gw->group->color[1],
					             gw->group->color[2]};

				/* Apply brightness to color. */
				color[0] *= (float)attrib->brightness / BRIGHT;
				color[1] *= (float)attrib->brightness / BRIGHT;
				color[2] *= (float)attrib->brightness / BRIGHT;

				/* Apply saturation to color. */
				average = (color[0] + color[1] + color[2]) / 3;
				color[0] = average + (color[0] - average) *
				           attrib->saturation / COLOR;
				color[1] = average + (color[1] - average) *
				           attrib->saturation / COLOR;
				color[2] = average + (color[2] - average) *
				           attrib->saturation / COLOR;

				fAttrib.opacity = OPAQUE;
				fAttrib.saturation = COLOR;
				fAttrib.brightness = BRIGHT;

				screenTexEnvMode (s, GL_MODULATE);
				glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glColor4us (color[0], color[1], color[2], attrib->opacity);

				/* we use PAINT_WINDOW_TRANSFORMED_MASK here to force
				   the usage of a good texture filter */
				(*s->drawWindowTexture)(w, &gs->glowTexture, &fAttrib,
				                        mask | PAINT_WINDOW_BLEND_MASK |
				                        PAINT_WINDOW_TRANSLUCENT_MASK |
				                        PAINT_WINDOW_TRANSFORMED_MASK);

				glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
				screenTexEnvMode (s, GL_REPLACE);
				glColor4usv (defaultColor);
			}
		}
	}

	UNWRAP (gs, s, drawWindow);
	status = (*s->drawWindow)(w, transform, attrib, region, mask);
	WRAP (gs, s, drawWindow, groupDrawWindow);

	return status;
}
Beispiel #30
0
/*
 * groupPaintWindow
 *
 */
Bool
groupPaintWindow (CompWindow              *w,
                  const WindowPaintAttrib *attrib,
                  const CompTransform     *transform,
                  Region                  region,
                  unsigned int            mask)
{
	Bool status;
	Bool doRotate, doTabbing, showTabbar;
	CompScreen *s = w->screen;

	GROUP_SCREEN (s);
	GROUP_WINDOW (w);

	if (gw->group)
	{
		GroupSelection *group = gw->group;

		doRotate = (group->changeState != NoTabChange) &&
		           HAS_TOP_WIN (group) && HAS_PREV_TOP_WIN (group) &&
		           (IS_TOP_TAB (w, group) || IS_PREV_TOP_TAB (w, group));

		doTabbing = (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION)) &&
		            !(IS_TOP_TAB (w, group) &&
		              (group->tabbingState == Tabbing));

		showTabbar = group->tabBar && (group->tabBar->state != PaintOff) &&
		             (((IS_TOP_TAB (w, group)) &&
		               ((group->changeState == NoTabChange) ||
		                (group->changeState == TabChangeNewIn))) ||
		              (IS_PREV_TOP_TAB (w, group) &&
		               (group->changeState == TabChangeOldOut)));
	}
	else
	{
		doRotate   = FALSE;
		doTabbing  = FALSE;
		showTabbar = FALSE;
	}

	if (gw->windowHideInfo)
		mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;

	if (gw->inSelection || gw->resizeGeometry || doRotate ||
	    doTabbing || showTabbar)
	{
		WindowPaintAttrib wAttrib = *attrib;
		CompTransform wTransform = *transform;
		float animProgress = 0.0f;
		int drawnPosX = 0, drawnPosY = 0;

		if (gw->inSelection)
		{
			const BananaValue *
			option_select_opacity = bananaGetOption (bananaIndex,
			                                         "select_opacity",
			                                         s->screenNum);

			const BananaValue *
			option_select_saturation = bananaGetOption (bananaIndex,
			                                            "select_saturation",
			                                            s->screenNum);

			const BananaValue *
			option_select_brightness = bananaGetOption (bananaIndex,
			                                            "select_brightness",
			                                            s->screenNum);

			wAttrib.opacity    = OPAQUE * option_select_opacity->i / 100;
			wAttrib.saturation = COLOR * option_select_saturation->i / 100;
			wAttrib.brightness = BRIGHT * option_select_brightness->i / 100;
		}

		if (doTabbing)
		{
			/* fade the window out */
			float progress;
			int distanceX, distanceY;
			float origDistance, distance;

			if (gw->animateState & FINISHED_ANIMATION)
			{
				drawnPosX = gw->destination.x;
				drawnPosY = gw->destination.y;
			}
			else
			{
				drawnPosX = gw->orgPos.x + gw->tx;
				drawnPosY = gw->orgPos.y + gw->ty;
			}

			distanceX = drawnPosX - gw->destination.x;
			distanceY = drawnPosY - gw->destination.y;
			distance = sqrt (pow (distanceX, 2) + pow (distanceY, 2));

			distanceX = (gw->orgPos.x - gw->destination.x);
			distanceY = (gw->orgPos.y - gw->destination.y);
			origDistance = sqrt (pow (distanceX, 2) + pow (distanceY, 2));

			if (!distanceX && !distanceY)
				progress = 1.0f;
			else
				progress = 1.0f - (distance / origDistance);

			animProgress = progress;

			progress = MAX (progress, 0.0f);
			if (gw->group->tabbingState == Tabbing)
				progress = 1.0f - progress;

			wAttrib.opacity = (float)wAttrib.opacity * progress;
		}

		if (doRotate)
		{
			const BananaValue *
			option_change_animation_time = bananaGetOption (bananaIndex,
			                                          "change_animation_time",
			                                          s->screenNum);

			float timeLeft = gw->group->changeAnimationTime;
			int animTime = option_change_animation_time->f * 500;

			if (gw->group->changeState == TabChangeOldOut)
				timeLeft += animTime;

			/* 0 at the beginning, 1 at the end */
			animProgress = 1 - (timeLeft / (2 * animTime));
		}

		if (gw->resizeGeometry)
		{
			int xOrigin, yOrigin;
			float xScale, yScale;
			BoxRec box;

			groupGetStretchRectangle (w, &box, &xScale, &yScale);

			xOrigin = w->attrib.x - w->input.left;
			yOrigin = w->attrib.y - w->input.top;

			matrixTranslate (&wTransform, xOrigin, yOrigin, 0.0f);
			matrixScale (&wTransform, xScale, yScale, 1.0f);
			matrixTranslate (&wTransform,
			                 (gw->resizeGeometry->x - w->attrib.x) /
			                 xScale - xOrigin,
			                 (gw->resizeGeometry->y - w->attrib.y) /
			                 yScale - yOrigin,
			                 0.0f);

			mask |= PAINT_WINDOW_TRANSFORMED_MASK;
		}
		else if (doRotate || doTabbing)
		{
			float animWidth, animHeight;
			float animScaleX, animScaleY;
			CompWindow *morphBase, *morphTarget;

			if (doTabbing)
			{
				if (gw->group->tabbingState == Tabbing)
				{
					morphBase   = w;
					morphTarget = TOP_TAB (gw->group);
				}
				else
				{
					morphTarget = w;
					if (HAS_TOP_WIN (gw->group))
						morphBase = TOP_TAB (gw->group);
					else
						morphBase = gw->group->lastTopTab;
				}
			}
			else
			{
				morphBase   = PREV_TOP_TAB (gw->group);
				morphTarget = TOP_TAB (gw->group);
			}

			animWidth = (1 - animProgress) * WIN_REAL_WIDTH (morphBase) +
			            animProgress * WIN_REAL_WIDTH (morphTarget);
			animHeight = (1 - animProgress) * WIN_REAL_HEIGHT (morphBase) +
			             animProgress * WIN_REAL_HEIGHT (morphTarget);

			animWidth = MAX (1.0f, animWidth);
			animHeight = MAX (1.0f, animHeight);
			animScaleX = animWidth / WIN_REAL_WIDTH (w);
			animScaleY = animHeight / WIN_REAL_HEIGHT (w);

			if (doRotate)
				matrixScale (&wTransform, 1.0f, 1.0f, 1.0f / s->width);

			matrixTranslate (&wTransform,
			                 WIN_REAL_X (w) + WIN_REAL_WIDTH (w) / 2.0f,
			                 WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) / 2.0f,
			                 0.0f);

			if (doRotate)
			{
				float rotateAngle = animProgress * 180.0f;
				if (IS_TOP_TAB (w, gw->group))
					rotateAngle += 180.0f;

				if (gw->group->changeAnimationDirection < 0)
					rotateAngle *= -1.0f;

				matrixRotate (&wTransform, rotateAngle, 0.0f, 1.0f, 0.0f);
			}

			if (doTabbing)
				matrixTranslate (&wTransform,
				                 drawnPosX - WIN_X (w),
				                 drawnPosY - WIN_Y (w), 0.0f);

			matrixScale (&wTransform, animScaleX, animScaleY, 1.0f);

			matrixTranslate (&wTransform,
			                 -(WIN_REAL_X (w) + WIN_REAL_WIDTH (w) / 2.0f),
			                 -(WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) / 2.0f),
			                 0.0f);

			mask |= PAINT_WINDOW_TRANSFORMED_MASK;
		}

		UNWRAP (gs, s, paintWindow);
		status = (*s->paintWindow)(w, &wAttrib, &wTransform, region, mask);

		if (showTabbar)
			groupPaintTabBar (gw->group, &wAttrib, &wTransform, mask, region);

		WRAP (gs, s, paintWindow, groupPaintWindow);
	}
	else
	{
		UNWRAP (gs, s, paintWindow);
		status = (*s->paintWindow)(w, attrib, transform, region, mask);
		WRAP (gs, s, paintWindow, groupPaintWindow);
	}

	return status;
}