83322e0
--- WindowMaker-0.91.0/src/application.c.vns	2005-05-19 12:42:35 +0400
83322e0
+++ WindowMaker-0.91.0/src/application.c	2005-05-19 12:42:35 +0400
83322e0
@@ -448,6 +448,16 @@
83322e0
     if (wapp->refcount>0)
83322e0
         return;
83322e0
 
83322e0
+#ifdef BOUNCE_APP
83322e0
+    if (wapp->flags.bouncing)
83322e0
+    {
83322e0
+	/* event.c:handleDestroyNotify forced this destroy
83322e0
+	   and thereby overlooked the bounce callback */
83322e0
+	wapp->refcount = 1;
83322e0
+	return;
83322e0
+    }
83322e0
+#endif
83322e0
+
83322e0
 
83322e0
     scr = wapp->main_window_desc->screen_ptr;
83322e0
     main_window = wapp->main_window;
83322e0
--- WindowMaker-0.91.0/src/application.h.vns	2005-05-19 12:42:35 +0400
83322e0
+++ WindowMaker-0.91.0/src/application.h	2005-05-19 12:44:51 +0400
83322e0
@@ -46,6 +46,9 @@
83322e0
         unsigned int skip_next_animation:1;
83322e0
         unsigned int hidden:1;
83322e0
         unsigned int emulated:1;
83322e0
+#ifdef BOUNCE_APP
83322e0
+	unsigned int bouncing:1;
83322e0
+#endif
83322e0
     } flags;
83322e0
 } WApplication;
83322e0
 
83322e0
@@ -58,6 +61,8 @@
83322e0
 void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance,
83322e0
                                     char *wm_class);
83322e0
 
83322e0
+void wAppBounce(WApplication *);
83322e0
+
83322e0
 #ifdef NEWAPPICON
83322e0
 
83322e0
 #define wApplicationActivate(wapp) do { \
83322e0
--- WindowMaker-0.91.0/src/superfluous.c.vns	2004-10-12 21:46:38 +0400
83322e0
+++ WindowMaker-0.91.0/src/superfluous.c	2005-05-19 12:42:35 +0400
83322e0
@@ -41,6 +41,7 @@
83322e0
 #include "window.h"
83322e0
 #include "icon.h"
83322e0
 #include "appicon.h"
83322e0
+#include "xinerama.h"
83322e0
 
83322e0
 
83322e0
 extern WPreferences wPreferences;
83322e0
@@ -810,3 +811,164 @@
83322e0
 
83322e0
 #endif /* GHOST_WINDOW_MOVE */
83322e0
 
