1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00

Bouncing appicon effect

When starting application (or opening transient dialog) bounce
its appicon.

Original-patch-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Alexey I. Froloff <raorn@altlinux.org>
This commit is contained in:
Alexey I. Froloff
2010-09-10 20:51:03 +04:00
committed by Carlos R. Mafra
parent 17cc7c3c77
commit a257e16593
4 changed files with 167 additions and 0 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -1200,6 +1200,7 @@ WWindow *wManageWindow(WScreen *scr, Window window)
raise = True;
}
}
wAppBounce(app);
}
}