From: Alexey I. Froloff Date: Fri, 10 Sep 2010 16:51:03 +0000 (+0400) Subject: Bouncing appicon effect X-Git-Tag: wmaker-0.95.0-crm~140 X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/commitdiff_plain/a257e16593bb471662ce46f65d489c2ba6d87813?hp=17cc7c3c773fd311d83eb244f0e48ea7c44d3abb Bouncing appicon effect When starting application (or opening transient dialog) bounce its appicon. Original-patch-by: Peter Zijlstra Signed-off-by: Alexey I. Froloff --- diff --git a/src/application.c b/src/application.c index f19788b6..19fcb520 100644 --- a/src/application.c +++ b/src/application.c @@ -409,6 +409,15 @@ void wApplicationDestroy(WApplication * wapp) if (wapp->refcount > 0) return; +#ifdef BOUNCE_APP + if (wapp->flags.bouncing) { + /* event.c:handleDestroyNotify forced this destroy + and thereby overlooked the bounce callback */ + wapp->refcount = 1; + return; + } +#endif + scr = wapp->main_window_desc->screen_ptr; main_window = wapp->main_window; diff --git a/src/application.h b/src/application.h index d4ded889..b7c1e095 100644 --- a/src/application.h +++ b/src/application.h @@ -46,6 +46,9 @@ typedef struct WApplication { unsigned int skip_next_animation:1; unsigned int hidden:1; unsigned int emulated:1; +#ifdef BOUNCE_APP + unsigned int bouncing:1; +#endif } flags; } WApplication; @@ -57,5 +60,7 @@ WApplication *wApplicationOf(Window window); void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance, char *wm_class); + +void wAppBounce(WApplication *); #endif diff --git a/src/superfluous.c b/src/superfluous.c index a270b530..04db09e2 100644 --- a/src/superfluous.c +++ b/src/superfluous.c @@ -39,6 +39,7 @@ #include "framewin.h" #include "window.h" #include "actions.h" +#include "xinerama.h" extern WPreferences wPreferences; @@ -251,3 +252,154 @@ void DoWindowBirth(WWindow *wwin) /* dummy stub */ } #endif + +#ifdef BOUNCE_APP + +#define BOUNCE_HZ 25 +#define BOUNCE_DELAY (1000/BOUNCE_HZ) +#define BOUNCE_HEIGHT 24 +#define BOUNCE_LENGTH 0.3 +#define BOUNCE_DAMP 0.6 + +typedef struct AppBouncerData { + WApplication *wapp; + int count; + int pow; + int dir; + WMHandlerID *timer; +} AppBouncerData; + +static void doAppBounce(void *arg) +{ + AppBouncerData *data = (AppBouncerData*)arg; + WAppIcon *aicon = data->wapp->app_icon; + +reinit: + if (aicon && data->wapp->refcount > 1) { + const double ticks = BOUNCE_HZ * BOUNCE_LENGTH; + const double s = sqrt(BOUNCE_HEIGHT)/(ticks/2); + double h = BOUNCE_HEIGHT*pow(BOUNCE_DAMP, data->pow); + double sqrt_h = sqrt(h); + if (h > 3) { + double offset, x = s * data->count - sqrt_h; + if (x > sqrt_h) { + ++data->pow; + data->count = 0; + goto reinit; + } else ++data->count; + offset = h - x*x; + + switch (data->dir) { + case 0: /* left, bounce to right */ + XMoveWindow(dpy, aicon->icon->core->window, + aicon->x_pos + (int)offset, aicon->y_pos); + break; + case 1: /* right, bounce to left */ + XMoveWindow(dpy, aicon->icon->core->window, + aicon->x_pos - (int)offset, aicon->y_pos); + break; + case 2: /* top, bounce down */ + XMoveWindow(dpy, aicon->icon->core->window, + aicon->x_pos, aicon->y_pos + (int)offset); + break; + case 3: /* bottom, bounce up */ + XMoveWindow(dpy, aicon->icon->core->window, + aicon->x_pos, aicon->y_pos - (int)offset); + break; + } + return; + } + XMoveWindow(dpy, aicon->icon->core->window, + aicon->x_pos, aicon->y_pos); + } + + data->wapp->flags.bouncing = 0; + WMDeleteTimerHandler(data->timer); + wApplicationDestroy(data->wapp); + free(data); +} + +static int bounceDirection(WAppIcon *aicon) +{ + enum { left_e = 1, right_e = 2, top_e = 4, bottom_e = 8 }; + + WScreen *scr = aicon->icon->core->screen_ptr; + WMRect rr, sr; + int l, r, t, b, h, v; + int dir = 0; + + rr.pos.x = aicon->x_pos; + rr.pos.y = aicon->y_pos; + rr.size.width = rr.size.height = 64; + + sr = wGetRectForHead(scr, wGetHeadForRect(scr, rr)); + + l = rr.pos.x - sr.pos.x; + r = sr.pos.x + sr.size.width - rr.pos.x - rr.size.width; + t = rr.pos.y - sr.pos.y; + b = sr.pos.y + sr.size.height - rr.pos.y - rr.size.height; + + if (l < r) { + dir |= left_e; + h = l; + } else { + dir |= right_e; + h = r; + } + + if (t < b) { + dir |= top_e; + v = t; + } else { + dir |= bottom_e; + v = b; + } + + if (h < v) dir &= ~(top_e | bottom_e); + else dir &= ~(left_e | right_e); + + switch (dir) { + case left_e: + dir = 0; + break; + + case right_e: + dir = 1; + break; + + case top_e: + dir = 2; + break; + + case bottom_e: + dir = 3; + break; + + default: + wwarning(_("Impossible direction: %d\n"), dir); + dir = 3; + break; + } + + return dir; +} + +void wAppBounce(WApplication *wapp) +{ + if (wapp->app_icon && !wapp->flags.bouncing) { + ++wapp->refcount; + wapp->flags.bouncing = 1; + + AppBouncerData *data = (AppBouncerData *)malloc(sizeof(AppBouncerData)); + data->wapp = wapp; + data->count = data->pow = 0; + data->dir = bounceDirection(wapp->app_icon); + data->timer = WMAddPersistentTimerHandler(BOUNCE_DELAY, doAppBounce, data); + } +} + +#else +void wAppBounce(WApplication *wapp) +{ +} +#endif diff --git a/src/window.c b/src/window.c index 39116dbb..80259830 100644 --- a/src/window.c +++ b/src/window.c @@ -1200,6 +1200,7 @@ WWindow *wManageWindow(WScreen *scr, Window window) raise = True; } } + wAppBounce(app); } }