diff -Nru compiz-plugins-main-0.9.6.2011.10/animation/src/animation.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/animation/src/animation.cpp --- compiz-plugins-main-0.9.6.2011.10/animation/src/animation.cpp 2011-10-20 12:37:25.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/animation/src/animation.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -1397,35 +1397,13 @@ } } - popLockedPaintList (); - - foreach (CompWindow *w, windowsFinishedAnimations) - { - AnimWindow *aw = AnimWindow::get (w); - aw->priv->notifyAnimation (false); - aw->priv->postAnimationCleanUp (); - } - - const CompWindowList &ppl = pushLockedPaintList (); - - foreach (CompWindow *w, ppl) + foreach (CompWindow *w, pl) { PrivateAnimWindow *aw = AnimWindow::get (w)->priv; if (aw->curAnimation ()) aw->curAnimation ()->postPreparePaint (); } - if (!animStillInProgress) - { - activateEvent (false); - mLastRedrawTimeFresh = false; - - // Reset stacking related info after all animations are done. - ExtensionPluginAnimation *extPlugin = - static_cast (mExtensionPlugins[0]); - extPlugin->resetStackingInfo (); - } - popLockedPaintList (); } @@ -1450,6 +1428,50 @@ { assert (mAnimInProgress); + const CompWindowList &pl = pushLockedPaintList (); + CompWindowList windowsFinishedAnimations; + + bool animStillInProgress = false; + + /* Paint list includes destroyed windows */ + for (CompWindowList::const_reverse_iterator rit = pl.rbegin (); + rit != pl.rend (); rit++) + { + CompWindow *w = (*rit); + AnimWindow *animWin = AnimWindow::get (w); + PrivateAnimWindow *aw = animWin->priv; + Animation *curAnim = aw->curAnimation (); + + if (curAnim) + { + bool finished = (curAnim->remainingTime () <= 0); + if (finished) // Animation is done + windowsFinishedAnimations.push_back (w); + else + animStillInProgress = true; + } + } + + popLockedPaintList (); + + foreach (CompWindow *w, windowsFinishedAnimations) + { + AnimWindow *aw = AnimWindow::get (w); + aw->priv->notifyAnimation (false); + aw->priv->postAnimationCleanUp (); + } + + if (!animStillInProgress) + { + activateEvent (false); + mLastRedrawTimeFresh = false; + + // Reset stacking related info after all animations are done. + ExtensionPluginAnimation *extPlugin = + static_cast (mExtensionPlugins[0]); + extPlugin->resetStackingInfo (); + } + cScreen->damagePending (); cScreen->donePaint (); diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/bzr-builder.manifest compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/bzr-builder.manifest --- compiz-plugins-main-0.9.6.2011.10/debian/bzr-builder.manifest 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/bzr-builder.manifest 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1,3 @@ +# bzr-builder format 0.3 deb-version 1:{debupstream}+51+234+201202040052 +lp:~linaro-graphics-wg/compiz-plugins-main/linaro-gles2 revid:alexandros.frantzis@linaro.org-20120125103945-kq0y1d5kwoijfdsp +nest-part packaging lp:~linaro-maintainers/compiz-plugins-main/overlay debian debian revid:ricardo.salveti@linaro.org-20120202054513-8o33hxmaawyy06xj diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/changelog compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/changelog --- compiz-plugins-main-0.9.6.2011.10/debian/changelog 2012-01-05 13:24:12.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/changelog 2012-02-24 16:43:55.000000000 +0000 @@ -1,3 +1,40 @@ +compiz-plugins-main (1:0.9.6.2012.02+51+234+201202040052~oneiric1+ti1) oneiric; urgency=low + + * debian/rules: Make dependent on sgx libs + + -- Frederic Plourde Fri, 24 Feb 2012 11:43:06 -0500 + +compiz-plugins-main (1:0.9.6.2012.02+51+234+201202040052~oneiric1) UNRELEASED; urgency=low + + * Auto build. + + -- Ricardo Salveti Sat, 04 Feb 2012 00:52:45 +0000 + +compiz-plugins-main (1:0.9.6.2012.02-0linaro1) UNRELEASED; urgency=low + + * Bump to be newer than the one available at the Overlay PPA + + -- Ricardo Salveti de Araujo Thu, 02 Feb 2012 03:44:06 -0200 + +compiz-plugins-main (1:0.9.6+bzr20120117.2012.01-0linaro3) oneiric; urgency=low + + * debian/rules: enable GLES for all archs + + -- Ricardo Salveti de Araujo Tue, 31 Jan 2012 02:12:47 -0200 + +compiz-plugins-main (1:0.9.6+bzr20120117.2012.01-0linaro2) oneiric; urgency=low + + * debian/rules: also adding GLES support for armhf + + -- Ricardo Salveti de Araujo Tue, 31 Jan 2012 02:10:40 -0200 + +compiz-plugins-main (1:0.9.6+bzr20120117.2012.01-0linaro1) oneiric; urgency=low + + * New snapshot Linaro Compiz Plugins Main release (2012.01) + * Enabling parallel build + + -- Ricardo Salveti de Araujo Sun, 22 Jan 2012 20:35:39 -0200 + compiz-plugins-main (1:0.9.6.2011.10-0linaro2+ti3) oneiric; urgency=low * Fixed egl-related Build-Depends @@ -16,12 +53,6 @@ -- Frederic Plourde Thu, 22 Dec 2011 09:49:36 -0500 -compiz-plugins-main (1:0.9.6.2011.10-0linaro2) oneiric; urgency=low - - * Rebuild to generate dbgsym packages - - -- Ricardo Salveti de Araujo Fri, 16 Dec 2011 17:11:54 -0200 - compiz-plugins-main (1:0.9.6.2011.10-0linaro1) oneiric; urgency=low [ Travis Watkins ] diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-862261.patch compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-862261.patch --- compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-862261.patch 2011-12-22 14:48:48.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-862261.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -=== modified file 'src/snap.cpp' -Index: compiz-plugins-main-0.9.6/snap/src/snap.cpp -=================================================================== ---- compiz-plugins-main-0.9.6.orig/snap/src/snap.cpp 2011-10-08 00:03:55.037329027 +0800 -+++ compiz-plugins-main-0.9.6/snap/src/snap.cpp 2011-10-08 00:04:10.165404044 +0800 -@@ -581,6 +581,13 @@ - return; - } - -+ // don't snap maximized windows -+ if (window->state () & CompWindowStateMaximizedHorzMask) -+ dx = 0; -+ -+ if (window->state () & CompWindowStateMaximizedVertMask) -+ dy = 0; -+ - // avoiding snap, nothing buffered - if (!ss->snapping) - return; diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-864476.patch compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-864476.patch --- compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-864476.patch 2011-12-22 14:48:48.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-864476.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -=== modified file 'src/animation.cpp' -Index: compiz-plugins-main-0.9.6/animation/src/animation.cpp -=================================================================== ---- compiz-plugins-main-0.9.6.orig/animation/src/animation.cpp 2011-10-04 01:29:40.068111883 +0800 -+++ compiz-plugins-main-0.9.6/animation/src/animation.cpp 2011-10-04 01:29:57.396197802 +0800 -@@ -1343,35 +1343,13 @@ - } - } - -- popLockedPaintList (); -- -- foreach (CompWindow *w, windowsFinishedAnimations) -- { -- AnimWindow *aw = AnimWindow::get (w); -- aw->priv->notifyAnimation (false); -- aw->priv->postAnimationCleanUp (); -- } -- -- const CompWindowList &ppl = pushLockedPaintList (); -- -- foreach (CompWindow *w, ppl) -+ foreach (CompWindow *w, pl) - { - PrivateAnimWindow *aw = AnimWindow::get (w)->priv; - if (aw->curAnimation ()) - aw->curAnimation ()->postPreparePaint (); - } - -- if (!animStillInProgress) -- { -- activateEvent (false); -- mLastRedrawTimeFresh = false; -- -- // Reset stacking related info after all animations are done. -- ExtensionPluginAnimation *extPlugin = -- static_cast (mExtensionPlugins[0]); -- extPlugin->resetStackingInfo (); -- } -- - popLockedPaintList (); - } - -@@ -1396,6 +1374,50 @@ - { - assert (mAnimInProgress); - -+ const CompWindowList &pl = pushLockedPaintList (); -+ CompWindowList windowsFinishedAnimations; -+ -+ bool animStillInProgress = false; -+ -+ /* Paint list includes destroyed windows */ -+ for (CompWindowList::const_reverse_iterator rit = pl.rbegin (); -+ rit != pl.rend (); rit++) -+ { -+ CompWindow *w = (*rit); -+ AnimWindow *animWin = AnimWindow::get (w); -+ PrivateAnimWindow *aw = animWin->priv; -+ Animation *curAnim = aw->curAnimation (); -+ -+ if (curAnim) -+ { -+ bool finished = (curAnim->remainingTime () <= 0); -+ if (finished) // Animation is done -+ windowsFinishedAnimations.push_back (w); -+ else -+ animStillInProgress = true; -+ } -+ } -+ -+ popLockedPaintList (); -+ -+ foreach (CompWindow *w, windowsFinishedAnimations) -+ { -+ AnimWindow *aw = AnimWindow::get (w); -+ aw->priv->notifyAnimation (false); -+ aw->priv->postAnimationCleanUp (); -+ } -+ -+ if (!animStillInProgress) -+ { -+ activateEvent (false); -+ mLastRedrawTimeFresh = false; -+ -+ // Reset stacking related info after all animations are done. -+ ExtensionPluginAnimation *extPlugin = -+ static_cast (mExtensionPlugins[0]); -+ extPlugin->resetStackingInfo (); -+ } -+ - cScreen->damagePending (); - - cScreen->donePaint (); diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-868121.patch compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-868121.patch --- compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-868121.patch 2011-12-22 14:48:48.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-868121.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -=== modified file 'src/expo.cpp' -Index: compiz-plugins-main-0.9.6/expo/src/expo.cpp -=================================================================== ---- compiz-plugins-main-0.9.6.orig/expo/src/expo.cpp 2011-10-08 00:06:59.998246191 +0800 -+++ compiz-plugins-main-0.9.6/expo/src/expo.cpp 2011-10-08 00:07:17.022330628 +0800 -@@ -444,7 +444,6 @@ - screen->handleEventSetEnabled (this, enable); - cScreen->preparePaintSetEnabled (this, enable); - cScreen->paintSetEnabled (this, enable); -- cScreen->getWindowPaintListSetEnabled (this, false); - cScreen->donePaintSetEnabled (this, enable); - gScreen->glPaintOutputSetEnabled (this, enable); - gScreen->glPaintTransformedOutputSetEnabled (this, enable); -@@ -784,12 +783,14 @@ - DEFAULT_Z_CAMERA - curveDistance); - } - -- cScreen->getWindowPaintListSetEnabled (this, paintingDndWindow); -+ if (paintingDndWindow) -+ cScreen->getWindowPaintListSetEnabled (this, true); - gScreen->glPaintTransformedOutput (attrib, sTransform3, - screen->region (), output, - mask); - -- cScreen->getWindowPaintListSetEnabled (this, !paintingDndWindow); -+ if (paintingDndWindow) -+ cScreen->getWindowPaintListSetEnabled (this, false); - - if (!reflection && !paintingDndWindow) - { -@@ -821,6 +822,8 @@ - invertTransformedVertex (attrib, sTransform3, output, br); - - viewport_size = CompSize (br[0] - tl[0], br[1] - tl[1]); -+ -+ cScreen->setWindowPaintOffset (0, 0); - } - - void -@@ -1105,8 +1108,6 @@ - - expoActive = false; - -- cScreen->setWindowPaintOffset (0, 0); -- - gScreen->glPaintTransformedOutputSetCurrentIndex (glPaintTransformedOutputIndex); - gScreen->setTextureFilter (oldFilter); - } -@@ -1437,16 +1438,15 @@ - { - GLMatrix wTransform (transform); - GLWindowPaintAttrib wAttrib (attrib); -- CompPoint vp; - CompRegion clip (region); - -- screen->viewportForGeometry (window->geometry (), vp); -- - if (eScreen->expoActive) - { -- float opacity = 1.0; -- bool hide; -- bool zoomAnim; -+ float opacity = 1.0; -+ bool hide; -+ bool zoomAnim; -+ CompPoint vp; -+ screen->viewportForGeometry (window->geometry (), vp); - - zoomAnim = eScreen->optionGetExpoAnimation () == - ExpoScreen::ExpoAnimationZoom; -@@ -1477,39 +1477,40 @@ - mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; - else - wAttrib.opacity = wAttrib.opacity * opacity; -- } - -- /* Stretch maximized windows a little so that you don't -- * have an awkward gap */ -+ /* Stretch maximized windows a little so that you don't -+ * have an awkward gap */ - -- if (window->state () & MAXIMIZE_STATE) -- { -- CompOutput *o = &screen->outputDevs ()[screen->outputDeviceForGeometry(window->geometry())]; -- float yS = 1.0 + ((o->height () / (float) window->height ()) - 1.0f) * sigmoidProgress (eScreen->expoCam); -- wTransform.translate (window->x () + window->width () / 2, -- window->y () + window->height (), -- 0.0f); -- wTransform.scale (1.0f, yS, 1.0f); -- wTransform.translate (-(window->x () + window->width () / 2), -- -(window->y () + window->height ()), -- 0.0f); -+ if (window->state () & MAXIMIZE_STATE && -+ !window->border ().top) -+ { -+ CompOutput *o = &screen->outputDevs ()[screen->outputDeviceForGeometry(window->geometry())]; -+ float yS = 1.0 + ((o->height () / (float) window->height ()) - 1.0f) * sigmoidProgress (eScreen->expoCam); -+ wTransform.translate (window->x () + window->width () / 2, -+ window->y () + window->height (), -+ 0.0f); -+ wTransform.scale (1.0f, yS, 1.0f); -+ wTransform.translate (-(window->x () + window->width () / 2), -+ -(window->y () + window->height ()), -+ 0.0f); - -- if (eScreen->paintingVp != vp) -- mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; -+ if (eScreen->paintingVp != vp) -+ mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; - -- mask |= PAINT_WINDOW_TRANSFORMED_MASK; -- } -- -- if (std::find (eScreen->dndWindows.begin(), eScreen->dndWindows.end (), window) != eScreen->dndWindows.end ()) -- { -- if (!eScreen->paintingDndWindow) -- { -- mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; -+ mask |= PAINT_WINDOW_TRANSFORMED_MASK; - } -- else -+ -+ if (std::find (eScreen->dndWindows.begin(), eScreen->dndWindows.end (), window) != eScreen->dndWindows.end ()) - { -- mask |= PAINT_WINDOW_TRANSFORMED_MASK; -- clip = infiniteRegion; -+ if (!eScreen->paintingDndWindow) -+ { -+ mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; -+ } -+ else -+ { -+ mask |= PAINT_WINDOW_TRANSFORMED_MASK; -+ clip = infiniteRegion; -+ } - } - } - diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-868392.patch compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-868392.patch --- compiz-plugins-main-0.9.6.2011.10/debian/patches/fix-868392.patch 2011-12-22 14:48:48.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/fix-868392.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -=== modified file 'src/snap.cpp' -Index: compiz-plugins-main-0.9.6/snap/src/snap.cpp -=================================================================== ---- compiz-plugins-main-0.9.6.orig/snap/src/snap.cpp 2011-10-08 00:07:30.750398687 +0800 -+++ compiz-plugins-main-0.9.6/snap/src/snap.cpp 2011-10-08 00:07:49.882493524 +0800 -@@ -396,7 +396,7 @@ - // Update snapping data - if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) - { -- snapGeometry = window->serverGeometry (); -+ snapGeometry = window->geometry (); - this->snapDirection |= snapDirection; - } - // Attract the window if needed, moving it of the correct dist diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/patches/series compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/series --- compiz-plugins-main-0.9.6.2011.10/debian/patches/series 2011-12-22 14:48:48.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -fix-862261.patch -fix-864476.patch -fix-868121.patch -fix-868392.patch diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/rules compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/rules --- compiz-plugins-main-0.9.6.2011.10/debian/rules 2011-12-22 14:48:48.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/rules 2012-02-24 16:39:32.000000000 +0000 @@ -3,20 +3,15 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 -DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) CORE_ABIVERSION := $(shell sed -rn 's/^\#define[[:space:]]+CORE_ABIVERSION[[:space:]]+//p' /usr/include/compiz/core/core.h ) override_dh_auto_configure: -ifeq ($(DEB_HOST_ARCH),armel) dh_auto_configure -- -DCOMPIZ_BUILD_WITH_RPATH=FALSE -DCOMPIZ_PACKAGING_ENABLED=TRUE -DCOMPIZ_PLUGIN_INSTALL_TYPE=package -DUSE_GSETTINGS=OFF -DCOMPIZ_DISABLE_GS_SCHEMAS_INSTALL=ON -DBUILD_GLES=ON -else - dh_auto_configure -- -DCOMPIZ_BUILD_WITH_RPATH=FALSE -DCOMPIZ_PACKAGING_ENABLED=TRUE -DCOMPIZ_PLUGIN_INSTALL_TYPE=package -DUSE_GSETTINGS=OFF -DCOMPIZ_DISABLE_GS_SCHEMAS_INSTALL=ON -endif override_dh_gencontrol: dh_gencontrol -- -Vcoreabiversion=$(CORE_ABIVERSION) %: - dh $@ + dh $@ --parallel diff -Nru compiz-plugins-main-0.9.6.2011.10/debian/source/format compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/source/format --- compiz-plugins-main-0.9.6.2011.10/debian/source/format 2012-02-24 17:38:46.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/debian/source/format 2012-02-24 17:38:46.000000000 +0000 @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff -Nru compiz-plugins-main-0.9.6.2011.10/expo/src/expo.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/expo/src/expo.cpp --- compiz-plugins-main-0.9.6.2011.10/expo/src/expo.cpp 2011-10-20 12:37:25.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/expo/src/expo.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -446,7 +446,6 @@ screen->handleEventSetEnabled (this, enable); cScreen->preparePaintSetEnabled (this, enable); cScreen->paintSetEnabled (this, enable); - cScreen->getWindowPaintListSetEnabled (this, false); cScreen->donePaintSetEnabled (this, enable); gScreen->glPaintOutputSetEnabled (this, enable); gScreen->glPaintTransformedOutputSetEnabled (this, enable); @@ -647,7 +646,7 @@ const GLint viewport[4], float *objx, float *objy, float *objz) { - GLMatrix finalMatrix = modelview * projection; + GLMatrix finalMatrix = projection * modelview; float in[4], out[4]; if (!finalMatrix.invert ()) @@ -831,12 +830,14 @@ DEFAULT_Z_CAMERA - curveDistance); } - cScreen->getWindowPaintListSetEnabled (this, paintingDndWindow); + if (paintingDndWindow) + cScreen->getWindowPaintListSetEnabled (this, true); gScreen->glPaintTransformedOutput (attrib, sTransform3, screen->region (), output, mask); - cScreen->getWindowPaintListSetEnabled (this, !paintingDndWindow); + if (paintingDndWindow) + cScreen->getWindowPaintListSetEnabled (this, false); if (!reflection && !paintingDndWindow) { @@ -868,6 +869,8 @@ invertTransformedVertex (attrib, sTransform3, output, br); viewport_size = CompSize (br[0] - tl[0], br[1] - tl[1]); + + cScreen->setWindowPaintOffset (0, 0); } void @@ -1250,8 +1253,6 @@ expoActive = false; - cScreen->setWindowPaintOffset (0, 0); - gScreen->glPaintTransformedOutputSetCurrentIndex (glPaintTransformedOutputIndex); gScreen->setTextureFilter (oldFilter); } @@ -1581,16 +1582,15 @@ { GLMatrix wTransform (transform); GLWindowPaintAttrib wAttrib (attrib); - CompPoint vp; CompRegion clip (region); - screen->viewportForGeometry (window->geometry (), vp); - if (eScreen->expoActive) { - float opacity = 1.0; - bool hide; - bool zoomAnim; + float opacity = 1.0; + bool hide; + bool zoomAnim; + CompPoint vp; + screen->viewportForGeometry (window->geometry (), vp); zoomAnim = eScreen->optionGetExpoAnimation () == ExpoScreen::ExpoAnimationZoom; @@ -1621,39 +1621,40 @@ mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; else wAttrib.opacity = wAttrib.opacity * opacity; - } - /* Stretch maximized windows a little so that you don't - * have an awkward gap */ + /* Stretch maximized windows a little so that you don't + * have an awkward gap */ - if (window->state () & MAXIMIZE_STATE) - { - CompOutput *o = &screen->outputDevs ()[screen->outputDeviceForGeometry(window->geometry())]; - float yS = 1.0 + ((o->height () / (float) window->height ()) - 1.0f) * sigmoidProgress (eScreen->expoCam); - wTransform.translate (window->x () + window->width () / 2, - window->y () + window->height (), - 0.0f); - wTransform.scale (1.0f, yS, 1.0f); - wTransform.translate (-(window->x () + window->width () / 2), - -(window->y () + window->height ()), - 0.0f); + if (window->state () & MAXIMIZE_STATE && + !window->border ().top) + { + CompOutput *o = &screen->outputDevs ()[screen->outputDeviceForGeometry(window->geometry())]; + float yS = 1.0 + ((o->height () / (float) window->height ()) - 1.0f) * sigmoidProgress (eScreen->expoCam); + wTransform.translate (window->x () + window->width () / 2, + window->y () + window->height (), + 0.0f); + wTransform.scale (1.0f, yS, 1.0f); + wTransform.translate (-(window->x () + window->width () / 2), + -(window->y () + window->height ()), + 0.0f); - if (eScreen->paintingVp != vp) - mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + if (eScreen->paintingVp != vp) + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; - mask |= PAINT_WINDOW_TRANSFORMED_MASK; - } - - if (std::find (eScreen->dndWindows.begin(), eScreen->dndWindows.end (), window) != eScreen->dndWindows.end ()) - { - if (!eScreen->paintingDndWindow) - { - mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + mask |= PAINT_WINDOW_TRANSFORMED_MASK; } - else + + if (std::find (eScreen->dndWindows.begin(), eScreen->dndWindows.end (), window) != eScreen->dndWindows.end ()) { - mask |= PAINT_WINDOW_TRANSFORMED_MASK; - clip = infiniteRegion; + if (!eScreen->paintingDndWindow) + { + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + } + else + { + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + clip = infiniteRegion; + } } } diff -Nru compiz-plugins-main-0.9.6.2011.10/expo/src/glow.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/expo/src/glow.cpp --- compiz-plugins-main-0.9.6.2011.10/expo/src/glow.cpp 2011-10-20 12:37:25.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/expo/src/glow.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -47,8 +47,19 @@ const CompRegion &paintRegion, unsigned int mask) { - CompRegion reg; - int i; + CompRegion reg; + int i; + GLushort colorData[4]; + const GLushort *selColorData = ExpoScreen::get (screen)->optionGetSelectedColor (); + float alpha = (float) selColorData[3] / 65535.0f; + + /* Premultiply color */ + colorData[0] = selColorData[0] * alpha; + colorData[1] = selColorData[1] * alpha; + colorData[2] = selColorData[2] * alpha; + colorData[3] = selColorData[3]; + + gWindow->vertexBuffer ()->begin (); /* There are 8 glow parts of the glow texture which we wish to paint * separately with different transformations @@ -62,24 +73,21 @@ reg.boundingRect ().y1 () < reg.boundingRect ().y2 ()) { GLTexture::MatrixList matl; - GLushort *colorData = (GLushort*) calloc (4, sizeof (GLushort)); reg = CompRegion (reg.boundingRect ().x1 (), reg.boundingRect ().y1 (), reg.boundingRect ().width (), reg.boundingRect ().height ()); matl.push_back (mGlowQuads[i].mMatrix); - gWindow->vertexBuffer ()->begin (); - colorData = ExpoScreen::get (screen)->optionGetSelectedColor (); - colorData[0] *= colorData[3]; - colorData[1] *= colorData[3]; - colorData[2] *= colorData[3]; - gWindow->vertexBuffer ()->addColors (1, colorData); + /* Add color data for all 6 vertices of the quad */ + for (int n = 0; n < 6; n++) + gWindow->vertexBuffer ()->addColors (1, colorData); gWindow->glAddGeometry (matl, reg, paintRegion); - gWindow->vertexBuffer ()->end (); } } + gWindow->vertexBuffer ()->end (); + //GLScreen::get (screen)->setTexEnvMode (GL_MODULATE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff -Nru compiz-plugins-main-0.9.6.2011.10/grid/src/grid.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/grid/src/grid.cpp --- compiz-plugins-main-0.9.6.2011.10/grid/src/grid.cpp 2011-10-20 12:37:25.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/grid/src/grid.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -410,6 +410,7 @@ GLfloat vertexData[12]; GLushort colorData[4]; GLushort *color; + GLboolean isBlendingEnabled; getPaintRectangle (rect); @@ -418,17 +419,19 @@ sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); + glGetBooleanv (GL_BLEND, &isBlendingEnabled); + glEnable (GL_BLEND); for (iter = animations.begin (); iter != animations.end () && animating; iter++) { Animation& anim = *iter; - GLushort alpha = optionGetFillColorAlpha () * anim.opacity; + float alpha = ((float) optionGetFillColorAlpha () / 65535.0f) * anim.opacity; color = optionGetFillColor (); colorData[0] = alpha * color[0]; colorData[1] = alpha * color[1]; colorData[2] = alpha * color[2]; - colorData[3] = alpha; + colorData[3] = alpha * 65535.0f; vertexData[0] = anim.currentRect.x1 (); vertexData[1] = anim.currentRect.y1 (); @@ -456,14 +459,14 @@ anim.currentRect.width () - 2, anim.currentRect.height () - 2); - alpha = optionGetOutlineColorAlpha () * anim.opacity; + alpha = ((float) optionGetOutlineColorAlpha () / 65535.0f) * anim.opacity; /* draw outline */ color = optionGetOutlineColor (); colorData[0] = alpha * color[0]; colorData[1] = alpha * color[1]; colorData[2] = alpha * color[2]; - colorData[3] = alpha; + colorData[3] = alpha * 65535.0f; vertexData[0] = anim.currentRect.x1 (); vertexData[1] = anim.currentRect.y1 (); @@ -487,13 +490,13 @@ if (!animating) { /* fill rectangle */ - GLushort alpha = optionGetFillColorAlpha (); + float alpha = (float) optionGetFillColorAlpha () / 65535.0f; color = optionGetFillColor (); colorData[0] = alpha * color[0]; colorData[1] = alpha * color[1]; colorData[2] = alpha * color[2]; - colorData[3] = alpha; + colorData[3] = alpha * 65535.0f; vertexData[0] = rect.x1 (); vertexData[1] = rect.y1 (); @@ -517,13 +520,13 @@ rect.width () - 2, rect.height () - 2); /* draw outline */ - alpha = optionGetOutlineColorAlpha (); + alpha = (float) optionGetOutlineColorAlpha () / 65535.0f; color = optionGetOutlineColor (); colorData[0] = alpha * color[0]; colorData[1] = alpha * color[1]; colorData[2] = alpha * color[2]; - colorData[3] = alpha; + colorData[3] = alpha * 65535.0f; /* draw outline */ vertexData[0] = rect.x1 (); @@ -544,6 +547,9 @@ streamingBuffer->end (); streamingBuffer->render (sTransform); } + + if (!isBlendingEnabled) + glDisable (GL_BLEND); } bool diff -Nru compiz-plugins-main-0.9.6.2011.10/.pc/applied-patches compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/applied-patches --- compiz-plugins-main-0.9.6.2011.10/.pc/applied-patches 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/applied-patches 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1,4 @@ +fix-862261.patch +fix-864476.patch +fix-868121.patch +fix-868392.patch diff -Nru compiz-plugins-main-0.9.6.2011.10/.pc/fix-862261.patch/snap/src/snap.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-862261.patch/snap/src/snap.cpp --- compiz-plugins-main-0.9.6.2011.10/.pc/fix-862261.patch/snap/src/snap.cpp 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-862261.patch/snap/src/snap.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1,833 @@ +/* + * Compiz snap plugin + * Author : Guillaume "iXce" Seguin + * Email : ixce@beryl-project.org + * + * Ported to compiz by : Patrick "marex" Niklaus + * Email : marex@beryl-project.org + * + * Ported to C++ by : Travis Watkins + * Email : amaranth@ubuntu.com + * + * Copyright (C) 2009 Guillaume Seguin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * TODO + * - Apply Edge Resistance to resize + */ + +#include +#include +#include + +#include "snap.h" + + +COMPIZ_PLUGIN_20090315 (snap, SnapPluginVTable); + +// helper functions + +/* + * Wrapper functions to avoid infinite notify loops + */ +void +SnapWindow::move (int dx, int dy) +{ + skipNotify = true; + window->move (dx, dy, true); + screen->warpPointer (dx, dy); + skipNotify = false; +} + +void +SnapWindow::resize (int dx, int dy, int dwidth, int dheight) +{ + CompWindow::Geometry geometry = window->geometry (); + skipNotify = true; + window->resize (geometry.x () + dx, geometry.y () + dy, + geometry.width () + dwidth, geometry.height () + dheight, + geometry.border ()); + skipNotify = false; +} + +void +SnapWindow::addEdge (Window id, + int position, + int start, + int end, + EdgeType type, + bool screenEdge) +{ + Edge edge; + + edge.position = position; + edge.start = start; + edge.end = end; + edge.type = type; + edge.screenEdge = screenEdge; + edge.snapped = false; + edge.passed = false; + edge.id = id; + + edges.push_back (edge); +} + +/* + * Add an edge for each rectangle of the region + */ +void +SnapWindow::addRegionEdges (Edge *parent, CompRegion region) +{ + int position, start, end; + + foreach (const CompRect &r, region.rects ()) + { + switch (parent->type) + { + case LeftEdge: + case RightEdge: + position = r.x1 (); + start = r.y1 (); + end = r.y2 (); + break; + case TopEdge: + case BottomEdge: + default: + position = r.y1 (); + start = r.x1 (); + end = r.x2 (); + } + + addEdge (parent->id, position, start, end, + parent->type, parent->screenEdge); + edges.back ().passed = parent->passed; + } +} + +/* Checks if a window is considered a snap window. If it's + * not visible, returns false. If it's a panel and we're + * snapping to screen edges, it's considered a snap-window. + */ + +#define UNLIKELY(x) __builtin_expect(!!(x),0) + +static inline bool +isSnapWindow (CompWindow *w) +{ + SNAP_SCREEN (screen); + + if (UNLIKELY(!w)) + return false; + if (!w->isViewable ()) + return false; + if ((w->type () & SNAP_WINDOW_TYPE) && + (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesWindowEdgesMask)) + return true; + if (w->struts () && + (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask)) + return true; + return false; +} + +// Edges update functions ------------------------------------------------------ +/* + * Detect visible windows edges + */ +void +SnapWindow::updateWindowsEdges () +{ + CompRegion edgeRegion, resultRegion; + CompRect input; + bool remove = false; + + // First add all the windows + foreach (CompWindow *w, screen->windows ()) + { + + // Just check that we're not trying to snap to current window, + // that the window is not invisible and of a valid type + if (w == window || !isSnapWindow (w)) + { + continue; + } + + input = w->borderRect (); + addEdge (w->id (), input.top (), input.left (), + input.right (), TopEdge, false); + addEdge (w->id (), input.bottom (), input.left (), + input.right (), BottomEdge, false); + addEdge (w->id (), input.left (), input.top (), + input.bottom (), LeftEdge, false); + addEdge (w->id (), input.right (), input.top (), + input.bottom (), RightEdge, false); + } + + // 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 + foreach (CompWindow *w, screen->windows ()) + { + if (w == window || !isSnapWindow (w)) + continue; + + // can't use foreach here because we need the iterator for erase() + for (std::list::iterator it = edges.begin (); it != edges.end (); ) + { + Edge *e = &*it; + CompRect rect; + + if (!e->passed) + { + if (e->id == w->id ()) + e->passed = true; + it++; + continue; + } + + switch (e->type) + { + case LeftEdge: + case RightEdge: + rect.setGeometry (e->position, + e->start, + 1, + e->end - e->start); + break; + case TopEdge: + case BottomEdge: + default: + rect.setGeometry (e->start, + e->position, + e->end - e->start, + 1); + } + + // If the edge is in the window region, remove it, + // if it's partly in the region, split it + edgeRegion = CompRegion (rect); + resultRegion = edgeRegion - w->region (); + if (resultRegion.isEmpty ()) + { + remove = true; + } + else if (edgeRegion != resultRegion) + { + addRegionEdges (e, resultRegion); + remove = true; + } + + if (remove) + { + it = edges.erase (it); + remove = false; + } + else + { + it++; + } + } + } +} + +/* + * Loop on outputDevs and add the extents as edges + * Note that left side is a right edge, right side a left edge, + * top side a bottom edge and bottom side a top edge, + * since they will be snapped as the right/left/bottom/top edge of a window + */ +void +SnapWindow::updateScreenEdges () +{ + CompRegion edgeRegion, resultRegion; + bool remove = false; + + foreach (CompOutput output, screen->outputDevs ()) + { + const CompRect& area = output.workArea (); + addEdge (0, area.top (), area.left (), area.right () - 1, + BottomEdge, true); + addEdge (0, area.bottom (), area.left (), area.right () - 1, + TopEdge, true); + addEdge (0, area.left (), area.top (), area.bottom () - 1, + RightEdge, true); + addEdge (0, area.right (), area.top (), area.bottom () - 1, + LeftEdge, true); + } + + // Drop screen edges parts that are under struts, basically apply the + // same strategy than for windows edges visibility + foreach (CompWindow *w, screen->windows ()) + { + if (w == window || !w->struts ()) + continue; + + for (std::list::iterator it = edges.begin (); it != edges.end ();) + { + Edge *e = &*it; + CompRect rect; + + if (!e->screenEdge) + { + it++; + continue; + } + + switch (e->type) + { + case LeftEdge: + case RightEdge: + rect.setGeometry (e->position, + e->start, + 1, + e->end - e->start); + break; + case TopEdge: + case BottomEdge: + default: + rect.setGeometry (e->start, + e->position, + e->end - e->start, + 1); + } + + edgeRegion = CompRegion (rect); + resultRegion = edgeRegion - w->region (); + if (resultRegion.isEmpty ()) + { + remove = true; + } + else if (edgeRegion != resultRegion) + { + addRegionEdges (e, resultRegion); + remove = true; + } + + if (remove) + { + it = edges.erase (it); + remove = false; + } + else + { + it++; + } + } + } +} + +/* + * Clean edges and fill it again with appropriate edges + */ +void +SnapWindow::updateEdges () +{ + SNAP_SCREEN (screen); + + edges.clear (); + updateWindowsEdges (); + + if (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask) + updateScreenEdges (); +} + +// Edges checking functions (move) --------------------------------------------- + +/* + * Find nearest edge in the direction set by "type", + * w is the grabbed window, position/start/end are the window edges coordinates + * before : if true the window has to be before the edge (top/left being origin) + * snapDirection : just an helper, related to type + */ +void +SnapWindow::moveCheckNearestEdge (int position, + int start, + int end, + bool before, + EdgeType type, + int snapDirection) +{ + SNAP_SCREEN (screen); + + Edge *edge = &edges.front (); + int dist, min = 65535; + + foreach (Edge ¤t, edges) + { + // Skip wrong type or outbound edges + if (current.type != type || current.end < start || current.start > end) + continue; + + // Compute distance + dist = before ? position - current.position : current.position - position; + // Update minimum distance if needed + if (dist < min && dist >= 0) + { + min = dist; + edge = ¤t; + } + // 0-dist edge, just break + if (dist == 0) + break; + // Unsnap edges that aren't snapped anymore + if (current.snapped && dist > ss->optionGetResistanceDistance ()) + current.snapped = false; + } + // We found a 0-dist edge, or we have a snapping candidate + if (min == 0 || (min <= ss->optionGetAttractionDistance () + && ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask)) + { + // Update snapping data + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + snapGeometry = window->serverGeometry (); + this->snapDirection |= snapDirection; + } + // Attract the window if needed, moving it of the correct dist + if (min != 0 && !edge->snapped) + { + edge->snapped = true; + switch (type) + { + case LeftEdge: + move (min, 0); + break; + case RightEdge: + move (-min, 0); + break; + case TopEdge: + move (0, min); + break; + case BottomEdge: + move (0, -min); + break; + default: + break; + } + } + } +} + +/* + * Call the previous function for each of the 4 sides of the window + */ +void +SnapWindow::moveCheckEdges () +{ + CompRect input (window->borderRect ()); + moveCheckNearestEdge (input.left (), input.top (), input.bottom (), + true, RightEdge, HorizontalSnap); + moveCheckNearestEdge (input.right (), input.top (), input.bottom (), + false, LeftEdge, HorizontalSnap); + moveCheckNearestEdge (input.top (), input.left (), input.right (), + true, BottomEdge, VerticalSnap); + moveCheckNearestEdge (input.bottom (), input.left (), input.right (), + false, TopEdge, VerticalSnap); +} + +// Edges checking functions (resize) ------------------------------------------- + +/* + * Similar function for Snap on Resize + */ +void +SnapWindow::resizeCheckNearestEdge (int position, + int start, + int end, + bool before, + EdgeType type, + int snapDirection) +{ + SNAP_SCREEN (screen); + + Edge *edge = &edges.front (); + int dist, min = 65535; + + foreach (Edge ¤t, edges) + { + // Skip wrong type or outbound edges + if (current.type != type || current.end < start || current.start > end) + continue; + + // Compute distance + dist = before ? position - current.position : current.position - position; + // Update minimum distance if needed + if (dist < min && dist >= 0) + { + min = dist; + edge = ¤t; + } + // 0-dist edge, just break + if (dist == 0) + break; + // Unsnap edges that aren't snapped anymore + if (current.snapped && dist > ss->optionGetResistanceDistance ()) + current.snapped = false; + } + // We found a 0-dist edge, or we have a snapping candidate + if (min == 0 || (min <= ss->optionGetAttractionDistance () + && ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask)) + { + // Update snapping data + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + snapGeometry = window->serverGeometry (); + this->snapDirection |= snapDirection; + } + // FIXME : this needs resize-specific code. + // Attract the window if needed, moving it of the correct dist + if (min != 0 && !edge->snapped) + { + edge->snapped = true; + switch (type) + { + case LeftEdge: + resize (min, 0, 0, 0); + break; + case RightEdge: + resize (-min, 0, 0, 0); + break; + case TopEdge: + resize (0, min, 0, 0); + break; + case BottomEdge: + resize (0, -min, 0, 0); + break; + default: + break; + } + } + } +} + +/* + * Call the previous function for each of the 4 sides of the window + */ +void +SnapWindow::resizeCheckEdges (int dx, int dy, int dwidth, int dheight) +{ + CompRect input (window->borderRect ()); + + resizeCheckNearestEdge (input.left (), input.top (), input.bottom (), + true, RightEdge, HorizontalSnap); + resizeCheckNearestEdge (input.right (), input.top (), input.bottom (), + false, LeftEdge, HorizontalSnap); + resizeCheckNearestEdge (input.top (), input.left (), input.right (), + true, BottomEdge, VerticalSnap); + resizeCheckNearestEdge (input.bottom (), input.left (), input.right (), + false, TopEdge, VerticalSnap); +} + +// Check if avoidSnap is matched, and enable/disable snap consequently +void +SnapScreen::handleEvent (XEvent *event) +{ + if (event->type == screen->xkbEvent ()) + { + XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event; + + if (xkbEvent->xkb_type == XkbStateNotify) + { + XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event; + + unsigned int mods = 0xffffffff; + if (avoidSnapMask) + mods = avoidSnapMask; + + if ((stateEvent->mods & mods) == mods) + snapping = false; + else + snapping = true; + } + } + + screen->handleEvent (event); +} + +// Events notifications -------------------------------------------------------- + +void +SnapWindow::resizeNotify (int dx, int dy, int dwidth, int dheight) +{ + SNAP_SCREEN (screen); + + window->resizeNotify (dx, dy, dwidth, dheight); + + // avoid-infinite-notify-loop mode/not grabbed + if (skipNotify || !(grabbed & ResizeGrab)) + return; + + // we have to avoid snapping but there's still some buffered moving + if (!ss->snapping && (m_dx || m_dy || m_dwidth || m_dheight)) + { + resize (m_dx, m_dy, m_dwidth, m_dheight); + m_dx = m_dy = m_dwidth = m_dheight = 0; + return; + } + + // avoiding snap, nothing buffered + if (!ss->snapping) + return; + + // apply edge resistance + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + // If there's horizontal snapping, add dx to current buffered + // dx and resist (move by -dx) or release the window and move + // by buffered dx - dx, same for dh + if (!snapGeometry.isEmpty () && snapDirection & HorizontalSnap) + { + m_dx += dx; + if (m_dx < ss->optionGetResistanceDistance () + && m_dx > -ss->optionGetResistanceDistance ()) + { + resize (-dx, 0, 0, 0); + } + else + { + resize (m_dx - dx, 0, 0, 0); + m_dx = 0; + if (!m_dwidth) + snapDirection &= VerticalSnap; + } + m_dwidth += dwidth; + if (m_dwidth < ss->optionGetResistanceDistance () + && m_dwidth > -ss->optionGetResistanceDistance ()) + { + resize (0, 0, -dwidth, 0); + } + else + { + resize (0, 0, m_dwidth - dwidth, 0); + m_dwidth = 0; + if (!m_dx) + snapDirection &= VerticalSnap; + } + } + + // Same for vertical snapping and dy/dh + if (snapGeometry.isEmpty () && snapDirection & VerticalSnap) + { + m_dy += dy; + if (m_dy < ss->optionGetResistanceDistance () + && m_dy > -ss->optionGetResistanceDistance ()) + { + resize (0, -dy, 0, 0); + } + else + { + resize (0, m_dy - dy, 0, 0); + m_dy = 0; + if (!m_dheight) + snapDirection &= HorizontalSnap; + } + m_dheight += dheight; + if (m_dheight < ss->optionGetResistanceDistance () + && m_dheight > -ss->optionGetResistanceDistance ()) + { + resize (0, 0, 0, -dheight); + } + else + { + resize (0, 0, 0, m_dheight - dheight); + m_dheight = 0; + if (!m_dy) + snapDirection &= HorizontalSnap; + } + } + // If we are no longer snapping in any direction, reset snapped + if (!snapGeometry.isEmpty () && !snapDirection) + snapGeometry = CompWindow::Geometry (); + } + + // If we don't already snap vertically and horizontally, + // check edges status + if (snapDirection != (VerticalSnap | HorizontalSnap)) + resizeCheckEdges (dx, dy, dwidth, dheight); +} + +void +SnapWindow::moveNotify (int dx, int dy, bool immediate) +{ + SNAP_SCREEN (screen); + + window->moveNotify (dx, dy, immediate); + + // avoid-infinite-notify-loop mode/not grabbed + if (skipNotify || !(grabbed & MoveGrab)) + return; + + // we have to avoid snapping but there's still some buffered moving + if (!ss->snapping && (m_dx || m_dy)) + { + move (m_dx, m_dy); + m_dx = m_dy = 0; + return; + } + + // avoiding snap, nothing buffered + if (!ss->snapping) + return; + + // apply edge resistance + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + // If there's horizontal snapping, add dx to current buffered + // dx and resist (move by -dx) or release the window and move + // by buffered dx - dx + if (!snapGeometry.isEmpty () && snapDirection & HorizontalSnap) + { + m_dx += dx; + if (m_dx < ss->optionGetResistanceDistance () + && m_dx > -ss->optionGetResistanceDistance ()) + { + dx = snapGeometry.x () - window->geometry ().x (); + move (dx, 0); + } + else + { + move (m_dx - dx, 0); + m_dx = 0; + snapDirection &= VerticalSnap; + } + } + // Same for vertical snapping and dy + if (!snapGeometry.isEmpty () && snapDirection & VerticalSnap) + { + m_dy += dy; + if (m_dy < ss->optionGetResistanceDistance () + && m_dy > -ss->optionGetResistanceDistance ()) + { + dy = snapGeometry.y () - window->geometry ().y (); + move (0, dy); + } + else + { + move (0, m_dy - dy); + m_dy = 0; + snapDirection &= HorizontalSnap; + } + } + // If we are no longer snapping in any direction, reset snapped + if (!snapGeometry.isEmpty () && !snapDirection) + snapGeometry = CompWindow::Geometry (); + } + // If we don't already snap vertically and horizontally, + // check edges status + if (snapDirection != (VerticalSnap | HorizontalSnap)) + moveCheckEdges (); +} + +/* + * Initiate snap, get edges + */ +void +SnapWindow::grabNotify (int x, int y, unsigned int state, unsigned int mask) +{ + grabbed = (mask & CompWindowGrabResizeMask) ? ResizeGrab : MoveGrab; + updateEdges (); + + window->grabNotify (x, y, state, mask); +} + +/* + * Clean edges data, reset dx/dy to avoid buggy moves + * when snap will be triggered again. + */ +void +SnapWindow::ungrabNotify () +{ + edges.clear (); + + snapGeometry = CompWindow::Geometry (); + snapDirection = 0; + grabbed = 0; + m_dx = m_dy = m_dwidth = m_dheight = 0; + + window->ungrabNotify (); +} + +// Internal stuff -------------------------------------------------------------- + +void +SnapScreen::optionChanged (CompOption *opt, SnapOptions::Options num) +{ + switch (num) + { + case SnapOptions::AvoidSnap: + { + unsigned int mask = optionGetAvoidSnapMask (); + avoidSnapMask = 0; + if (mask & AvoidSnapShiftMask) + avoidSnapMask |= ShiftMask; + if (mask & AvoidSnapAltMask) + avoidSnapMask |= CompAltMask; + if (mask & AvoidSnapControlMask) + avoidSnapMask |= ControlMask; + if (mask & AvoidSnapMetaMask) + avoidSnapMask |= CompMetaMask; + } + + default: + break; + } +} + +SnapScreen::SnapScreen (CompScreen *screen) : + PluginClassHandler (screen), + SnapOptions (), + snapping (true), + avoidSnapMask (0) +{ + ScreenInterface::setHandler (screen); + +#define setNotify(func) \ + optionSet##func##Notify (boost::bind (&SnapScreen::optionChanged, this, _1, _2)) + + setNotify (AvoidSnap); +} + +SnapWindow::SnapWindow (CompWindow *window) : + PluginClassHandler (window), + window (window), + snapDirection (0), + m_dx (0), + m_dy (0), + m_dwidth (0), + m_dheight (0), + snapGeometry (0, 0, 0, 0, 0), + grabbed (0), + skipNotify (false) +{ + WindowInterface::setHandler (window); +} + +SnapWindow::~SnapWindow () +{ +} + +bool +SnapPluginVTable::init () +{ + if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION)) + return false; + + return true; +} + diff -Nru compiz-plugins-main-0.9.6.2011.10/.pc/fix-864476.patch/animation/src/animation.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-864476.patch/animation/src/animation.cpp --- compiz-plugins-main-0.9.6.2011.10/.pc/fix-864476.patch/animation/src/animation.cpp 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-864476.patch/animation/src/animation.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1,2967 @@ +/** + * Animation plugin for compiz/beryl + * + * animation.c + * + * Copyright : (C) 2006 Erkin Bahceci + * E-mail : erkinbah@gmail.com + * + * Based on Wobbly and Minimize plugins by + * : David Reveman + * E-mail : davidr@novell.com> + * + * Airplane added by : Carlo Palma + * E-mail : carlopalma@salug.it + * Based on code originally written by Mark J. Kilgard + * + * Beam-Up added by : Florencio Guimaraes + * E-mail : florencio@nexcorp.com.br + * + * Fold and Skewer added by : Tomasz Kolodziejski + * E-mail : tkolodziejski@gmail.com + * + * Hexagon tessellator added by : Mike Slegeir + * E-mail : mikeslegeir@mail.utexas.edu> + * + * Particle system added by : (C) 2006 Dennis Kasprzyk + * E-mail : onestone@beryl-project.org + * + * Ported to GLES by : Travis Watkins + * (C) 2011 Linaro Limited + * E-mail : travis.watkins@linaro.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + **/ + +/* + * TODO: + * + * - Custom bounding box update function for Airplane + * + * - Auto direction option: Close in opposite direction of opening + * - Proper side surface normals for lighting + * - decoration shadows + * - shadow quad generation + * - shadow texture coords (from clip tex. matrices) + * - draw shadows + * - fade in shadows + * + * - Voronoi tessellation + * - Brick tessellation + * - Triangle tessellation + * - Hexagonal tessellation + * + * Effects: + * - Circular action for tornado type fx + * - Tornado 3D (especially for minimize) + * - Helix 3D (hor. strips descend while they rotate and fade in) + * - Glass breaking 3D + * - Gaussian distr. points (for gradually increasing polygon size + * starting from center or near mouse pointer) + * - Drawing cracks + * - Gradual cracking + * + * - fix slowness during transparent cube with <100 opacity + * - fix occasional wrong side color in some windows + * - fix on top windows and panels + * (These two only matter for viewing during Rotate Cube. + * All windows should be painted with depth test on + * like 3d-plugin does) + * - play better with rotate (fix cube face drawn on top of polygons + * after 45 deg. rotation) + * + */ + +#include +#include +#include +#include +#include +#include "private.h" + +class AnimPluginVTable : + public CompPlugin::VTableForScreenAndWindow +{ +public: + bool init (); + void fini (); +}; + +COMPIZ_PLUGIN_20090315 (animation, AnimPluginVTable); + +#define FAKE_ICON_SIZE 4 + +const char *eventNames[AnimEventNum] = +{"Open", "Close", "Minimize", "Shade", "Focus"}; + +int chosenEffectOptionIds[AnimEventNum] = +{ + AnimationOptions::OpenEffects, + AnimationOptions::CloseEffects, + AnimationOptions::MinimizeEffects, + AnimationOptions::ShadeEffects, + AnimationOptions::FocusEffects +}; + +int randomEffectOptionIds[AnimEventNum] = +{ + AnimationOptions::OpenRandomEffects, + AnimationOptions::CloseRandomEffects, + AnimationOptions::MinimizeRandomEffects, + AnimationOptions::ShadeRandomEffects, + -1 +}; + +int customOptionOptionIds[AnimEventNum] = +{ + AnimationOptions::OpenOptions, + AnimationOptions::CloseOptions, + AnimationOptions::MinimizeOptions, + AnimationOptions::ShadeOptions, + AnimationOptions::FocusOptions +}; + +int matchOptionIds[AnimEventNum] = +{ + AnimationOptions::OpenMatches, + AnimationOptions::CloseMatches, + AnimationOptions::MinimizeMatches, + AnimationOptions::ShadeMatches, + AnimationOptions::FocusMatches +}; + +int durationOptionIds[AnimEventNum] = +{ + AnimationOptions::OpenDurations, + AnimationOptions::CloseDurations, + AnimationOptions::MinimizeDurations, + AnimationOptions::ShadeDurations, + AnimationOptions::FocusDurations +}; + +// Bind each effect in the list of chosen effects for every event, to the +// corresponding animation effect (i.e. effect with that name) if it is +// provided by a plugin, otherwise set it to None. +void +PrivateAnimScreen::updateEventEffects (AnimEvent e, + bool forRandom, + bool callPost) +{ + CompOption::Value::Vector *listVal; + EffectSet *effectSet; + if (forRandom) + { + listVal = &getOptions ()[(unsigned)randomEffectOptionIds[e]].value (). + list (); + effectSet = &mRandomEffects[e]; + } + else + { + listVal = &getOptions ()[(unsigned)chosenEffectOptionIds[e]].value (). + list (); + effectSet = &mEventEffects[e]; + } + unsigned int n = listVal->size (); + + effectSet->effects.clear (); + effectSet->effects.reserve (n); + + AnimEffectVector &eventEffectsAllowed = mEventEffectsAllowed[e]; + + for (unsigned int r = 0; r < n; r++) // for each row + { + const CompString &animName = (*listVal)[r].s (); + + // Find the animation effect with matching name + AnimEffectVector::iterator it = + find_if (eventEffectsAllowed.begin (), + eventEffectsAllowed.end (), + boost::bind (&AnimEffectInfo::matchesEffectName, + _1, animName)); + + effectSet->effects.push_back (it == eventEffectsAllowed.end () ? + AnimEffectNone : *it); + } + + if (callPost) + { + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->postUpdateEventEffects (e, forRandom); + } +} + +void +PrivateAnimScreen::updateAllEventEffects () +{ + // for each anim event + for (int e = 0; e < AnimEventNum; e++) + updateEventEffects ((AnimEvent)e, false); + + // for each anim event except focus + for (int e = 0; e < AnimEventNum - 1; e++) + updateEventEffects ((AnimEvent)e, true); +} + +bool +PrivateAnimScreen::isAnimEffectInList (AnimEffect theEffect, + EffectSet &effectList) +{ + for (unsigned int i = 0; i < effectList.effects.size (); i++) + if (effectList.effects[i] == theEffect) + return true; + return false; +} + +bool +PrivateAnimScreen::isAnimEffectPossibleForEvent (AnimEffect theEffect, + AnimEvent event) +{ + // Check all rows to see if the effect is chosen there + unsigned int nRows = mEventEffects[event].effects.size (); + for (unsigned int i = 0; i < nRows; i++) + { + AnimEffect chosenEffect = mEventEffects[event].effects[i]; + // if chosen directly + if (chosenEffect == theEffect) + return true; + // if chosen in random pool + if (mRandomEffects[event].effects.size () && + chosenEffect == AnimEffectRandom && + isAnimEffectInList (theEffect, mRandomEffects[event])) + return true; + } + return false; +} + +bool +PrivateAnimScreen::isAnimEffectPossible (AnimEffect theEffect) +{ + for (int e = 0; e < AnimEventNum; e++) + if (isAnimEffectPossibleForEvent (theEffect, (AnimEvent)e)) + return true; + return false; +} + +bool +PrivateAnimScreen::isRestackAnimPossible () +{ + // Check all rows to see if the chosen effect is a restack animation + unsigned int nRows = mEventEffects[AnimEventFocus].effects.size (); + + for (unsigned int i = 0; i < nRows; i++) + { + AnimEffect chosenEffect = mEventEffects[(unsigned)AnimEventFocus]. + effects[i]; + if (chosenEffect->isRestackAnim) + return true; + } + return false; +} + +bool +AnimScreen::isRestackAnimPossible () +{ + return priv->isRestackAnimPossible (); +} + +// Extension functions + +void +AnimScreen::addExtension (ExtensionPluginInfo *extensionPluginInfo) +{ + priv->addExtension (extensionPluginInfo, true); +} + +void +PrivateAnimScreen::addExtension (ExtensionPluginInfo *extensionPluginInfo, + bool shouldInitPersistentData) +{ + mExtensionPlugins.push_back (extensionPluginInfo); + + unsigned int nPluginEffects = extensionPluginInfo->nEffects; + + bool eventEffectsNeedUpdate[AnimEventNum] = + {false, false, false, false, false}; + + // Put this plugin's effects into mEventEffects and + // mEventEffectsAllowed + for (unsigned int j = 0; j < nPluginEffects; j++) + { + const AnimEffect effect = extensionPluginInfo->effects[j]; + + // Update allowed effects for each event + for (int e = 0; e < AnimEventNum; e++) + { + if (effect->usedForEvents[e]) + { + mEventEffectsAllowed[e].push_back (effect); + eventEffectsNeedUpdate[e] = true; + } + } + } + + for (int e = 0; e < AnimEventNum; e++) + if (eventEffectsNeedUpdate[e]) + { + updateEventEffects ((AnimEvent)e, false, false); + if (e != AnimEventFocus) + updateEventEffects ((AnimEvent)e, true, false); + } + + if (shouldInitPersistentData) + { + const CompWindowList &pl = pushLockedPaintList (); + // Initialize persistent window data for the extension plugin + foreach (CompWindow *w, pl) + { + AnimWindow *aw = AnimWindow::get (w); + extensionPluginInfo->initPersistentData (aw); + } + + popLockedPaintList (); + } +} + +void +AnimScreen::removeExtension (ExtensionPluginInfo *extensionPluginInfo) +{ + priv->removeExtension (extensionPluginInfo); +} + +void +PrivateAnimScreen::removeExtension (ExtensionPluginInfo *extensionPluginInfo) +{ + // Stop all ongoing animations + const CompWindowList &pl = pushLockedPaintList (); + + foreach (CompWindow *w, pl) + { + PrivateAnimWindow *aw = AnimWindow::get (w)->priv; + if (aw->curAnimation ()) + aw->postAnimationCleanUp (); + } + + popLockedPaintList (); + + // Find the matching plugin and delete it + + ExtensionPluginVector::iterator it = find (mExtensionPlugins.begin (), + mExtensionPlugins.end (), + extensionPluginInfo); + + if (it == mExtensionPlugins.end ()) + return; // couldn't find that extension plugin + + mExtensionPlugins.erase (it); + + if (extensionPluginInfo->nEffects == 0) + return; // no animation effects -> we're done here + + + // Also delete the "allowed effect" entries for that plugin + + for (int e = 0; e < AnimEventNum; e++) + { + AnimEffectVector &eventEffectsAllowed = mEventEffectsAllowed[e]; + + // Find the first animation effect with matching name + AnimEffectVector::iterator itBeginEffect = + find_if (eventEffectsAllowed.begin (), + eventEffectsAllowed.end (), + boost::bind (&AnimEffectInfo::matchesPluginName, + _1, extensionPluginInfo->name)); + + if (itBeginEffect == eventEffectsAllowed.end ()) + continue; // plugin didn't provide any effects for this event + + // Find the first animation effect with non-matching name, + // starting with itBeginEffect + AnimEffectVector::iterator itEndEffect = + find_if (itBeginEffect, + eventEffectsAllowed.end (), + boost::bind (&AnimEffectInfo::matchesPluginName, + _1, extensionPluginInfo->name) == false); + + eventEffectsAllowed.erase (itBeginEffect, itEndEffect); + + // Update event effects to complete removal + updateEventEffects ((AnimEvent)e, false); + if (e != AnimEventFocus) + updateEventEffects ((AnimEvent)e, true); + } + + const CompWindowList &cpl = pushLockedPaintList (); + + // Destroy persistent window data for the extension plugin + foreach (CompWindow *w, cpl) + { + AnimWindow *aw = AnimWindow::get (w); + extensionPluginInfo->destroyPersistentData (aw); + } + + popLockedPaintList (); +} + +ExtensionPluginInfo::ExtensionPluginInfo (const CompString &name, + unsigned int nEffects, + AnimEffect *effects, + CompOption::Vector *effectOptions, + unsigned int firstEffectOptionIndex) : + name (name), + nEffects (nEffects), + effects (effects), + effectOptions (effectOptions), + firstEffectOptionIndex (firstEffectOptionIndex) +{ +} + +// End of extension functions + +Animation::Animation (CompWindow *w, + WindowEvent curWindowEvent, + float duration, + const AnimEffect info, + const CompRect &icon) : + mWindow (w), + mAWindow (AnimWindow::get (w)), + mTotalTime (duration), + mRemainingTime (duration), + mTimeElapsedWithinTimeStep (0), + mOverrideProgressDir (0), + mCurPaintAttrib (GLWindow::defaultPaintAttrib), + mStoredOpacity (CompositeWindow::get (w)->opacity ()), + mCurWindowEvent (curWindowEvent), + mInitialized (false), // store window opacity + mInfo (info), + mIcon (icon) +{ + if (curWindowEvent == WindowEventShade || + curWindowEvent == WindowEventUnshade) + { + mDecorTopHeight = w->output ().top; + mDecorBottomHeight = w->output ().bottom; + } + + texturesCache = new GLTexture::List (GLWindow::get (w)->textures ()); + PrivateAnimScreen *as = mAWindow->priv->paScreen (); + + mTimestep = as->optionGetTimeStep (); +} + +Animation::~Animation () +{ + delete texturesCache; +} + +CompOption::Value & +Animation::optVal (unsigned int optionId) +{ + return mAWindow->pluginOptVal (getExtensionPluginInfo (), optionId, this); +} + +/// Play the animation effect backwards from where it left off. +void +Animation::reverse () +{ + mRemainingTime = mTotalTime - mRemainingTime; + + // avoid window remains + if (mRemainingTime <= 0) + mRemainingTime = 1; + + switch (mCurWindowEvent) // the old event + { + case WindowEventOpen: + mCurWindowEvent = WindowEventClose; + break; + case WindowEventClose: + mCurWindowEvent = WindowEventOpen; + break; + case WindowEventMinimize: + mCurWindowEvent = WindowEventUnminimize; + break; + case WindowEventUnminimize: + mCurWindowEvent = WindowEventMinimize; + break; + case WindowEventShade: + mCurWindowEvent = WindowEventUnshade; + break; + case WindowEventUnshade: + mCurWindowEvent = WindowEventShade; + break; + default: + break; + } + + // 1: forward, 2: backward (3 - progressDir is opposite direction) + int progressDir = 1; + + switch (mCurWindowEvent) // the new event + { + case WindowEventClose: + case WindowEventMinimize: + case WindowEventShade: + progressDir = 2; + break; + default: + break; + } + + if (mOverrideProgressDir == 0) + mOverrideProgressDir = progressDir; + else if (mOverrideProgressDir == 3 - progressDir) + mOverrideProgressDir = 0; // disable override +} + +PartialWindowAnim::PartialWindowAnim (CompWindow *w, + WindowEvent curWindowEvent, + float duration, + const AnimEffect info, + const CompRect &icon) : + Animation::Animation (w, curWindowEvent, duration, info, icon), + mUseDrawRegion (false), + mDrawRegion () +{ +} + +void +PrivateAnimWindow::updateSelectionRow (unsigned int r) +{ + mPrevAnimSelectionRow = mCurAnimSelectionRow; + mCurAnimSelectionRow = (int)r; +} + +// Assumes events in the metadata are in +// [Open, Close, Minimize, Focus, Shade] order +// and effects among those are in alphabetical order +// but with "(Event) None" first and "(Event) Random" last. +AnimEffect +PrivateAnimScreen::getMatchingAnimSelection (CompWindow *w, + AnimEvent e, + int *duration) +{ + PrivateAnimWindow *aw = AnimWindow::get (w)->priv; + + EffectSet *eventEffects = &mEventEffects[e]; + CompOption::Value &valMatch = + getOptions ()[(unsigned)matchOptionIds[e]].value (); + CompOption::Value &valDuration = + getOptions ()[(unsigned)durationOptionIds[e]].value (); + CompOption::Value &valCustomOptions = + getOptions ()[(unsigned)customOptionOptionIds[e]].value (); + + unsigned int nRows = valMatch.list ().size (); + if (nRows != eventEffects->effects.size () || + nRows != valDuration.list ().size () || + nRows != valCustomOptions.list ().size ()) + { + compLogMessage ("animation", CompLogLevelError, + "Animation settings mismatch in \"Animation " + "Selection\" list for %s event.", eventNames[e]); + return AnimEffectNone; + } + + // Find the first row that matches this window for this event + for (unsigned int i = 0; i < nRows; i++) + { + if (!valMatch.list ()[i].match ().evaluate (w)) + continue; + + aw->updateSelectionRow (i); + + if (duration) + *duration = valDuration.list ()[i].i (); + + AnimEffect effect = eventEffects->effects[i]; + + return (effect ? effect : AnimEffectNone); + } + + return AnimEffectNone; +} + +AnimEffect +PrivateAnimScreen::getActualEffect (AnimEffect effect, + AnimEvent animEvent) +{ + bool allRandom = optionGetAllRandom (); + AnimEffectVector *randomEffects = &mRandomEffects[animEvent].effects; + unsigned int nRandomEffects = randomEffects->size (); + unsigned int nFirstRandomEffect = 0; + + if ((effect == AnimEffectRandom) || allRandom) + { + if (nRandomEffects == 0) // no random animation selected, assume "all" + { + randomEffects = &mEventEffectsAllowed[animEvent]; + + // exclude None and Random + nFirstRandomEffect = 2; + nRandomEffects = randomEffects->size () - 2; + } + unsigned int index = nFirstRandomEffect + + (unsigned int)(nRandomEffects * (double)rand () / RAND_MAX); + return (*randomEffects)[index]; + } + else + return effect; +} + +/// Converts animation direction (up, down, left, right, random, auto) +/// to an actual direction (up, down, left, or right). +AnimDirection +Animation::getActualAnimDirection (AnimDirection dir, + bool openDir) +{ + if (dir == AnimDirectionRandom) + { + dir = (AnimDirection)(rand () % 4); + } + else if (dir == AnimDirectionAuto) + { + CompRect outRect (mAWindow->savedRectsValid () ? + mAWindow->savedOutRect () : + mWindow->outputRect ()); + + // away from icon + int centerX = outRect.x () + outRect.width () / 2 ; + int centerY = outRect.y () + outRect.height () / 2 ; + float relDiffX = ((float)centerX - mIcon.x ()) / outRect.width (); + float relDiffY = ((float)centerY - mIcon.y ()) / outRect.height (); + + if (openDir) + { + if (mCurWindowEvent == WindowEventMinimize || + mCurWindowEvent == WindowEventUnminimize) + // min/unmin. should always result in +/- y direction + dir = (mIcon.y () < (int)::screen->height () - mIcon.y ()) ? + AnimDirectionDown : AnimDirectionUp; + else if (fabs (relDiffY) > fabs (relDiffX)) + dir = relDiffY > 0 ? AnimDirectionDown : AnimDirectionUp; + else + dir = relDiffX > 0 ? AnimDirectionRight : AnimDirectionLeft; + } + else + { + if (mCurWindowEvent == WindowEventMinimize || + mCurWindowEvent == WindowEventUnminimize) + // min/unmin. should always result in +/- y direction + dir = (mIcon.y () < (int)::screen->height () - mIcon.y ()) ? + AnimDirectionUp : AnimDirectionDown; + else if (fabs (relDiffY) > fabs (relDiffX)) + dir = relDiffY > 0 ? AnimDirectionUp : AnimDirectionDown; + else + dir = relDiffX > 0 ? AnimDirectionLeft : AnimDirectionRight; + } + } + return dir; +} + +float +Animation::progressLinear () +{ + float forwardProgress = + 1 - mRemainingTime / (mTotalTime - mTimestep); + forwardProgress = MIN (forwardProgress, 1); + forwardProgress = MAX (forwardProgress, 0); + + if (mCurWindowEvent == WindowEventOpen || + mCurWindowEvent == WindowEventUnminimize || + mCurWindowEvent == WindowEventUnshade || + mCurWindowEvent == WindowEventFocus) + forwardProgress = 1 - forwardProgress; + + return forwardProgress; +} + +float +Animation::progressEaseInEaseOut () +{ + float forwardProgress = + 1 - mRemainingTime / (mTotalTime - mTimestep); + forwardProgress = MIN (forwardProgress, 1); + forwardProgress = MAX (forwardProgress, 0); + + // Apply sigmoid and normalize + forwardProgress = + (sigmoid (forwardProgress) - sigmoid (0)) / + (sigmoid (1) - sigmoid (0)); + + if (mCurWindowEvent == WindowEventOpen || + mCurWindowEvent == WindowEventUnminimize || + mCurWindowEvent == WindowEventUnshade || + mCurWindowEvent == WindowEventFocus) + forwardProgress = 1 - forwardProgress; + + return forwardProgress; +} + +/// Gives some acceleration (when closing a window) +/// or deceleration (when opening a window). +/// Applies a sigmoid with slope s, +/// where minx and maxx are the +/// starting and ending points on the sigmoid. +float +Animation::progressDecelerateCustom (float progress, float minx, float maxx) +{ + float x = 1 - progress; + float s = 8; + + return + 1 - ((sigmoid2 (minx + (x * (maxx - minx)), s) - sigmoid2 (minx, s)) / + (sigmoid2 (maxx, s) - sigmoid2 (minx, s))); +} + +float +Animation::progressDecelerate (float progress) +{ + return progressDecelerateCustom (progress, 0.5, 0.75); +} + +BoxPtr +AnimWindow::BB () +{ + return &priv->mBB; +} + +CompRegion & +AnimWindow::stepRegion () +{ + return priv->mStepRegion; +} + +void +PrivateAnimWindow::copyResetStepRegion () +{ + mLastStepRegion = mStepRegion; + + // Reset bounding box for current step + mBB.x1 = mBB.y1 = MAXSHORT; + mBB.x2 = mBB.y2 = MINSHORT; +} + +void +AnimWindow::expandBBWithBox (Box &source) +{ + Box &target = priv->BB (); + + if (source.x1 < target.x1) + target.x1 = source.x1; + if (source.x2 > target.x2) + target.x2 = source.x2; + if (source.y1 < target.y1) + target.y1 = source.y1; + if (source.y2 > target.y2) + target.y2 = source.y2; +} + +void +AnimWindow::expandBBWithPoint (float fx, float fy) +{ + Box &target = priv->BB (); + + short x = MAX (MIN (fx, MAXSHORT - 1), MINSHORT); + short y = MAX (MIN (fy, MAXSHORT - 1), MINSHORT); + + if (target.x1 == MAXSHORT) + { + target.x1 = x; + target.y1 = y; + target.x2 = x + 1; + target.y2 = y + 1; + return; + } + if (x < target.x1) + target.x1 = x; + else if (x > target.x2) + target.x2 = x; + + if (y < target.y1) + target.y1 = y; + else if (y > target.y2) + target.y2 = y; +} + +/// This will work for zoom-like 2D transforms, +/// but not for glide-like 3D transforms. +void +AnimWindow::expandBBWithPoint2DTransform (GLVector &coords, + GLMatrix &transformMat) +{ + GLVector coordsTransformed = transformMat * coords; + expandBBWithPoint (coordsTransformed[GLVector::x], + coordsTransformed[GLVector::y]); +} + +static bool +project (float objx, float objy, float objz, + GLMatrix modelview, GLMatrix projection, + const GLint viewport[4], + float *winx, float *winy, float *winz) +{ + unsigned int i; + float in[4]; + float out[4]; + + in[0] = objx; + in[1] = objy; + in[2] = objz; + in[3] = 1.0; + + for (i = 0; i < 4; i++) { + out[i] = + in[0] * modelview[i] + + in[1] * modelview[4 + i] + + in[2] * modelview[8 + i] + + in[3] * modelview[12 + i]; + } + + for (i = 0; i < 4; i++) { + in[i] = + out[0] * projection[i] + + out[1] * projection[4 + i] + + out[2] * projection[8 + i] + + out[3] * projection[12 + i]; + } + + if (in[3] == 0.0) + return false; + + in[0] /= in[3]; + in[1] /= in[3]; + in[2] /= in[3]; + /* Map x, y and z to range 0-1 */ + in[0] = in[0] * 0.5 + 0.5; + in[1] = in[1] * 0.5 + 0.5; + in[2] = in[2] * 0.5 + 0.5; + + /* Map x,y to viewport */ + in[0] = in[0] * viewport[2] + viewport[0]; + in[1] = in[1] * viewport[3] + viewport[1]; + + *winx = in[0]; + *winy = in[1]; + *winz = in[2]; + return true; +} + +/// Either points or objects should be non-0. +bool +AnimWindow::expandBBWithPoints3DTransform (CompOutput &output, + GLMatrix &transform, + const float *points, + GridAnim::GridModel::GridObject *objects, + unsigned int nPoints) +{ + GLfloat x, y, z; + GLint viewport[4] = + {output.region ()->extents.x1, + output.region ()->extents.y1, + output.width (), + output.height ()}; + + if (points) // use points + { + for (; nPoints; nPoints--, points += 3) + { + if (!project (points[0], points[1], points[2], + transform, + *GLScreen::get (::screen)->projectionMatrix (), + viewport, + &x, &y, &z)) + return false; + + expandBBWithPoint (x + 0.5, (::screen->height () - y) + 0.5); + } + } + else // use grid model objects + { + GridAnim::GridModel::GridObject *object = objects; + for (; nPoints; nPoints--, object++) + { + if (!project (object->position ().x (), + object->position ().y (), + object->position ().z (), + transform, + *GLScreen::get (::screen)->projectionMatrix (), + viewport, + &x, &y, &z)) + return false; + + expandBBWithPoint (x + 0.5, (::screen->height () - y) + 0.5); + } + } + return true; +} + +void +AnimWindow::expandBBWithWindow () +{ + CompRect outRect (savedRectsValid () ? + savedOutRect () : + mWindow->outputRect ()); + Box windowBox = { + outRect.x (), outRect.x () + outRect.width (), + outRect.y (), outRect.y () + outRect.height () + }; + expandBBWithBox (windowBox); +} + +void +AnimWindow::expandBBWithScreen () +{ + Box screenBox = {0, ::screen->width (), + 0, ::screen->height ()}; + expandBBWithBox (screenBox); +} + +void +Animation::prepareTransform (CompOutput &output, + GLMatrix &resultTransform, + GLMatrix &transform) +{ + GLMatrix sTransform; + sTransform.toScreenSpace (&output, -DEFAULT_Z_CAMERA); + resultTransform = sTransform * transform; +} + +void +AnimWindow::resetStepRegionWithBB () +{ + // Have a 1 pixel margin to prevent occasional 1 pixel line artifact + CompRegion region (priv->mBB.x1 - 1, + priv->mBB.y1 - 1, + priv->mBB.x2 - priv->mBB.x1 + 2, + priv->mBB.y2 - priv->mBB.y1 + 2); + priv->mStepRegion = region; +} + +/// Damage the union of window's bounding box +/// before and after animStepFunc does its job. +void +PrivateAnimWindow::damageThisAndLastStepRegion () +{ + // Find union of the regions for this step and last step + CompRegion totalRegionToDamage (mStepRegion + mLastStepRegion); + + mPAScreen->cScreen->damageRegion (totalRegionToDamage); +} + +CompOutput & +AnimScreen::output () +{ + return priv->output (); +} + +bool +AnimScreen::getMousePointerXY (short *x, short *y) +{ + Window w1, w2; + int xp, yp, xj, yj; + unsigned int m; + + if (XQueryPointer + (::screen->dpy (), ::screen->root (), &w1, &w2, &xj, &yj, &xp, &yp, &m)) + { + *x = xp; + *y = yp; + return true; + } + return false; +} + +unsigned int +PrivateAnimWindow::getState () +{ + Atom actual; + int result, format; + unsigned long n, left; + unsigned char *data; + unsigned int retval = WithdrawnState; + + result = XGetWindowProperty (::screen->dpy (), mWindow->id (), + Atoms::wmState, 0L, + 1L, false, + Atoms::wmState, + &actual, &format, &n, &left, &data); + + if (result == Success && data) + { + if (n) + memcpy (&retval, data, sizeof (int)); + + XFree ((void *)data); + } + + return retval; +} + +CompOption::Vector & +AnimScreen::getOptions () +{ + return priv->getOptions (); +} + +bool +AnimScreen::setOption (const CompString &name, + CompOption::Value &value) +{ + return priv->setOption (name, value); +} + +void +PrivateAnimScreen::eventMatchesChanged (CompOption *opt, + AnimationOptions::Options num) +{ + if (mExtensionPlugins.size () == 0) + initAnimationList (); + foreach (CompOption::Value &val, opt->value ().list ()) + val.match ().update (); +} + +void +PrivateAnimScreen::eventOptionsChanged (CompOption *opt, + AnimationOptions::Options num) +{ + if (mExtensionPlugins.size () == 0) + initAnimationList (); + updateOptionSets (getCorrespondingAnimEvent (num)); +} + +void +PrivateAnimScreen::eventEffectsChanged (CompOption *opt, + AnimationOptions::Options num) +{ + if (mExtensionPlugins.size () == 0) + initAnimationList (); + updateEventEffects (getCorrespondingAnimEvent (num), false); +} + +void +PrivateAnimScreen::eventRandomEffectsChanged (CompOption *opt, + AnimationOptions::Options num) +{ + if (mExtensionPlugins.size () == 0) + initAnimationList (); + updateEventEffects (getCorrespondingAnimEvent (num), true); +} + +void +PrivateAnimWindow::postAnimationCleanUpCustom (bool closing, + bool destructing, + bool clearMatchingRow) +{ + bool shouldDamageWindow = false; + + notifyAnimation (false); + + if (mCurAnimation) + { + if (mCurAnimation->shouldDamageWindowOnEnd ()) + shouldDamageWindow = true; + } + enablePainting (false); + + if (shouldDamageWindow) + mAWindow->expandBBWithWindow (); + + if (shouldDamageWindow || + (mCurAnimation && + !mCurAnimation->stepRegionUsed () && + mAWindow->BB ()->x1 != MAXSHORT)) // BB intialized + mAWindow->resetStepRegionWithBB (); + + damageThisAndLastStepRegion (); + + if (mCurAnimation) + { + mCurAnimation->cleanUp (closing, destructing); + delete mCurAnimation; + mCurAnimation = 0; + } + + mBB.x1 = mBB.y1 = MAXSHORT; + mBB.x2 = mBB.y2 = MINSHORT; + + mState = mNewState; + + if (clearMatchingRow) + mCurAnimSelectionRow = -1; + + mFinishingAnim = true; + if (!destructing) + { + mIgnoreDamage = true; + while (mUnmapCnt > 0) + { + mWindow->unmap (); + mUnmapCnt--; + } + if (mUnmapCnt < 0) + mUnmapCnt = 0; + mIgnoreDamage = false; + } + + while (mDestroyCnt) + { + mWindow->destroy (); + mDestroyCnt--; + } + mFinishingAnim = false; + + foreach (ExtensionPluginInfo *extPlugin, mPAScreen->mExtensionPlugins) + extPlugin->cleanUpAnimation (closing, destructing); +} + +void +AnimWindow::postAnimationCleanUp () +{ + priv->postAnimationCleanUp (); +} + +void +PrivateAnimWindow::postAnimationCleanUp () +{ + if (mCurAnimation->curWindowEvent () == WindowEventClose) + postAnimationCleanUpCustom (true, false, true); + else + postAnimationCleanUpCustom (false, false, true); +} + +void +PrivateAnimWindow::postAnimationCleanUpPrev (bool closing, + bool clearMatchingRow) +{ + int curAnimSelectionRow = mCurAnimSelectionRow; + // Use previous event's anim selection row + mCurAnimSelectionRow = mPrevAnimSelectionRow; + + postAnimationCleanUpCustom (closing, false, clearMatchingRow); + + // Restore current event's anim selection row + mCurAnimSelectionRow = curAnimSelectionRow; +} + +void +PrivateAnimScreen::activateEvent (bool activating) +{ + if (activating) + { + if (mAnimInProgress) + return; + } + else + { + // Animations have finished for all windows + // (Keep preparePaint enabled) + + aScreen->enableCustomPaintList (false); + } + cScreen->donePaintSetEnabled (this, activating); + gScreen->glPaintOutputSetEnabled (this, activating); + + mAnimInProgress = activating; + + CompOption::Vector o (0); + + o.push_back (CompOption ("root", CompOption::TypeInt)); + o.push_back (CompOption ("active", CompOption::TypeBool)); + + o[0].value ().set ((int) ::screen->root ()); + o[1].value ().set (activating); + + ::screen->handleCompizEvent ("animation", "activate", o); +} + +void +PrivateAnimWindow::notifyAnimation (bool activation) +{ + CompOption::Vector o (0); + + if (!mCurAnimation) + return; + + o.push_back (CompOption ("root", CompOption::TypeInt)); + o.push_back (CompOption ("window", CompOption::TypeInt)); + o.push_back (CompOption ("type", CompOption::TypeString)); + o.push_back (CompOption ("active", CompOption::TypeBool)); + + o[0].value ().set ((int) ::screen->root ()); + o[1].value ().set ((int) mWindow->id ()); + + switch (mCurAnimation->curWindowEvent ()) + { + case WindowEventOpen: + o[2].value ().set ("open"); + break; + case WindowEventClose: + o[2].value ().set ("close"); + break; + case WindowEventMinimize: + o[2].value ().set ("minimize"); + break; + case WindowEventUnminimize: + o[2].value ().set ("unminimize"); + break; + case WindowEventShade: + o[2].value ().set ("shade"); + break; + case WindowEventUnshade: + o[2].value ().set ("unshade"); + break; + case WindowEventFocus: + o[2].value ().set ("focus"); + break; + case WindowEventNum: + case WindowEventNone: + default: + o[2].value ().set ("none"); + break; + } + + o[3].value ().set (activation); + + screen->handleCompizEvent ("animation", "window_animation", o); +} + +bool +PrivateAnimScreen::otherPluginsActive () +{ + for (int i = 0; i < WatchedScreenPluginNum; i++) + if (mPluginActive[i]) + return true; + return false; +} + +bool +Animation::shouldSkipFrame (int msSinceLastPaintActual) +{ + mTimeElapsedWithinTimeStep += msSinceLastPaintActual; + if (mTimeElapsedWithinTimeStep < mTimestep) // if timestep not yet completed + return true; + + mTimeElapsedWithinTimeStep = fmod (mTimeElapsedWithinTimeStep, mTimestep); + return false; +} + +bool +Animation::advanceTime (int msSinceLastPaint) +{ + mRemainingTime -= msSinceLastPaint; + mRemainingTime = MAX (mRemainingTime, 0); // avoid sub-zero values + + mTimeSinceLastPaint = msSinceLastPaint; + + return (mRemainingTime > 0); +} + +void +PrivateAnimScreen::preparePaint (int msSinceLastPaint) +{ + // Check and update "switcher post wait" counter + if (mSwitcherPostWait > 0) + { + mSwitcherPostWait++; + if (mSwitcherPostWait > 5) // wait over + { + mSwitcherPostWait = 0; + + // Reset stacking related info since it will + // cause problems because of the restacking + // just done by Switcher. + ExtensionPluginAnimation *extPlugin = + static_cast (mExtensionPlugins[0]); + extPlugin->resetStackingInfo (); + } + } + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->prePreparePaintGeneral (); + + if (mAnimInProgress) + { + int msSinceLastPaintActual; + const CompWindowList &pl = pushLockedPaintList (); + CompWindowList windowsFinishedAnimations; + + struct timeval curTime; + gettimeofday (&curTime, 0); + + if (mLastRedrawTimeFresh) + { + msSinceLastPaintActual = TIMEVALDIFF (&curTime, &mLastRedrawTime); + // handle clock rollback + if (msSinceLastPaintActual < 0) + msSinceLastPaintActual = 0; + } + else + msSinceLastPaintActual = 20; // assume 20 ms passed + + mLastRedrawTime = curTime; // Store current time for next time + mLastRedrawTimeFresh = true; + + bool animStillInProgress = false; + + /* Paint list includes destroyed windows */ + for (CompWindowList::const_reverse_iterator rit = pl.rbegin (); + rit != pl.rend (); rit++) + { + CompWindow *w = (*rit); + AnimWindow *animWin = AnimWindow::get (w); + PrivateAnimWindow *aw = animWin->priv; + Animation *curAnim = aw->curAnimation (); + + if (curAnim) + { + if (!curAnim->initialized ()) + curAnim->init (); + + if (curAnim->prePreparePaint (msSinceLastPaint)) + animStillInProgress = true; + + /* TODO optimize grid model by reusing one GridModel + if (aw->com.mModel && + (aw->com.mModel->winWidth != outRect.width () || + aw->com.mModel->winHeight != outRect.height ())) + { + // mModel needs update + // re-create mModel + if (!animEnsureModel (w)) + { + // Abort this window's animation + postAnimationCleanUp (w); + continue; + } + }*/ + + bool animShouldSkipFrame = + (curAnim->shouldSkipFrame (msSinceLastPaintActual) && + // Skip only if we're not on the first animation frame + curAnim->initialized ()); + + // Skip only if we're not on the last animation frame + animShouldSkipFrame &= + curAnim->advanceTime (msSinceLastPaint); + + if (!animShouldSkipFrame) + { + if (curAnim->updateBBUsed ()) + { + aw->copyResetStepRegion (); + + if (!curAnim->initialized () && + curAnim->shouldDamageWindowOnStart ()) + aw->aWindow ()->expandBBWithWindow (); + } + + if (!curAnim->initialized ()) + curAnim->setInitialized (); + + curAnim->step (); + + if (curAnim->updateBBUsed ()) + { + foreach (CompOutput &output, ::screen->outputDevs ()) + curAnim->updateBB (output); + + if (!curAnim->stepRegionUsed () && + aw->BB ().x1 != MAXSHORT) // BB initialized + { + // BB is used instead of step region, + // so reset step region here with BB. + animWin->resetStepRegionWithBB (); + } + if (!(cScreen->damageMask () & + COMPOSITE_SCREEN_DAMAGE_ALL_MASK)) + aw->damageThisAndLastStepRegion (); + } + } + + bool finished = (curAnim->remainingTime () <= 0); + if (finished) // Animation is done + windowsFinishedAnimations.push_back (w); + else + animStillInProgress = true; + } + } + + popLockedPaintList (); + + foreach (CompWindow *w, windowsFinishedAnimations) + { + AnimWindow *aw = AnimWindow::get (w); + aw->priv->notifyAnimation (false); + aw->priv->postAnimationCleanUp (); + } + + const CompWindowList &ppl = pushLockedPaintList (); + + foreach (CompWindow *w, ppl) + { + PrivateAnimWindow *aw = AnimWindow::get (w)->priv; + if (aw->curAnimation ()) + aw->curAnimation ()->postPreparePaint (); + } + + if (!animStillInProgress) + { + activateEvent (false); + mLastRedrawTimeFresh = false; + + // Reset stacking related info after all animations are done. + ExtensionPluginAnimation *extPlugin = + static_cast (mExtensionPlugins[0]); + extPlugin->resetStackingInfo (); + } + + popLockedPaintList (); + } + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->postPreparePaintGeneral (); + + cScreen->preparePaint (msSinceLastPaint); + + if (mStartCountdown) + { + mStartCountdown--; + if (!mStartCountdown) + { + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->postStartupCountdown (); + } + } +} + +void +PrivateAnimScreen::donePaint () +{ + assert (mAnimInProgress); + + cScreen->damagePending (); + + cScreen->donePaint (); +} + +void +PrivateAnimWindow::enablePainting (bool enabling) +{ + gWindow->glPaintSetEnabled (this, enabling); + gWindow->glAddGeometrySetEnabled (this, enabling); + gWindow->glDrawTextureSetEnabled (this, enabling); +} + +void +PrivateAnimWindow::glAddGeometry (const GLTexture::MatrixList &matrix, + const CompRegion ®ion, + const CompRegion &clip, + unsigned int maxGridWidth, + unsigned int maxGridHeight) +{ + // if window is being animated + if (mCurAnimation) + { + if (mCurAnimation->initialized ()) + mCurAnimation->addGeometry (matrix, region, clip, + maxGridWidth, maxGridHeight); + } + else + { + gWindow->glAddGeometry (matrix, region, clip, + maxGridWidth, maxGridHeight); + } +} + +bool +Animation::shouldDamageWindowOnStart () +{ + return (mCurWindowEvent == WindowEventClose || + mCurWindowEvent == WindowEventMinimize || + mCurWindowEvent == WindowEventShade); +} + +bool +Animation::shouldDamageWindowOnEnd () +{ + return (mCurWindowEvent == WindowEventOpen || + mCurWindowEvent == WindowEventUnminimize || + mCurWindowEvent == WindowEventUnshade); +} + +void +Animation::addGeometry (const GLTexture::MatrixList &matrix, + const CompRegion ®ion, + const CompRegion &clip, + unsigned int maxGridWidth, + unsigned int maxGridHeight) +{ + mAWindow->priv->gWindow->glAddGeometry (matrix, region, clip, + maxGridWidth, maxGridHeight); +} + +void +PartialWindowAnim::addGeometry (const GLTexture::MatrixList &matrix, + const CompRegion ®ion, + const CompRegion &clip, + unsigned int maxGridWidth, + unsigned int maxGridHeight) +{ + if (mUseDrawRegion) + { + CompRegion awRegion (region.intersected (mDrawRegion)); + Animation::addGeometry (matrix, awRegion, clip, + maxGridWidth, maxGridHeight); + } + else + { + Animation::addGeometry (matrix, region, clip, + maxGridWidth, maxGridHeight); + } +} + +void +PrivateAnimWindow::glDrawTexture (GLTexture *texture, + const GLMatrix &transform, + const GLWindowPaintAttrib &attrib, + unsigned int mask) +{ + if (mCurAnimation) + { + mCurAnimation->setCurPaintAttrib (attrib); + } + + gWindow->glDrawTexture (texture, transform, attrib, mask); +} + +void +Animation::drawTexture (GLTexture *texture, + const GLMatrix &transform, + const GLWindowPaintAttrib &attrib, + unsigned int mask) +{ + mCurPaintAttrib = attrib; +} + +bool +PrivateAnimWindow::glPaint (const GLWindowPaintAttrib &attrib, + const GLMatrix &transform, + const CompRegion ®ion, unsigned int mask) +{ + bool status; + + // Is this the first glPaint call this round + // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK? + if (mPAScreen->mStartingNewPaintRound && + !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)) + { + mPAScreen->mStartingNewPaintRound = false; + + // Back-to-front painting of windows is starting now. + if (mPAScreen->mPrePaintWindowsBackToFrontEnabled) + mPAScreen->prePaintWindowsBackToFront (); + } + + assert (mCurAnimation); + + foreach (ExtensionPluginInfo *extPlugin, mPAScreen->mExtensionPlugins) + { + if (extPlugin->paintShouldSkipWindow (mWindow)) + return false; + } + + if (mCurAnimation->curWindowEvent () == WindowEventFocus && + mPAScreen->otherPluginsActive ()) + { + postAnimationCleanUp (); + return gWindow->glPaint (attrib, transform, region, mask); + } + + GLWindowPaintAttrib wAttrib = attrib; + GLMatrix wTransform (transform.getMatrix ()); + + /* TODO check if this is still necessary + if (mCurAnimation->addCustomGeometryFunc) + { + // Use slightly smaller brightness to force core + // to handle indexCount = 0; // TODO check if this is still necessary + + // TODO: should only happen for distorting effects + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + + wAttrib.xScale = 1.0f; + wAttrib.yScale = 1.0f; + + mCurAnimation->updateAttrib (wAttrib); + mCurAnimation->updateTransform (wTransform); + mCurAnimation->prePaintWindow (); + + if (mCurAnimation->paintWindowUsed ()) + status = mCurAnimation->paintWindow (gWindow, wAttrib, wTransform, region, mask); + else + status = gWindow->glPaint (wAttrib, wTransform, region, mask); + + if (mCurAnimation->postPaintWindowUsed ()) + { + mCurAnimation->postPaintWindow (); + } + + return status; +} + +const CompWindowList & +PrivateAnimScreen::pushLockedPaintList () +{ + if (!mLockedPaintListCnt) + { + mLockedPaintList = &cScreen->getWindowPaintList (); + + if (!mGetWindowPaintListEnableCnt) + { + mGetWindowPaintListEnableCnt++; + cScreen->getWindowPaintListSetEnabled (this, true); + } + } + + mLockedPaintListCnt++; + return *mLockedPaintList; +} + +void +PrivateAnimScreen::popLockedPaintList () +{ + mLockedPaintListCnt--; + + if (!mLockedPaintListCnt) + { + mLockedPaintList = NULL; + + mGetWindowPaintListEnableCnt--; + + if (!mGetWindowPaintListEnableCnt) + cScreen->getWindowPaintListSetEnabled (this, false); + } +} + +/// This is enabled only during restack animations. +/// or when we need to lock it +const CompWindowList & +PrivateAnimScreen::getWindowPaintList () +{ + if (mLockedPaintList) + return *mLockedPaintList; + + ExtensionPluginAnimation *extPlugin = + static_cast (mExtensionPlugins[0]); + return extPlugin->getWindowPaintList (); +} + +/// This is enabled only during restack animations. +void +PrivateAnimScreen::prePaintWindowsBackToFront () +{ + assert (mAnimInProgress); + + ExtensionPluginAnimation *extPlugin = + static_cast (mExtensionPlugins[0]); + extPlugin->prePaintWindowsBackToFront (); +} + +void +PrivateAnimScreen::enablePrePaintWindowsBackToFront (bool enabled) +{ + mPrePaintWindowsBackToFrontEnabled = enabled; +} + +void +PrivateAnimScreen::pushPaintList () +{ + if (!mGetWindowPaintListEnableCnt) + cScreen->getWindowPaintListSetEnabled (this, true); + + mGetWindowPaintListEnableCnt++; +} + +void +PrivateAnimScreen::popPaintList () +{ + mGetWindowPaintListEnableCnt--; + + if (!mGetWindowPaintListEnableCnt) + cScreen->getWindowPaintListSetEnabled (this, false); +} + +void +AnimScreen::enableCustomPaintList (bool enabled) +{ + enabled ? priv->pushPaintList () : priv->popPaintList (); + + priv->enablePrePaintWindowsBackToFront (enabled); +} + +static const PluginEventInfo watchedScreenPlugins[] = +{ + {"switcher", "activate"}, + {"ring", "activate"}, + {"shift", "activate"}, + {"scale", "activate"}, + {"group", "tabChangeActivate"}, + {"fadedesktop", "activate"} +}; + +static const PluginEventInfo watchedWindowPlugins[] = +{ + {"kdecompat", "slide"}, +}; + +void +PrivateAnimScreen::handleCompizEvent (const char *pluginName, + const char *eventName, + CompOption::Vector &options) +{ + ::screen->handleCompizEvent (pluginName, eventName, options); + + for (int i = 0; i < WatchedScreenPluginNum; i++) + if (strcmp (pluginName, watchedScreenPlugins[i].pluginName) == 0) + { + if (strcmp (eventName, + watchedScreenPlugins[i].activateEventName) == 0) + { + mPluginActive[i] = + CompOption::getBoolOptionNamed (options, "active", false); + + if (!mPluginActive[i] && + (i == WatchedPluginSwitcher || + i == WatchedPluginRing || + i == WatchedPluginShift || + i == WatchedPluginScale)) + { + mSwitcherPostWait = 1; + } + } + break; + } + + for (int i = 0; i < WatchedWindowPluginNum; i++) + if (strcmp (pluginName, + watchedWindowPlugins[i].pluginName) == 0) + { + if (strcmp (eventName, + watchedWindowPlugins[i].activateEventName) == 0) + { + Window xid = CompOption::getIntOptionNamed (options, + "window", + 0); + CompWindow *w = screen->findWindow (xid); + + if (w) + { + AnimWindow *aw = AnimWindow::get (w); + PrivateAnimWindow *pw = aw->priv; + pw->mPluginActive[i] = CompOption::getBoolOptionNamed ( + options, + "active", + false); + } + } + break; + } +} + +/// Returns true for windows that don't have a pixmap or certain properties, +/// like the dimming layer of gksudo and x-session-manager. +inline bool +PrivateAnimScreen::shouldIgnoreWindowForAnim (CompWindow *w, bool checkPixmap) +{ + AnimWindow *aw = AnimWindow::get (w); + + for (int i = 0; i < WatchedWindowPluginNum; i++) + if (aw->priv->mPluginActive[i]) + return true; + + return ((checkPixmap && !CompositeWindow::get (w)->pixmap ()) || + mNeverAnimateMatch.evaluate (w)); +} + +void +PrivateAnimWindow::reverseAnimation () +{ + mCurAnimation->reverse (); + + // Inflict the pending unmaps + while (mUnmapCnt > 0) + { + mWindow->unmap (); + mUnmapCnt--; + } + if (mUnmapCnt < 0) + mUnmapCnt = 0; +} + +void +PrivateAnimScreen::initiateCloseAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->preInitiateCloseAnim (aw->mAWindow); + + if (shouldIgnoreWindowForAnim (w, true)) + return; + int duration = 200; + AnimEffect chosenEffect = + getMatchingAnimSelection (w, AnimEventClose, &duration); + + aw->mState = NormalState; + aw->mNewState = WithdrawnState; + + if (chosenEffect != AnimEffectNone) + { + bool startingNew = true; + WindowEvent curWindowEvent = WindowEventNone; + + if (aw->curAnimation ()) + curWindowEvent = aw->curAnimation ()->curWindowEvent (); + + if (curWindowEvent != WindowEventNone) + { + if (curWindowEvent == WindowEventOpen) + { + startingNew = false; + aw->reverseAnimation (); + } + /* TODO check if necessary + else if (aw->com.curWindowEvent == WindowEventClose) + { + if (aw->com.animOverrideProgressDir == 2) + { + aw->com.animRemainingTime = tmpSteps; + startingNew = false; + } + }*/ + else + { + aw->postAnimationCleanUpPrev (true, false); + } + } + + if (startingNew) + { + AnimEffect effectToBePlayed = + getActualEffect (chosenEffect, AnimEventClose); + + // handle empty random effect list + if (effectToBePlayed && effectToBePlayed == AnimEffectNone) + { + aw->mState = aw->mNewState; + return; + } + + aw->mCurAnimation = + effectToBePlayed->create (w, WindowEventClose, duration, + effectToBePlayed, getIcon (w, true)); + aw->mCurAnimation->adjustPointerIconSize (); + aw->enablePainting (true); + } + + activateEvent (true); + aw->notifyAnimation (true); + + // Increment 3 times to make sure close animation works + // (e.g. for popup menus). + for (int i = 0; i < 3; i++) + { + aw->mUnmapCnt++; + w->incrementUnmapReference (); + } + cScreen->damagePending (); + } + /* TODO check if necessary + else if (AnimEffectNone != + getMatchingAnimSelection (w, AnimEventOpen, &duration)) + { + // stop the current animation and prevent it from rewinding + + if (aw->com.animRemainingTime > 0 && + aw->com.curWindowEvent != WindowEventOpen) + { + aw->com.animRemainingTime = 0; + } + if ((aw->com.curWindowEvent != WindowEventNone) && + (aw->com.curWindowEvent != WindowEventClose)) + { + postAnimationCleanUp (w); + } + // set some properties to make sure this window will use the + // correct open effect the next time it's "opened" + + activateEvent (w->screen, true); + aw->com.curWindowEvent = WindowEventClose; + + aw->mUnmapCnt++; + w->incrementUnmapRefCnt (); + + damagePendingOnScreen (w->screen); + }*/ + else + aw->mState = aw->mNewState; + + // Make sure non-animated closing windows get a damage. + if (!aw->curAnimation ()) + { + aw->mAWindow->expandBBWithWindow (); + } +} + +CompRect +PrivateAnimScreen::getIcon (CompWindow *w, bool alwaysUseMouse) +{ + CompRect icon; + + if (!alwaysUseMouse) + { + icon = w->iconGeometry (); + } + if (alwaysUseMouse || + (icon.x () == 0 && + icon.y () == 0 && + icon.width () == 0 && + icon.height () == 0)) // that is, couldn't get icon from window + { + // Minimize to mouse pointer if there is no + // window list or if the window skips taskbar + short x, y; + if (!aScreen->getMousePointerXY (&x, &y)) + { + // Use screen center if can't get mouse coords + x = ::screen->width () / 2; + y = ::screen->height () / 2; + } + icon.setX (x); + icon.setY (y); + icon.setWidth (FAKE_ICON_SIZE); + icon.setHeight (FAKE_ICON_SIZE); + } + + return icon; +} + +void +PrivateAnimScreen::initiateMinimizeAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + + if (aw->mWindow->destroyed ()) + return; + + // Store window geometry for use during animation. + aw->mAWindow->mSavedInRect = w->inputRect (); + aw->mAWindow->mSavedOutRect = w->outputRect (); + aw->mAWindow->mSavedOutExtents = w->output (); + aw->mAWindow->mSavedWinRect = w->geometry (); + aw->mAWindow->mSavedRectsValid = true; + + aw->mNewState = IconicState; + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->preInitiateMinimizeAnim (aw->mAWindow); + + int duration = 200; + AnimEffect chosenEffect = + getMatchingAnimSelection (w, AnimEventMinimize, &duration); + + if (chosenEffect != AnimEffectNone) + { + bool startingNew = true; + WindowEvent curWindowEvent = WindowEventNone; + + if (aw->curAnimation ()) + curWindowEvent = aw->curAnimation ()->curWindowEvent (); + + if (curWindowEvent != WindowEventNone) + { + if (curWindowEvent != WindowEventUnminimize) + { + aw->postAnimationCleanUpPrev (false, false); + } + else + { + startingNew = false; + aw->reverseAnimation (); + } + } + + if (startingNew) + { + AnimEffect effectToBePlayed = + getActualEffect (chosenEffect, AnimEventMinimize); + + // handle empty random effect list + if (effectToBePlayed == AnimEffectNone) + { + aw->mState = aw->mNewState; + return; + } + + aw->mCurAnimation = + effectToBePlayed->create (w, WindowEventMinimize, duration, + effectToBePlayed, getIcon (w, false)); + aw->enablePainting (true); + } + + activateEvent (true); + aw->notifyAnimation (true); + + cScreen->damagePending (); + } + else + aw->mState = aw->mNewState; +} + +void +PrivateAnimScreen::initiateShadeAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + + int duration = 200; + AnimEffect chosenEffect = + getMatchingAnimSelection (w, AnimEventShade, &duration); + + aw->setShaded (true); + + if (chosenEffect != AnimEffectNone) + { + bool startingNew = true; + WindowEvent curWindowEvent = WindowEventNone; + if (aw->curAnimation ()) + curWindowEvent = aw->curAnimation ()->curWindowEvent (); + + if (curWindowEvent != WindowEventNone) + { + if (curWindowEvent != WindowEventUnshade) + { + aw->postAnimationCleanUpPrev (false, false); + } + else + { + startingNew = false; + aw->reverseAnimation (); + } + } + + if (startingNew) + { + AnimEffect effectToBePlayed = + getActualEffect (chosenEffect, AnimEventShade); + + // handle empty random effect list + if (effectToBePlayed == AnimEffectNone) + return; + + aw->mCurAnimation = + effectToBePlayed->create (w, WindowEventShade, duration, + effectToBePlayed, getIcon (w, false)); + aw->enablePainting (true); + } + + activateEvent (true); + aw->notifyAnimation (true); + + aw->mUnmapCnt++; + w->incrementUnmapReference (); + + cScreen->damagePending (); + } +} + +void +PrivateAnimScreen::initiateOpenAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + + int duration = 200; + AnimEffect chosenEffect; + + aw->mNewState = NormalState; + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->preInitiateOpenAnim (aw->mAWindow); + + WindowEvent curWindowEvent = WindowEventNone; + if (aw->curAnimation ()) + curWindowEvent = aw->curAnimation ()->curWindowEvent (); + + if (!shouldIgnoreWindowForAnim (w, false) && + (AnimEffectNone != + (chosenEffect = + getMatchingAnimSelection (w, AnimEventOpen, &duration)) || + // reversing case + curWindowEvent == WindowEventClose)) + { + bool startingNew = true; + bool playEffect = true; + + if (curWindowEvent != WindowEventNone) + { + if (curWindowEvent != WindowEventClose) + { + aw->postAnimationCleanUpPrev (false, false); + } + else + { + startingNew = false; + aw->reverseAnimation (); + } + } + + if (startingNew) + { + AnimEffect effectToBePlayed = + getActualEffect (chosenEffect, AnimEventOpen); + + // handle empty random effect list + if (effectToBePlayed == AnimEffectNone) + playEffect = false; + + if (playEffect) + { + aw->mCurAnimation = + effectToBePlayed->create (w, WindowEventOpen, duration, + effectToBePlayed, + getIcon (w, true)); + aw->mCurAnimation->adjustPointerIconSize (); + aw->enablePainting (true); + } + } + + if (playEffect) + { + activateEvent (true); + aw->notifyAnimation (true); + cScreen->damagePending (); + } + } +} + +void +PrivateAnimScreen::initiateUnminimizeAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + + if (aw->mWindow->destroyed ()) + return; + + aw->mAWindow->mSavedRectsValid = false; + + int duration = 200; + AnimEffect chosenEffect = + getMatchingAnimSelection (w, AnimEventMinimize, &duration); + + aw->mNewState = NormalState; + + if (chosenEffect != AnimEffectNone && + !mPluginActive[3]) // fadedesktop + { + bool startingNew = true; + bool playEffect = true; + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->preInitiateUnminimizeAnim (aw->mAWindow); + + // TODO Refactor the rest? (almost the same in other initiateX methods) + WindowEvent curWindowEvent = WindowEventNone; + if (aw->curAnimation ()) + curWindowEvent = aw->curAnimation ()->curWindowEvent (); + + if (curWindowEvent != WindowEventNone) + { + if (curWindowEvent != WindowEventMinimize) + { + aw->postAnimationCleanUpPrev (false, false); + } + else + { + startingNew = false; + aw->reverseAnimation (); + } + } + + if (startingNew) + { + AnimEffect effectToBePlayed = + getActualEffect (chosenEffect, AnimEventMinimize); + + // handle empty random effect list + if (effectToBePlayed == AnimEffectNone) + playEffect = false; + + if (playEffect) + { + aw->mCurAnimation = + effectToBePlayed->create (w, WindowEventUnminimize, + duration, effectToBePlayed, + getIcon (w, false)); + aw->enablePainting (true); + } + } + + if (playEffect) + { + activateEvent (true); + aw->notifyAnimation (true); + cScreen->damagePending (); + } + } +} + +void +PrivateAnimScreen::initiateUnshadeAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + + aw->mAWindow->mSavedRectsValid = false; + + aw->setShaded (false); + + aw->mNewState = NormalState; + + int duration = 200; + AnimEffect chosenEffect = + getMatchingAnimSelection (w, AnimEventShade, &duration); + + if (chosenEffect != AnimEffectNone) + { + bool startingNew = true; + bool playEffect = true; + + WindowEvent curWindowEvent = WindowEventNone; + if (aw->curAnimation ()) + curWindowEvent = aw->curAnimation ()->curWindowEvent (); + + if (curWindowEvent != WindowEventNone) + { + if (curWindowEvent != WindowEventShade) + { + aw->postAnimationCleanUpPrev (false, false); + } + else + { + startingNew = false; + aw->reverseAnimation (); + } + } + + if (startingNew) + { + AnimEffect effectToBePlayed = + getActualEffect (chosenEffect, AnimEventShade); + + // handle empty random effect list + if (effectToBePlayed == AnimEffectNone) + playEffect = false; + + if (playEffect) + { + aw->mCurAnimation = + effectToBePlayed->create (w, WindowEventUnshade, + duration, effectToBePlayed, + getIcon (w, false)); + aw->enablePainting (true); + } + } + + if (playEffect) + { + activateEvent (true); + aw->notifyAnimation (true); + cScreen->damagePending (); + } + } +} + +bool +PrivateAnimScreen::initiateFocusAnim (PrivateAnimWindow *aw) +{ + CompWindow *w = aw->mWindow; + int duration = 200; + + if (aw->curAnimation () || otherPluginsActive () || + // Check the "switcher post-wait" counter that effectively prevents + // focus animation to be initiated when the zoom option value is low + // in Switcher. + mSwitcherPostWait) + return false; + + AnimEffect chosenEffect = + getMatchingAnimSelection (w, AnimEventFocus, &duration); + + if (chosenEffect != AnimEffectNone) + { + aw->createFocusAnimation (chosenEffect, duration); + + if (chosenEffect->isRestackAnim && + !(dynamic_cast (aw->mCurAnimation)-> + initiateRestackAnim (duration))) + { + aw->postAnimationCleanUp (); + return false; + } + + activateEvent (true); + aw->notifyAnimation (true); + cScreen->damagePending (); + return true; + } + return false; +} + +void +PrivateAnimWindow::resizeNotify (int dx, + int dy, + int dwidth, + int dheight) +{ + if (mUnshadePending) + { + mUnshadePending = false; + mPAScreen->initiateUnshadeAnim (this); + } + else if (mCurAnimation && mCurAnimation->inProgress () && + // Don't let transient window open anim be interrupted with a resize notify + !(mCurAnimation->curWindowEvent () == WindowEventOpen && + (mWindow->wmType () & + (CompWindowTypeDropdownMenuMask | + CompWindowTypePopupMenuMask | + CompWindowTypeMenuMask | + CompWindowTypeTooltipMask | + CompWindowTypeNotificationMask | + CompWindowTypeComboMask | + CompWindowTypeDndMask))) && + // Ignore resize with dx=0, dy=0, dwidth=0, dheight=0 + !(dx == 0 && dy == 0 && dwidth == 0 && dheight == 0) && + !mCurAnimation->resizeUpdate (dx, dy, dwidth, dheight)) + { + postAnimationCleanUp (); + mPAScreen->updateAnimStillInProgress (); + } + + mWindow->resizeNotify (dx, dy, dwidth, dheight); +} + +void +PrivateAnimScreen::updateAnimStillInProgress () +{ + bool animStillInProgress = false; + const CompWindowList &pl = pushLockedPaintList (); + + foreach (CompWindow *w, pl) + { + PrivateAnimWindow *aw = AnimWindow::get (w)->priv; + if (aw->curAnimation () && + aw->curAnimation ()->inProgress ()) + { + animStillInProgress = true; + break; + } + else + { + aw->notifyAnimation (false); + } + } + + popLockedPaintList (); + + if (!animStillInProgress) + activateEvent (false); +} + +void +PrivateAnimWindow::moveNotify (int dx, + int dy, + bool immediate) +{ + if (mCurAnimation && mCurAnimation->inProgress () && + (mGrabbed || !mCurAnimation->moveUpdate (dx, dy))) + { + // Stop the animation + postAnimationCleanUp (); + mPAScreen->updateAnimStillInProgress (); + } + + mWindow->moveNotify (dx, dy, immediate); +} + +void +PrivateAnimWindow::grabNotify (int x, + int y, + unsigned int state, + unsigned int mask) +{ + mGrabbed = true; + + mWindow->grabNotify (x, y, state, mask); +} + +void +PrivateAnimWindow::ungrabNotify () +{ + mGrabbed = false; + + mWindow->ungrabNotify (); +} + +bool +PrivateAnimScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, + const GLMatrix &matrix, + const CompRegion ®ion, + CompOutput *output, + unsigned int mask) +{ + assert (mAnimInProgress); + + mStartingNewPaintRound = true; + + foreach (ExtensionPluginInfo *extPlugin, mExtensionPlugins) + extPlugin->prePaintOutput (output); + + mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; + + mOutput = output; + + return gScreen->glPaintOutput (attrib, matrix, region, output, mask); +} + +AnimEffectInfo::AnimEffectInfo (const char *name, + bool usedO, bool usedC, bool usedM, + bool usedS, bool usedF, + CreateAnimFunc create, + bool isRestackAnim) : + name (name), + create (create), + isRestackAnim (isRestackAnim) +{ + usedForEvents[AnimEventOpen] = usedO; + usedForEvents[AnimEventClose] = usedC; + usedForEvents[AnimEventMinimize] = usedM; + usedForEvents[AnimEventShade] = usedS; + usedForEvents[AnimEventFocus] = usedF; +} + +bool +AnimEffectInfo::matchesEffectName (const CompString &animName) +{ + return (0 == strcasecmp (animName.c_str (), name)); +} + +bool +AnimEffectInfo::matchesPluginName (const CompString &pluginName) +{ + return (0 == strncmp (pluginName.c_str (), name, pluginName.length ())); +} + +AnimEffect animEffects[NUM_EFFECTS]; + +ExtensionPluginAnimation animExtensionPluginInfo (CompString ("animation"), + NUM_EFFECTS, animEffects, 0, + NUM_NONEFFECT_OPTIONS); +ExtensionPluginInfo * +Animation::getExtensionPluginInfo () +{ + return &animExtensionPluginInfo; +} + +AnimEffect AnimEffectNone; +AnimEffect AnimEffectRandom; +AnimEffect AnimEffectCurvedFold; +AnimEffect AnimEffectDodge; +AnimEffect AnimEffectDream; +AnimEffect AnimEffectFade; +AnimEffect AnimEffectFocusFade; +AnimEffect AnimEffectGlide1; +AnimEffect AnimEffectGlide2; +AnimEffect AnimEffectHorizontalFolds; +AnimEffect AnimEffectMagicLamp; +AnimEffect AnimEffectMagicLampWavy; +AnimEffect AnimEffectRollUp; +AnimEffect AnimEffectSidekick; +AnimEffect AnimEffectWave; +AnimEffect AnimEffectZoom; + +PrivateAnimScreen::PrivateAnimScreen (CompScreen *s, AnimScreen *as) : + cScreen (CompositeScreen::get (s)), + gScreen (GLScreen::get (s)), + aScreen (as), + mLastRedrawTimeFresh (false), + mSwitcherPostWait (0), + mStartCountdown (20), // start the countdown + mLastActiveWindow (0), + mAnimInProgress (false), + mStartingNewPaintRound (false), + mPrePaintWindowsBackToFrontEnabled (false), + mOutput (0), + mLockedPaintList (NULL), + mLockedPaintListCnt (0), + mGetWindowPaintListEnableCnt (0) +{ + for (int i = 0; i < WatchedScreenPluginNum; i++) + mPluginActive[i] = false; + + // Never animate screen-dimming layer of logout window and gksu. + mNeverAnimateMatch |= "title=gksu"; + mNeverAnimateMatch |= "title=x-session-manager"; + mNeverAnimateMatch |= "title=gnome-session"; + mNeverAnimateMatch.update (); + + // Set-up option notifiers + +#define MATCHES_BIND \ + boost::bind (&PrivateAnimScreen::eventMatchesChanged, this, _1, _2) +#define OPTIONS_BIND \ + boost::bind (&PrivateAnimScreen::eventOptionsChanged, this, _1, _2) +#define EFFECTS_BIND \ + boost::bind (&PrivateAnimScreen::eventEffectsChanged, this, _1, _2) +#define RANDOM_EFFECTS_BIND \ + boost::bind (&PrivateAnimScreen::eventRandomEffectsChanged, this, _1, _2) + + optionSetOpenMatchesNotify (MATCHES_BIND); + optionSetCloseMatchesNotify (MATCHES_BIND); + optionSetMinimizeMatchesNotify (MATCHES_BIND); + optionSetFocusMatchesNotify (MATCHES_BIND); + optionSetShadeMatchesNotify (MATCHES_BIND); + + optionSetOpenOptionsNotify (OPTIONS_BIND); + optionSetCloseOptionsNotify (OPTIONS_BIND); + optionSetMinimizeOptionsNotify (OPTIONS_BIND); + optionSetFocusOptionsNotify (OPTIONS_BIND); + optionSetShadeOptionsNotify (OPTIONS_BIND); + + optionSetOpenEffectsNotify (EFFECTS_BIND); + optionSetCloseEffectsNotify (EFFECTS_BIND); + optionSetMinimizeEffectsNotify (EFFECTS_BIND); + optionSetFocusEffectsNotify (EFFECTS_BIND); + optionSetShadeEffectsNotify (EFFECTS_BIND); + + optionSetOpenRandomEffectsNotify (RANDOM_EFFECTS_BIND); + optionSetCloseRandomEffectsNotify (RANDOM_EFFECTS_BIND); + optionSetMinimizeRandomEffectsNotify (RANDOM_EFFECTS_BIND); + optionSetShadeRandomEffectsNotify (RANDOM_EFFECTS_BIND); + + ScreenInterface::setHandler (::screen); + CompositeScreenInterface::setHandler (cScreen, false); + GLScreenInterface::setHandler (gScreen, false); +} + +PrivateAnimScreen::~PrivateAnimScreen () +{ + if (mAnimInProgress) + activateEvent (false); + + for (int i = 0; i < NUM_EFFECTS; i++) + delete animEffects[i]; +} + +void +PrivateAnimScreen::initAnimationList () +{ + int i = 0; + animEffects[i++] = AnimEffectNone = + new AnimEffectInfo ("animation:None", + true, true, true, true, true, 0); + animEffects[i++] = AnimEffectRandom = + new AnimEffectInfo ("animation:Random", + true, true, true, true, false, 0); + animEffects[i++] = AnimEffectCurvedFold = + new AnimEffectInfo ("animation:Curved Fold", + true, true, true, true, false, + &createAnimation); + animEffects[i++] = AnimEffectDodge = + new AnimEffectInfo ("animation:Dodge", + false, false, false, false, true, + &createAnimation, + true); + animEffects[i++] = AnimEffectDream = + new AnimEffectInfo ("animation:Dream", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectFade = + new AnimEffectInfo ("animation:Fade", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectFocusFade = + new AnimEffectInfo ("animation:Focus Fade", + false, false, false, false, true, + &createAnimation, + true); + animEffects[i++] = AnimEffectGlide1 = + new AnimEffectInfo ("animation:Glide 1", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectGlide2 = + new AnimEffectInfo ("animation:Glide 2", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectHorizontalFolds = + new AnimEffectInfo ("animation:Horizontal Folds", + true, true, true, true, false, + &createAnimation); + animEffects[i++] = AnimEffectMagicLamp = + new AnimEffectInfo ("animation:Magic Lamp", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectMagicLampWavy = + new AnimEffectInfo ("animation:Magic Lamp Wavy", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectRollUp = + new AnimEffectInfo ("animation:Roll Up", + false, false, false, true, false, + &createAnimation); + animEffects[i++] = AnimEffectSidekick = + new AnimEffectInfo ("animation:Sidekick", + true, true, true, false, false, + &createAnimation); + animEffects[i++] = AnimEffectWave = + new AnimEffectInfo ("animation:Wave", + true, true, true, false, true, + &createAnimation); + animEffects[i++] = AnimEffectZoom = + new AnimEffectInfo ("animation:Zoom", + true, true, true, false, false, + &createAnimation); + + animExtensionPluginInfo.effectOptions = &getOptions (); + + // Extends itself with the basic set of animation effects. + addExtension (&animExtensionPluginInfo, false); + + for (int e = 0; e < AnimEventNum; e++) // for each anim event + updateOptionSets ((AnimEvent)e); + + updateAllEventEffects (); + + cScreen->preparePaintSetEnabled (this, true); +} + +PrivateAnimWindow::PrivateAnimWindow (CompWindow *w, + AnimWindow *aw) : + gWindow (GLWindow::get (w)), + mWindow (w), + mAWindow (aw), + mPAScreen (AnimScreen::get (::screen)->priv), + mCurAnimation (0), + mUnshadePending (false), + mEventNotOpenClose (false), + mNowShaded (false), + mGrabbed (false), + mUnmapCnt (0), + mDestroyCnt (0), + mIgnoreDamage (false), + mFinishingAnim (false), + mCurAnimSelectionRow (-1) +{ + mBB.x1 = mBB.y1 = MAXSHORT; + mBB.x2 = mBB.y2 = MINSHORT; + + for (int i = 0; i < WatchedWindowPluginNum; i++) + mPluginActive[i] = false; + + if (w->minimized ()) + { + mState = mNewState = IconicState; + } + else if (w->shaded ()) + { + mState = mNewState = NormalState; + mNowShaded = true; + } + else + { + mState = mNewState = getState (); + } + + WindowInterface::setHandler (mWindow, true); + GLWindowInterface::setHandler (gWindow, false); +} + +PrivateAnimWindow::~PrivateAnimWindow () +{ + notifyAnimation (false); + postAnimationCleanUpCustom (false, true, true); +} + +void +PrivateAnimWindow::windowNotify (CompWindowNotify n) +{ + switch (n) + { + case CompWindowNotifyEnterShowDesktopMode: + case CompWindowNotifyMinimize: + mPAScreen->initiateMinimizeAnim (this); + mEventNotOpenClose = true; + break; + case CompWindowNotifyShade: + mPAScreen->initiateShadeAnim (this); + mEventNotOpenClose = true; + break; + case CompWindowNotifyLeaveShowDesktopMode: + case CompWindowNotifyUnminimize: + mPAScreen->initiateUnminimizeAnim (this); + mEventNotOpenClose = true; + break; + case CompWindowNotifyUnshade: + if (mNowShaded && + mCurAnimation && + mCurAnimation->curWindowEvent () == WindowEventShade) + mPAScreen->initiateUnshadeAnim (this); // reverse the shade anim + break; + case CompWindowNotifyClose: + if (!(mCurAnimation && + (mCurAnimation->curWindowEvent () == WindowEventClose || + mCurAnimation->curWindowEvent () == WindowEventUnminimize))) + mPAScreen->initiateCloseAnim (this); + break; + case CompWindowNotifyShow: + case CompWindowNotifyBeforeMap: + // Prevent dialog disappearing when a dialog is reopened during + // its close animation. + if (mCurAnimation && + mCurAnimation->curWindowEvent () == WindowEventClose) + { + mPAScreen->initiateOpenAnim (this); + mEventNotOpenClose = false; + } + break; + case CompWindowNotifyMap: + if (mNowShaded) + mUnshadePending = true; + else if (!mUnshadePending && + !mEventNotOpenClose && + !mPAScreen->mStartCountdown && + !(mCurAnimation && + (mCurAnimation->curWindowEvent () == + WindowEventUnminimize || + mCurAnimation->curWindowEvent () == WindowEventOpen))) + mPAScreen->initiateOpenAnim (this); + mEventNotOpenClose = false; + break; + case CompWindowNotifyBeforeUnmap: + if (mCurAnimation && mCurAnimation->curWindowEvent () == WindowEventMinimize) + { + mUnmapCnt++; + mWindow->incrementUnmapReference (); + } + break; + case CompWindowNotifyBeforeDestroy: + if (!mFinishingAnim) + { + int duration; + + if (mPAScreen->shouldIgnoreWindowForAnim (mWindow, true)) + break; + + if (AnimEffectNone == + mPAScreen->getMatchingAnimSelection (mWindow, + AnimEventClose, + &duration)) + break; + + mDestroyCnt++; + mWindow->incrementDestroyReference (); + } + break; + case CompWindowNotifyUnreparent: + if (!mFinishingAnim) + { + if (mPAScreen->shouldIgnoreWindowForAnim (mWindow, false)) + break; + } + break; + case CompWindowNotifyFocusChange: + if (!mPAScreen->mLastActiveWindow || + mPAScreen->mLastActiveWindow != mWindow->id ()) + { + mPAScreen->mLastActiveWindow = mWindow->id (); + + if (mPAScreen->mStartCountdown) // Don't animate at startup + break; + + int duration = 200; + AnimEffect chosenEffect = + mPAScreen->getMatchingAnimSelection (mWindow, + AnimEventFocus, + &duration); + + if (chosenEffect && + chosenEffect != AnimEffectNone && + !chosenEffect->isRestackAnim) + mPAScreen->initiateFocusAnim (this); + } + + break; + case CompWindowNotifyRestack: + { + // Prevent menu disappearing when a menu is reopened during + // its close animation. In that case a restack notify is thrown + // for menus. + if (mCurAnimation && + mCurAnimation->curWindowEvent () == WindowEventClose) + { + mPAScreen->initiateOpenAnim (this); + mEventNotOpenClose = false; + break; + } + + // Handle CompWindowNotifyRestack only when necessary. + if (!mPAScreen->isRestackAnimPossible ()) + break; + + if (mPAScreen->mStartCountdown) // Don't animate at startup + break; + + foreach (ExtensionPluginInfo *extPlugin, + mPAScreen->mExtensionPlugins) + extPlugin->handleRestackNotify (mAWindow); + + break; + } + default: + break; + } + + mWindow->windowNotify (n); +} + +Animation * +AnimWindow::curAnimation () +{ + return priv->curAnimation (); +} + +AnimEffect +AnimScreen::getMatchingAnimSelection (CompWindow *w, + AnimEvent e, + int *duration) +{ + return priv->getMatchingAnimSelection (w, e, duration); +} + +bool +AnimScreen::otherPluginsActive () +{ + return priv->otherPluginsActive (); +} + +bool +AnimScreen::isAnimEffectPossible (AnimEffect theEffect) +{ + return priv->isAnimEffectPossible (theEffect); +} + +bool +AnimScreen::initiateFocusAnim (AnimWindow *aw) +{ + return priv->initiateFocusAnim (aw->priv); +} + +/// If duration is 0, it should be set to a positive value later. +void +AnimWindow::createFocusAnimation (AnimEffect effect, int duration) +{ + priv->createFocusAnimation (effect, duration); +} + +void +AnimWindow::deletePersistentData (const char *name) +{ + PersistentDataMap::iterator itData = + persistentData.find (name); + if (itData != persistentData.end ()) // if found + { + delete itData->second; + persistentData.erase (itData); + } +} + +void +PrivateAnimWindow::createFocusAnimation (AnimEffect effect, int duration) +{ + mCurAnimation = + effect->create (mWindow, WindowEventFocus, + duration, + effect, + CompRect ()); + enablePainting (true); +} + +AnimScreen::AnimScreen (CompScreen *s) : + PluginClassHandler (s), + priv (new PrivateAnimScreen (s, this)) +{ + priv->initAnimationList (); +} + +AnimScreen::~AnimScreen () +{ + delete priv; +} + +AnimWindow::AnimWindow (CompWindow *w) : + PluginClassHandler (w), + mWindow (w), + priv (new PrivateAnimWindow (w, this)), + mSavedRectsValid (false) +{ + foreach (ExtensionPluginInfo *extPlugin, priv->mPAScreen->mExtensionPlugins) + extPlugin->initPersistentData (this); +} + +AnimWindow::~AnimWindow () +{ + delete priv; + + // Destroy each persistent data object + PersistentDataMap::iterator itData = persistentData.begin (); + for (; itData != persistentData.end (); itData++) + delete itData->second; + + persistentData.clear (); +} + +bool +AnimPluginVTable::init () +{ + if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) | + !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) | + !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI)) + return false; + + CompPrivate p; + p.uval = ANIMATION_ABI; + ::screen->storeValue ("animation_ABI", p); + + return true; +} + +void +AnimPluginVTable::fini () +{ + ::screen->eraseValue ("animation_ABI"); +} + diff -Nru compiz-plugins-main-0.9.6.2011.10/.pc/fix-868121.patch/expo/src/expo.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-868121.patch/expo/src/expo.cpp --- compiz-plugins-main-0.9.6.2011.10/.pc/fix-868121.patch/expo/src/expo.cpp 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-868121.patch/expo/src/expo.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1,1812 @@ +/** + * + * Compiz expo plugin + * + * expo.c + * + * Copyright (c) 2011 Linaro Limited + * Copyright (c) 2008 Dennis Kasprzyk + * Copyright (c) 2006 Robert Carr + * + * Authors: + * Robert Carr + * Dennis Kasprzyk + * Travis Watkins + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + **/ + +#include "expo.h" +#include +#include +#include + +COMPIZ_PLUGIN_20090315 (expo, ExpoPluginVTable); + +#define sigmoid(x) (1.0f / (1.0f + exp (-5.5f * 2 * ((x) - 0.5)))) +#define sigmoidProgress(x) ((sigmoid (x) - sigmoid (0)) / \ + (sigmoid (1) - sigmoid (0))) + +#define interpolate(a, b, val) (((val) * (a)) + ((1 - (val)) * (b))) + +bool +ExpoScreen::dndInit (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid != screen->root ()) + return false; + + if (expoMode) + { + dndState = DnDStart; + action->setState (action->state () | CompAction::StateTermButton); + cScreen->damageScreen (); + + return true; + } + + return false; +} + +bool +ExpoScreen::dndFini (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid != screen->root ()) + return false; + + if (dndState == DnDDuring || dndState == DnDStart) + { + if (dndWindows.size ()) + finishWindowMovement (); + + dndState = DnDNone; + + action->setState (action->state () & CompAction::StateInitButton); + cScreen->damageScreen (); + + return true; + } + + return false; +} + +bool +ExpoScreen::doExpo (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid != screen->root ()) + return false; + + if (screen->otherGrabExist ("expo", NULL)) + return false; + + if (!expoMode) + { + if (!grabIndex) + grabIndex = screen->pushGrab (None, "expo"); + + updateWraps (true); + + expoMode = true; + anyClick = false; + doubleClick = false; + clickTime = 0; + + dndState = DnDNone; + + selectedVp = screen->vp (); + origVp = screen->vp (); + + screen->addAction (&optionGetDndButton ()); + screen->addAction (&optionGetExitButton ()); + screen->addAction (&optionGetNextVpButton ()); + screen->addAction (&optionGetPrevVpButton ()); + + cScreen->damageScreen (); + } + else + { + termExpo (action, state, options); + } + + return true; +} + +bool +ExpoScreen::termExpo (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid && xid != screen->root ()) + return false; + + if (!expoMode) + return true; + + expoMode = false; + + if (dndState != DnDNone) + dndFini (action, state, options); + + if (state & CompAction::StateCancel) + vpUpdateMode = VPUpdatePrevious; + else + vpUpdateMode = VPUpdateMouseOver; + + dndState = DnDNone; + + screen->removeAction (&optionGetDndButton ()); + screen->removeAction (&optionGetExitButton ()); + screen->removeAction (&optionGetNextVpButton ()); + screen->removeAction (&optionGetPrevVpButton ()); + + cScreen->damageScreen (); + screen->focusDefaultWindow (); + + return true; +} + +bool +ExpoScreen::exitExpo (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid != screen->root ()) + return false; + + if (!expoMode) + return false; + + termExpo (action, 0, noOptions); + anyClick = true; + cScreen->damageScreen (); + + return true; +} + +bool +ExpoScreen::nextVp (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + unsigned int newX, newY; + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid != screen->root ()) + return false; + + if (!expoMode) + return false; + + newX = selectedVp.x () + 1; + newY = selectedVp.y (); + + if (newX >= (unsigned int) screen->vpSize ().width ()) + { + newX = 0; + newY = newY + 1; + if (newY >= (unsigned int) screen->vpSize ().height ()) + newY = 0; + } + + moveFocusViewport (newX - selectedVp.x (), + newY - selectedVp.y ()); + cScreen->damageScreen (); + + return true; +} + +bool +ExpoScreen::prevVp (CompAction *action, + CompAction::State state, + CompOption::Vector &options) +{ + unsigned int newX, newY; + Window xid = CompOption::getIntOptionNamed (options, "root", 0); + if (xid != screen->root ()) + return false; + + if (!expoMode) + return false; + + newX = selectedVp.x () - 1; + newY = selectedVp.y (); + + if (newX < 0) + { + newX = screen->vpSize ().width () - 1; + newY = newY - 1; + if (newY < 0) + newY = screen->vpSize ().height () - 1; + } + + moveFocusViewport (newX - selectedVp.x (), + newY - selectedVp.y ()); + cScreen->damageScreen (); + + return true; +} + +void +ExpoScreen::moveFocusViewport (int dx, + int dy) +{ + int newX, newY; + + newX = selectedVp.x () + dx; + newY = selectedVp.y () + dy; + + newX = MAX (0, MIN ((int) screen->vpSize ().width () - 1, newX)); + newY = MAX (0, MIN ((int) screen->vpSize ().height () - 1, newY)); + + selectedVp.set (newX, newY); + cScreen->damageScreen (); +} + +void +ExpoScreen::finishWindowMovement () +{ + foreach (CompWindow *dndWindow, dndWindows) + { + if (dndWindow->grabbed ()) + { + dndWindow->syncPosition (); + dndWindow->ungrabNotify (); + + screen->updateGrab (grabIndex, None); + + screen->moveViewport (screen->vp ().x () - selectedVp.x (), + screen->vp ().y () - selectedVp.y (), true); + + /* update saved window attributes in case we moved the + window to a new viewport */ + if (dndWindow->saveMask () & CWX) + { + dndWindow->saveWc ().x = dndWindow->saveWc ().x % screen->width (); + if (dndWindow->saveWc ().x < 0) + dndWindow->saveWc ().x += screen->width (); + } + if (dndWindow->saveMask () & CWY) + { + dndWindow->saveWc ().y = dndWindow->saveWc ().y % screen->height (); + if (dndWindow->saveWc ().y < 0) + dndWindow->saveWc ().y += screen->height (); + } + + /* update window attibutes to make sure a moved maximized window + is properly snapped to the work area */ + if (dndWindow->state () & MAXIMIZE_STATE) + dndWindow->updateAttributes (CompStackingUpdateModeNone); + } + } + + dndWindows.clear (); +} + +void +ExpoScreen::handleEvent (XEvent *event) +{ + switch (event->type) { + case KeyPress: + if (expoMode && event->xkey.root == screen->root ()) + { + if (event->xkey.keycode == leftKey) + moveFocusViewport (-1, 0); + else if (event->xkey.keycode == rightKey) + moveFocusViewport (1, 0); + else if (event->xkey.keycode == upKey) + moveFocusViewport (0, -1); + else if (event->xkey.keycode == downKey) + moveFocusViewport (0, 1); + } + break; + + case ButtonPress: + if (expoMode && event->xbutton.button == Button1 && + event->xbutton.root == screen->root ()) + { + anyClick = true; + if (clickTime == 0) + { + clickTime = event->xbutton.time; + } + else if (event->xbutton.time - clickTime <= + (unsigned int) optionGetDoubleClickTime ()) + { + doubleClick = true; + } + else + { + clickTime = event->xbutton.time; + doubleClick = false; + } + cScreen->damageScreen (); + } + break; + + case ButtonRelease: + if (expoMode && event->xbutton.button == Button1 && + event->xbutton.root == screen->root ()) + { + if (event->xbutton.time - clickTime > + (unsigned int) optionGetDoubleClickTime ()) + { + clickTime = 0; + doubleClick = false; + } + else if (doubleClick) + { + CompAction& action = optionGetExpoKey (); + + clickTime = 0; + doubleClick = false; + + termExpo (&action, 0, noOptions); + anyClick = true; + } + } + break; + } + + screen->handleEvent (event); +} + +bool +ExpoScreen::windowsOnVp (CompPoint &p) +{ + foreach (CompWindow *w, screen->clientList (true)) + { + CompPoint viewport; + + screen->viewportForGeometry (w->geometry (), viewport); + + if (viewport == p&& + w->type () != CompWindowTypeDesktopMask && + w->type () != CompWindowTypeDockMask) + { + return true; + } + } + + return false; +} + +void +ExpoScreen::preparePaint (int msSinceLastPaint) +{ + float val = ((float) msSinceLastPaint / 1000.0) / optionGetZoomTime (); + + if (expoMode) + expoCam = MIN (1.0, expoCam + val); + else + expoCam = MAX (0.0, expoCam - val); + + if (expoCam) + { + unsigned int i, j, vp; + unsigned int vpCount = screen->vpSize ().width () * + screen->vpSize ().height (); + + if (vpActivity.size () < vpCount) + { + vpActivity.resize (vpCount); + foreach (float& activity, vpActivity) + activity = 1.0f; + } + + for (i = 0; i < (unsigned int) screen->vpSize ().width (); i++) + { + for (j = 0; j < (unsigned int) screen->vpSize ().height (); j++) + { + vp = (j * screen->vpSize ().width ()) + i; + CompPoint vpPos = CompPoint (i, j); + + if (windowsOnVp (vpPos)) + vpActivity[vp] = MIN (1.0, vpActivity[vp] + val); + else + vpActivity[vp] = MAX (0.0, vpActivity[vp] - val); + } + } + + for (i = 0; i < 360; i++) + { + float fi = (float) i; + + vpNormals[i * 3] = (-sin (fi * DEG2RAD) / screen->width ()) * + expoCam; + vpNormals[(i * 3) + 1] = 0.0; + vpNormals[(i * 3) + 2] = (-cos (fi * DEG2RAD) * expoCam) - + (1 - expoCam); + } + } + + cScreen->preparePaint (msSinceLastPaint); +} + +void +ExpoScreen::updateWraps (bool enable) +{ + screen->handleEventSetEnabled (this, enable); + cScreen->preparePaintSetEnabled (this, enable); + cScreen->paintSetEnabled (this, enable); + cScreen->getWindowPaintListSetEnabled (this, false); + cScreen->donePaintSetEnabled (this, enable); + gScreen->glPaintOutputSetEnabled (this, enable); + gScreen->glPaintTransformedOutputSetEnabled (this, enable); + + foreach (CompWindow *w, screen->windows ()) + { + ExpoWindow *ew = ExpoWindow::get (w); + + ew->cWindow->damageRectSetEnabled (ew, enable); + ew->gWindow->glPaintSetEnabled (ew, enable); + ew->gWindow->glDrawSetEnabled (ew, enable); + ew->gWindow->glAddGeometrySetEnabled (ew, enable); + ew->gWindow->glDrawTextureSetEnabled (ew, enable); + } +} + +void +ExpoScreen::paint (CompOutput::ptrList &outputs, + unsigned int mask) +{ + int width = outputs.front ()->width (); + int height = outputs.front ()->height (); + bool sizeDiff = false; + + /* "One big wall" does not make sense where outputs are different + * sizes, so force multiple walls in this case + * + * TODO: Is it possible to re-create "one big wall" using + * independent output painting in this case? */ + + foreach (CompOutput *o, outputs) + { + if (o->width () != width || o->height () != height) + { + sizeDiff = true; + break; + } + } + + if (expoCam > 0.0 && outputs.size () > 1 && + optionGetMultioutputMode () == MultioutputModeOneBigWall && + !sizeDiff) + { + outputs.clear (); + outputs.push_back (&screen->fullscreenOutput ()); + } + + cScreen->paint (outputs, mask); +} + +void +ExpoScreen::donePaint () +{ + switch (vpUpdateMode) { + case VPUpdateMouseOver: + screen->moveViewport (screen->vp ().x () - selectedVp.x (), + screen->vp ().y () - selectedVp.y (), true); + screen->focusDefaultWindow (); + vpUpdateMode = VPUpdateNone; + break; + case VPUpdatePrevious: + screen->moveViewport (screen->vp ().x () - origVp.x (), + screen->vp ().y () - origVp.y (), true); + selectedVp = origVp; + screen->focusDefaultWindow (); + vpUpdateMode = VPUpdateNone; + break; + default: + break; + } + + if ((expoCam > 0.0f && expoCam < 1.0f) || dndState != DnDNone) + cScreen->damageScreen (); + + if (expoCam == 1.0f) + { + foreach (float& vp, vpActivity) + if (vp != 0.0 && vp != 1.0) + cScreen->damageScreen (); + } + + if (grabIndex && expoCam <= 0.0f && !expoMode) + { + screen->removeGrab (grabIndex, NULL); + grabIndex = 0; + updateWraps (false); + cScreen->damageScreen (); + } + + cScreen->donePaint (); + + switch (dndState) { + case DnDDuring: + { + if (dndWindows.size ()) + { + foreach (CompWindow *dndWindow, dndWindows) + { + if (dndWindow->grabbed ()) + { + dndWindow->move (newCursor.x () - prevCursor.x (), + newCursor.y () - prevCursor.y (), + optionGetExpoImmediateMove ()); + } + } + } + + prevCursor = newCursor; + cScreen->damageScreen (); + } + break; + + case DnDStart: + { + int xOffset, yOffset; + CompWindowList::reverse_iterator iter; + + xOffset = screen->vpSize ().width () * screen->width (); + yOffset = screen->vpSize ().height () * screen->height (); + + dndState = DnDNone; + + for (iter = screen->windows ().rbegin (); + iter != screen->windows ().rend (); ++iter) + { + CompWindow *w = *iter; + CompRect input (w->inputRect ()); + bool inWindow; + int nx, ny; + + if (w->destroyed ()) + continue; + + if (!w->shaded () && !w->isViewable ()) + continue; + + if (w->onAllViewports ()) + { + nx = (newCursor.x () + xOffset) % screen->width (); + ny = (newCursor.y () + yOffset) % screen->height (); + } + else + { + nx = newCursor.x () - + (screen->vp ().x () * screen->width ()); + ny = newCursor.y () - + (screen->vp ().y () * screen->height ()); + } + + inWindow = (nx >= input.left () && nx <= input.right ()) || + (nx >= (input.left () + xOffset) && + nx <= (input.right () + xOffset)); + + inWindow &= (ny >= input.top () && ny <= input.bottom ()) || + (ny >= (input.top () + yOffset) && + ny <= (input.bottom () + yOffset)); + + if (!inWindow) + continue; + + /* make sure we never move windows we're not allowed to move */ + if (!w->managed ()) + break; + else if (!(w->actions () & CompWindowActionMoveMask)) + break; + else if (w->type () & (CompWindowTypeDockMask | + CompWindowTypeDesktopMask)) + break; + + dndState = DnDDuring; + + if (std::find (dndWindows.begin (), dndWindows.end (), w) == dndWindows.end ()) + dndWindows.push_back (w); + + w->grabNotify (nx, ny, 0, + CompWindowGrabMoveMask | + CompWindowGrabButtonMask); + + screen->updateGrab (grabIndex, mMoveCursor); + + w->raise (); + w->moveInputFocusTo (); + break; + } + + prevCursor = newCursor; + } + break; + default: + break; + } +} + +static bool +unproject (float winx, float winy, float winz, + const GLMatrix &modelview, + const GLMatrix &projection, + const GLint viewport[4], + float *objx, float *objy, float *objz) +{ + GLMatrix finalMatrix = projection * modelview; + float in[4], out[4]; + + if (!finalMatrix.invert ()) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = 1.0; + + /* Map x and y from window coordinates */ + in[0] = (in[0] - viewport[0]) / viewport[2]; + in[1] = (in[1] - viewport[1]) / viewport[3]; + + /* Map to range -1 to 1 */ + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + for (int i = 0; i < 4; i++) + { + out[i] = in[0] * finalMatrix[i] + + in[1] * finalMatrix[4 + i] + + in[2] * finalMatrix[8 + i] + + in[3] * finalMatrix[12 + i]; + } + + if (out[3] == 0.0) + return false; + + out[0] /= out[3]; + out[1] /= out[3]; + out[2] /= out[3]; + + *objx = out[0]; + *objy = out[1]; + *objz = out[2]; + + return true; +} + +void +ExpoScreen::invertTransformedVertex (const GLScreenPaintAttrib &attrib, + const GLMatrix &transform, + CompOutput *output, + int vertex[2]) +{ + GLMatrix sTransform (transform); + float p1[3], p2[3], v[3], alpha; + GLint viewport[4]; + int i; + + gScreen->glApplyTransform (attrib, output, &sTransform); + sTransform.toScreenSpace (output, -attrib.zTranslate); + + glGetIntegerv (GL_VIEWPORT, viewport); + + unproject (vertex[0], screen->height () - vertex[1], 0, + sTransform, *gScreen->projectionMatrix (), viewport, + &p1[0], &p1[1], &p1[2]); + unproject (vertex[0], screen->height () - vertex[1], -1.0, + sTransform, *gScreen->projectionMatrix (), viewport, + &p2[0], &p2[1], &p2[2]); + + for (i = 0; i < 3; i++) + v[i] = p1[i] - p2[i]; + + alpha = -p1[2] / v[2]; + + if (optionGetDeform () == DeformCurve && screen->desktopWindowCount ()) + { + const float sws = screen->width () * screen->width (); + const float rs = (curveDistance * curveDistance) + 0.25; + const float p = ((2.0 * sws * (p1[2] - curveDistance) * v[2]) + + (2.0 * p1[0] * v[0]) - + (v[0] * (float) screen->width ())) / + ((v[2] * v[2] * sws) + (v[0] * v[0])); + const float q = (-(sws * rs) + (sws * (p1[2] - curveDistance) * + (p1[2] - curveDistance)) + + (0.25 * sws) + (p1[0] * p1[0]) - + (p1[0] * (float) screen->width ())) / + ((v[2] * v[2] * sws) + (v[0] * v[0])); + + const float rq = (0.25 * p * p) - q; + const float ph = -p * 0.5; + + if (rq < 0.0) + { + vertex[0] = -1000; + vertex[1] = -1000; + return; + } + else + { + alpha = ph + sqrt(rq); + if (p1[2] + (alpha * v[2]) > 0.0) + { + vertex[0] = -1000; + vertex[1] = -1000; + return; + } + } + } + + vertex[0] = ceil (p1[0] + (alpha * v[0])); + vertex[1] = ceil (p1[1] + (alpha * v[1])); +} + +void +ExpoScreen::paintViewport (const GLScreenPaintAttrib& attrib, + const GLMatrix& transform, + const CompRegion& region, + CompOutput *output, + unsigned int mask, + CompPoint vpPos, + GLVector &vpCamPos, + bool reflection) +{ + GLMatrix sTransform (transform); + GLMatrix sTransform2, sTransform3; + float sx = (float) screen->width () / output->width (); + float sy = (float) screen->height () / output->height (); + float vpp; + float progress = sigmoidProgress (expoCam); + unsigned int vp; + CompPoint vpSize (screen->vpSize ().width (), screen->vpSize ().height ()); + + const float gapY = optionGetVpDistance () * 0.1f * expoCam; + const float gapX = optionGetVpDistance () * 0.1f * screen->height () / + screen->width () * expoCam; + + /* not sure this will work with different resolutions */ + sTransform.translate (0.0, MAX (0, vpPos.y ()) * -(sy + gapY), 0.0f); + + sTransform2 = sTransform; + + /* not sure this will work with different resolutions */ + if (optionGetDeform () != DeformCurve) + sTransform2.translate (MAX (0, vpPos.x ()) * (sx + gapX), 0.0f, 0.0); + + + if (optionGetExpoAnimation () == ExpoAnimationVortex) + sTransform2.rotate (360 * expoCam, + 0.0f, 1.0f, 2.0f * expoCam); + + sTransform3 = sTransform2; + + sTransform3.translate (output->x () / output->width (), + -output->y () / output->height (), 0.0); + + cScreen->setWindowPaintOffset ((screen->vp ().x () - vpPos.x ()) * + screen->width (), + (screen->vp ().y () - vpPos.y ()) * + screen->height ()); + + vp = (vpPos.y () * vpSize.x ()) + vpPos.x (); + + vpp = (expoCam * vpActivity[vp]) + (1 - expoCam); + vpp = sigmoidProgress (vpp); + + vpBrightness = vpp + ((1.0 - vpp) * + optionGetVpBrightness () / 100.0); + vpSaturation = vpp + ((1.0 - vpp) * + optionGetVpSaturation () / 100.0); + + paintingVp = vpPos; + + if (optionGetDeform () == DeformCurve) + { + float rotateX; + + sTransform3.translate (-vpCamPos[GLVector::x], 0.0f, + curveDistance - DEFAULT_Z_CAMERA); + + rotateX = -vpPos.x () + interpolate (((float) vpSize.x () / 2.0) - 0.5, + screen->vp ().x (), progress); + + sTransform3.rotate (curveAngle * rotateX, 0.0, 1.0, 0.0); + + sTransform3.translate (vpCamPos[GLVector::x], 0.0f, + DEFAULT_Z_CAMERA - curveDistance); + } + + cScreen->getWindowPaintListSetEnabled (this, paintingDndWindow); + gScreen->glPaintTransformedOutput (attrib, sTransform3, + screen->region (), output, + mask); + + cScreen->getWindowPaintListSetEnabled (this, !paintingDndWindow); + + if (!reflection && !paintingDndWindow) + { + int cursor[2] = { pointerX, pointerY }; + + invertTransformedVertex (attrib, sTransform3, + output, cursor); + + if ((cursor[0] > 0) && (cursor[0] < (int) screen->width ()) && + (cursor[1] > 0) && (cursor[1] < (int) screen->height ())) + { + newCursor.setX (vpPos.x () * screen->width () + cursor[0]); + newCursor.setY (vpPos.y () * screen->height () + cursor[1]); + + if (anyClick || dndState != DnDNone) + { + /* Used to save last viewport interaction was in */ + selectedVp = vpPos; + anyClick = false; + } + } + } + + /* Calculate the current viewport size */ + int tl[2] = { 0, 0 }; + int br[2] = { screen->width (), screen->height () }; + + invertTransformedVertex (attrib, sTransform3, output, tl); + invertTransformedVertex (attrib, sTransform3, output, br); + + viewport_size = CompSize (br[0] - tl[0], br[1] - tl[1]); +} + +void +ExpoScreen::paintWall (const GLScreenPaintAttrib &attrib, + const GLMatrix &transform, + const CompRegion ®ion, + CompOutput *output, + unsigned int mask, + bool reflection) +{ + GLfloat vertexData[12]; + GLushort colorData[16]; + GLMatrix sTransformW, sTransform (transform); + GLenum oldFilter = gScreen->textureFilter (); + float sx = (float) screen->width () / output->width (); + float sy = (float) screen->height () / output->height (); + float biasZ; + float oScale, rotation = 0.0f, progress; + float aspectX = 1.0f, aspectY = 1.0f; + GLVector cam; + CompPoint vpSize (screen->vpSize ().width (), screen->vpSize ().height ()); + + /* amount of gap between viewports */ + const float gapY = optionGetVpDistance () * 0.1f * expoCam; + const float gapX = optionGetVpDistance () * 0.1f * screen->height () / + screen->width () * expoCam; + + int glPaintTransformedOutputIndex = + gScreen->glPaintTransformedOutputGetCurrentIndex (); + + GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer (); + + // Make sure that the base glPaintTransformedOutput function is called + gScreen->glPaintTransformedOutputSetCurrentIndex (MAXSHORT); + + /* Zoom animation stuff */ + /* camera position for the selected viewport */ + GLVector vpCamPos (0, 0, 0, 0); + + /* camera position during expo mode */ + GLVector expoCamPos (0, 0, 0, 0); + + if (optionGetDeform () == DeformCurve) + { + vpCamPos[GLVector::x] = -sx * (0.5 - (((float) output->x () + + (output->width () / 2.0)) / + (float) screen->width ())); + } + else + { + vpCamPos[GLVector::x] = (screen->vp ().x () * sx) + 0.5 + + (output->x () / output->width ()) - + (vpSize.x () * 0.5 * sx) + + gapX * screen->vp ().x (); + } + vpCamPos[GLVector::y] = -((screen->vp ().y () * sy) + 0.5 + + (output->y () / output->height ())) + + (vpSize.y () * 0.5 * sy) - + gapY * screen->vp ().y (); + + biasZ = MAX (vpSize.x () * sx, vpSize.y () * sy); + if (optionGetDeform () == DeformTilt || optionGetReflection ()) + biasZ *= (0.15 + optionGetDistance ()); + else + biasZ *= optionGetDistance (); + + progress = sigmoidProgress (expoCam); + + if (optionGetDeform () != DeformCurve) + expoCamPos[GLVector::x] = gapX * (vpSize.x () - 1) * 0.5; + + expoCamPos[GLVector::y] = -gapY * (vpSize.y () - 1) * 0.5; + expoCamPos[GLVector::z] = -DEFAULT_Z_CAMERA + DEFAULT_Z_CAMERA * + (MAX (vpSize.x () + (vpSize.x () - 1) * gapX, + vpSize.y () + (vpSize.y () - 1) * gapY) + + biasZ); + + /* interpolate between vpCamPos and expoCamPos */ + cam[GLVector::x] = vpCamPos[GLVector::x] * (1 - progress) + + expoCamPos[GLVector::x] * progress; + cam[GLVector::y] = vpCamPos[GLVector::y] * (1 - progress) + + expoCamPos[GLVector::y] * progress; + cam[GLVector::z] = vpCamPos[GLVector::z] * (1 - progress) + + expoCamPos[GLVector::z] * progress; + + if (vpSize.x () > vpSize.y ()) + { + aspectY = (float) vpSize.x () / (float) vpSize.y (); + aspectY -= 1.0; + aspectY *= -optionGetAspectRatio () + 1.0; + aspectY *= progress; + aspectY += 1.0; + } + else + { + aspectX = (float) vpSize.y () / (float) vpSize.x (); + aspectX -= 1.0; + aspectX *= -optionGetAspectRatio () + 1.0; + aspectX *= progress; + aspectX += 1.0; + } + + /* End of Zoom animation stuff */ + + if (optionGetDeform () == DeformTilt) + { + if (optionGetExpoAnimation () == ExpoAnimationZoom) + rotation = 10.0 * sigmoidProgress (expoCam); + else + rotation = 10.0 * expoCam; + } + + if (optionGetMipmaps ()) + gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR); + + /* ALL TRANSFORMATION ARE EXECUTED FROM BOTTOM TO TOP */ + + oScale = 1 / (1 + ((MAX (sx, sy) - 1) * progress)); + + sTransform.scale (oScale, oScale, 1.0); + + /* zoom out */ + oScale = DEFAULT_Z_CAMERA / (cam[GLVector::z] + DEFAULT_Z_CAMERA); + sTransform.scale (oScale, oScale, oScale); +// glNormal3f (0.0, 0.0, -oScale); + sTransform.translate (-cam[GLVector::x], -cam[GLVector::y], + -cam[GLVector::z] - DEFAULT_Z_CAMERA); + + if (reflection) + { + float scaleFactor = optionGetScaleFactor (); + + sTransform.translate (0.0, + (vpSize.y () + ((vpSize.y () - 1) * gapY * 2)) * + -sy * aspectY, + 0.0); + sTransform.scale (1.0, -1.0, 1.0); + sTransform.translate (0.0, + - (1 - scaleFactor) / 2 * sy * aspectY * + (vpSize.y () + ((vpSize.y () - 1) * gapY * 2)), + 0.0); + sTransform.scale (1.0, scaleFactor, 1.0); + glCullFace (GL_FRONT); + } + + /* rotate */ + sTransform.rotate (rotation, 0.0f, 1.0f, 0.0f); + sTransform.scale (aspectX, aspectY, 1.0); + + float xoffset = 0.0; + float yoffset = 0.0; + float xadjs = 1.0f; + float yadjs = 1.0f; + + if (output->left () == 0) + { + xoffset = ((vpSize.x () * sx) / ((float) output->width ()) * (optionGetXOffset ()) * sigmoidProgress (expoCam)); + xadjs = 1.0f - ((float) (optionGetXOffset ()) / (float) (output->width ())) * sigmoidProgress (expoCam); + } + + if (output->top () == 0) + { + yoffset = ((vpSize.y () * sy) / ((float) output->height ()) * (optionGetYOffset ()) * sigmoidProgress (expoCam)); + + yadjs = 1.0f - ((float) (optionGetYOffset ()) / (float) output->height ()) * sigmoidProgress (expoCam); + } + + /* translate expo to center */ + sTransform.translate (vpSize.x () * sx * -0.5 + xoffset, + vpSize.y () * sy * 0.5 - yoffset, 0.0f); + sTransform.scale (xadjs, yadjs, 1.0f); + + if (optionGetDeform () == DeformCurve) + sTransform.translate ((vpSize.x () - 1) * sx * 0.5, 0.0, 0.0); + + sTransformW = sTransform; + + /* revert prepareXCoords region shift. Now all screens display the same */ + sTransform.translate (0.5f, -0.5f, DEFAULT_Z_CAMERA); + + if (vpSize.x () > 2) + /* we can't have 90 degree for the left/right most viewport */ + curveAngle = interpolate (359 / ((vpSize.x () - 1) * 2), 1, + optionGetCurve ()); + else + curveAngle = interpolate (180 / vpSize.x (), 1, optionGetCurve ()); + + curveDistance = ((0.5f * sx) + (gapX / 2.0)) / + tanf (DEG2RAD * curveAngle / 2.0); + curveRadius = ((0.5f * sx) + (gapX / 2.0)) / + sinf (DEG2RAD * curveAngle / 2.0); + + expoActive = true; + + for (int j = 0; j < screen->vpSize ().height (); j++) + for (int i = 0; i < screen->vpSize().width (); i++) + paintViewport (attrib, sTransform, region, output, mask, CompPoint (i, j), vpCamPos, reflection); + + paintingDndWindow = true; + + foreach (CompWindow *dndWindow, dndWindows) + { + CompPoint vp; + + screen->viewportForGeometry (dndWindow->geometry (), vp); + + while (vp.x () < 0) + vp.setX (screen->vpSize ().width () + vp.x ()); + + while (vp.y () < 0) + vp.setY (screen->vpSize ().height () + vp.y ()); + + paintViewport (attrib, sTransform, region, output, mask, vp, vpCamPos, reflection); + } + + paintingDndWindow = false; + +// glNormal3f (0.0, 0.0, -1.0); + + if (reflection) + { + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (optionGetDeform () != DeformCurve) + { + streamingBuffer->begin (GL_TRIANGLE_STRIP); + + colorData[0] = 0; + colorData[1] = 0; + colorData[2] = 0; + colorData[3] = 65535; + colorData[4] = 0; + colorData[5] = 0; + colorData[6] = 0; + colorData[7] = 32768; + colorData[8] = 0; + colorData[9] = 0; + colorData[10] = 0; + colorData[11] = 65535; + colorData[12] = 0; + colorData[13] = 0; + colorData[14] = 0; + colorData[15] = 32768; + + vertexData[0] = 0; + vertexData[1] = 0; + vertexData[2] = 0; + vertexData[3] = 0; + vertexData[4] = -vpSize.y () * (sy + gapY); + vertexData[5] = 0; + vertexData[6] = vpSize.x () * sx * (1.0 + gapX); + vertexData[7] = 0; + vertexData[8] = 0; + vertexData[9] = vpSize.x () * sx * (1.0 + gapX); + vertexData[10] = -vpSize.y () * sy * (1.0 + gapY); + vertexData[11] = 0; + + streamingBuffer->addColors (4, colorData); + streamingBuffer->addVertices (4, vertexData); + + streamingBuffer->end (); + streamingBuffer->render (sTransformW); + } + else + { + GLMatrix cTransform; + cTransform.translate (0.0, 0.0, -DEFAULT_Z_CAMERA); + + glCullFace (GL_BACK); + + streamingBuffer->begin (GL_TRIANGLE_STRIP); + + colorData[0] = 0; + colorData[1] = 0; + colorData[2] = 0; + colorData[3] = (1.0 * expoCam) * 65536; + colorData[4] = 0; + colorData[5] = 0; + colorData[6] = 0; + colorData[7] = (1.0 * expoCam) * 65536; + colorData[8] = 0; + colorData[9] = 0; + colorData[10] = 0; + colorData[11] = (0.5 * expoCam) * 65536; + colorData[12] = 0; + colorData[13] = 0; + colorData[14] = 0; + colorData[15] = (0.5 * expoCam) * 65536; + + vertexData[0] = -0.5; + vertexData[1] = -0.5; + vertexData[2] = 0; + vertexData[3] = 0.5; + vertexData[4] = -0.5; + vertexData[5] = 0; + vertexData[6] = -0.5; + vertexData[7] = 0; + vertexData[8] = 0; + vertexData[9] = 0.5; + vertexData[10] = 0; + vertexData[11] = 0; + + streamingBuffer->addColors (4, colorData); + streamingBuffer->addVertices (4, vertexData); + + streamingBuffer->end (); + streamingBuffer->render (cTransform); + + streamingBuffer->begin (GL_TRIANGLE_STRIP); + + colorData[0] = 0; + colorData[1] = 0; + colorData[2] = 0; + colorData[3] = (0.5 * expoCam) * 65536; + colorData[4] = 0; + colorData[5] = 0; + colorData[6] = 0; + colorData[7] = (0.5 * expoCam) * 65536; + colorData[8] = 0; + colorData[9] = 0; + colorData[10] = 0; + colorData[11] = 0; + colorData[12] = 0; + colorData[13] = 0; + colorData[14] = 0; + colorData[15] = 0; + + vertexData[0] = -0.5; + vertexData[1] = 0; + vertexData[2] = 0; + vertexData[3] = 0.5; + vertexData[4] = 0; + vertexData[5] = 0; + vertexData[6] = -0.5; + vertexData[7] = 0.5; + vertexData[8] = 0; + vertexData[9] = 0.5; + vertexData[10] = 0.5; + vertexData[11] = 0; + + streamingBuffer->addColors (4, colorData); + streamingBuffer->addVertices (4, vertexData); + + streamingBuffer->end (); + streamingBuffer->render (cTransform); + } + glCullFace (GL_BACK); + + if (optionGetGroundSize () > 0.0) + { + GLMatrix gTransform; + gTransform.translate (0.0, 0.0, -DEFAULT_Z_CAMERA); + + streamingBuffer->begin (GL_TRIANGLE_STRIP); + + vertexData[0] = -0.5; + vertexData[1] = -0.5; + vertexData[2] = 0; + vertexData[3] = 0.5; + vertexData[4] = -0.5; + vertexData[5] = 0; + vertexData[6] = -0.5; + vertexData[7] = -0.5 + optionGetGroundSize (); + vertexData[8] = 0; + vertexData[9] = 0.5; + vertexData[10] = -0.5 + optionGetGroundSize (); + vertexData[11] = 0; + + streamingBuffer->addColors (1, optionGetGroundColor1 ()); + streamingBuffer->addColors (1, optionGetGroundColor1 ()); + streamingBuffer->addColors (1, optionGetGroundColor2 ()); + streamingBuffer->addColors (1, optionGetGroundColor2 ()); + streamingBuffer->addVertices (4, vertexData); + + streamingBuffer->end (); + streamingBuffer->render (gTransform); + } + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + + expoActive = false; + + cScreen->setWindowPaintOffset (0, 0); + + gScreen->glPaintTransformedOutputSetCurrentIndex (glPaintTransformedOutputIndex); + gScreen->setTextureFilter (oldFilter); +} + +const CompWindowList & +ExpoScreen::getWindowPaintList () +{ + return dndWindows; +} + +bool +ExpoScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, + const GLMatrix &transform, + const CompRegion ®ion, + CompOutput *output, + unsigned int mask) +{ + if (expoCam > 0.0) + mask |= PAINT_SCREEN_TRANSFORMED_MASK | PAINT_SCREEN_CLEAR_MASK; + + return gScreen->glPaintOutput (attrib, transform, region, output, mask); +} + +void +ExpoScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &attrib, + const GLMatrix &transform, + const CompRegion ®ion, + CompOutput *output, + unsigned int mask) +{ + expoActive = false; + + if (expoCam > 0) + mask |= PAINT_SCREEN_CLEAR_MASK; + + if (expoCam <= 0 || (expoCam > 0.0 && expoCam < 1.0 && + optionGetExpoAnimation () != ExpoAnimationZoom)) + { + gScreen->glPaintTransformedOutput (attrib, transform, region, + output, mask); + } + else + { + gScreen->clearOutput (output, GL_COLOR_BUFFER_BIT); + } + + mask &= ~PAINT_SCREEN_CLEAR_MASK; + + if (expoCam > 0.0) + { + if (optionGetReflection ()) + paintWall (attrib, transform, region, output, mask, true); + + paintWall (attrib, transform, region, output, mask, false); + anyClick = false; + } +} + +bool +ExpoWindow::glDraw (const GLMatrix &transform, + const GLWindowPaintAttrib &attrib, + const CompRegion ®ion, + unsigned int mask) +{ + GLMatrix wTransform (transform); + CompPoint vp; + + screen->viewportForGeometry (window->geometry (), vp); + + if (eScreen->expoCam == 0.0f) + return gWindow->glDraw (transform, attrib, region, mask); + + GLWindowPaintAttrib eAttrib (attrib); + int expoAnimation; + + expoAnimation = eScreen->optionGetExpoAnimation (); + + if (eScreen->expoActive) + { + if (expoAnimation != ExpoScreen::ExpoAnimationZoom) + eAttrib.opacity = attrib.opacity * eScreen->expoCam; + + if (window->wmType () & CompWindowTypeDockMask && + eScreen->optionGetHideDocks ()) + { + if (expoAnimation == ExpoScreen::ExpoAnimationZoom && + eScreen->paintingVp == eScreen->selectedVp) + { + eAttrib.opacity = attrib.opacity * + (1 - sigmoidProgress (eScreen->expoCam)); + } + else + { + eAttrib.opacity = 0; + } + } + + if ((vp == eScreen->paintingVp || window->onAllViewports ()) && !eScreen->paintingDndWindow) + { + eAttrib.brightness = attrib.brightness * eScreen->vpBrightness; + eAttrib.saturation = attrib.saturation * eScreen->vpSaturation; + } + } + else + { + if (expoAnimation == ExpoScreen::ExpoAnimationZoom) + eAttrib.brightness = 0; + else + eAttrib.brightness = attrib.brightness * + (1 - sigmoidProgress (eScreen->expoCam)); + } + + bool status = gWindow->glDraw (transform, eAttrib, region, mask); + + if (window->type () & CompWindowTypeDesktopMask) + { + /* We want to set the geometry of the polka dots to the window + * region */ + CompRegion reg = CompRegion (0, 0, window->width (), window->height ()); + + foreach(GLTexture * tex, eScreen->polkadots_texture) + { + GLTexture::MatrixList matl; + GLTexture::Matrix mat = tex->matrix(); + CompRegion paintRegion(region); + + float xScale = screen->width () / (float) eScreen->viewport_size.width (); + float yScale = screen->height () / (float) eScreen->viewport_size.height (); + + mat.xx *= xScale; + mat.yy *= yScale; + + /* Not sure what this does, but it is necessary + * (adjusts for scale?) */ + mat.x0 -= mat.xx * reg.boundingRect().x1(); + mat.y0 -= mat.yy * reg.boundingRect().y1(); + + matl.push_back(mat); + + if (mask & PAINT_WINDOW_TRANSFORMED_MASK) + paintRegion = infiniteRegion; + + /* Now allow plugins to mess with the geometry of our + * dim (so we get a nice render for things like + * wobbly etc etc */ + gWindow->vertexBuffer()->begin(); + gWindow->glAddGeometry(matl, reg, paintRegion); + gWindow->vertexBuffer()->end(); + + unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex(); + eAttrib.opacity = attrib.opacity * (((1.0 - eScreen->vpBrightness) + (1.0 - eScreen->vpSaturation) / 2.0)); + /* Texture rendering set-up */ + //eScreen->gScreen->setTexEnvMode(GL_MODULATE); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + /* Draw the dim texture with all of it's modified + * geometry glory */ + gWindow->glDrawTextureSetCurrentIndex(MAXSHORT); + gWindow->glDrawTexture(tex, transform, eAttrib, mask | + PAINT_WINDOW_BLEND_MASK | + PAINT_WINDOW_TRANSLUCENT_MASK | + PAINT_WINDOW_TRANSFORMED_MASK); + gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex); + /* Texture rendering tear-down */ + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + eScreen->gScreen->setTexEnvMode(GL_REPLACE); + } + + /* Paint the outline */ + if (mGlowQuads && eScreen->paintingVp == eScreen->selectedVp) + { + if (region.numRects ()) + { + /* reset geometry and paint */ + gWindow->vertexBuffer ()->begin (); + gWindow->vertexBuffer ()->end (); + + paintGlow (transform, attrib, infiniteRegion, mask); + } + } + + } + return status; + +} + +#define EXPO_GRID_SIZE 100 + +void +ExpoWindow::glAddGeometry (const GLTexture::MatrixList &matrices, + const CompRegion ®ion, + const CompRegion &clip, + unsigned int maxGridWidth, + unsigned int maxGridHeight) +{ + if (eScreen->expoCam > 0.0 && + screen->desktopWindowCount () && + eScreen->optionGetDeform () == ExpoScreen::DeformCurve) + { + #warning Curve not ported, needs shaders now +/* int i, oldVCount = gWindow->geometry ().vCount; + GLfloat *v; + CompPoint offset; + float lastX, lastZ = 0.0; + const float radSquare = pow (eScreen->curveDistance, 2) + 0.25; + float ang; + + gWindow->glAddGeometry (matrices, region, clip, + MIN(maxGridWidth , EXPO_GRID_SIZE), + maxGridHeight); + + v = gWindow->geometry ().vertices; + v += gWindow->geometry ().vertexStride - 3; + v += gWindow->geometry ().vertexStride * oldVCount; + + if (!window->onAllViewports ()) + { + offset = eScreen->cScreen->windowPaintOffset (); + offset = window->getMovementForOffset (offset); + } + + lastX = -1000000000.0; + + for (i = oldVCount; i < gWindow->geometry ().vCount; i++) + { + if (v[0] == lastX) + { + v[2] = lastZ; + } + else if (v[0] + offset.x () >= -EXPO_GRID_SIZE && + v[0] + offset.x () < screen->width () + EXPO_GRID_SIZE) + { + ang = (((v[0] + offset.x ()) / (float) screen->width ()) - 0.5); + ang *= ang; + if (ang < radSquare) + { + v[2] = eScreen->curveDistance - sqrt (radSquare - ang); + v[2] *= sigmoidProgress (eScreen->expoCam); + } + } + + lastX = v[0]; + lastZ = v[2]; + + v += gWindow->geometry ().vertexStride; + } */ + } + else + { + gWindow->glAddGeometry (matrices, region, clip, maxGridWidth, maxGridHeight); + } +} + +void +ExpoWindow::glDrawTexture (GLTexture *texture, + const GLMatrix &transform, + const GLWindowPaintAttrib &attrib, + unsigned int mask) +{ + if (eScreen->expoCam > 0.0 && + eScreen->optionGetDeform () == ExpoScreen::DeformCurve && + eScreen->gScreen->lighting () && + screen->desktopWindowCount ()) + { + #warning Curve not ported, needs shaders now +/* unsigned int i, idx, vCount; + CompPoint offset; + float x; + GLfloat *v; + + vCount = gWindow->geometry ().vCount; + + if (eScreen->winNormals.size () < vCount * 3) + eScreen->winNormals.resize (vCount * 3); + + if (!window->onAllViewports ()) + { + offset = eScreen->cScreen->windowPaintOffset (); + offset = window->getMovementForOffset (offset); + } + + v = gWindow->geometry ().vertices + + (gWindow->geometry ().vertexStride - 3); + + for (i = 0; i < vCount; i++) + { + x = (float) (v[0] + offset.x () - screen->width () / 2) * + eScreen->curveAngle / screen->width (); + + while (x < 0) + x += 360.0; + + idx = floor (x); + + eScreen->winNormals[i * 3] = -eScreen->vpNormals[idx * 3]; + eScreen->winNormals[(i * 3) + 1] = + eScreen->vpNormals[(idx * 3) + 1]; + eScreen->winNormals[(i * 3) + 2] = + eScreen->vpNormals[(idx * 3) + 2]; + + v += gWindow->geometry ().vertexStride; + } + + glEnable (GL_NORMALIZE); + glNormalPointer (GL_FLOAT,0, &eScreen->winNormals.at (0)); + + glEnableClientState (GL_NORMAL_ARRAY); + + gWindow->glDrawTexture (texture, attrib, mask); + + glDisable (GL_NORMALIZE); + glDisableClientState (GL_NORMAL_ARRAY); + glNormal3f (0.0, 0.0, -1.0); */ + } + else + { +// glEnable (GL_NORMALIZE); + gWindow->glDrawTexture (texture, transform, attrib, mask); +// glDisable (GL_NORMALIZE); + } +} + +bool +ExpoWindow::glPaint (const GLWindowPaintAttrib &attrib, + const GLMatrix &transform, + const CompRegion ®ion, + unsigned int mask) +{ + GLMatrix wTransform (transform); + GLWindowPaintAttrib wAttrib (attrib); + CompPoint vp; + CompRegion clip (region); + + screen->viewportForGeometry (window->geometry (), vp); + + if (eScreen->expoActive) + { + float opacity = 1.0; + bool hide; + bool zoomAnim; + + zoomAnim = eScreen->optionGetExpoAnimation () == + ExpoScreen::ExpoAnimationZoom; + hide = eScreen->optionGetHideDocks () && + (window->wmType () & CompWindowTypeDockMask); + + if (eScreen->expoCam > 0.0) + { + if (eScreen->expoCam < 1.0 && !zoomAnim) + mask |= PAINT_WINDOW_TRANSLUCENT_MASK; + else if (hide) + mask |= PAINT_WINDOW_TRANSLUCENT_MASK; + } + + if (!zoomAnim) + opacity = attrib.opacity * eScreen->expoCam; + + if (hide) + { + if (zoomAnim && eScreen->paintingVp == eScreen->selectedVp) + opacity = attrib.opacity * + (1 - sigmoidProgress (eScreen->expoCam)); + else + opacity = 0; + } + + if (opacity <= 0) + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + else + wAttrib.opacity = wAttrib.opacity * opacity; + } + + /* Stretch maximized windows a little so that you don't + * have an awkward gap */ + + if (window->state () & MAXIMIZE_STATE) + { + CompOutput *o = &screen->outputDevs ()[screen->outputDeviceForGeometry(window->geometry())]; + float yS = 1.0 + ((o->height () / (float) window->height ()) - 1.0f) * sigmoidProgress (eScreen->expoCam); + wTransform.translate (window->x () + window->width () / 2, + window->y () + window->height (), + 0.0f); + wTransform.scale (1.0f, yS, 1.0f); + wTransform.translate (-(window->x () + window->width () / 2), + -(window->y () + window->height ()), + 0.0f); + + if (eScreen->paintingVp != vp) + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + } + + if (std::find (eScreen->dndWindows.begin(), eScreen->dndWindows.end (), window) != eScreen->dndWindows.end ()) + { + if (!eScreen->paintingDndWindow) + { + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + } + else + { + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + clip = infiniteRegion; + } + } + + bool status = gWindow->glPaint (wAttrib, wTransform, clip, mask); + + return status; +} + +bool +ExpoWindow::damageRect (bool initial, + const CompRect &rect) +{ + if (eScreen->expoCam > 0.0f) + eScreen->cScreen->damageScreen (); + + return cWindow->damageRect (initial, rect); +} + +#define EXPOINITBIND(opt, func) \ + optionSet##opt##Initiate (boost::bind (&ExpoScreen::func, \ + this, _1, _2, _3)); +#define EXPOTERMBIND(opt, func) \ + optionSet##opt##Terminate (boost::bind (&ExpoScreen::func, \ + this, _1, _2, _3)); + +ExpoScreen::ExpoScreen (CompScreen *s) : + PluginClassHandler (s), + ExpoOptions (), + cScreen (CompositeScreen::get (s)), + gScreen (GLScreen::get (s)), + expoCam (0.0f), + expoActive (false), + expoMode (false), + dndState (DnDNone), + dndWindows (0), + origVp (s->vp ()), + selectedVp (s->vp ()), + vpUpdateMode (VPUpdateNone), + clickTime (0), + doubleClick (false), + vpNormals (360 * 3), + grabIndex (0), + paintingDndWindow (false), + mGlowTextureProperties (&glowTextureProperties) +{ + CompString fname; + CompString pname = "expo"; + CompSize size; + + + leftKey = XKeysymToKeycode (s->dpy (), XStringToKeysym ("Left")); + rightKey = XKeysymToKeycode (s->dpy (), XStringToKeysym ("Right")); + upKey = XKeysymToKeycode (s->dpy (), XStringToKeysym ("Up")); + downKey = XKeysymToKeycode (s->dpy (), XStringToKeysym ("Down")); + + mMoveCursor = XCreateFontCursor (screen->dpy (), XC_fleur); + + EXPOINITBIND (ExpoKey, doExpo); + EXPOTERMBIND (ExpoKey, termExpo); + EXPOINITBIND (ExpoButton, doExpo); + EXPOTERMBIND (ExpoButton, termExpo); + EXPOINITBIND (ExpoEdge, doExpo); + EXPOTERMBIND (ExpoButton, termExpo); + + EXPOINITBIND (DndButton, dndInit); + EXPOTERMBIND (DndButton, dndFini); + EXPOINITBIND (ExitButton, exitExpo); + EXPOINITBIND (NextVpButton, nextVp); + EXPOINITBIND (PrevVpButton, prevVp); + + ScreenInterface::setHandler (screen, false); + CompositeScreenInterface::setHandler (cScreen, false); + GLScreenInterface::setHandler (gScreen, false); + + outline_texture = GLTexture::imageDataToTexture (mGlowTextureProperties->textureData, + CompSize (mGlowTextureProperties->textureSize, + mGlowTextureProperties->textureSize), + GL_RGBA, GL_UNSIGNED_BYTE); + fname = "texture_tile.png"; + polkadots_texture = GLTexture::readImageToTexture (fname, pname, polkadots_texture_size); + + if (polkadots_texture.empty ()) + compLogMessage ("expo", CompLogLevelWarn, "failed to bind image to texture"); + else + { + foreach (GLTexture *tex, polkadots_texture) + { + tex->enable (GLTexture::Good); + glTexParameteri (tex->target (), GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (tex->target (), GL_TEXTURE_WRAP_T, GL_REPEAT); + tex->disable (); + } + } +} + +ExpoScreen::~ExpoScreen () +{ + if (mMoveCursor) + XFreeCursor (screen->dpy (), mMoveCursor); +} + +void +ExpoWindow::resizeNotify(int dx, int dy, int dw, int dh) +{ + window->resizeNotify (dx, dy, dw, dh); + + /* mGlowQuads contains positional info, so we need to recalc that */ + if (mGlowQuads) + { + /* FIXME: we need to find a more multitexture friendly way + * of doing this */ + GLTexture::Matrix tMat = eScreen->outline_texture.at (0)->matrix (); + computeGlowQuads (&tMat); + } +} + +ExpoWindow::ExpoWindow (CompWindow *w) : + PluginClassHandler (w), + window (w), + cWindow (CompositeWindow::get (w)), + gWindow (GLWindow::get (w)), + eScreen (ExpoScreen::get (screen)), + mGlowQuads (NULL) +{ + CompositeWindowInterface::setHandler (cWindow, false); + GLWindowInterface::setHandler (gWindow, false); + WindowInterface::setHandler (window, true); + + if (window->type () & CompWindowTypeDesktopMask) + { + foreach (GLTexture *tex, eScreen->outline_texture) + { + GLTexture::Matrix mat = tex->matrix (); + computeGlowQuads (&mat); + } + } +} + +ExpoWindow::~ExpoWindow () +{ + eScreen->dndWindows.remove (window); + computeGlowQuads (NULL); +} + +bool +ExpoPluginVTable::init () +{ + if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) || + !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) || + !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI)) + return false; + + return true; +} + + diff -Nru compiz-plugins-main-0.9.6.2011.10/.pc/fix-868392.patch/snap/src/snap.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-868392.patch/snap/src/snap.cpp --- compiz-plugins-main-0.9.6.2011.10/.pc/fix-868392.patch/snap/src/snap.cpp 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/fix-868392.patch/snap/src/snap.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1,840 @@ +/* + * Compiz snap plugin + * Author : Guillaume "iXce" Seguin + * Email : ixce@beryl-project.org + * + * Ported to compiz by : Patrick "marex" Niklaus + * Email : marex@beryl-project.org + * + * Ported to C++ by : Travis Watkins + * Email : amaranth@ubuntu.com + * + * Copyright (C) 2009 Guillaume Seguin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * TODO + * - Apply Edge Resistance to resize + */ + +#include +#include +#include + +#include "snap.h" + + +COMPIZ_PLUGIN_20090315 (snap, SnapPluginVTable); + +// helper functions + +/* + * Wrapper functions to avoid infinite notify loops + */ +void +SnapWindow::move (int dx, int dy) +{ + skipNotify = true; + window->move (dx, dy, true); + screen->warpPointer (dx, dy); + skipNotify = false; +} + +void +SnapWindow::resize (int dx, int dy, int dwidth, int dheight) +{ + CompWindow::Geometry geometry = window->geometry (); + skipNotify = true; + window->resize (geometry.x () + dx, geometry.y () + dy, + geometry.width () + dwidth, geometry.height () + dheight, + geometry.border ()); + skipNotify = false; +} + +void +SnapWindow::addEdge (Window id, + int position, + int start, + int end, + EdgeType type, + bool screenEdge) +{ + Edge edge; + + edge.position = position; + edge.start = start; + edge.end = end; + edge.type = type; + edge.screenEdge = screenEdge; + edge.snapped = false; + edge.passed = false; + edge.id = id; + + edges.push_back (edge); +} + +/* + * Add an edge for each rectangle of the region + */ +void +SnapWindow::addRegionEdges (Edge *parent, CompRegion region) +{ + int position, start, end; + + foreach (const CompRect &r, region.rects ()) + { + switch (parent->type) + { + case LeftEdge: + case RightEdge: + position = r.x1 (); + start = r.y1 (); + end = r.y2 (); + break; + case TopEdge: + case BottomEdge: + default: + position = r.y1 (); + start = r.x1 (); + end = r.x2 (); + } + + addEdge (parent->id, position, start, end, + parent->type, parent->screenEdge); + edges.back ().passed = parent->passed; + } +} + +/* Checks if a window is considered a snap window. If it's + * not visible, returns false. If it's a panel and we're + * snapping to screen edges, it's considered a snap-window. + */ + +#define UNLIKELY(x) __builtin_expect(!!(x),0) + +static inline bool +isSnapWindow (CompWindow *w) +{ + SNAP_SCREEN (screen); + + if (UNLIKELY(!w)) + return false; + if (!w->isViewable ()) + return false; + if ((w->type () & SNAP_WINDOW_TYPE) && + (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesWindowEdgesMask)) + return true; + if (w->struts () && + (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask)) + return true; + return false; +} + +// Edges update functions ------------------------------------------------------ +/* + * Detect visible windows edges + */ +void +SnapWindow::updateWindowsEdges () +{ + CompRegion edgeRegion, resultRegion; + CompRect input; + bool remove = false; + + // First add all the windows + foreach (CompWindow *w, screen->windows ()) + { + + // Just check that we're not trying to snap to current window, + // that the window is not invisible and of a valid type + if (w == window || !isSnapWindow (w)) + { + continue; + } + + input = w->borderRect (); + addEdge (w->id (), input.top (), input.left (), + input.right (), TopEdge, false); + addEdge (w->id (), input.bottom (), input.left (), + input.right (), BottomEdge, false); + addEdge (w->id (), input.left (), input.top (), + input.bottom (), LeftEdge, false); + addEdge (w->id (), input.right (), input.top (), + input.bottom (), RightEdge, false); + } + + // 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 + foreach (CompWindow *w, screen->windows ()) + { + if (w == window || !isSnapWindow (w)) + continue; + + // can't use foreach here because we need the iterator for erase() + for (std::list::iterator it = edges.begin (); it != edges.end (); ) + { + Edge *e = &*it; + CompRect rect; + + if (!e->passed) + { + if (e->id == w->id ()) + e->passed = true; + it++; + continue; + } + + switch (e->type) + { + case LeftEdge: + case RightEdge: + rect.setGeometry (e->position, + e->start, + 1, + e->end - e->start); + break; + case TopEdge: + case BottomEdge: + default: + rect.setGeometry (e->start, + e->position, + e->end - e->start, + 1); + } + + // If the edge is in the window region, remove it, + // if it's partly in the region, split it + edgeRegion = CompRegion (rect); + resultRegion = edgeRegion - w->region (); + if (resultRegion.isEmpty ()) + { + remove = true; + } + else if (edgeRegion != resultRegion) + { + addRegionEdges (e, resultRegion); + remove = true; + } + + if (remove) + { + it = edges.erase (it); + remove = false; + } + else + { + it++; + } + } + } +} + +/* + * Loop on outputDevs and add the extents as edges + * Note that left side is a right edge, right side a left edge, + * top side a bottom edge and bottom side a top edge, + * since they will be snapped as the right/left/bottom/top edge of a window + */ +void +SnapWindow::updateScreenEdges () +{ + CompRegion edgeRegion, resultRegion; + bool remove = false; + + foreach (CompOutput output, screen->outputDevs ()) + { + const CompRect& area = output.workArea (); + addEdge (0, area.top (), area.left (), area.right () - 1, + BottomEdge, true); + addEdge (0, area.bottom (), area.left (), area.right () - 1, + TopEdge, true); + addEdge (0, area.left (), area.top (), area.bottom () - 1, + RightEdge, true); + addEdge (0, area.right (), area.top (), area.bottom () - 1, + LeftEdge, true); + } + + // Drop screen edges parts that are under struts, basically apply the + // same strategy than for windows edges visibility + foreach (CompWindow *w, screen->windows ()) + { + if (w == window || !w->struts ()) + continue; + + for (std::list::iterator it = edges.begin (); it != edges.end ();) + { + Edge *e = &*it; + CompRect rect; + + if (!e->screenEdge) + { + it++; + continue; + } + + switch (e->type) + { + case LeftEdge: + case RightEdge: + rect.setGeometry (e->position, + e->start, + 1, + e->end - e->start); + break; + case TopEdge: + case BottomEdge: + default: + rect.setGeometry (e->start, + e->position, + e->end - e->start, + 1); + } + + edgeRegion = CompRegion (rect); + resultRegion = edgeRegion - w->region (); + if (resultRegion.isEmpty ()) + { + remove = true; + } + else if (edgeRegion != resultRegion) + { + addRegionEdges (e, resultRegion); + remove = true; + } + + if (remove) + { + it = edges.erase (it); + remove = false; + } + else + { + it++; + } + } + } +} + +/* + * Clean edges and fill it again with appropriate edges + */ +void +SnapWindow::updateEdges () +{ + SNAP_SCREEN (screen); + + edges.clear (); + updateWindowsEdges (); + + if (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask) + updateScreenEdges (); +} + +// Edges checking functions (move) --------------------------------------------- + +/* + * Find nearest edge in the direction set by "type", + * w is the grabbed window, position/start/end are the window edges coordinates + * before : if true the window has to be before the edge (top/left being origin) + * snapDirection : just an helper, related to type + */ +void +SnapWindow::moveCheckNearestEdge (int position, + int start, + int end, + bool before, + EdgeType type, + int snapDirection) +{ + SNAP_SCREEN (screen); + + Edge *edge = &edges.front (); + int dist, min = 65535; + + foreach (Edge ¤t, edges) + { + // Skip wrong type or outbound edges + if (current.type != type || current.end < start || current.start > end) + continue; + + // Compute distance + dist = before ? position - current.position : current.position - position; + // Update minimum distance if needed + if (dist < min && dist >= 0) + { + min = dist; + edge = ¤t; + } + // 0-dist edge, just break + if (dist == 0) + break; + // Unsnap edges that aren't snapped anymore + if (current.snapped && dist > ss->optionGetResistanceDistance ()) + current.snapped = false; + } + // We found a 0-dist edge, or we have a snapping candidate + if (min == 0 || (min <= ss->optionGetAttractionDistance () + && ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask)) + { + // Update snapping data + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + snapGeometry = window->serverGeometry (); + this->snapDirection |= snapDirection; + } + // Attract the window if needed, moving it of the correct dist + if (min != 0 && !edge->snapped) + { + edge->snapped = true; + switch (type) + { + case LeftEdge: + move (min, 0); + break; + case RightEdge: + move (-min, 0); + break; + case TopEdge: + move (0, min); + break; + case BottomEdge: + move (0, -min); + break; + default: + break; + } + } + } +} + +/* + * Call the previous function for each of the 4 sides of the window + */ +void +SnapWindow::moveCheckEdges () +{ + CompRect input (window->borderRect ()); + moveCheckNearestEdge (input.left (), input.top (), input.bottom (), + true, RightEdge, HorizontalSnap); + moveCheckNearestEdge (input.right (), input.top (), input.bottom (), + false, LeftEdge, HorizontalSnap); + moveCheckNearestEdge (input.top (), input.left (), input.right (), + true, BottomEdge, VerticalSnap); + moveCheckNearestEdge (input.bottom (), input.left (), input.right (), + false, TopEdge, VerticalSnap); +} + +// Edges checking functions (resize) ------------------------------------------- + +/* + * Similar function for Snap on Resize + */ +void +SnapWindow::resizeCheckNearestEdge (int position, + int start, + int end, + bool before, + EdgeType type, + int snapDirection) +{ + SNAP_SCREEN (screen); + + Edge *edge = &edges.front (); + int dist, min = 65535; + + foreach (Edge ¤t, edges) + { + // Skip wrong type or outbound edges + if (current.type != type || current.end < start || current.start > end) + continue; + + // Compute distance + dist = before ? position - current.position : current.position - position; + // Update minimum distance if needed + if (dist < min && dist >= 0) + { + min = dist; + edge = ¤t; + } + // 0-dist edge, just break + if (dist == 0) + break; + // Unsnap edges that aren't snapped anymore + if (current.snapped && dist > ss->optionGetResistanceDistance ()) + current.snapped = false; + } + // We found a 0-dist edge, or we have a snapping candidate + if (min == 0 || (min <= ss->optionGetAttractionDistance () + && ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask)) + { + // Update snapping data + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + snapGeometry = window->serverGeometry (); + this->snapDirection |= snapDirection; + } + // FIXME : this needs resize-specific code. + // Attract the window if needed, moving it of the correct dist + if (min != 0 && !edge->snapped) + { + edge->snapped = true; + switch (type) + { + case LeftEdge: + resize (min, 0, 0, 0); + break; + case RightEdge: + resize (-min, 0, 0, 0); + break; + case TopEdge: + resize (0, min, 0, 0); + break; + case BottomEdge: + resize (0, -min, 0, 0); + break; + default: + break; + } + } + } +} + +/* + * Call the previous function for each of the 4 sides of the window + */ +void +SnapWindow::resizeCheckEdges (int dx, int dy, int dwidth, int dheight) +{ + CompRect input (window->borderRect ()); + + resizeCheckNearestEdge (input.left (), input.top (), input.bottom (), + true, RightEdge, HorizontalSnap); + resizeCheckNearestEdge (input.right (), input.top (), input.bottom (), + false, LeftEdge, HorizontalSnap); + resizeCheckNearestEdge (input.top (), input.left (), input.right (), + true, BottomEdge, VerticalSnap); + resizeCheckNearestEdge (input.bottom (), input.left (), input.right (), + false, TopEdge, VerticalSnap); +} + +// Check if avoidSnap is matched, and enable/disable snap consequently +void +SnapScreen::handleEvent (XEvent *event) +{ + if (event->type == screen->xkbEvent ()) + { + XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event; + + if (xkbEvent->xkb_type == XkbStateNotify) + { + XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event; + + unsigned int mods = 0xffffffff; + if (avoidSnapMask) + mods = avoidSnapMask; + + if ((stateEvent->mods & mods) == mods) + snapping = false; + else + snapping = true; + } + } + + screen->handleEvent (event); +} + +// Events notifications -------------------------------------------------------- + +void +SnapWindow::resizeNotify (int dx, int dy, int dwidth, int dheight) +{ + SNAP_SCREEN (screen); + + window->resizeNotify (dx, dy, dwidth, dheight); + + // avoid-infinite-notify-loop mode/not grabbed + if (skipNotify || !(grabbed & ResizeGrab)) + return; + + // we have to avoid snapping but there's still some buffered moving + if (!ss->snapping && (m_dx || m_dy || m_dwidth || m_dheight)) + { + resize (m_dx, m_dy, m_dwidth, m_dheight); + m_dx = m_dy = m_dwidth = m_dheight = 0; + return; + } + + // don't snap maximized windows + if (window->state () & CompWindowStateMaximizedHorzMask) + dx = 0; + + if (window->state () & CompWindowStateMaximizedVertMask) + dy = 0; + + // avoiding snap, nothing buffered + if (!ss->snapping) + return; + + // apply edge resistance + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + // If there's horizontal snapping, add dx to current buffered + // dx and resist (move by -dx) or release the window and move + // by buffered dx - dx, same for dh + if (!snapGeometry.isEmpty () && snapDirection & HorizontalSnap) + { + m_dx += dx; + if (m_dx < ss->optionGetResistanceDistance () + && m_dx > -ss->optionGetResistanceDistance ()) + { + resize (-dx, 0, 0, 0); + } + else + { + resize (m_dx - dx, 0, 0, 0); + m_dx = 0; + if (!m_dwidth) + snapDirection &= VerticalSnap; + } + m_dwidth += dwidth; + if (m_dwidth < ss->optionGetResistanceDistance () + && m_dwidth > -ss->optionGetResistanceDistance ()) + { + resize (0, 0, -dwidth, 0); + } + else + { + resize (0, 0, m_dwidth - dwidth, 0); + m_dwidth = 0; + if (!m_dx) + snapDirection &= VerticalSnap; + } + } + + // Same for vertical snapping and dy/dh + if (snapGeometry.isEmpty () && snapDirection & VerticalSnap) + { + m_dy += dy; + if (m_dy < ss->optionGetResistanceDistance () + && m_dy > -ss->optionGetResistanceDistance ()) + { + resize (0, -dy, 0, 0); + } + else + { + resize (0, m_dy - dy, 0, 0); + m_dy = 0; + if (!m_dheight) + snapDirection &= HorizontalSnap; + } + m_dheight += dheight; + if (m_dheight < ss->optionGetResistanceDistance () + && m_dheight > -ss->optionGetResistanceDistance ()) + { + resize (0, 0, 0, -dheight); + } + else + { + resize (0, 0, 0, m_dheight - dheight); + m_dheight = 0; + if (!m_dy) + snapDirection &= HorizontalSnap; + } + } + // If we are no longer snapping in any direction, reset snapped + if (!snapGeometry.isEmpty () && !snapDirection) + snapGeometry = CompWindow::Geometry (); + } + + // If we don't already snap vertically and horizontally, + // check edges status + if (snapDirection != (VerticalSnap | HorizontalSnap)) + resizeCheckEdges (dx, dy, dwidth, dheight); +} + +void +SnapWindow::moveNotify (int dx, int dy, bool immediate) +{ + SNAP_SCREEN (screen); + + window->moveNotify (dx, dy, immediate); + + // avoid-infinite-notify-loop mode/not grabbed + if (skipNotify || !(grabbed & MoveGrab)) + return; + + // we have to avoid snapping but there's still some buffered moving + if (!ss->snapping && (m_dx || m_dy)) + { + move (m_dx, m_dy); + m_dx = m_dy = 0; + return; + } + + // avoiding snap, nothing buffered + if (!ss->snapping) + return; + + // apply edge resistance + if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) + { + // If there's horizontal snapping, add dx to current buffered + // dx and resist (move by -dx) or release the window and move + // by buffered dx - dx + if (!snapGeometry.isEmpty () && snapDirection & HorizontalSnap) + { + m_dx += dx; + if (m_dx < ss->optionGetResistanceDistance () + && m_dx > -ss->optionGetResistanceDistance ()) + { + dx = snapGeometry.x () - window->geometry ().x (); + move (dx, 0); + } + else + { + move (m_dx - dx, 0); + m_dx = 0; + snapDirection &= VerticalSnap; + } + } + // Same for vertical snapping and dy + if (!snapGeometry.isEmpty () && snapDirection & VerticalSnap) + { + m_dy += dy; + if (m_dy < ss->optionGetResistanceDistance () + && m_dy > -ss->optionGetResistanceDistance ()) + { + dy = snapGeometry.y () - window->geometry ().y (); + move (0, dy); + } + else + { + move (0, m_dy - dy); + m_dy = 0; + snapDirection &= HorizontalSnap; + } + } + // If we are no longer snapping in any direction, reset snapped + if (!snapGeometry.isEmpty () && !snapDirection) + snapGeometry = CompWindow::Geometry (); + } + // If we don't already snap vertically and horizontally, + // check edges status + if (snapDirection != (VerticalSnap | HorizontalSnap)) + moveCheckEdges (); +} + +/* + * Initiate snap, get edges + */ +void +SnapWindow::grabNotify (int x, int y, unsigned int state, unsigned int mask) +{ + grabbed = (mask & CompWindowGrabResizeMask) ? ResizeGrab : MoveGrab; + updateEdges (); + + window->grabNotify (x, y, state, mask); +} + +/* + * Clean edges data, reset dx/dy to avoid buggy moves + * when snap will be triggered again. + */ +void +SnapWindow::ungrabNotify () +{ + edges.clear (); + + snapGeometry = CompWindow::Geometry (); + snapDirection = 0; + grabbed = 0; + m_dx = m_dy = m_dwidth = m_dheight = 0; + + window->ungrabNotify (); +} + +// Internal stuff -------------------------------------------------------------- + +void +SnapScreen::optionChanged (CompOption *opt, SnapOptions::Options num) +{ + switch (num) + { + case SnapOptions::AvoidSnap: + { + unsigned int mask = optionGetAvoidSnapMask (); + avoidSnapMask = 0; + if (mask & AvoidSnapShiftMask) + avoidSnapMask |= ShiftMask; + if (mask & AvoidSnapAltMask) + avoidSnapMask |= CompAltMask; + if (mask & AvoidSnapControlMask) + avoidSnapMask |= ControlMask; + if (mask & AvoidSnapMetaMask) + avoidSnapMask |= CompMetaMask; + } + + default: + break; + } +} + +SnapScreen::SnapScreen (CompScreen *screen) : + PluginClassHandler (screen), + SnapOptions (), + snapping (true), + avoidSnapMask (0) +{ + ScreenInterface::setHandler (screen); + +#define setNotify(func) \ + optionSet##func##Notify (boost::bind (&SnapScreen::optionChanged, this, _1, _2)) + + setNotify (AvoidSnap); +} + +SnapWindow::SnapWindow (CompWindow *window) : + PluginClassHandler (window), + window (window), + snapDirection (0), + m_dx (0), + m_dy (0), + m_dwidth (0), + m_dheight (0), + snapGeometry (0, 0, 0, 0, 0), + grabbed (0), + skipNotify (false) +{ + WindowInterface::setHandler (window); +} + +SnapWindow::~SnapWindow () +{ +} + +bool +SnapPluginVTable::init () +{ + if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION)) + return false; + + return true; +} + diff -Nru compiz-plugins-main-0.9.6.2011.10/.pc/.version compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/.version --- compiz-plugins-main-0.9.6.2011.10/.pc/.version 1970-01-01 00:00:00.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/.pc/.version 2012-02-24 16:39:32.000000000 +0000 @@ -0,0 +1 @@ +2 diff -Nru compiz-plugins-main-0.9.6.2011.10/session/.gitignore compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/session/.gitignore --- compiz-plugins-main-0.9.6.2011.10/session/.gitignore 2011-10-20 12:37:25.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/session/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -build diff -Nru compiz-plugins-main-0.9.6.2011.10/snap/src/snap.cpp compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/snap/src/snap.cpp --- compiz-plugins-main-0.9.6.2011.10/snap/src/snap.cpp 2011-10-20 12:37:25.000000000 +0000 +++ compiz-plugins-main-0.9.6.2012.02+51+234+201202040052~oneiric1+ti1/snap/src/snap.cpp 2012-02-24 16:39:32.000000000 +0000 @@ -396,7 +396,7 @@ // Update snapping data if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask) { - snapGeometry = window->serverGeometry (); + snapGeometry = window->geometry (); this->snapDirection |= snapDirection; } // Attract the window if needed, moving it of the correct dist @@ -581,6 +581,13 @@ return; } + // don't snap maximized windows + if (window->state () & CompWindowStateMaximizedHorzMask) + dx = 0; + + if (window->state () & CompWindowStateMaximizedVertMask) + dy = 0; + // avoiding snap, nothing buffered if (!ss->snapping) return;