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:
committed by
Carlos R. Mafra
parent
17cc7c3c77
commit
a257e16593
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1200,6 +1200,7 @@ WWindow *wManageWindow(WScreen *scr, Window window)
|
||||
raise = True;
|
||||
}
|
||||
}
|
||||
wAppBounce(app);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user