static int organicCompareWindows(const void *elem1, const void *elem2) { CompWindow *w1 = *((CompWindow **) elem1); CompWindow *w2 = *((CompWindow **) elem2); return (WIN_X(w1) + WIN_Y(w1)) - (WIN_X(w2) + WIN_Y(w2)); }
/* * 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 ExpandAnim::applyTransform () { GLMatrix *transform = &mTransform; float defaultXScale = 0.3f; float forwardProgress; float expandProgress; const float expandPhaseEnd = 0.5f; forwardProgress = getProgress (); if ((1 - forwardProgress) < expandPhaseEnd) expandProgress = (1 - forwardProgress) / expandPhaseEnd; else expandProgress = 1.0f; // animation movement transform->translate (WIN_X (mWindow) + WIN_W (mWindow) / 2.0f, WIN_Y (mWindow) + WIN_H (mWindow) / 2.0f, 0.0f); transform->scale (defaultXScale + (1.0f - defaultXScale) * expandProgress, (1 - forwardProgress), 0.0f); transform->translate (-(WIN_X (mWindow) + WIN_W (mWindow) / 2.0f), -(WIN_Y (mWindow) + WIN_H (mWindow) / 2.0f), 0.0f); }
Bool fxSidekickInit (CompWindow *w) { ANIM_WINDOW (w); const BananaValue * option_sidekick_num_rotations = bananaGetOption (bananaIndex, "sidekick_num_rotations", w->screen->screenNum); // determine number of rotations randomly in [0.9, 1.1] range aw->numZoomRotations = option_sidekick_num_rotations->f * (1.0f + 0.2f * rand () / RAND_MAX - 0.1f); float winCenterX = WIN_X (w) + WIN_W (w) / 2.0; float iconCenterX = aw->com.icon.x + aw->com.icon.width / 2.0; // if window is to the right of icon, rotate clockwise instead // to make rotation look more pleasant if (winCenterX > iconCenterX) aw->numZoomRotations *= -1; return fxZoomInit (w); }
static void fxDodgeProcessSubject (CompWindow *wCur, Region wRegion, Region dodgeRegion, Bool alwaysInclude) { XRectangle rect; rect.x = WIN_X(wCur); rect.y = WIN_Y(wCur); rect.width = WIN_W(wCur); rect.height = WIN_H(wCur); Region wCurRegion = XCreateRegion(); if (!wCurRegion) return; XUnionRectWithRegion(&rect, &emptyRegion, wCurRegion); if (!alwaysInclude) { Region intersectionRegion = XCreateRegion(); if (intersectionRegion) { XIntersectRegion(wRegion, wCurRegion, intersectionRegion); if (!XEmptyRegion(intersectionRegion)) XUnionRegion(dodgeRegion, wCurRegion, dodgeRegion); XDestroyRegion (intersectionRegion); } } else XUnionRegion(dodgeRegion, wCurRegion, dodgeRegion); XDestroyRegion (wCurRegion); }
static void getZoomCenterScaleFull (CompWindow *w, Point *pCurCenter, Point *pCurScale, Point *pWinCenter, Point *pIconCenter, float *pRotateProgress) { ANIM_WINDOW(w); Point winCenter = {(WIN_X(w) + WIN_W(w) / 2.0), (WIN_Y(w) + WIN_H(w) / 2.0)}; Point iconCenter = {aw->com.icon.x + aw->com.icon.width / 2.0, aw->com.icon.y + aw->com.icon.height / 2.0}; Point winSize = {WIN_W(w), WIN_H(w)}; winSize.x = (winSize.x == 0 ? 1 : winSize.x); winSize.y = (winSize.y == 0 ? 1 : winSize.y); float scaleProgress; float moveProgress; float rotateProgress = 0; if (aw->com.curAnimEffect == AnimEffectSidekick) { fxZoomAnimProgress (w, &moveProgress, &scaleProgress, FALSE); rotateProgress = moveProgress; } else if (aw->com.curAnimEffect == AnimEffectZoom) { fxZoomAnimProgress (w, &moveProgress, &scaleProgress, FALSE); } else { // other effects use this for minimization fxZoomAnimProgress (w, &moveProgress, &scaleProgress, TRUE); } Point curCenter = {(1 - moveProgress) * winCenter.x + moveProgress * iconCenter.x, (1 - moveProgress) * winCenter.y + moveProgress * iconCenter.y}; Point curScale = {((1 - scaleProgress) * winSize.x + scaleProgress * aw->com.icon.width) / winSize.x, ((1 - scaleProgress) * winSize.y + scaleProgress * aw->com.icon.height) / winSize.y}; // Copy calculated variables if (pCurCenter) *pCurCenter = curCenter; if (pCurScale) *pCurScale = curScale; if (pWinCenter) *pWinCenter = winCenter; if (pIconCenter) *pIconCenter = iconCenter; if (pRotateProgress) *pRotateProgress = rotateProgress; }
Bool fxZoomInit (CompWindow * w) { ANIM_WINDOW(w); if ((aw->com.curAnimEffect == AnimEffectSidekick && (animGetI (w, ANIM_SCREEN_OPTION_SIDEKICK_ZOOM_FROM_CENTER) == ZoomFromCenterOn || ((aw->com.curWindowEvent == WindowEventMinimize || aw->com.curWindowEvent == WindowEventUnminimize) && animGetI (w, ANIM_SCREEN_OPTION_SIDEKICK_ZOOM_FROM_CENTER) == ZoomFromCenterMin) || ((aw->com.curWindowEvent == WindowEventOpen || aw->com.curWindowEvent == WindowEventClose) && animGetI (w, ANIM_SCREEN_OPTION_SIDEKICK_ZOOM_FROM_CENTER) == ZoomFromCenterCreate))) || (aw->com.curAnimEffect == AnimEffectZoom && (animGetI (w, ANIM_SCREEN_OPTION_ZOOM_FROM_CENTER) == ZoomFromCenterOn || ((aw->com.curWindowEvent == WindowEventMinimize || aw->com.curWindowEvent == WindowEventUnminimize) && animGetI (w, ANIM_SCREEN_OPTION_ZOOM_FROM_CENTER) == ZoomFromCenterMin) || ((aw->com.curWindowEvent == WindowEventOpen || aw->com.curWindowEvent == WindowEventClose) && animGetI (w, ANIM_SCREEN_OPTION_ZOOM_FROM_CENTER) == ZoomFromCenterCreate)))) { aw->com.icon.x = WIN_X(w) + WIN_W(w) / 2 - aw->com.icon.width / 2; aw->com.icon.y = WIN_Y(w) + WIN_H(w) / 2 - aw->com.icon.height / 2; } // allow extra time for spring damping / deceleration if ((aw->com.curWindowEvent == WindowEventUnminimize || aw->com.curWindowEvent == WindowEventOpen) && fxZoomGetSpringiness (w) > 1e-4) { aw->com.animTotalTime /= SPRINGY_ZOOM_PERCEIVED_T; } else if ((aw->com.curAnimEffect == AnimEffectZoom || aw->com.curAnimEffect == AnimEffectSidekick) && (aw->com.curWindowEvent == WindowEventOpen || aw->com.curWindowEvent == WindowEventClose)) { aw->com.animTotalTime /= NONSPRINGY_ZOOM_PERCEIVED_T; } else { aw->com.animTotalTime /= ZOOM_PERCEIVED_T; } aw->com.animRemainingTime = aw->com.animTotalTime; aw->com.usingTransform = TRUE; return defaultAnimInit (w); }
static void inline fxRollUpModelStepObject(CompWindow * w, Model * model, Object * object, float forwardProgress, Bool fixedInterior) { ANIM_WINDOW(w); float origx = WIN_X(w) + WIN_W(w) * object->gridPosition.x; if (aw->com.curWindowEvent == WindowEventShade || aw->com.curWindowEvent == WindowEventUnshade) { // Execute shade mode // find position in window contents // (window contents correspond to 0.0-1.0 range) float relPosInWinContents = (object->gridPosition.y * WIN_H(w) - model->topHeight) / w->height; if (object->gridPosition.y == 0) { object->position.x = origx; object->position.y = WIN_Y(w); } else if (object->gridPosition.y == 1) { object->position.x = origx; object->position.y = (1 - forwardProgress) * (WIN_Y(w) + WIN_H(w) * object->gridPosition.y) + forwardProgress * (WIN_Y(w) + model->topHeight + model->bottomHeight); } else { object->position.x = origx; if (relPosInWinContents > forwardProgress) { object->position.y = (1 - forwardProgress) * (WIN_Y(w) + WIN_H(w) * object->gridPosition.y) + forwardProgress * (WIN_Y(w) + model->topHeight); if (fixedInterior) object->offsetTexCoordForQuadBefore.y = -forwardProgress * w->height; } else { object->position.y = WIN_Y(w) + model->topHeight; if (!fixedInterior) object->offsetTexCoordForQuadAfter.y = (forwardProgress - relPosInWinContents) * w->height; } } } }
static void applyGlideTransform(CompWindow *w, CompTransform *transform) { ANIM_SCREEN(w->screen); ANIM_WINDOW(w); float finalDistFac; float finalRotAng; float thickness; fxGlideGetParams(as, aw, &finalDistFac, &finalRotAng, &thickness); float forwardProgress; if (fxGlideZoomToTaskBar(as, aw)) { float dummy; fxZoomAnimProgress(as, aw, &forwardProgress, &dummy, TRUE); } else forwardProgress = fxGlideAnimProgress(aw); float finalz = finalDistFac * 0.8 * DEFAULT_Z_CAMERA * w->screen->width; Vector3d rotAxis = {1, 0, 0}; Point3d rotAxisOffset = {WIN_X(w) + WIN_W(w) / 2.0f, WIN_Y(w) + WIN_H(w) / 2.0f, 0}; Point3d translation = {0, 0, finalz * forwardProgress}; float rotAngle = finalRotAng * forwardProgress; aw->glideModRotAngle = fmodf(rotAngle + 720, 360.0f); // put back to window position matrixTranslate (transform, rotAxisOffset.x, rotAxisOffset.y, 0); resetAndPerspectiveDistortOnZ (transform, -1.0 / w->screen->width); // animation movement matrixTranslate (transform, translation.x, translation.y, translation.z); // animation rotation matrixRotate (transform, rotAngle, rotAxis.x, rotAxis.y, rotAxis.z); // intentional scaling of z by 0 to prevent weird opacity results and // flashing that happen when z coords are between 0 and 1 (bug in ecomp?) matrixScale (transform, 1.0f, 1.0f, 0.0f); // place window rotation axis at origin matrixTranslate (transform, -rotAxisOffset.x, -rotAxisOffset.y, 0); }
Bool fxSidekickInit (CompWindow * w) { ANIM_WINDOW(w); // determine number of rotations randomly in [0.9, 1.1] range aw->numZoomRotations = animGetF (w, ANIM_SCREEN_OPTION_SIDEKICK_NUM_ROTATIONS) * (1.0f + 0.2f * rand() / RAND_MAX - 0.1f); float winCenterX = WIN_X(w) + WIN_W(w) / 2.0; float iconCenterX = aw->com.icon.x + aw->com.icon.width / 2.0; // if window is to the right of icon, rotate clockwise instead // to make rotation look more pleasant if (winCenterX > iconCenterX) aw->numZoomRotations *= -1; return fxZoomInit (w); }
/* * Call the previous function for each of the 4 sides of the window */ static void snapMoveCheckEdges(CompWindow * w) { snapMoveCheckNearestEdge(w, WIN_X(w), WIN_Y(w), WIN_Y(w) + WIN_H(w), TRUE, RightEdge, HorizontalSnap); snapMoveCheckNearestEdge(w, WIN_X(w) + WIN_W(w), WIN_Y(w), WIN_Y(w) + WIN_H(w), FALSE, LeftEdge, HorizontalSnap); snapMoveCheckNearestEdge(w, WIN_Y(w), WIN_X(w), WIN_X(w) + WIN_W(w), TRUE, BottomEdge, VerticalSnap); snapMoveCheckNearestEdge(w, WIN_Y(w) + WIN_H(w), WIN_X(w), WIN_X(w) + WIN_W(w), FALSE, TopEdge, VerticalSnap); }
Bool fxZoomInit (CompWindow *w) { ANIM_WINDOW (w); const BananaValue * option_sidekick_zoom_from_center = bananaGetOption (bananaIndex, "sidekick_zoom_from_center", w->screen->screenNum); if ((aw->com.curAnimEffect == AnimEffectSidekick && (option_sidekick_zoom_from_center->i == 3 || ((aw->com.curWindowEvent == WindowEventMinimize || aw->com.curWindowEvent == WindowEventUnminimize) && option_sidekick_zoom_from_center->i == 1) || ((aw->com.curWindowEvent == WindowEventOpen || aw->com.curWindowEvent == WindowEventClose) && option_sidekick_zoom_from_center->i == 2))) || (aw->com.curAnimEffect == AnimEffectZoom && (option_sidekick_zoom_from_center->i == 3 || ((aw->com.curWindowEvent == WindowEventMinimize || aw->com.curWindowEvent == WindowEventUnminimize) && option_sidekick_zoom_from_center->i == 1) || ((aw->com.curWindowEvent == WindowEventOpen || aw->com.curWindowEvent == WindowEventClose) && option_sidekick_zoom_from_center->i == 2)))) { aw->com.icon.x = WIN_X (w) + WIN_W (w) / 2 - aw->com.icon.width / 2; aw->com.icon.y = WIN_Y (w) + WIN_H (w) / 2 - aw->com.icon.height / 2; } // allow extra time for spring damping / deceleration if ((aw->com.curWindowEvent == WindowEventUnminimize || aw->com.curWindowEvent == WindowEventOpen) && fxZoomGetSpringiness (w) > 1e-4) { aw->com.animTotalTime /= SPRINGY_ZOOM_PERCEIVED_T; } else if ((aw->com.curAnimEffect == AnimEffectZoom || aw->com.curAnimEffect == AnimEffectSidekick) && (aw->com.curWindowEvent == WindowEventOpen || aw->com.curWindowEvent == WindowEventClose)) { aw->com.animTotalTime /= NONSPRINGY_ZOOM_PERCEIVED_T; } else { aw->com.animTotalTime /= ZOOM_PERCEIVED_T; } aw->com.animRemainingTime = aw->com.animTotalTime; aw->com.usingTransform = TRUE; return defaultAnimInit (w); }
static unsigned int groupUpdateResizeRectangle (CompWindow *w, XRectangle *masterGeometry, Bool damage) { XRectangle newGeometry; unsigned int mask = 0; int newWidth, newHeight; int widthDiff, heightDiff; GROUP_WINDOW (w); GROUP_DISPLAY (&display); if (!gw->resizeGeometry || !gd->resizeInfo) return 0; newGeometry.x = WIN_X (w) + (masterGeometry->x - gd->resizeInfo->origGeometry.x); newGeometry.y = WIN_Y (w) + (masterGeometry->y - gd->resizeInfo->origGeometry.y); widthDiff = masterGeometry->width - gd->resizeInfo->origGeometry.width; newGeometry.width = MAX (1, WIN_WIDTH (w) + widthDiff); heightDiff = masterGeometry->height - gd->resizeInfo->origGeometry.height; newGeometry.height = MAX (1, WIN_HEIGHT (w) + heightDiff); if (constrainNewWindowSize (w, newGeometry.width, newGeometry.height, &newWidth, &newHeight)) { newGeometry.width = newWidth; newGeometry.height = newHeight; } if (damage) { if (memcmp (&newGeometry, gw->resizeGeometry, sizeof (newGeometry)) != 0) { addWindowDamage (w); } } if (newGeometry.x != gw->resizeGeometry->x) { gw->resizeGeometry->x = newGeometry.x; mask |= CWX; } if (newGeometry.y != gw->resizeGeometry->y) { gw->resizeGeometry->y = newGeometry.y; mask |= CWY; } if (newGeometry.width != gw->resizeGeometry->width) { gw->resizeGeometry->width = newGeometry.width; mask |= CWWidth; } if (newGeometry.height != gw->resizeGeometry->height) { gw->resizeGeometry->height = newGeometry.height; mask |= CWHeight; } return mask; }
void drawParticles(CompScreen *s, CompWindow *w, ParticleSystem *ps) { glPushMatrix(); if (w) glTranslated(WIN_X(w) - ps->x, WIN_Y(w) - ps->y, 0); glEnable(GL_BLEND); if (ps->tex) { glBindTexture(GL_TEXTURE_2D, ps->tex); glEnable(GL_TEXTURE_2D); } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); int i; Particle *part; /* Check that the cache is big enough */ if (ps->numParticles > ps->vertex_cache_count) { ps->vertices_cache = realloc(ps->vertices_cache, ps->numParticles * 4 * 3 * sizeof(GLfloat)); ps->vertex_cache_count = ps->numParticles; } if (ps->numParticles > ps->coords_cache_count) { ps->coords_cache = realloc(ps->coords_cache, ps->numParticles * 4 * 2 * sizeof(GLfloat)); ps->coords_cache_count = ps->numParticles; } if (ps->numParticles > ps->color_cache_count) { ps->colors_cache = realloc(ps->colors_cache, ps->numParticles * 4 * 4 * sizeof(GLfloat)); ps->color_cache_count = ps->numParticles; } if (ps->darken > 0) { if (ps->dcolors_cache_count < ps->numParticles) { ps->dcolors_cache = realloc(ps->dcolors_cache, ps->numParticles * 4 * 4 * sizeof(GLfloat)); ps->dcolors_cache_count = ps->numParticles; } } GLfloat *dcolors = ps->dcolors_cache; GLfloat *vertices = ps->vertices_cache; GLfloat *coords = ps->coords_cache; GLfloat *colors = ps->colors_cache; int numActive = 0; for (i = 0; i < ps->numParticles; i++) { part = &ps->particles[i]; if (part->life > 0.0f) { numActive += 4; float w = part->width / 2; float h = part->height / 2; w += (w * part->w_mod) * part->life; h += (h * part->h_mod) * part->life; vertices[0] = part->x - w; vertices[1] = part->y - h; vertices[2] = part->z; vertices[3] = part->x - w; vertices[4] = part->y + h; vertices[5] = part->z; vertices[6] = part->x + w; vertices[7] = part->y + h; vertices[8] = part->z; vertices[9] = part->x + w; vertices[10] = part->y - h; vertices[11] = part->z; vertices += 12; coords[0] = 0.0; coords[1] = 0.0; coords[2] = 0.0; coords[3] = 1.0; coords[4] = 1.0; coords[5] = 1.0; coords[6] = 1.0; coords[7] = 0.0; coords += 8; colors[0] = part->r; colors[1] = part->g; colors[2] = part->b; colors[3] = part->life * part->a; colors[4] = part->r; colors[5] = part->g; colors[6] = part->b; colors[7] = part->life * part->a; colors[8] = part->r; colors[9] = part->g; colors[10] = part->b; colors[11] = part->life * part->a; colors[12] = part->r; colors[13] = part->g; colors[14] = part->b; colors[15] = part->life * part->a; colors += 16; if (ps->darken > 0) { dcolors[0] = part->r; dcolors[1] = part->g; dcolors[2] = part->b; dcolors[3] = part->life * part->a * ps->darken; dcolors[4] = part->r; dcolors[5] = part->g; dcolors[6] = part->b; dcolors[7] = part->life * part->a * ps->darken; dcolors[8] = part->r; dcolors[9] = part->g; dcolors[10] = part->b; dcolors[11] = part->life * part->a * ps->darken; dcolors[12] = part->r; dcolors[13] = part->g; dcolors[14] = part->b; dcolors[15] = part->life * part->a * ps->darken; dcolors += 16; } } } glEnableClientState(GL_COLOR_ARRAY); glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), ps->coords_cache); glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), ps->vertices_cache); // darken the background if (ps->darken > 0) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), ps->dcolors_cache); glDrawArrays(GL_QUADS, 0, numActive); } // draw particles glBlendFunc(GL_SRC_ALPHA, ps->blendMode); glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), ps->colors_cache); glDrawArrays(GL_QUADS, 0, numActive); glDisableClientState(GL_COLOR_ARRAY); glPopMatrix(); glColor4usv(defaultColor); screenTexEnvMode(s, GL_REPLACE); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); }
/* * 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; }
/* * groupPaintThumb - taken from switcher and modified for tab bar * */ static void groupPaintThumb (GroupSelection *group, GroupTabBarSlot *slot, const CompTransform *transform, int targetOpacity) { CompWindow *w = slot->window; CompScreen *s = w->screen; AddWindowGeometryProc oldAddWindowGeometry; WindowPaintAttrib wAttrib = w->paint; int tw, th; tw = slot->region->extents.x2 - slot->region->extents.x1; th = slot->region->extents.y2 - slot->region->extents.y1; /* Wrap drawWindowGeometry to make sure the general drawWindowGeometry function is used */ oldAddWindowGeometry = s->addWindowGeometry; s->addWindowGeometry = addWindowGeometry; const BananaValue * option_fade_time = bananaGetOption (bananaIndex, "fade_time", s->screenNum); /* animate fade */ if (group && group->tabBar->state == PaintFadeIn) { wAttrib.opacity -= wAttrib.opacity * group->tabBar->animationTime / (option_fade_time->f * 1000); } else if (group && group->tabBar->state == PaintFadeOut) { wAttrib.opacity = wAttrib.opacity * group->tabBar->animationTime / (option_fade_time->f * 1000); } wAttrib.opacity = wAttrib.opacity * targetOpacity / OPAQUE; if (w->mapNum) { FragmentAttrib fragment; CompTransform wTransform = *transform; int width, height; int vx, vy; width = w->width + w->output.left + w->output.right; height = w->height + w->output.top + w->output.bottom; if (width > tw) wAttrib.xScale = (float) tw / width; else wAttrib.xScale = 1.0f; if (height > th) wAttrib.yScale = (float) tw / height; else wAttrib.yScale = 1.0f; if (wAttrib.xScale < wAttrib.yScale) wAttrib.yScale = wAttrib.xScale; else wAttrib.xScale = wAttrib.yScale; /* FIXME: do some more work on the highlight on hover feature // Highlight on hover if (group && group->tabBar && group->tabBar->hoveredSlot == slot) { wAttrib.saturation = 0; wAttrib.brightness /= 1.25f; }*/ groupGetDrawOffsetForSlot (slot, &vx, &vy); wAttrib.xTranslate = (slot->region->extents.x1 + slot->region->extents.x2) / 2 + vx; wAttrib.yTranslate = slot->region->extents.y1 + vy; initFragmentAttrib (&fragment, &wAttrib); matrixTranslate (&wTransform, wAttrib.xTranslate, wAttrib.yTranslate, 0.0f); matrixScale (&wTransform, wAttrib.xScale, wAttrib.yScale, 1.0f); matrixTranslate (&wTransform, -(WIN_X (w) + WIN_WIDTH (w) / 2), -(WIN_Y (w) - w->output.top), 0.0f); glPushMatrix (); glLoadMatrixf (wTransform.m); (*s->drawWindow)(w, &wTransform, &fragment, &infiniteRegion, PAINT_WINDOW_TRANSFORMED_MASK | PAINT_WINDOW_TRANSLUCENT_MASK); glPopMatrix (); } s->addWindowGeometry = oldAddWindowGeometry; }
/* * 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 (); } } } }
// Returns FALSE if the subject is destroyed or if there was an error when // calculating the dodge box static Bool fxDodgeFindDodgeBox (CompWindow *w, XRectangle *dodgeBox) { ANIM_SCREEN(w->screen); ANIM_WINDOW(w); if (!aw->dodgeSubjectWin) // if the subject is destroyed return FALSE; // Find the box to be dodged, it can contain multiple windows // when there are dialog/utility windows of subject windows // (stacked in the moreToBePaintedNext chain) // Then this would be a bounding box of the subject windows // intersecting with dodger. Region wRegion = XCreateRegion(); if (!wRegion) return FALSE; Region dodgeRegion = XCreateRegion(); if (!dodgeRegion) { XDestroyRegion (wRegion); return FALSE; } XRectangle rect; rect.x = WIN_X(w); rect.y = WIN_Y(w); rect.width = WIN_W(w); rect.height = WIN_H(w); int dodgeMaxAmount = (int)aw->dodgeMaxAmount; // to compute if subject(s) intersect with dodger w, // enlarge dodger window's box so that it encloses all of the covered // region during dodge movement. This corrects the animation when // there are >1 subjects (a window with its dialog/utility windows). switch (aw->dodgeDirection) { case 0: rect.y += dodgeMaxAmount; rect.height -= dodgeMaxAmount; break; case 1: rect.height += dodgeMaxAmount; break; case 2: rect.x += dodgeMaxAmount; rect.width -= dodgeMaxAmount; break; case 3: rect.width += dodgeMaxAmount; break; } XUnionRectWithRegion(&rect, &emptyRegion, wRegion); AnimWindow *awCur; CompWindow *wCur = aw->dodgeSubjectWin; for (; wCur; wCur = awCur->moreToBePaintedNext) { fxDodgeProcessSubject(wCur, wRegion, dodgeRegion, wCur == aw->dodgeSubjectWin); awCur = GET_ANIM_WINDOW(wCur, as); if (!awCur) break; } AnimWindow *awSubj = GET_ANIM_WINDOW(aw->dodgeSubjectWin, as); wCur = awSubj->moreToBePaintedPrev; for (; wCur; wCur = awCur->moreToBePaintedPrev) { fxDodgeProcessSubject(wCur, wRegion, dodgeRegion, FALSE); awCur = GET_ANIM_WINDOW(wCur, as); if (!awCur) break; } XClipBox(dodgeRegion, dodgeBox); XDestroyRegion (wRegion); XDestroyRegion (dodgeRegion); return TRUE; }
void groupWindowGrabNotify (CompWindow *w, int x, int y, unsigned int state, unsigned int mask) { CompScreen *s = w->screen; GROUP_SCREEN (s); GROUP_DISPLAY (&display); GROUP_WINDOW (w); if (gw->group && !gd->ignoreMode && !gs->queued) { Bool doResizeAll; int i; const BananaValue * option_resize_all = bananaGetOption (bananaIndex, "resize_all", s->screenNum); doResizeAll = option_resize_all->b && (mask & CompWindowGrabResizeMask); if (gw->group->tabBar) groupTabSetVisibility (gw->group, FALSE, 0); for (i = 0; i < gw->group->nWins; i++) { CompWindow *cw = gw->group->windows[i]; if (!cw) continue; if (cw->id != w->id) { GroupWindow *gcw = GET_GROUP_WINDOW (cw, gs); groupEnqueueGrabNotify (cw, x, y, state, mask); if (doResizeAll && !(cw->state & MAXIMIZE_STATE)) { if (!gcw->resizeGeometry) gcw->resizeGeometry = malloc (sizeof (XRectangle)); if (gcw->resizeGeometry) { gcw->resizeGeometry->x = WIN_X (cw); gcw->resizeGeometry->y = WIN_Y (cw); gcw->resizeGeometry->width = WIN_WIDTH (cw); gcw->resizeGeometry->height = WIN_HEIGHT (cw); } } } } if (doResizeAll) { if (!gd->resizeInfo) gd->resizeInfo = malloc (sizeof (GroupResizeInfo)); if (gd->resizeInfo) { gd->resizeInfo->resizedWindow = w; gd->resizeInfo->origGeometry.x = WIN_X (w); gd->resizeInfo->origGeometry.y = WIN_Y (w); gd->resizeInfo->origGeometry.width = WIN_WIDTH (w); gd->resizeInfo->origGeometry.height = WIN_HEIGHT (w); } } gw->group->grabWindow = w->id; gw->group->grabMask = mask; } UNWRAP (gs, s, windowGrabNotify); (*s->windowGrabNotify)(w, x, y, state, mask); WRAP (gs, s, windowGrabNotify, groupWindowGrabNotify); }
void groupWindowUngrabNotify (CompWindow *w) { CompScreen *s = w->screen; GROUP_SCREEN (s); GROUP_DISPLAY (&display); GROUP_WINDOW (w); if (gw->group && !gd->ignoreMode && !gs->queued) { int i; XRectangle rect; groupDequeueMoveNotifies (s); if (gd->resizeInfo) { rect.x = WIN_X (w); rect.y = WIN_Y (w); rect.width = WIN_WIDTH (w); rect.height = WIN_HEIGHT (w); } for (i = 0; i < gw->group->nWins; i++) { CompWindow *cw = gw->group->windows[i]; if (!cw) continue; if (cw->id != w->id) { GROUP_WINDOW (cw); if (gw->resizeGeometry) { unsigned int mask; gw->resizeGeometry->x = WIN_X (cw); gw->resizeGeometry->y = WIN_Y (cw); gw->resizeGeometry->width = WIN_WIDTH (cw); gw->resizeGeometry->height = WIN_HEIGHT (cw); mask = groupUpdateResizeRectangle (cw, &rect, FALSE); if (mask) { XWindowChanges xwc; xwc.x = gw->resizeGeometry->x; xwc.y = gw->resizeGeometry->y; xwc.width = gw->resizeGeometry->width; xwc.height = gw->resizeGeometry->height; if (w->mapNum && (mask & (CWWidth | CWHeight))) sendSyncRequest (w); configureXWindow (cw, mask, &xwc); } else { free (gw->resizeGeometry); gw->resizeGeometry = NULL; } } if (gw->needsPosSync) { syncWindowPosition (cw); gw->needsPosSync = FALSE; } groupEnqueueUngrabNotify (cw); } } if (gd->resizeInfo) { free (gd->resizeInfo); gd->resizeInfo = NULL; } gw->group->grabWindow = None; gw->group->grabMask = 0; } UNWRAP (gs, s, windowUngrabNotify); (*s->windowUngrabNotify)(w); WRAP ( gs, s, windowUngrabNotify, groupWindowUngrabNotify); }
/* * groupAddWindowToGroup * */ void groupAddWindowToGroup (CompWindow *w, GroupSelection *group, long int initialIdent) { GROUP_SCREEN (w->screen); GROUP_WINDOW (w); if (gw->group) return; if (group) { CompWindow *topTab = NULL; group->windows = realloc (group->windows, sizeof (CompWindow *) * (group->nWins + 1)); group->windows[group->nWins] = w; group->nWins++; gw->group = group; updateWindowOutputExtents (w); groupUpdateWindowProperty (w); if (group->nWins == 2) { /* first window in the group got its glow, too */ updateWindowOutputExtents (group->windows[0]); } if (group->tabBar) { if (HAS_TOP_WIN (group)) topTab = TOP_TAB (group); else if (HAS_PREV_TOP_WIN (group)) { topTab = PREV_TOP_TAB (group); group->topTab = group->prevTopTab; group->prevTopTab = NULL; } if (topTab) { if (!gw->slot) groupCreateSlot (group, w); gw->destination.x = WIN_CENTER_X (topTab) - (WIN_WIDTH (w) / 2); gw->destination.y = WIN_CENTER_Y (topTab) - (WIN_HEIGHT (w) / 2); gw->mainTabOffset.x = WIN_X (w) - gw->destination.x; gw->mainTabOffset.y = WIN_Y (w) - gw->destination.y; gw->orgPos.x = WIN_X (w); gw->orgPos.y = WIN_Y (w); gw->xVelocity = gw->yVelocity = 0.0f; gw->animateState = IS_ANIMATED; groupStartTabbingAnimation (group, TRUE); addWindowDamage (w); } } } else { /* create new group */ GroupSelection *g = malloc (sizeof (GroupSelection)); if (!g) return; g->windows = malloc (sizeof (CompWindow *)); if (!g->windows) { free (g); return; } g->windows[0] = w; g->screen = w->screen; g->nWins = 1; g->topTab = NULL; g->prevTopTab = NULL; g->nextTopTab = NULL; g->changeAnimationTime = 0; g->changeAnimationDirection = 0; g->changeState = NoTabChange; g->tabbingState = NoTabbing; g->ungroupState = UngroupNone; g->tabBar = NULL; g->checkFocusAfterTabChange = FALSE; g->grabWindow = None; g->grabMask = 0; g->inputPrevention = None; g->ipwMapped = FALSE; /* glow color */ g->color[0] = (int)(rand () / (((double)RAND_MAX + 1) / 0xffff)); g->color[1] = (int)(rand () / (((double)RAND_MAX + 1) / 0xffff)); g->color[2] = (int)(rand () / (((double)RAND_MAX + 1) / 0xffff)); g->color[3] = 0xffff; if (initialIdent) g->identifier = initialIdent; else { /* we got no valid group Id passed, so find out a new valid unique one */ GroupSelection *tg; Bool invalidID = FALSE; g->identifier = gs->groups ? gs->groups->identifier : 0; do { invalidID = FALSE; for (tg = gs->groups; tg; tg = tg->next) { if (tg->identifier == g->identifier) { invalidID = TRUE; g->identifier++; break; } } } while (invalidID); } /* relink stack */ if (gs->groups) gs->groups->prev = g; g->next = gs->groups; g->prev = NULL; gs->groups = g; gw->group = g; groupUpdateWindowProperty (w); } }
static void thumbUpdateThumbnail (CompScreen *s) { int igMidPoint[2], tMidPoint[2]; int tPos[2], tmpPos[2]; float distance = 1000000; int off, oDev, tHeight; int ox1, oy1, ox2, oy2, ow, oh; const BananaValue * option_thumb_size = bananaGetOption (bananaIndex, "thumb_size", s->screenNum); float maxSize = option_thumb_size->i; double scale = 1.0; CompWindow *w; THUMB_SCREEN (s); if (ts->thumb.win == ts->pointedWin) return; if (ts->thumb.opacity > 0.0 && ts->oldThumb.opacity > 0.0) return; if (ts->thumb.win) damageThumbRegion (s, &ts->thumb); freeThumbText (s, &ts->oldThumb); ts->oldThumb = ts->thumb; ts->thumb.textData = NULL; ts->thumb.win = ts->pointedWin; ts->thumb.dock = ts->dock; if (!ts->thumb.win || !ts->dock) { ts->thumb.win = NULL; ts->thumb.dock = NULL; return; } w = ts->thumb.win; /* do we nee to scale the window down? */ if (WIN_W (w) > maxSize || WIN_H (w) > maxSize) { if (WIN_W (w) >= WIN_H (w)) scale = maxSize / WIN_W (w); else scale = maxSize / WIN_H (w); } ts->thumb.width = WIN_W (w)* scale; ts->thumb.height = WIN_H (w) * scale; ts->thumb.scale = scale; const BananaValue * option_title_enabled = bananaGetOption (bananaIndex, "title_enabled", s->screenNum); if (option_title_enabled->b) renderThumbText (s, &ts->thumb, FALSE); else freeThumbText (s, &ts->thumb); igMidPoint[0] = w->iconGeometry.x + (w->iconGeometry.width / 2); igMidPoint[1] = w->iconGeometry.y + (w->iconGeometry.height / 2); const BananaValue * option_border = bananaGetOption (bananaIndex, "border", s->screenNum); off = option_border->i; oDev = outputDeviceForPoint (s, w->iconGeometry.x + (w->iconGeometry.width / 2), w->iconGeometry.y + (w->iconGeometry.height / 2)); if (s->nOutputDev == 1 || oDev > s->nOutputDev) { ox1 = 0; oy1 = 0; ox2 = s->width; oy2 = s->height; ow = s->width; oh = s->height; } else { ox1 = s->outputDev[oDev].region.extents.x1; ox2 = s->outputDev[oDev].region.extents.x2; oy1 = s->outputDev[oDev].region.extents.y1; oy2 = s->outputDev[oDev].region.extents.y2; ow = ox2 - ox1; oh = oy2 - oy1; } tHeight = ts->thumb.height; if (ts->thumb.textData) tHeight += ts->thumb.textData->height + TEXT_DISTANCE; // failsave position tPos[0] = igMidPoint[0] - (ts->thumb.width / 2.0); if (w->iconGeometry.y - tHeight >= 0) tPos[1] = w->iconGeometry.y - tHeight; else tPos[1] = w->iconGeometry.y + w->iconGeometry.height; // above tmpPos[0] = igMidPoint[0] - (ts->thumb.width / 2.0); if (tmpPos[0] - off < ox1) tmpPos[0] = ox1 + off; if (tmpPos[0] + off + ts->thumb.width > ox2) { if (ts->thumb.width + (2 * off) <= ow) tmpPos[0] = ox2 - ts->thumb.width - off; else tmpPos[0] = ox1 + off; } tMidPoint[0] = tmpPos[0] + (ts->thumb.width / 2.0); tmpPos[1] = WIN_Y (ts->dock) - tHeight - off; tMidPoint[1] = tmpPos[1] + (tHeight / 2.0); if (tmpPos[1] > oy1) { tPos[0] = tmpPos[0]; tPos[1] = tmpPos[1]; distance = GET_DISTANCE (igMidPoint, tMidPoint); } // below tmpPos[1] = WIN_Y (ts->dock) + WIN_H (ts->dock) + off; tMidPoint[1] = tmpPos[1] + (tHeight / 2.0); if (tmpPos[1] + tHeight + off < oy2 && GET_DISTANCE (igMidPoint, tMidPoint) < distance) { tPos[0] = tmpPos[0]; tPos[1] = tmpPos[1]; distance = GET_DISTANCE (igMidPoint, tMidPoint); } // left tmpPos[1] = igMidPoint[1] - (tHeight / 2.0); if (tmpPos[1] - off < oy1) tmpPos[1] = oy1 + off; if (tmpPos[1] + off + tHeight > oy2) { if (tHeight + (2 * off) <= oh) tmpPos[1] = oy2 - ts->thumb.height - off; else tmpPos[1] = oy1 + off; } tMidPoint[1] = tmpPos[1] + (tHeight / 2.0); tmpPos[0] = WIN_X (ts->dock) - ts->thumb.width - off; tMidPoint[0] = tmpPos[0] + (ts->thumb.width / 2.0); if (tmpPos[0] > ox1 && GET_DISTANCE (igMidPoint, tMidPoint) < distance) { tPos[0] = tmpPos[0]; tPos[1] = tmpPos[1]; distance = GET_DISTANCE (igMidPoint, tMidPoint); } // right tmpPos[0] = WIN_X (ts->dock) + WIN_W (ts->dock) + off; tMidPoint[0] = tmpPos[0] + (ts->thumb.width / 2.0); if (tmpPos[0] + ts->thumb.width + off < ox2 && GET_DISTANCE (igMidPoint, tMidPoint) < distance) { tPos[0] = tmpPos[0]; tPos[1] = tmpPos[1]; distance = GET_DISTANCE (igMidPoint, tMidPoint); } ts->thumb.x = tPos[0]; ts->thumb.y = tPos[1]; ts->thumb.offset = off; ts->thumb.opacity = 0.0; damageThumbRegion (s, &ts->thumb); }
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; }
/* * Detect visible windows edges */ static void snapUpdateWindowsEdges(CompWindow * w) { CompWindow *c = NULL; Edge *e = NULL, *next = NULL; SNAP_WINDOW(w); Region edgeRegion, resultRegion; XRectangle rect; Bool remove = FALSE; // First add all the windows c = w->screen->windows; while (c) { // Just check that we're not trying to snap to current window, // that the window is not invisible and of a valid type if (c == w || !isSnapWindow(c)) { c = c->next; continue; } snapAddEdge(&sw->edges, &sw->reverseEdges, c->id, WIN_Y(c), WIN_X(c), WIN_X(c) + WIN_W(c), TopEdge, FALSE); snapAddEdge(&sw->edges, &sw->reverseEdges, c->id, WIN_Y(c) + WIN_H(c), WIN_X(c), WIN_X(c) + WIN_W(c), BottomEdge, FALSE); snapAddEdge(&sw->edges, &sw->reverseEdges, c->id, WIN_X(c), WIN_Y(c), WIN_Y(c) + WIN_H(c), LeftEdge, FALSE); snapAddEdge(&sw->edges, &sw->reverseEdges, c->id, WIN_X(c) + WIN_W(c), WIN_Y(c), WIN_Y(c) + WIN_H(c), RightEdge, FALSE); c = c->next; } // Now strip invisible edges // Loop through all the windows stack, and through all the edges // If an edge has been passed, check if it's in the region window, // if the edge is fully under the window, drop it, or if it's only // partly covered, cut it/split it in one/two smaller visible edges for (c = w->screen->windows; c; c = c->next) { if (c == w || !isSnapWindow(c)) continue; for (e = sw->edges; e; e = next) { if (!e->passed) { if (e->id == c->id) e->passed = TRUE; next = e->next; continue; } switch (e->type) { case LeftEdge: case RightEdge: rect.x = e->position; rect.y = e->start; rect.width = 1; rect.height = e->end - e->start; break; case TopEdge: case BottomEdge: default: rect.x = e->start; rect.y = e->position; rect.width = e->end - e->start; rect.height = 1; } // If the edge is in the window region, remove it, // if it's partly in the region, split it edgeRegion = XCreateRegion(); resultRegion = XCreateRegion(); XUnionRectWithRegion(&rect, edgeRegion, edgeRegion); XSubtractRegion(edgeRegion, c->region, resultRegion); if (XEmptyRegion(resultRegion)) remove = TRUE; else if (!XEqualRegion(edgeRegion, resultRegion)) { snapAddRegionEdges(sw, e, resultRegion); remove = TRUE; } next = e->next; if (remove) { if (e->prev == NULL) sw->edges = e->next; if (e->next == NULL) sw->reverseEdges = e->prev; snapRemoveEdge(e); remove = FALSE; } XDestroyRegion(resultRegion); XDestroyRegion(edgeRegion); } } }