mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-20 04:48:06 +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)
|
if (wapp->refcount > 0)
|
||||||
return;
|
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;
|
scr = wapp->main_window_desc->screen_ptr;
|
||||||
main_window = wapp->main_window;
|
main_window = wapp->main_window;
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ typedef struct WApplication {
|
|||||||
unsigned int skip_next_animation:1;
|
unsigned int skip_next_animation:1;
|
||||||
unsigned int hidden:1;
|
unsigned int hidden:1;
|
||||||
unsigned int emulated:1;
|
unsigned int emulated:1;
|
||||||
|
#ifdef BOUNCE_APP
|
||||||
|
unsigned int bouncing:1;
|
||||||
|
#endif
|
||||||
} flags;
|
} flags;
|
||||||
} WApplication;
|
} WApplication;
|
||||||
|
|
||||||
@@ -57,5 +60,7 @@ WApplication *wApplicationOf(Window window);
|
|||||||
|
|
||||||
void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance,
|
void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance,
|
||||||
char *wm_class);
|
char *wm_class);
|
||||||
|
|
||||||
|
void wAppBounce(WApplication *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "framewin.h"
|
#include "framewin.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
|
#include "xinerama.h"
|
||||||
|
|
||||||
extern WPreferences wPreferences;
|
extern WPreferences wPreferences;
|
||||||
|
|
||||||
@@ -251,3 +252,154 @@ void DoWindowBirth(WWindow *wwin)
|
|||||||
/* dummy stub */
|
/* dummy stub */
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
raise = True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wAppBounce(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user