Пример #1
0
/*  Handle the velocity */
static void
throwPreparePaintScreen (CompScreen *s,
			int        ms)
{
    CompWindow *w;
    THROW_SCREEN (s);

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

	if (tw->moving)
	    tw->time += ms;

        tw->xVelocity /= (1.0 + (throwGetFrictionConstant (s) / 100));
	tw->yVelocity /= (1.0 + (throwGetFrictionConstant (s) / 100));

	if (!tw->moving && (
	    (tw->xVelocity < 0.0f || tw->xVelocity > 0.0f) ||
	    (tw->yVelocity < 0.0f || tw->yVelocity > 0.0)))
	{
	    int dx = roundf(tw->xVelocity * (ms / 10) * (throwGetVelocityX (s) / 10));
	    int dy = roundf (tw->yVelocity * (ms / 10) * (throwGetVelocityY (s) / 10));

	    if (throwGetConstrainX (s))
	    {
		if ((WIN_REAL_X (w) + dx) < 0)
		    dx = 0;
		else if ((WIN_REAL_X (w) + WIN_REAL_W (w) + dx) > w->screen->width)
		    dx = 0;
	    }
	    if (throwGetConstrainY (s))
	    {
		if ((WIN_REAL_Y (w) + dy) < 0)
		    dy = 0;
		else if ((WIN_REAL_Y (w) + WIN_REAL_H (w) + dy) > w->screen->height)
		    dy = 0;
	    }

	    moveWindow (w, dx, dy, TRUE, FALSE);
	    syncWindowPosition (w);
	}

    }

    UNWRAP (ts, s, preparePaintScreen);
    (*s->preparePaintScreen) (s, ms);
    WRAP (ts, s, preparePaintScreen, throwPreparePaintScreen);
}
Пример #2
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;
}
Пример #3
0
void
groupComputeGlowQuads (CompWindow *w,
                       CompMatrix *matrix)
{
	BoxRec            *box;
	CompMatrix        *quadMatrix;
	int glowSize, glowOffset;
	int glowType;

	GROUP_WINDOW (w);

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

	if (option_glow->b && matrix)
	{
		if (!gw->glowQuads)
			gw->glowQuads = malloc (NUM_GLOWQUADS * sizeof (GlowQuad));
		if (!gw->glowQuads)
			return;
	}
	else
	{
		if (gw->glowQuads)
		{
			free (gw->glowQuads);
			gw->glowQuads = NULL;
		}
		return;
	}

	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);

	glowSize = option_glow_size->i;
	glowType = option_glow_type->i;
	glowOffset = (glowSize * gd->glowTextureProperties[glowType].glowOffset /
	              gd->glowTextureProperties[glowType].textureSize) + 1;

	/* Top left corner */
	box = &gw->glowQuads[GLOWQUAD_TOPLEFT].box;
	gw->glowQuads[GLOWQUAD_TOPLEFT].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_TOPLEFT].matrix;

	box->x1 = WIN_REAL_X (w) - glowSize + glowOffset;
	box->y1 = WIN_REAL_Y (w) - glowSize + glowOffset;
	box->x2 = WIN_REAL_X (w) + glowOffset;
	box->y2 = WIN_REAL_Y (w) + glowOffset;

	quadMatrix->xx = 1.0f / glowSize;
	quadMatrix->yy = -1.0f / glowSize;
	quadMatrix->x0 = -(box->x1 * quadMatrix->xx);
	quadMatrix->y0 = 1.0 -(box->y1 * quadMatrix->yy);

	box->x2 = MIN (WIN_REAL_X (w) + glowOffset,
	               WIN_REAL_X (w) + (WIN_REAL_WIDTH (w) / 2));
	box->y2 = MIN (WIN_REAL_Y (w) + glowOffset,
	               WIN_REAL_Y (w) + (WIN_REAL_HEIGHT (w) / 2));

	/* Top right corner */
	box = &gw->glowQuads[GLOWQUAD_TOPRIGHT].box;
	gw->glowQuads[GLOWQUAD_TOPRIGHT].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_TOPRIGHT].matrix;

	box->x1 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset;
	box->y1 = WIN_REAL_Y (w) - glowSize + glowOffset;
	box->x2 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) + glowSize - glowOffset;
	box->y2 = WIN_REAL_Y (w) + glowOffset;

	quadMatrix->xx = -1.0f / glowSize;
	quadMatrix->yy = -1.0f / glowSize;
	quadMatrix->x0 = 1.0 - (box->x1 * quadMatrix->xx);
	quadMatrix->y0 = 1.0 - (box->y1 * quadMatrix->yy);

	box->x1 = MAX (WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset,
	               WIN_REAL_X (w) + (WIN_REAL_WIDTH (w) / 2));
	box->y2 = MIN (WIN_REAL_Y (w) + glowOffset,
	               WIN_REAL_Y (w) + (WIN_REAL_HEIGHT (w) / 2));

	/* Bottom left corner */
	box = &gw->glowQuads[GLOWQUAD_BOTTOMLEFT].box;
	gw->glowQuads[GLOWQUAD_BOTTOMLEFT].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_BOTTOMLEFT].matrix;

	box->x1 = WIN_REAL_X (w) - glowSize + glowOffset;
	box->y1 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset;
	box->x2 = WIN_REAL_X (w) + glowOffset;
	box->y2 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) + glowSize - glowOffset;

	quadMatrix->xx = 1.0f / glowSize;
	quadMatrix->yy = 1.0f / glowSize;
	quadMatrix->x0 = -(box->x1 * quadMatrix->xx);
	quadMatrix->y0 = -(box->y1 * quadMatrix->yy);

	box->y1 = MAX (WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset,
	               WIN_REAL_Y (w) + (WIN_REAL_HEIGHT (w) / 2));
	box->x2 = MIN (WIN_REAL_X (w) + glowOffset,
	               WIN_REAL_X (w) + (WIN_REAL_WIDTH (w) / 2));

	/* Bottom right corner */
	box = &gw->glowQuads[GLOWQUAD_BOTTOMRIGHT].box;
	gw->glowQuads[GLOWQUAD_BOTTOMRIGHT].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_BOTTOMRIGHT].matrix;

	box->x1 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset;
	box->y1 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset;
	box->x2 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) + glowSize - glowOffset;
	box->y2 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) + glowSize - glowOffset;

	quadMatrix->xx = -1.0f / glowSize;
	quadMatrix->yy = 1.0f / glowSize;
	quadMatrix->x0 = 1.0 - (box->x1 * quadMatrix->xx);
	quadMatrix->y0 = -(box->y1 * quadMatrix->yy);

	box->x1 = MAX (WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset,
	               WIN_REAL_X (w) + (WIN_REAL_WIDTH (w) / 2));
	box->y1 = MAX (WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset,
	               WIN_REAL_Y (w) + (WIN_REAL_HEIGHT (w) / 2));

	/* Top edge */
	box = &gw->glowQuads[GLOWQUAD_TOP].box;
	gw->glowQuads[GLOWQUAD_TOP].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_TOP].matrix;

	box->x1 = WIN_REAL_X (w) + glowOffset;
	box->y1 = WIN_REAL_Y (w) - glowSize + glowOffset;
	box->x2 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset;
	box->y2 = WIN_REAL_Y (w) + glowOffset;

	quadMatrix->xx = 0.0f;
	quadMatrix->yy = -1.0f / glowSize;
	quadMatrix->x0 = 1.0;
	quadMatrix->y0 = 1.0 - (box->y1 * quadMatrix->yy);

	/* Bottom edge */
	box = &gw->glowQuads[GLOWQUAD_BOTTOM].box;
	gw->glowQuads[GLOWQUAD_BOTTOM].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_BOTTOM].matrix;

	box->x1 = WIN_REAL_X (w) + glowOffset;
	box->y1 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset;
	box->x2 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset;
	box->y2 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) + glowSize - glowOffset;

	quadMatrix->xx = 0.0f;
	quadMatrix->yy = 1.0f / glowSize;
	quadMatrix->x0 = 1.0;
	quadMatrix->y0 = -(box->y1 * quadMatrix->yy);

	/* Left edge */
	box = &gw->glowQuads[GLOWQUAD_LEFT].box;
	gw->glowQuads[GLOWQUAD_LEFT].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_LEFT].matrix;

	box->x1 = WIN_REAL_X (w) - glowSize + glowOffset;
	box->y1 = WIN_REAL_Y (w) + glowOffset;
	box->x2 = WIN_REAL_X (w) + glowOffset;
	box->y2 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset;

	quadMatrix->xx = 1.0f / glowSize;
	quadMatrix->yy = 0.0f;
	quadMatrix->x0 = -(box->x1 * quadMatrix->xx);
	quadMatrix->y0 = 0.0;

	/* Right edge */
	box = &gw->glowQuads[GLOWQUAD_RIGHT].box;
	gw->glowQuads[GLOWQUAD_RIGHT].matrix = *matrix;
	quadMatrix = &gw->glowQuads[GLOWQUAD_RIGHT].matrix;

	box->x1 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) - glowOffset;
	box->y1 = WIN_REAL_Y (w) + glowOffset;
	box->x2 = WIN_REAL_X (w) + WIN_REAL_WIDTH (w) + glowSize - glowOffset;
	box->y2 = WIN_REAL_Y (w) + WIN_REAL_HEIGHT (w) - glowOffset;

	quadMatrix->xx = -1.0f / glowSize;
	quadMatrix->yy = 0.0f;
	quadMatrix->x0 = 1.0 - (box->x1 * quadMatrix->xx);
	quadMatrix->y0 = 0.0;
}
Пример #4
0
/* Handle Rotation */
static void FWHandleRotateMotionEvent (CompWindow *w, float dx, float dy, int x, int y)
{
    FREEWINS_WINDOW (w);
    FREEWINS_DISPLAY (w->screen->display);

    x -= 100;
    y -= 100;

    int oldX = lastPointerX - 100;
    int oldY = lastPointerY - 100;

    float midX = WIN_REAL_X(w) + WIN_REAL_W(w)/2.0;
    float midY = WIN_REAL_Y(w) + WIN_REAL_H(w)/2.0;

    float angX;
    float angY;
    float angZ;

    /* Save the current angles so we can work with them */
    if (freewinsGetSnap (w->screen) || fwd->snap)
    {
         angX = fww->transform.unsnapAngX;
         angY = fww->transform.unsnapAngY;
         angZ = fww->transform.unsnapAngZ;
    }
    else
    {
         angX = fww->animate.destAngX;
         angY = fww->animate.destAngY;
         angZ = fww->animate.destAngZ;
    }

  /* Check for Y axis clicking (Top / Bottom) */
    if (pointerY > midY)
    {
	/* Check for X axis clicking (Left / Right) */
	if (pointerX > midX)
	    fww->corner = CornerBottomRight;
	else if (pointerX < midX)
	    fww->corner = CornerBottomLeft;
    }
    else if (pointerY < midY)
    {
	/* Check for X axis clicking (Left / Right) */
	if (pointerX > midX)
	    fww->corner = CornerTopRight;
	else if (pointerX < midX)
	    fww->corner = CornerTopLeft;
    }

    float percentFromXAxis = 0.0, percentFromYAxis = 0.0;

    if (freewinsGetZAxisRotation (w->screen) == ZAxisRotationInterchangable)
    {

        /* Trackball rotation was too hard to implement. If anyone can implement it,
         * please come forward so I can replace this hacky solution to the problem.
         * Anyways, what happens here, is that we determine how far away we are from
         * each axis (y and x). The further we are away from the y axis, the more
         * up / down movements become Z axis movements and the further we are away from
         * the x-axis, the more left / right movements become z rotations. */

        /* We determine this by taking a percentage of how far away the cursor is from
         * each axis. We divide the 3D rotation by this percentage ( and divide by the
         * percentage squared in order to ensure that rotation is not too violent when we
         * are quite close to the origin. We multiply the 2D rotation by this percentage also
         * so we are essentially rotating in 3D and 2D all the time, but this is only really
         * noticeable when you move the cursor over to the extremes of a window. In every case
         * percentage can be defined as decimal-percentage (i.e 0.036 == 3.6%). Like I mentioned
         * earlier, if you can replace this with trackball rotation, please come forward! */

        float halfWidth = WIN_REAL_W (w) / 2.0f;
        float halfHeight = WIN_REAL_H (w) / 2.0f;

        float distFromXAxis = fabs (fww->iMidX - pointerX);
        float distFromYAxis = fabs (fww->iMidY - pointerY);

        percentFromXAxis = distFromXAxis / halfWidth;
        percentFromYAxis = distFromYAxis / halfHeight;

    }
    else if (freewinsGetZAxisRotation (w->screen) == ZAxisRotationSwitch)
        FWDetermineZAxisClick (w, pointerX, pointerY, TRUE);

    dx *= 360;
    dy *= 360;

    /* Handle inversion */

    Bool can2D = fww->can2D, can3D = fww->can3D;

    if (fwd->invert && freewinsGetZAxisRotation (w->screen) != ZAxisRotationInterchangable)
    {
        can2D = !fww->can2D;
        can3D = !fww->can3D;
    }

    if(can2D)
    {

       float zX = 1.0f;
       float zY = 1.0f;

       if (freewinsGetZAxisRotation (w->screen) == ZAxisRotationInterchangable)
       {
            zX = percentFromXAxis;
            zY = percentFromYAxis;
       }

       zX = zX > 1.0f ? 1.0f : zX;
       zY = zY > 1.0f ? 1.0f : zY;

       switch (fww->corner)
       {
            case CornerTopRight:

                if ((x) < oldX)
                angZ -= dx * zX;
                else if ((x) > oldX)
                angZ += dx * zX;


                if ((y) < oldY)
                angZ -= dy * zY;
                else if ((y) > oldY)
                angZ += dy * zY;

                break;

            case CornerTopLeft:

                if ((x) < oldX)
                angZ -= dx * zX;
                else if ((x) > oldX)
                angZ += dx * zX;


                if ((y) < oldY)
                angZ += dy * zY;
                else if ((y) > oldY)
                angZ -= dy * zY;

                break;

            case CornerBottomLeft:

                if ((x) < oldX)
                angZ += dx * zX;
                else if ((x) > oldX)
                angZ -= dx * zX;


                if ((y) < oldY)
                angZ += dy * zY;
                else if ((y) > oldY)
                angZ -= dy * zY;

                break;

            case CornerBottomRight:

                if ((x) < oldX)
                angZ += dx * zX;
                else if ((x) > oldX)
                angZ -= dx * zX;


                if ((y) < oldY)
                angZ -= dy * zY;
                else if ((y) > oldY)
                angZ += dy * zY;
                break;
        }
    }

    if (can3D)
    {
        if (freewinsGetZAxisRotation (w->screen) != ZAxisRotationInterchangable)
        {
            percentFromXAxis = 0.0f;
            percentFromYAxis = 0.0f;
        }


    angX -= dy * (1 - percentFromXAxis);
    angY += dx * (1 - percentFromYAxis);
    }

    /* Restore angles */

    if (freewinsGetSnap (w->screen) || fwd->snap)
    {
         fww->transform.unsnapAngX = angX;
         fww->transform.unsnapAngY = angY;
         fww->transform.unsnapAngZ = angZ;
    }
    else
    {
         fww->animate.destAngX = angX;
         fww->animate.destAngY = angY;
         fww->animate.destAngZ = angZ;
    }

    FWHandleSnap(w);
}