Репозитории ALT
S: | 0.96.0-alt1 |
5.1: | 0.92.0-alt6 |
4.1: | 0.92.0-alt2 |
4.0: | 0.92.0-alt2 |
3.0: | 0.91.0-alt1 |
+backports: | 0.92.0-alt0.M30.1 |
Группа :: Графические оболочки/Window Maker
Пакет: WindowMaker
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: WindowMaker-0.92.0-peter-appicon-bouncer2.patch
Скачать
Скачать
src/application.c | 10 +++
src/application.h | 5 ++
src/superfluous.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/window.c | 1 +
4 files changed, 178 insertions(+), 0 deletions(-)
diff --git a/src/application.c b/src/application.c
index 5676f25..9514a46 100644
--- a/src/application.c
+++ b/src/application.c
@@ -448,6 +448,16 @@ 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 c0165ce..961e1e5 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;
@@ -58,6 +61,8 @@ WApplication *wApplicationOf(Window window);
void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance,
char *wm_class);
+void wAppBounce(WApplication *);
+
#ifdef NEWAPPICON
#define wApplicationActivate(wapp) do { \
diff --git a/src/superfluous.c b/src/superfluous.c
index 8699d81..e9ab2fc 100644
--- a/src/superfluous.c
+++ b/src/superfluous.c
@@ -41,6 +41,7 @@
#include "window.h"
#include "icon.h"
#include "appicon.h"
+#include "xinerama.h"
extern WPreferences wPreferences;
@@ -811,3 +812,164 @@ UpdateGhostWindowMove(void *data, int x, int y)
#endif /* GHOST_WINDOW_MOVE */
+#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 4c0a8fc..372a110 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1399,6 +1399,7 @@ wManageWindow(WScreen *scr, Window window)
raise = True;
}
}
+ wAppBounce(app);
}
}