rendered paste body#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <compiz-core.h> #include "sound_options.h"#include "../animation/animation-internal.h"static void animHandleEvent(CompDisplay * d, XEvent * event);static Bool animGetWindowIconGeometry(CompWindow * w, XRectangle * rect);static Bool windowHasUserTime(CompWindow *w);static inline Bool isWinVisible(CompWindow *w);static void updateLastClientListStacking(CompScreen *s);static void animHandleEvent(CompDisplay * d, XEvent * event){ CompWindow *w; ANIM_DISPLAY(d); switch (event->type) { case PropertyNotify: if (event->xproperty.atom == d->clientListStackingAtom) { CompScreen *s = findScreenAtDisplay (d, event->xproperty.window); if (s) updateLastClientListStacking(s); } break; case MapNotify: w = findWindowAtDisplay(d, event->xmap.window); if (w) { ANIM_WINDOW(w); if (aw->animRemainingTime > 0) { aw->state = aw->newState; } while (aw->unmapCnt) { unmapWindow(w); aw->unmapCnt--; } } break; case DestroyNotify: w = findWindowAtDisplay(d, event->xunmap.window); if (w) { ANIM_WINDOW(w); aw->destroyCnt++; w->destroyRefCnt++; addWindowDamage(w); } break; case UnmapNotify: w = findWindowAtDisplay(d, event->xunmap.window); if (w) {// ANIM_SCREEN(w->screen); if (w->pendingUnmaps && onCurrentDesktop(w)) // Normal -> Iconic { ANIM_WINDOW(w);// int duration = 200;// AnimEffect chosenEffect =// getMatchingAnimSelection (w, WindowEventShade, &duration); if (w->shaded) { // SHADE event! compLogMessage( w->screen->display, "sound", CompLogLevelDebug, "SHADE event" ); aw->nowShaded = TRUE;/* if (chosenEffect) { Bool startingNew = TRUE; if (aw->curWindowEvent != WindowEventNone) { if (aw->curWindowEvent != WindowEventUnshade) { postAnimationCleanupCustom(w, TRUE, FALSE, FALSE); } else { // Play the unshade effect backwards from where it left aw->animRemainingTime = aw->animTotalTime - aw->animRemainingTime; // avoid window remains if (aw->animRemainingTime <= 0) aw->animRemainingTime = 1; startingNew = FALSE; if (aw->animOverrideProgressDir == 0) aw->animOverrideProgressDir = 2; else if (aw->animOverrideProgressDir == 1) aw->animOverrideProgressDir = 0; } } if (startingNew) { AnimEffect effectToBePlayed; effectToBePlayed = animGetAnimEffect( chosenEffect, as->shadeRandomEffects, as->nShadeRandomEffects, as->opt[ANIM_SCREEN_OPTION_ALL_RANDOM].value.b); // handle empty random effect list if (effectToBePlayed == AnimEffectNone) break; aw->curAnimEffect = effectToBePlayed; aw->animTotalTime = duration; aw->animRemainingTime = aw->animTotalTime; } animActivateEvent(w->screen, TRUE); aw->curWindowEvent = WindowEventShade; // Store coords in this viewport to omit 3d effect // painting in other viewports aw->lastKnownCoords.x = w->attrib.x; aw->lastKnownCoords.y = w->attrib.y; if (!animEnsureModel(w)) { postAnimationCleanup(w, TRUE); } aw->unmapCnt++; w->unmapRefCnt++; damagePendingOnScreen (w->screen); }*/ } else if (!w->invisible && animGetWindowIconGeometry(w, &aw->icon)) { // MINIMIZE event! compLogMessage( w->screen->display, "sound", CompLogLevelDebug, "MINIMIZE event" );/* aw->newState = IconicState; chosenEffect = getMatchingAnimSelection (w, WindowEventMinimize, &duration); if (chosenEffect) { Bool startingNew = TRUE; if (aw->curWindowEvent != WindowEventNone) { if (aw->curWindowEvent != WindowEventUnminimize) { postAnimationCleanupCustom(w, TRUE, FALSE, FALSE); } else { // Play the unminimize effect backwards from where it left aw->animRemainingTime = aw->animTotalTime - aw->animRemainingTime; // avoid window remains if (aw->animRemainingTime == 0) aw->animRemainingTime = 1; startingNew = FALSE; if (aw->animOverrideProgressDir == 0) aw->animOverrideProgressDir = 2; else if (aw->animOverrideProgressDir == 1) aw->animOverrideProgressDir = 0; } } if (startingNew) { AnimEffect effectToBePlayed; effectToBePlayed = animGetAnimEffect( chosenEffect, as->minimizeRandomEffects, as->nMinimizeRandomEffects, as->opt[ANIM_SCREEN_OPTION_ALL_RANDOM].value.b); // handle empty random effect list if (effectToBePlayed == AnimEffectNone) break; aw->curAnimEffect = effectToBePlayed; aw->animTotalTime = duration; aw->animRemainingTime = aw->animTotalTime; } animActivateEvent(w->screen, TRUE); aw->curWindowEvent = WindowEventMinimize; // Store coords in this viewport to omit 3d effect // painting in other viewports aw->lastKnownCoords.x = w->attrib.x; aw->lastKnownCoords.y = w->attrib.y; if (!animEnsureModel(w)) { postAnimationCleanup(w, TRUE); } else { aw->unmapCnt++; w->unmapRefCnt++; damagePendingOnScreen (w->screen); } } }*/ } else // X -> Withdrawn { ANIM_WINDOW(w); // don't animate windows that don't have certain properties // like the fullscreen darkening layer of gksudo // or the darkening layer of x-session-manager if (!(w->resName || windowHasUserTime (w)) || (aw->wmName && strcasecmp (aw->wmName, "x-session-manager") == 0)) break; // CLOSE event! compLogMessage( w->screen->display, "sound", CompLogLevelDebug, "CLOSE event!" );/* int duration = 200; AnimEffect chosenEffect = getMatchingAnimSelection (w, WindowEventClose, &duration); aw->state = NormalState; aw->newState = WithdrawnState; if (chosenEffect) { int tmpSteps = 0; Bool startingNew = TRUE; if (aw->animRemainingTime > 0 && aw->curWindowEvent != WindowEventOpen) { tmpSteps = aw->animRemainingTime; aw->animRemainingTime = 0; } if (aw->curWindowEvent != WindowEventNone) { if (aw->curWindowEvent == WindowEventOpen) { // Play the create effect backward from where it left aw->animRemainingTime = aw->animTotalTime - aw->animRemainingTime; // avoid window remains if (aw->animRemainingTime <= 0) aw->animRemainingTime = 1; startingNew = FALSE; if (aw->animOverrideProgressDir == 0) aw->animOverrideProgressDir = 2; else if (aw->animOverrideProgressDir == 1) aw->animOverrideProgressDir = 0; } else if (aw->curWindowEvent == WindowEventClose) { if (aw->animOverrideProgressDir == 2) { aw->animRemainingTime = tmpSteps; startingNew = FALSE; } } else { postAnimationCleanupCustom(w, TRUE, TRUE, FALSE); } } if (startingNew) { AnimEffect effectToBePlayed; effectToBePlayed = animGetAnimEffect( chosenEffect, as->closeRandomEffects, as->nCloseRandomEffects, as->opt[ANIM_SCREEN_OPTION_ALL_RANDOM].value.b); // handle empty random effect list if (effectToBePlayed == AnimEffectNone) break; aw->curAnimEffect = effectToBePlayed; aw->animTotalTime = duration; aw->animRemainingTime = aw->animTotalTime; } animActivateEvent(w->screen, TRUE); aw->curWindowEvent = WindowEventClose; // Store coords in this viewport to omit 3d effect // painting in other viewports aw->lastKnownCoords.x = w->attrib.x; aw->lastKnownCoords.y = w->attrib.y; if (!animEnsureModel(w)) { postAnimationCleanup(w, TRUE); } else if (getMousePointerXY (w->screen, &aw->icon.x, &aw->icon.y)) { aw->icon.width = FAKE_ICON_SIZE; aw->icon.height = FAKE_ICON_SIZE; if (aw->curAnimEffect == AnimEffectMagicLamp) aw->icon.width = MAX(aw->icon.width, animGetI(as, aw, ANIM_SCREEN_OPTION_MAGIC_LAMP_OPEN_START_WIDTH)); else if (aw->curAnimEffect == AnimEffectVacuum) aw->icon.width = MAX(aw->icon.width, animGetI(as, aw, ANIM_SCREEN_OPTION_VACUUM_OPEN_START_WIDTH)); aw->unmapCnt++; w->unmapRefCnt++; damagePendingOnScreen (w->screen); } }/// else if (getMatchingAnimSelection (w, WindowEventOpen, &duration)) { // stop the current animation and prevent it from rewinding if (aw->animRemainingTime > 0 && aw->curWindowEvent != WindowEventOpen) { aw->animRemainingTime = 0; } if ((aw->curWindowEvent != WindowEventNone) && (aw->curWindowEvent != WindowEventClose)) { postAnimationCleanup(w, TRUE); } // set some properties to make sure this window will use the // correct open effect the next time it's "opened" animActivateEvent(w->screen, TRUE); aw->curWindowEvent = WindowEventClose; aw->unmapCnt++; w->unmapRefCnt++; damagePendingOnScreen (w->screen); }/// }*/ } break; case ConfigureNotify: { XConfigureEvent *ce = &event->xconfigure; w = findWindowAtDisplay (d, ce->window); if (!w) break; if (w->prev) { if (ce->above && ce->above == w->prev->id) break; } else if (ce->above == None) break; CompScreen *s = findScreenAtDisplay (d, event->xproperty.window); if (!s) break; ANIM_SCREEN(s); int i; int n = s->nClientList; Bool winOpenedClosed = FALSE; Window *clientList = (Window *) (s->clientList + n); Window *clientListStacking = clientList + n; if (n != as->nLastClientListStacking) winOpenedClosed = TRUE; // if restacking occurred and not window open/close if (!winOpenedClosed) { ANIM_WINDOW(w); aw->configureNotified = TRUE; // Find which window is restacked // e.g. here 8507730 was raised: // 54526074 8507730 48234499 14680072 6291497 // 54526074 48234499 14680072 8507730 6291497 // compare first changed win. of row 1 with last // changed win. of row 2, and vica versa // the matching one is the restacked one CompWindow *wRestacked = 0; CompWindow *wStart = 0; CompWindow *wEnd = 0; CompWindow *wOldAbove = 0; CompWindow *wChangeStart = 0; CompWindow *wChangeEnd = 0; Bool raised = FALSE; int changeStart = -1; int changeEnd = -1; for (i = 0; i < n; i++) { CompWindow *wi = findWindowAtScreen (s, clientListStacking[i]); // skip if minimized (prevents flashing problem) if (!wi || !isWinVisible(wi)) continue; // skip if (tabbed and) hidden by Group plugin if (wi->state & (CompWindowStateSkipPagerMask | CompWindowStateSkipTaskbarMask)) continue; if (clientListStacking[i] != as->lastClientListStacking[i]) { if (changeStart < 0) { changeStart = i; wChangeStart = wi; // make use of already found w } else { changeEnd = i; wChangeEnd = wi; } } else if (changeStart >= 0) // found some change earlier break; } // if restacking occurred if (changeStart >= 0 && changeEnd >= 0) { CompWindow *w2; // if we have only 2 windows changed, // choose the one clicked on Bool preferRaised = FALSE; Bool onlyTwo = FALSE; if (wChangeEnd && clientListStacking[changeEnd] == as->lastClientListStacking[changeStart] && clientListStacking[changeStart] == as->lastClientListStacking[changeEnd]) { // Check if the window coming on top was // configureNotified (clicked on) AnimWindow *aw2 = GET_ANIM_WINDOW(wChangeEnd, as); if (aw2->configureNotified) { preferRaised = TRUE; } onlyTwo = TRUE; } // Clear all configureNotified's for (w2 = s->windows; w2; w2 = w2->next) { AnimWindow *aw2 = GET_ANIM_WINDOW(w2, as); aw2->configureNotified = FALSE; } if (preferRaised || (!onlyTwo && clientListStacking[changeEnd] == as->lastClientListStacking[changeStart])) { // raised raised = TRUE; wRestacked = wChangeEnd; wStart = wChangeStart; wEnd = wRestacked; wOldAbove = wStart; } else if (clientListStacking[changeStart] == as->lastClientListStacking[changeEnd] && // lowered // We don't animate lowering if there is no // window above this window, since this window needs // to be drawn on such a "host" in animPaintWindow // (at least for now). changeEnd < n - 1) { wRestacked = wChangeStart; wStart = wRestacked; wEnd = wChangeEnd; wOldAbove = findWindowAtScreen (s, as->lastClientListStacking[changeEnd+1]); } for (; wOldAbove && !isWinVisible(wOldAbove); wOldAbove = wOldAbove->next) ; } if (wRestacked && wStart && wEnd && wOldAbove) { AnimWindow *awRestacked = GET_ANIM_WINDOW(wRestacked, as); if (awRestacked->created) { RestackInfo *restackInfo = calloc(1, sizeof(RestackInfo)); if (restackInfo) { restackInfo->wRestacked = wRestacked; restackInfo->wStart = wStart; restackInfo->wEnd = wEnd; restackInfo->wOldAbove = wOldAbove; restackInfo->raised = raised; if (awRestacked->restackInfo) free(awRestacked->restackInfo); awRestacked->restackInfo = restackInfo; as->aWinWasRestackedJustNow = TRUE; } } } } updateLastClientListStacking(s); } break; default: break; } UNWRAP(ad, d, handleEvent); (*d->handleEvent) (d, event); WRAP(ad, d, handleEvent, animHandleEvent); switch (event->type) { case PropertyNotify: if (event->xproperty.atom == d->winActiveAtom && d->activeWindow != ad->activeWindow) { ad->activeWindow = d->activeWindow; w = findWindowAtDisplay(d, d->activeWindow);/* if (w) { int duration = 200; AnimEffect chosenEffect = getMatchingAnimSelection (w, WindowEventFocus, &duration); if (!(chosenEffect == AnimEffectFocusFade || chosenEffect == AnimEffectDodge)) initiateFocusAnimation(w); }*/ } break; default: break; }}static inline BoolisWinVisible(CompWindow *w){ return (!w->destroyed && !(!w->shaded && (w->attrib.map_state != IsViewable)));}static voidupdateLastClientListStacking(CompScreen *s){ ANIM_SCREEN(s); int n = s->nClientList; Window *clientListStacking = (Window *) (s->clientList + n) + n; if (as->nLastClientListStacking != n) // the number of windows has changed { Window *list; list = realloc (as->lastClientListStacking, sizeof (Window) * n); as->lastClientListStacking = list; if (!list) { as->nLastClientListStacking = 0; return; } as->nLastClientListStacking = n; } // Store new client stack listing memcpy(as->lastClientListStacking, clientListStacking, sizeof (Window) * n);}static Bool animGetWindowIconGeometry(CompWindow * w, XRectangle * rect){ Atom actual; int result, format; unsigned long n, left; unsigned char *data; ANIM_DISPLAY(w->screen->display); result = XGetWindowProperty(w->screen->display->display, w->id, ad->winIconGeometryAtom, 0L, 4L, FALSE, XA_CARDINAL, &actual, &format, &n, &left, &data); if (result == Success && n && data) { if (n == 4) { unsigned long *geometry = (unsigned long *)data; rect->x = geometry[0]; rect->y = geometry[1]; rect->width = geometry[2]; rect->height = geometry[3]; XFree(data); return TRUE; } XFree(data); } return FALSE;}static BoolwindowHasUserTime(CompWindow *w){ Time t; return getWindowUserTime (w, &t);}