83322e0
+#ifdef BOUNCE_APP
83322e0
+
83322e0
+#define BOUNCE_HZ	25
83322e0
+#define BOUNCE_DELAY	(1000/BOUNCE_HZ)
83322e0
+#define BOUNCE_HEIGHT	24
83322e0
+#define BOUNCE_LENGTH	0.3
83322e0
+#define BOUNCE_DAMP	0.6
83322e0
+
83322e0
+typedef struct AppBouncerData {
83322e0
+    WApplication *wapp;
83322e0
+    int count;
83322e0
+    int pow;
83322e0
+    int dir;
83322e0
+    WMHandlerID *timer;
83322e0
+} AppBouncerData;
83322e0
+
83322e0
+static void 
83322e0
+doAppBounce(void *arg)
83322e0
+{
83322e0
+    AppBouncerData *data = (AppBouncerData*)arg;
83322e0
+    WAppIcon *aicon = data->wapp->app_icon;
83322e0
+
83322e0
+reinit:
83322e0
+    if (aicon && data->wapp->refcount > 1)
83322e0
+    {
83322e0
+	const double ticks = BOUNCE_HZ*BOUNCE_LENGTH;
83322e0
+	const double s = sqrt(BOUNCE_HEIGHT)/(ticks/2);
83322e0
+	double h = BOUNCE_HEIGHT*pow(BOUNCE_DAMP, data->pow);
83322e0
+	double sqrt_h = sqrt(h);
83322e0
+	if (h > 3)
83322e0
+	{
83322e0
+	    double offset, x = s * data->count - sqrt_h;
83322e0
+	    if (x > sqrt_h)
83322e0
+	    {
83322e0
+		++data->pow;
83322e0
+		data->count = 0;
83322e0
+		goto reinit;
83322e0
+	    } else ++data->count;
83322e0
+	    offset = h - x*x;
83322e0
+	    
83322e0
+	    switch(data->dir)
83322e0
+	    {
83322e0
+		case 0: /* left, bounce to right */
83322e0
+		    XMoveWindow(dpy, aicon->icon->core->window, 
83322e0
+				aicon->x_pos + (int)offset, aicon->y_pos);
83322e0
+		    break;
83322e0
+		case 1: /* right, bounce to left */
83322e0
+		    XMoveWindow(dpy, aicon->icon->core->window, 
83322e0
+				aicon->x_pos - (int)offset, aicon->y_pos);
83322e0
+		    break;
83322e0
+		case 2: /* top, bounce down */
83322e0
+		    XMoveWindow(dpy, aicon->icon->core->window, 
83322e0
+				aicon->x_pos, aicon->y_pos + (int)offset);
83322e0
+		    break;
83322e0
+		case 3: /* bottom, bounce up */
83322e0
+		    XMoveWindow(dpy, aicon->icon->core->window, 
83322e0
+				aicon->x_pos, aicon->y_pos - (int)offset);
83322e0
+		    break;
83322e0
+	    }
83322e0
+	    return;
83322e0
+	}
83322e0
+	XMoveWindow(dpy, aicon->icon->core->window, 
83322e0
+		    aicon->x_pos, aicon->y_pos);
83322e0
+    }
83322e0
+
83322e0
+    data->wapp->flags.bouncing = 0;
83322e0
+    WMDeleteTimerHandler(data->timer);
83322e0
+    wApplicationDestroy(data->wapp);
83322e0
+    free(data);
83322e0
+}
83322e0
+
83322e0
+static int
83322e0
+bounceDirection(WAppIcon *aicon)
83322e0
+{
83322e0
+    enum { left_e = 1, right_e = 2, top_e = 4, bottom_e = 8 };
83322e0
+
83322e0
+    WScreen *scr = aicon->icon->core->screen_ptr;
83322e0
+    WMRect rr, sr;
83322e0
+    int l,r,t,b, h,v;
83322e0
+    int dir = 0;
83322e0
+
83322e0
+    rr.pos.x = aicon->x_pos;
83322e0
+    rr.pos.y = aicon->y_pos;
83322e0
+    rr.size.width = rr.size.height = 64;
83322e0
+    
83322e0
+    sr = wGetRectForHead(scr, wGetHeadForRect(scr, rr));
83322e0
+
83322e0
+    l = rr.pos.x - sr.pos.x;
83322e0
+    r = sr.pos.x + sr.size.width - rr.pos.x - rr.size.width;
83322e0
+    t = rr.pos.y - sr.pos.y;
83322e0
+    b = sr.pos.y + sr.size.height - rr.pos.y - rr.size.height;
83322e0
+
83322e0
+    if (l < r) {
83322e0
+	dir |= left_e;
83322e0
+	h = l;
83322e0
+    } else {
83322e0
+	dir |= right_e;
83322e0
+	h = r;
83322e0
+    }
83322e0
+
83322e0
+    if (t < b) {
83322e0
+	dir |= top_e;
83322e0
+	v = t;
83322e0
+    } else {
83322e0
+	dir |= bottom_e;
83322e0
+	v = b;
83322e0
+    }
83322e0
+
83322e0
+    if (h < v) dir &= ~(top_e | bottom_e);
83322e0
+    else dir &= ~(left_e | right_e);
83322e0
+
83322e0
+    switch(dir)
83322e0
+    {
83322e0
+	case left_e:
83322e0
+	    dir = 0;
83322e0
+	    break;
83322e0
+
83322e0
+	case right_e:
83322e0
+	    dir = 1;
83322e0
+	    break;
83322e0
+
83322e0
+	case top_e:
83322e0
+	    dir = 2;
83322e0
+	    break;
83322e0
+
83322e0
+	case bottom_e:
83322e0
+	    dir = 3;
83322e0
+	    break;
83322e0
+
83322e0
+	default:
83322e0
+	    wwarning(_("impossible direction: %d\n"), dir);
83322e0
+	    dir = 3;
83322e0
+	    break;
83322e0
+    }
83322e0
+
83322e0
+    return dir;
83322e0
+}
83322e0
+
83322e0
+void 
83322e0
+wAppBounce(WApplication * wapp)
83322e0
+{
83322e0
+    if (wapp->app_icon && !wapp->flags.bouncing)
83322e0
+    {
83322e0
+	++wapp->refcount;
83322e0
+	wapp->flags.bouncing = 1;
83322e0
+
83322e0
+	AppBouncerData *data = 
83322e0
+	    (AppBouncerData*)malloc(sizeof(AppBouncerData));
83322e0
+	data->wapp = wapp;
83322e0
+	data->count = data->pow = 0;
83322e0
+	data->dir = bounceDirection(wapp->app_icon);
83322e0
+	data->timer = WMAddPersistentTimerHandler(BOUNCE_DELAY, doAppBounce, data);
83322e0
+    }
83322e0
+}
83322e0
+
83322e0
+#else
83322e0
+void
83322e0
+wAppBounce(WApplication * wapp)
83322e0
+{
83322e0
+}
83322e0
+#endif
e166f64
--- WindowMaker-0.92.0/src/window.c.orig	2006-11-04 09:57:52.000000000 +0100
e166f64
+++ WindowMaker-0.92.0/src/window.c	2006-11-04 10:00:33.000000000 +0100
e166f64
@@ -1399,6 +1399,11 @@
e166f64
                     raise = True;
e166f64
                 }
e166f64
             }
e166f64
+	    /* only do the Bounce when animations are activated */
e166f64
+	    if(!wPreferences.no_animations)
e166f64
+	    {
e166f64
+		wAppBounce(app);
e166f64
+	    }
e166f64
         }
e166f64
     }
e166f64