Attatched is a patch to add animation to the maximumization of a window.
The patch also adds structs, init functions and other things in order to
make this possible. It also adds the ability to 'toggle' between a
maximumized state and a non-maximumized state

-- Sam
From fd876af1b29a3a0fbc4207afa1655d57fa7d8e4f Mon Sep 17 00:00:00 2001
From: Sam <[EMAIL PROTECTED]>
Date: Sun, 25 May 2008 00:08:59 +0800
Subject: [PATCH] Add animation to maximumization

---
 maximumize.c      |  390 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 maximumize.xml.in |    9 ++
 2 files changed, 366 insertions(+), 33 deletions(-)

diff --git a/maximumize.c b/maximumize.c
index 0f11aa4..30b3251 100644
--- a/maximumize.c
+++ b/maximumize.c
@@ -29,6 +29,65 @@
 #include <compiz-core.h>
 #include "maximumize_options.h"
 
+#define GET_MAX_DISPLAY(d)                            \
+    ((MaximumizeDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
+
+#define MAX_DISPLAY(d)                                \
+    MaximumizeDisplay *md = GET_MAX_DISPLAY (d)
+
+#define GET_MAX_SCREEN(s, md)                         \
+    ((MaximumizeScreen *) (s)->base.privates[(md)->screenPrivateIndex].ptr)
+
+#define MAX_SCREEN(s)                                 \
+    MaximumizeScreen *ms = GET_MAX_SCREEN (s, GET_MAX_DISPLAY (s->display))
+    
+#define GET_MAX_WINDOW(w, ms) \
+    ((MaximumizeWindow *) (w)->base.privates[(ms)->windowPrivateIndex].ptr)
+
+#define MAX_WINDOW(w) \
+    MaximumizeWindow *mw = GET_MAX_WINDOW  (w,                  \
+		      GET_MAX_SCREEN  (w->screen,          \
+		      GET_MAX_DISPLAY (w->screen->display)))
+		      
+static int displayPrivateIndex;
+
+typedef enum _MaximumizeStage
+{
+    stageZoomOut = 0,
+    stageResize,
+    stageZoomIn,
+    stageNone
+} MaximumizeStage;
+
+typedef struct _MaximumizeDisplay
+{
+    int screenPrivateIndex;
+} MaximumizeDisplay;
+
+
+typedef struct _MaximumizeScreen
+{
+    int windowPrivateIndex;
+    float steps;
+        
+    PreparePaintScreenProc preparePaintScreen;
+    PaintWindowProc paintWindow;
+    WindowResizeNotifyProc windowResizeNotify;
+    
+} MaximumizeScreen;
+
+typedef struct _MaximumizeWindow
+{
+    MaximumizeStage stage;
+    float scale;
+    
+    Bool maximumized;
+    int savedH;
+    int savedW;
+    int savedX;
+    int savedY;
+} MaximumizeWindow;
+
 /* Returns true if rectangles a and b intersect by at least 40 in both directions
  */
 static Bool 
@@ -288,11 +347,168 @@ maximumizeComputeResize(CompWindow     *w,
     return mask;
 }
 
+static void
+maximumizeResizeWindow (CompWindow *w)
+{
+    if (w)
+    {
+	int            width, height;
+	unsigned int   mask;
+	XWindowChanges xwc;
+	
+	MAX_WINDOW (w);
+
+	mask = maximumizeComputeResize (w, &xwc);
+	if (mask)
+	{
+	    if (!mw->maximumized)
+	    {
+	        if (constrainNewWindowSize (w, xwc.width, xwc.height,
+					    &width, &height))
+	        {
+		    mask |= CWWidth | CWHeight;
+		    xwc.width  = width;
+		    xwc.height = height;
+		    mw->savedW = w->attrib.width;
+		    mw->savedH = w->attrib.height;
+		    mw->savedX = w->attrib.x;
+		    mw->savedY = w->attrib.y;
+	        }
+	    }
+	    else
+	    {
+	    		mask |= CWWidth | CWHeight;
+		        xwc.width  = mw->savedW;
+		        xwc.height = mw->savedH;;
+		        xwc.x = mw->savedX;
+		        xwc.y = mw->savedY;
+        }
+
+	    if (w->mapNum && (mask & (CWWidth | CWHeight)))
+		sendSyncRequest (w);
+
+	    configureXWindow (w, mask, &xwc);
+	    
+	}
+	
+	mw->stage = stageZoomIn;	    
+	
+   }
+}
+
+/* Wait until compiz tells us that it has resized
+     the window, so that we don't get ugly drawing artifacts
+     when the window 'resizes' when it is zooming in*/
+/*static void
+maximumizeWindowResizeNotify (CompWindow *w,
+                                                        int dx,
+                                                        int dy,
+                                                        int dw,
+                                                        int dh)
+{
+    MAX_WINDOW (w);
+    MAX_SCREEN (w->screen);
+    
+    fprintf(stderr, "resizeNotify\n");
+    
+    UNWRAP(ms, w->screen, windowResizeNotify);
+    (*w->screen->windowResizeNotify)(w, dx, dy, dw, dh);
+    WRAP(ms, w->screen, windowResizeNotify, maximumizeWindowResizeNotify);
+}*/
+
+/* Animation Prep */
+static void
+maximumizePreparePaintScreen (CompScreen *s,
+			                                            int	        time)
+{
+    MAX_SCREEN (s);
+
+    float speed = maximumizeGetSpeed (s);
+    ms->steps = (float) time / ((20.1 - speed) * 10);
+    
+    if (ms->steps < 0.005)
+        ms->steps = 0.005;
+    
+    UNWRAP (ms, s, preparePaintScreen);
+    (*s->preparePaintScreen) (s, time);
+    WRAP (ms, s, preparePaintScreen, maximumizePreparePaintScreen);
+}
+
+static Bool
+maximumizePaintWindow (CompWindow		    *w,
+		                                      const WindowPaintAttrib   *attrib,
+		                                      const CompTransform	    *transform,
+		                                      Region		    region,
+		                                      unsigned int		    mask)
+{
+    Bool       status;
+    CompScreen *s = w->screen;
+    CompTransform mTransform = *transform;
+
+    MAX_SCREEN (s);
+    MAX_WINDOW (w);
+    
+    switch (mw->stage)
+    {
+        case stageZoomOut:
+        {
+            mw->scale += (0.0f - mw->scale) * ms->steps;
+            if (mw->scale < 0.005f)
+            {
+                mw->scale = 0.0f;
+                mw->stage = stageResize;
+                maximumizeResizeWindow (w);
+            }
+        }
+            break;
+        case stageResize:
+            mw->scale = 0.0f; /* Ensure that scale is always 0 when resizing */
+            break;
+        case stageZoomIn:
+        {
+            mw->scale += (1.0f - mw->scale) * ms->steps;
+            if (mw->scale > 0.995f)
+            {
+                mw->scale = 1.0f;
+                mw->stage = stageNone;
+            }
+        }
+            break;
+        case stageNone:
+        {
+            mw->scale = 1.0f;
+        }
+        break;
+    }
+                
+    if (mw->scale != 1.0f)
+    {
+
+	matrixTranslate (&mTransform, w->attrib.x + w->attrib.width / 2, w->attrib.y + w->attrib.height / 2, 0);
+	matrixScale (&mTransform, mw->scale, mw->scale, 0);
+	matrixTranslate (&mTransform, -(w->attrib.x + w->attrib.width / 2), -(w->attrib.y + w->attrib.height / 2), 0);
+	
+	mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
+	/* FIXME: should better use DonePaintScreen for that */
+	if (mw->stage != stageNone)
+	addWindowDamage (w);	
+	
+	}
+
+	UNWRAP (ms, s, paintWindow);
+	status = (*s->paintWindow) (w, attrib, &mTransform, region, mask);
+	WRAP (ms, s, paintWindow, maximumizePaintWindow);
+    
+    return status;
+}
+
 /* 
  * Initially triggered keybinding.
  * Fetch the window, fetch the resize, constrain it.
  *
  */
+ 
 static Bool
 maximumizeTrigger(CompDisplay     *d,
 		 CompAction      *action,
@@ -307,27 +523,14 @@ maximumizeTrigger(CompDisplay     *d,
     w   = findWindowAtDisplay (d, xid);
     if (w)
     {
-	int            width, height;
-	unsigned int   mask;
-	XWindowChanges xwc;
-
-	mask = maximumizeComputeResize (w, &xwc);
-	if (mask)
-	{
-	    if (constrainNewWindowSize (w, xwc.width, xwc.height,
-					&width, &height))
-	    {
-		mask |= CWWidth | CWHeight;
-		xwc.width  = width;
-		xwc.height = height;
-	    }
-
-	    if (w->mapNum && (mask & (CWWidth | CWHeight)))
-		sendSyncRequest (w);
-
-	    configureXWindow (w, mask, &xwc);
+	    MAX_WINDOW (w);
+	    
+	    mw->stage = stageZoomOut;
+	    mw->maximumized = !mw->maximumized;
+	    
+	    damageScreen (w->screen);
+	    
 	}
-    }
 
     return TRUE;
 }
@@ -337,23 +540,144 @@ static Bool
 maximumizeInitDisplay (CompPlugin  *p,
 		      CompDisplay *d)
 {
+
+    MaximumizeDisplay *md;
+    
+    md = malloc (sizeof(MaximumizeDisplay));
+    if (!md)
+        return FALSE;
+
     if (!checkPluginABI ("core", CORE_ABIVERSION))
 	return FALSE;
-
+	
+	md->screenPrivateIndex = allocateScreenPrivateIndex (d); 
+    if (md->screenPrivateIndex < 0)
+    {
+	free (md);
+	return FALSE;
+    }
+    
     maximumizeSetTriggerKeyInitiate (d, maximumizeTrigger);
+    
+    d->base.privates[displayPrivateIndex].ptr = md;
+
+    return TRUE;
+}
+
+static Bool
+maximumizeInitScreen (CompPlugin *p,
+		 CompScreen *s)
+{
+    MaximumizeScreen *ms;
+
+    MAX_DISPLAY (s->display);
+    ms = malloc (sizeof (MaximumizeScreen));
+    if (!ms)
+	return FALSE; 
+
+    ms->windowPrivateIndex = allocateWindowPrivateIndex (s);
+    if (ms->windowPrivateIndex < 0)
+    {
+	free (ms);
+	return FALSE;
+    }
+
+    ms->steps = 0;
+
+    WRAP (ms, s, preparePaintScreen, maximumizePreparePaintScreen);
+    WRAP (ms, s, paintWindow, maximumizePaintWindow); 
+    //WRAP (ms, s, damageWindowRect, maximumizeDamageWindowRect);
+    //WRAP(ms, s, windowResizeNotify, maximumizeWindowResizeNotify);
+
+    s->base.privates[md->screenPrivateIndex].ptr = ms;
+
+    return TRUE; 
+}
+
+static void
+maximumizeFiniScreen (CompPlugin *p,
+		 CompScreen *s)
+{
+    MAX_SCREEN (s);
+
+    UNWRAP (ms, s, preparePaintScreen);
+    UNWRAP (ms, s, paintWindow);
+    //UNWRAP (ms, s, damageWindowRect);
+    //UNWRAP (ms, s, windowResizeNotify);
+
+    freeWindowPrivateIndex (s, ms->windowPrivateIndex);
+
+    free (ms);
+}
+static void
+maximumizeFiniDisplay (CompPlugin  *p,
+		  CompDisplay *d)
+{
+    MAX_DISPLAY (d);
+
+    freeScreenPrivateIndex (d, md->screenPrivateIndex);
+
+    free (md);
+}
+
+static Bool
+maximumizeInitWindow (CompPlugin *p,
+		 CompWindow *w)
+{
+    MaximumizeWindow *mw;
+
+    MAX_SCREEN (w->screen);
+
+    mw = malloc (sizeof (MaximumizeWindow));
+    if (!mw)
+	return FALSE;
+
+    mw->scale       = 1.0f;
+    mw->stage = stageNone;
+    mw->savedW = 0;
+    mw->savedH = 0;
+    mw->savedX = 0;
+    mw->savedY = 0;
+
+    w->base.privates[ms->windowPrivateIndex].ptr = mw;
+
+    return TRUE;
+}
+
+static void
+maximumizeFiniWindow (CompPlugin *p,
+		 CompWindow *w)
+{
+    MAX_WINDOW (w);
+
+    free (mw);
+}
+
+static void
+maximumizeFini (CompPlugin *p)
+{
+    freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+static Bool
+maximumizeInit (CompPlugin *p)
+{
+    displayPrivateIndex = allocateDisplayPrivateIndex ();
+    if (displayPrivateIndex < 0)
+	return FALSE;
 
     return TRUE;
 }
 
 static CompBool
 maximumizeInitObject (CompPlugin *p,
-		     CompObject *o)
+		 CompObject *o)
 {
     static InitPluginObjectProc dispTab[] = {
-	(InitPluginObjectProc) 0, /* InitCore */
-	(InitPluginObjectProc) maximumizeInitDisplay,
-	0, 
-	0 
+	    (InitPluginObjectProc) 0, /* InitCore */
+	    (InitPluginObjectProc) maximumizeInitDisplay,
+	    (InitPluginObjectProc) maximumizeInitScreen, 
+	    (InitPluginObjectProc) maximumizeInitWindow
     };
 
     RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
@@ -361,13 +685,13 @@ maximumizeInitObject (CompPlugin *p,
 
 static void
 maximumizeFiniObject (CompPlugin *p,
-		     CompObject *o)
+		 CompObject *o)
 {
     static FiniPluginObjectProc dispTab[] = {
-	(FiniPluginObjectProc) 0, /* FiniCore */
-	0, 
-	0, 
-	0 
+	(FiniPluginObjectProc) 0, /* InitCore */
+	(FiniPluginObjectProc) maximumizeFiniDisplay,
+	(FiniPluginObjectProc) maximumizeFiniScreen, 
+	(FiniPluginObjectProc) maximumizeFiniWindow
     };
 
     DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
@@ -376,8 +700,8 @@ maximumizeFiniObject (CompPlugin *p,
 CompPluginVTable maximumizeVTable = {
     "maximumize",
     0,
-    0,
-    0,
+    maximumizeInit,
+    maximumizeFini,
     maximumizeInitObject,
     maximumizeFiniObject,
     0,
diff --git a/maximumize.xml.in b/maximumize.xml.in
index 4787ebd..6538bcc 100644
--- a/maximumize.xml.in
+++ b/maximumize.xml.in
@@ -25,5 +25,14 @@
         </option>
       </group>
     </display>
+    <screen>
+        <option name="speed" type="float">
+            <_short>Speed</_short>
+            <_long>Animation Speed</_long>
+            <default>1.0</default>
+            <min>0.1</min>
+            <max>10.0</max>
+        </option>
+    </screen>
   </plugin>
 </compiz>
-- 
1.5.2.4

_______________________________________________
Dev mailing list
[email protected]
http://lists.compiz-fusion.org/mailman/listinfo/dev

Reply via email to