From 51a19d26e72b6286753a180b743a13443b25905e Mon Sep 17 00:00:00 2001 From: Kim Woelders Date: Sun, 9 Dec 2012 10:03:07 +0000 Subject: [PATCH] Introduce new animation engine. Based on work by Daniel Manjarres. One of the major changes is to eliminate the "TimedLoop" construction where we have "local" animation loops, in which we don't pass through the main event handler. SVN revision: 80542 --- src/E.h | 2 - src/Makefile.am | 1 + src/animation.c | 494 ++++++++++++++++++++++++++++++++++++++++++++++++ src/animation.h | 94 +++++++++ src/desktops.c | 256 ++++++++++++++++++------- src/ecompmgr.c | 30 +-- src/eobj.c | 2 + src/eobj.h | 1 + src/ewin-ops.c | 97 ++++------ src/ewins.c | 31 +-- src/ewins.h | 3 +- src/fx.c | 44 ++--- src/glwin.c | 9 +- src/magwin.c | 15 +- src/menus.c | 45 ++++- src/misc.c | 71 ------- src/slide.c | 259 +++++++++++++------------ src/slide.h | 8 +- src/startup.c | 28 +-- src/timers.c | 112 ----------- src/timers.h | 3 - 21 files changed, 1044 insertions(+), 561 deletions(-) create mode 100644 src/animation.c create mode 100644 src/animation.h diff --git a/src/E.h b/src/E.h index 32d40b6b..d227d3ef 100644 --- a/src/E.h +++ b/src/E.h @@ -546,8 +546,6 @@ void Etmp(char *s); void Quicksort(void **a, int l, int r, int (*CompareFunc) (const void *d1, const void *d2)); -void ETimedLoopInit(int k1, int k2, int speed); -int ETimedLoopNext(void); /* mod-misc.c */ void autosave(void); diff --git a/src/Makefile.am b/src/Makefile.am index f29f54bb..c9a35ca1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,7 @@ e16_SOURCES = \ text.c \ theme.c \ time.c \ + animation.c animation.h \ timers.c timers.h \ tooltips.c tooltips.h \ user.c user.h \ diff --git a/src/animation.c b/src/animation.c new file mode 100644 index 00000000..6cd6cdfa --- /dev/null +++ b/src/animation.c @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2012 Daniel Manjarres + * Copyright (C) 2012 Kim Woelders + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of the Software, its documentation and marketing & publicity + * materials, and acknowledgment shall be given in the documentation, materials + * and software packages that this Software was used. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "E.h" +#include "animation.h" +#include "eobj.h" +#include "timers.h" +#include "util.h" +#include + +#define ENABLE_DEBUG 1 +#if ENABLE_DEBUG +#define EDBUG_TYPE_ANIM 180 +#define Dprintf(fmt...) if(EDebug(EDBUG_TYPE_ANIM))Eprintf(fmt) +#define D2printf(fmt...) if(EDebug(EDBUG_TYPE_ANIM)>1)Eprintf(fmt) +#define D3printf(fmt...) +#define EOW(eo) (eo ? EobjGetXwin(eo) : None) +#else +#define Dprintf(fmt...) +#define D2printf(fmt...) +#define D3printf(fmt...) +#endif /* ENABLE_DEBUG */ + +static int timing_engine(void); + +/* + * State + */ +static struct { + Timer *timer; + Idler *idler; + unsigned int time_ms; +} Mode_anim = +{ +NULL, NULL, 0}; + +#define FPS 60 + +static int +_AnimatorsTimer(void *timer_call) +{ + int frame_skip; + int dt; + + /* Remember current event time */ + Mode_anim.time_ms = Mode.events.time_ms; + + frame_skip = timing_engine(); + + /* time = partial_frames * usecs_per_partial_frame */ + if (frame_skip < 1000000) + dt = (frame_skip + 1) * (1e3 / FPS); + else + dt = 1000000000; /* Some arbitrary high value */ + + if (timer_call) + { + TimerSetInterval(Mode_anim.timer, dt); + } + else + { + TIMER_DEL(Mode_anim.timer); + TIMER_ADD(Mode_anim.timer, dt, _AnimatorsTimer, (void *)1L); + } + + D2printf("%s (%s) frame_skip=%d dt=%d\n", __func__, + timer_call ? "TIMER" : "IDLER", frame_skip, dt); + + return 1; +} + +static void +_AnimatorsIdler(void *data) +{ + /* Don't run idler if we have just run timer */ + if (Mode_anim.time_ms == Mode.events.time_ms) + return; + + _AnimatorsTimer(data); +} + +static void +_AnimatorsInit(void) +{ + TIMER_ADD(Mode_anim.timer, 100, _AnimatorsTimer, (void *)1L); + Mode_anim.idler = IdlerAdd(_AnimatorsIdler, (void *)0L); +} + +/* + * The animation engine + */ + +#define LATER(frame, than) ((int)(frame - than) > 0) +#define LATER_EQ(frame, than) ((int)(frame - than) >= 0) + +struct _animator { + struct _animator *next; + AnimCbFunc *func; + AnimDoneFunc *done; + animation_category category; + int duration; + esound_e start_sound; + esound_e end_sound; + char serialize; + char cancelled; + unsigned int start_frame; + unsigned int end_frame; + unsigned int next_frame; + unsigned int last_tms; + EObj *eo; +}; + +static Animator *global_animators; + +/* This is the frame we THINk we are currently displaying. + * The next frame to render is this + 1. */ +static unsigned int current_frame_num = 1; + +/* This is the number of the next frame we need to render for a pending + * animation */ +static unsigned int skip_to_frame_num = 0; + +static char anim_recheck = 0; + +Animator * +AnimatorAdd(EObj * eo, animation_category category, AnimCbFunc * func, + int duration, int serialize, size_t data_size, void *data) +{ + Animator *an, **insert; + + an = (Animator *) calloc(1, sizeof(Animator) + data_size); + if (!an) + return NULL; + + Dprintf("%s: %u/%u: %#lx %p C%d\n", __func__, + current_frame_num, skip_to_frame_num, EOW(eo), an, category); + + if (!Mode_anim.timer) + _AnimatorsInit(); + + insert = eo ? &eo->animations : &global_animators; + while (*insert) + insert = &((*insert)->next); + *insert = an; + + an->func = func; + if (duration >= 0) + { + an->duration = (duration * FPS) / 1000; /* ms -> frames */ + if (an->duration == 0) + an->duration = 1; /* At least one frame */ + } + else + an->duration = -1; /* Forever */ + an->category = category; + an->serialize = serialize; + + an->eo = eo; + an->start_sound = an->end_sound = SOUND_NONE; + + if (data_size) + memcpy(an + 1, data, data_size); + + anim_recheck = 1; + + return an; +} + +static void +_AnimatorDel(Animator * an) +{ + Dprintf("%s: %u/%u: %#lx %p C%d\n", __func__, + current_frame_num, skip_to_frame_num, EOW(an->eo), an, an->category); + Efree(an); +} + +void +AnimatorSetSound(Animator * an, esound_e start_sound, esound_e end_sound) +{ + if (!an) + return; + an->start_sound = start_sound; + an->end_sound = end_sound; +} + +void +AnimatorSetDoneFunc(Animator * an, AnimDoneFunc * done) +{ + an->done = done; +} + +void +AnimatorsFree(EObj * eo) +{ + Animator *an, *next; + + for (an = eo->animations; an; an = next) + { + next = an->next; + _AnimatorDel(an); + } +} + +/* Quarter period sinusoidal used in time limited animations */ +#define REMAINING(elapsed, duration) \ + (int)(1024 * (1. - cos(((M_PI / 2 * (elapsed)) / (duration))))) + +static unsigned int +_AnimatorsRun(Animator ** head, unsigned int frame_num, unsigned int next_frame) +{ + Animator *an, *next, **pprev; + int res; + int first; + int remaining; + int delta_t; + + for (first = 1, pprev = head, an = *head; an; an = next) + { + D3printf("%s: %#lx %p\n", __func__, EOW(an->eo), an); + next = an->next; + + if (an->cancelled) + { + res = ANIM_RET_CANCEL_ANIM; + goto check_res; + } + if (an->serialize) + { + /* Start when other non-forever animations have run */ + if (!first) + goto do_next; + Dprintf("%s: %#lx %p C%d: De-serialize\n", __func__, EOW(an->eo), + an, an->category); + an->next_frame = frame_num; + an->start_frame = an->next_frame; + an->end_frame = an->start_frame + an->duration - 1; + an->serialize = 0; + } + else if (an->start_frame == an->end_frame) + { + /* Just added - calculate first/last frame */ + /* Start "now" or after initial delay (-serialize) */ + /* NB! New animations start one frame into the future */ + an->next_frame = current_frame_num + 1 - an->serialize; + an->start_frame = an->next_frame; + an->end_frame = an->start_frame + an->duration - 1; + an->last_tms = Mode_anim.time_ms; + } + + /* Don't serialize animations that follow an inf loop with the inf loop */ + if (an->duration > 0) + first = 0; + + if (an->category >= 0 && an->duration > 0 && + LATER(an->next_frame, frame_num)) + goto check_next_frame; + + /*{ start of old _AnimatorRun() */ + + if (an->start_sound) + { + SoundPlay(an->start_sound); + an->start_sound = SOUND_NONE; + } + + delta_t = Mode_anim.time_ms - an->last_tms; + an->last_tms = Mode_anim.time_ms; + + if (an->duration > 0) + { + remaining = 0; + if (frame_num < an->end_frame) + remaining = REMAINING(an->end_frame - frame_num, an->duration); + } + else + { + remaining = delta_t; + } + + D2printf("%s: eo=%p an=%p cat=%d rem=%4d dur=%4d dt=%4d\n", __func__, + an->eo, an, an->category, remaining, an->duration, delta_t); + res = an->func(an->eo, remaining, an + 1); + Dprintf("%s: res=%4d num=%u end=%u\n", __func__, res, frame_num, + an->end_frame); + + if (res >= 0) + { + if (an->duration > 0 && remaining <= 0) + { + Dprintf("%s: %#lx %p C%d: autocancelling\n", __func__, + EOW(an->eo), an, an->category); + res = ANIM_RET_CANCEL_ANIM; + } + } + else + { + Dprintf("%s: %#lx %p C%d: self cancelling\n", __func__, + EOW(an->eo), an, an->category); + } + + /*} end of old _AnimatorRun() */ + + check_res: + if (res >= 0) + { + /* animator will run again */ + an->next_frame = frame_num + 1 + res; + } + else + { + if (an->done) + an->done(an->eo, an + 1); + + if (an->end_sound) + SoundPlay(an->end_sound); + + _AnimatorDel(an); + *pprev = next; + continue; /* Skip pprev update */ + } + + check_next_frame: + if (an->category >= 0 && LATER(next_frame, an->next_frame)) + next_frame = an->next_frame; + + do_next: + pprev = &an->next; + } + + return next_frame; +} + +static unsigned int +_AnimatorsRunAll(unsigned int frame_num) +{ + EObj **lst; + EObj *const *lst2; + unsigned int next_frame; + int num, i; + + lst2 = EobjListStackGet(&num); + lst = EMALLOC(EObj *, num); + memcpy(lst, lst2, num * sizeof(EObj *)); + + next_frame = frame_num + 0x7fffffff; + + D3printf("%s: %u/%u\n", __func__, current_frame_num, skip_to_frame_num); + + for (i = 0; i < num; i++) + next_frame = _AnimatorsRun(&lst[i]->animations, frame_num, next_frame); + + Efree(lst); + + next_frame = _AnimatorsRun(&global_animators, frame_num, next_frame); + + return next_frame; +} + +int +AnimatorsDelCat(EObj * eo, animation_category category, int complete) +{ + Animator *an; + int accum = 0; + + Dprintf("%s: cat=%d?\n", __func__, category); + + for (an = (eo) ? eo->animations : global_animators; an; an = an->next) + { + if (an->category == category && !an->cancelled) + { + Dprintf("... %p: complete=%d\n", an, complete); + an->cancelled = 1 + complete; + accum++; + } + } + return accum; +} + +int +AnimatorsDelCatAll(animation_category category, int complete) +{ + EObj *const *lst; + int num, i, accum; + + accum = AnimatorsDelCat(NULL, category, complete); + lst = EobjListStackGet(&num); + + for (i = 0; i < num; i++) + { + accum += AnimatorsDelCat(lst[i], category, complete); + } + return accum; +} + +static unsigned int +_FrameNum(void) +{ + static char init = 0; + static unsigned int tp = 0; + static unsigned int fp = 0; + unsigned int t, frame, dx; + + t = GetTimeMs(); + + if (!init) + { + init = 1; + tp = t; + } + + dx = t - tp; + frame = fp + (dx * FPS) / 1000; + + if (dx > 1000000) + { + dx /= 1000; + tp += dx * 1000; + fp += dx * FPS; + } + + return frame; +} + +static unsigned int +get_check_frame_count(unsigned int last_frame __UNUSED__, + unsigned int skip_to_frame, + unsigned int *good_framesp, + unsigned int *last_skipped_framep, const char *msg) +{ + unsigned int frame_num; + + frame_num = _FrameNum(); + + if (frame_num > skip_to_frame) + { + Eprintf("@%u %s missed %u frames ;-( after %u [%u] good frames\n", + frame_num, msg, frame_num - skip_to_frame, *good_framesp, + skip_to_frame - 1 - *last_skipped_framep); + *good_framesp = 0; + *last_skipped_framep = frame_num - 1; + } + + return frame_num; +} + +static int +timing_engine(void) +{ + static unsigned int last_frame_num; + static unsigned int good_frames; + static unsigned int last_skipped_frame; + int frameskip; + + current_frame_num = get_check_frame_count(last_frame_num, skip_to_frame_num, + &good_frames, &last_skipped_frame, + "before render"); + + D2printf("%s: cur/last=%u/%u next=%u good=%u last-skipped=%u\n", + __func__, current_frame_num, last_frame_num, skip_to_frame_num, + good_frames, last_skipped_frame); + + if (current_frame_num == last_frame_num && !anim_recheck) + goto done; + + last_frame_num = current_frame_num; + anim_recheck = 0; + + skip_to_frame_num = _AnimatorsRunAll(current_frame_num); + + done: + frameskip = skip_to_frame_num - current_frame_num - 1; + + return frameskip; +} diff --git a/src/animation.h b/src/animation.h new file mode 100644 index 00000000..d5cd22a2 --- /dev/null +++ b/src/animation.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 Daniel Manjarres + * Copyright (C) 2012 Kim Woelders + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of the Software, its documentation and marketing & publicity + * materials, and acknowledgment shall be given in the documentation, materials + * and software packages that this Software was used. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _ANIMATION_H_ +#define _ANIMATION_H_ + +#include "eobj.h" + +/* + * Animator function prototype. + * + * eo : A pointer to the pertinent EObj. + * run : A parameter indicating animation progress. + * If the animation time is limited (duration > 0), run will go + * from ~1023 to 0. + * The first call will most likely not have run=1023, but (unless + * the animator is killed) the last call will have run=0. + * If the animation is not time limited, the first call will + * have run=0 (TBD), and the subsequent calls will have run equal + * to the time since last call in ms. + * data: A pointer to extra animator data, as specified when creating the + * animator. + * + * Because a EObj may be destroyed before then animation is complete, it + * must be safe to simply free the Animator struct and get on with life, + * so animations should not require destructor-like functions to run after + * they are complete. + */ +typedef int (AnimCbFunc) (EObj * eo, int run, void *data); +typedef void (AnimDoneFunc) (EObj * eo, void *data); + +/* + * If AnimCbFunc's (retval > 0) it will not be called for retval frames. + * If AnimCbFunc's (retval == -1) the animation is cancelled. + */ +#define ANIM_RET_CANCEL_ANIM -1 + +typedef enum { + /* lazy animations have negative names, and + * do not trigger frames to be drawn, but do draw things + * when other things trigger frames */ + ANIM_LAZY_MAGWIN = -8, + + ANIM_NOT_USED = 0, + + ANIM_FADE, + ANIM_SLIDE, + ANIM_SHADE, + + ANIM_STARTUP = 20, + ANIM_GLWIN, + + /* not a window animation, but a desktop animation */ + ANIM_FX_SPINNER = 40, + ANIM_FX_RAINDROPS, + ANIM_FX_WAVES, + ANIM_FX_RIPPLES, +} animation_category; + +Animator *AnimatorAdd(EObj * eo, animation_category category, + AnimCbFunc * func, int duration, int serialize, + size_t data_size, void *data); +void AnimatorSetSound(Animator * an, + esound_e start_sound, esound_e end_sound); +void AnimatorSetDoneFunc(Animator * an, AnimDoneFunc * done); + +int AnimatorsDelCat(EObj * eo, animation_category category, + int complete); +int AnimatorsDelCatAll(animation_category category, + int complete); + +void AnimatorsFree(EObj * eo); + +#endif /* _ANIMATION_H_ */ diff --git a/src/desktops.c b/src/desktops.c index d7e1439a..c8f5eb5e 100644 --- a/src/desktops.c +++ b/src/desktops.c @@ -23,6 +23,7 @@ */ #include "E.h" #include "aclass.h" +#include "animation.h" #include "backgrounds.h" #include "buttons.h" #include "desktops.h" @@ -64,6 +65,7 @@ typedef struct { unsigned int order[ENLIGHTENMENT_CONF_NUM_DESKTOPS]; int drag_x0, drag_y0; unsigned int prev_num; + Animator *anim_slide; } Desktops; static void DeskRaise(unsigned int num); @@ -1187,12 +1189,9 @@ DeskSwitchDone(void) FocusNewDesk(); } -void -DeskGoto(Desk * dsk) +static void +_DeskGotoStart(Desk * dsk) { - if (!dsk || dsk == desks.previous) - return; - if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskGoto %d\n", dsk->num); @@ -1200,13 +1199,57 @@ DeskGoto(Desk * dsk) MoveResizeSuspend(); DeskSwitchStart(); +} + +static void +_DeskGotoEnd(Desk * dsk) +{ + DeskSwitchDone(); + MoveResizeResume(); + + ModulesSignal(ESIGNAL_DESK_SWITCH_DONE, NULL); + + if (EDebug(EDBUG_TYPE_DESKS)) + Eprintf("DeskGoto %d done\n", dsk->num); +} + +static int +_DeskGotoRun(EObj * eo, int run, void *state) +{ + int *xy = (int *)state; + int x, y; + Desk *dsk = (Desk *) eo; + + x = (run * xy[0]) >> 10; + y = (run * xy[1]) >> 10; + + EobjMove(eo, x, y); + + if (run == 0) + { + if (xy[2]) + DeskEnter(dsk); + DeskMove(dsk, 0, 0); + _DeskGotoEnd(dsk); + EventsBlock(0); + } + + return 0; +} + +void +DeskGoto(Desk * dsk) +{ + if (!dsk || dsk == desks.previous) + return; + + _DeskGotoStart(dsk); if (dsk->num > 0) { if (Conf.desks.slidein) { - EObj *eo = &dsk->o; - + EventsBlock(1); if (!dsk->viewable) { int x, y; @@ -1232,15 +1275,20 @@ DeskGoto(Desk * dsk) break; } DeskMove(dsk, x, y); + int xy[3] = { x, y, 0 }; DeskEnter(dsk); - EobjsSlideBy(&eo, 1, -x, -y, Conf.desks.slidespeed); + AnimatorAdd(EoObj(dsk), ANIM_SLIDE, _DeskGotoRun, + 1000000 / Conf.desks.slidespeed, + 0, sizeof(xy), xy); } else { - EobjsSlideBy(&eo, 1, -EoGetX(dsk), -EoGetY(dsk), - Conf.desks.slidespeed); - DeskEnter(dsk); + int xy[3] = { EoGetX(dsk), EoGetY(dsk), 1 }; + AnimatorAdd(EoObj(dsk), ANIM_SLIDE, _DeskGotoRun, + 1000000 / Conf.desks.slidespeed, + 0, sizeof(xy), xy); } + return; } else { @@ -1253,13 +1301,7 @@ DeskGoto(Desk * dsk) DeskEnter(dsk); } - DeskSwitchDone(); - MoveResizeResume(); - - ModulesSignal(ESIGNAL_DESK_SWITCH_DONE, NULL); - - if (EDebug(EDBUG_TYPE_DESKS)) - Eprintf("DeskGoto %d done\n", dsk->num); + _DeskGotoEnd(dsk); } static void @@ -1646,40 +1688,21 @@ DeskAreaSwitchDone(void) FocusNewDesk(); } -void -DeskCurrentGotoArea(int ax, int ay) +static void +_DeskCurrentGotoAreaStart(int pax, int pay, int ax, int ay) { - EWin *const *lst, *ewin; - int i, num, dx, dy, pax, pay; - - if ((Mode.mode == MODE_RESIZE) || (Mode.mode == MODE_RESIZE_H) - || (Mode.mode == MODE_RESIZE_V)) - return; - - if (_DeskAreaSwitchCheckEwins()) - return; - - DesksFixArea(&ax, &ay); - DeskCurrentGetArea(&pax, &pay); - - if (ax == pax && ay == pay) - return; - if (EDebug(EDBUG_TYPE_DESKS)) - Eprintf("%s %d,%d\n", __func__, ax, ay); + Eprintf("DeskCurrentGotoArea %d,%d\n", ax, ay); ModulesSignal(ESIGNAL_AREA_SWITCH_START, NULL); - dx = WinGetW(VROOT) * (ax - pax); - dy = WinGetH(VROOT) * (ay - pay); - - if (dx < 0) + if (ax < pax) SoundPlay(SOUND_MOVE_AREA_LEFT); - else if (dx > 0) + else if (ax > pax) SoundPlay(SOUND_MOVE_AREA_RIGHT); - else if (dy < 0) + else if (ay < pay) SoundPlay(SOUND_MOVE_AREA_UP); - else if (dy > 0) + else if (ay > pay) SoundPlay(SOUND_MOVE_AREA_DOWN); MoveResizeSuspend(); @@ -1688,39 +1711,27 @@ DeskCurrentGotoArea(int ax, int ay) /* set the current area up in out data structs */ DeskCurrentSetArea(ax, ay); +} - /* move all the windows around */ - lst = EwinListGetAll(&num); - if (Conf.desks.slidein) - { - int wnum = 0; - EObj **wl = NULL; +typedef struct { + EWin *const *ewins_desk; + EWin *const *ewins_slide; + int n_ewins_desk, n_ewins_slide; + int slide_dx, slide_dy; +} slide_area_data_t; - /* create the list of windwos to move */ - for (i = 0; i < num; i++) - { - ewin = lst[i]; - if (EoIsSticky(ewin) || ewin->state.iconified) - continue; - if (EoGetDesk(ewin) != DesksGetCurrent() && !EoIsFloating(ewin)) - continue; +static void +_DeskCurrentGotoAreaEnd(slide_area_data_t * sad) +{ + EWin *const *lst, *ewin; + int i, num, dx, dy; - if (EoIsFloating(ewin) && Conf.movres.mode_move == MR_OPAQUE) - continue; + desks.anim_slide = NULL; - wnum++; - wl = EREALLOC(EObj *, wl, wnum); - wl[wnum - 1] = &ewin->o; - } - - /* slide them */ - if (wl) - { - EobjsSlideBy(wl, wnum, -dx, -dy, Conf.desks.slidespeed); - Efree(wl); - EobjsRepaint(); - } - } + lst = sad->ewins_desk; + num = sad->n_ewins_desk; + dx = sad->slide_dx; + dy = sad->slide_dy; /* move all windows to their final positions */ for (i = 0; i < num; i++) @@ -1757,6 +1768,105 @@ DeskCurrentGotoArea(int ax, int ay) EdgeWindowsShow(); } +static int +_DeskCurrentGotoAreaRun(EObj * eo __UNUSED__, int run, void *state) +{ + slide_area_data_t *sad = (slide_area_data_t *) state; + EWin *ewin; + int i, dx, dy; + + dx = (run * sad->slide_dx) >> 10; + dy = (run * sad->slide_dy) >> 10; + + for (i = 0; i < sad->n_ewins_slide; i++) + { + ewin = sad->ewins_slide[i]; + EoMove(ewin, ewin->trg_x + dx, ewin->trg_y + dy); + } + + if (run == 0) + { + _DeskCurrentGotoAreaEnd(sad); + EventsBlock(0); + } + + return 0; +} + +void +DeskCurrentGotoArea(int ax, int ay) +{ + slide_area_data_t _sad, *sad = &_sad; + EWin *const *lst, *ewin; + int i, num, dx, dy, pax, pay; + + if (desks.anim_slide) + return; + + if ((Mode.mode == MODE_RESIZE) || (Mode.mode == MODE_RESIZE_H) + || (Mode.mode == MODE_RESIZE_V)) + return; + + if (_DeskAreaSwitchCheckEwins()) + return; + + DesksFixArea(&ax, &ay); + DeskCurrentGetArea(&pax, &pay); + + if (ax == pax && ay == pay) + return; + + _DeskCurrentGotoAreaStart(pax, pay, ax, ay); + + /* move all the windows around */ + dx = WinGetW(VROOT) * (ax - pax); + dy = WinGetH(VROOT) * (ay - pay); + lst = EwinListGetAll(&num); + sad->ewins_desk = lst; + sad->n_ewins_desk = num; + sad->slide_dx = dx; + sad->slide_dy = dy; + + if (Conf.desks.slidein && Conf.desks.slidespeed > 10) + { + int wnum = 0; + EWin **wl = NULL; + + /* create the list of windwos to move */ + for (i = 0; i < num; i++) + { + ewin = lst[i]; + if (EoIsSticky(ewin) || ewin->state.iconified) + continue; + if (EoGetDesk(ewin) != DesksGetCurrent() && !EoIsFloating(ewin)) + continue; + + if (EoIsFloating(ewin) && Conf.movres.mode_move == MR_OPAQUE) + continue; + + wnum++; + wl = EREALLOC(EWin *, wl, wnum); + wl[wnum - 1] = ewin; + ewin->trg_x = EoGetX(ewin) - dx; + ewin->trg_y = EoGetY(ewin) - dy; + } + sad->ewins_slide = wl; + sad->n_ewins_slide = wnum; + + /* slide them */ + if (wl) + { + desks.anim_slide = + AnimatorAdd(NULL, ANIM_SLIDE, _DeskCurrentGotoAreaRun, + 1000000 / Conf.desks.slidespeed, + 0, sizeof(slide_area_data_t), sad); + EventsBlock(1); + return; + } + } + _DeskCurrentGotoAreaEnd(sad); +} + void DeskCurrentMoveAreaBy(int dx, int dy) { diff --git a/src/ecompmgr.c b/src/ecompmgr.c index 4dc824ec..abe29a2a 100644 --- a/src/ecompmgr.c +++ b/src/ecompmgr.c @@ -29,6 +29,7 @@ #include "E.h" #if USE_COMPOSITE +#include "animation.h" #include "desktops.h" #include "ecompmgr.h" #include "emodule.h" @@ -125,7 +126,6 @@ struct _cmhook { unsigned int damage_sequence; /* sequence when damage was created */ - Animator *anim_fade; unsigned int opacity_to; }; @@ -227,7 +227,6 @@ static ESelection *wm_cm_sel = NULL; static void ECompMgrDamageAll(void); static void ECompMgrHandleRootEvent(Win win, XEvent * ev, void *prm); static void ECompMgrHandleWindowEvent(Win win, XEvent * ev, void *prm); -static int doECompMgrWinFade(void *data); static void ECompMgrWinInvalidate(EObj * eo, int what); static void ECompMgrWinSetPicts(EObj * eo); static void ECompMgrWinFadeEnd(EObj * eo, int done); @@ -938,18 +937,11 @@ ECompMgrWinSetOpacity(EObj * eo, unsigned int opacity) } static int -doECompMgrWinFade(void *data) +doECompMgrWinFade(EObj * eo, int run, void *data __UNUSED__) { - EObj *eo; ECmWinInfo *cw; unsigned int op, step; - eo = (EObj *) data; - - /* May be gone */ - if (EobjListStackCheck(eo) < 0) - return 0; - cw = eo->cmhook; op = cw->opacity_to; @@ -962,10 +954,10 @@ doECompMgrWinFade(void *data) eo->fading = cw->fadeout; - step = Conf_compmgr.fading.time / Conf.animation.step; + step = Conf_compmgr.fading.time; if (step == 0) step = 1; - step = 0xffffffff / step; + step = run * (0xffffffff / step); if (op == cw->opacity) { op = eo->opacity; @@ -994,14 +986,13 @@ doECompMgrWinFade(void *data) ECompMgrWinSetOpacity(eo, op); if (eo->fading) - return 1; + return 0; if (eo->type == EOBJ_TYPE_EWIN) ModulesSignal(eo->shown ? ESIGNAL_EWIN_CHANGE : ESIGNAL_EWIN_UNMAP, eo); done: - cw->anim_fade = NULL; - return 0; + return ANIM_RET_CANCEL_ANIM; } static void @@ -1016,8 +1007,8 @@ ECompMgrWinFade(EObj * eo, unsigned int op_from, unsigned int op_to) return; } - if (!cw->anim_fade) - cw->anim_fade = AnimatorAdd(doECompMgrWinFade, eo); + if (!eo->fading) + AnimatorAdd(eo, ANIM_FADE, doECompMgrWinFade, -1, 0, 0, NULL); cw->opacity_to = op_to; eo->fading = 1; @@ -1066,10 +1057,7 @@ ECompMgrWinFadeEnd(EObj * eo, int done) } eo->fading = 0; if (done) - { - AnimatorDel(cw->anim_fade); - cw->anim_fade = NULL; - } + AnimatorsDelCat(eo, ANIM_FADE, 0); } void diff --git a/src/eobj.c b/src/eobj.c index 334a4f12..ad5c860d 100644 --- a/src/eobj.c +++ b/src/eobj.c @@ -21,6 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "desktops.h" #include "e16-ecore_hints.h" #include "ecompmgr.h" @@ -261,6 +262,7 @@ EobjFini(EObj * eo) Efree(eo->icccm.wm_name); Efree(eo->icccm.wm_res_name); Efree(eo->icccm.wm_res_class); + AnimatorsFree(eo); } void diff --git a/src/eobj.h b/src/eobj.h index f3d873fb..ca265e1a 100644 --- a/src/eobj.h +++ b/src/eobj.h @@ -60,6 +60,7 @@ struct _eobj { #if USE_GLX struct _glhook *glhook; #endif + Animator *animations; /* list of pending animations */ }; #define EOBJ_TYPE_EWIN 0 diff --git a/src/ewin-ops.c b/src/ewin-ops.c index 1fe04b9f..be874459 100644 --- a/src/ewin-ops.c +++ b/src/ewin-ops.c @@ -22,6 +22,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "borders.h" #include "desktops.h" #include "emodule.h" @@ -35,7 +36,6 @@ #include "iclass.h" /* FIXME - Should not be here */ #include "screen.h" #include "snaps.h" -#include "timers.h" #include "xwin.h" static const WinOp winops[] = { @@ -848,9 +848,9 @@ EwinInstantUnShade(EWin * ewin) typedef struct { int x, y, w, h; } _xywh; + typedef struct { EWin *ewin; - int k, dk; _xywh start; _xywh final; int a, b, c; @@ -863,9 +863,6 @@ _EwinShadeStart(_ewin_shade_data * esd) int minw, minh; XSetWindowAttributes att; - esd->k = 0; - esd->dk = 1024 * Conf.shading.speed * Conf.animation.step / 1000000; - esd->start.x = EoGetX(ewin); esd->start.y = EoGetY(ewin); esd->start.w = EoGetW(ewin); @@ -931,24 +928,16 @@ _EwinShadeEnd(_ewin_shade_data * esd) EwinStateUpdate(ewin); HintsSetWindowState(ewin); SnapshotEwinUpdate(ewin, SNAP_USE_SHADED); - - Efree(esd); } static int -_EwinShadeRun(void *data) +_EwinShadeRun(EObj * eobj, int remaining, void *state) { - _ewin_shade_data *esd = (_ewin_shade_data *) data; - EWin *ewin = esd->ewin; + _ewin_shade_data *esd = (_ewin_shade_data *) state; + EWin *ewin = (EWin *) eobj; int k, x, y, w, h, ww, hh, cow, coh, shx, shy; - if (!EwinFindByPtr(ewin)) /* Check, window may be gone */ - { - Efree(esd); - return 0; - } - - k = esd->k; + k = 1024 - remaining; x = esd->start.x; y = esd->start.y; @@ -1013,18 +1002,18 @@ _EwinShadeRun(void *data) EoMoveResize(ewin, x, y, w, h); EwinBorderCalcSizes(ewin, 1); - esd->k = k += esd->dk; - if (k < 1024) - return 1; + if (remaining == 0) + _EwinShadeEnd(esd); - _EwinShadeEnd(esd); return 0; } void EwinShade(EWin * ewin) { - _ewin_shade_data *esd; + Animator *an; + _ewin_shade_data esd; + int duration; if ((ewin->border->border.left == 0) && (ewin->border->border.right == 0) && (ewin->border->border.top == 0) && (ewin->border->border.bottom == 0)) @@ -1036,15 +1025,17 @@ EwinShade(EWin * ewin) if ((ewin->border) && (!strcmp(ewin->border->name, "BORDERLESS"))) return; - SoundPlay(SOUND_SHADE); - - esd = EMALLOC(_ewin_shade_data, 1); - esd->ewin = ewin; - _EwinShadeStart(esd); + esd.ewin = ewin; + _EwinShadeStart(&esd); if ((Conf.shading.animate) || (ewin->type == EWIN_TYPE_MENU)) - AnimatorAdd(_EwinShadeRun, esd); + { + duration = 1000000 / Conf.shading.speed; + an = AnimatorAdd(&ewin->o, ANIM_SHADE, _EwinShadeRun, duration, 0, + sizeof(esd), &esd); + AnimatorSetSound(an, SOUND_SHADE, SOUND_NONE); + } else - _EwinShadeEnd(esd); + _EwinShadeEnd(&esd); } static void @@ -1054,9 +1045,6 @@ _EwinUnshadeStart(_ewin_shade_data * esd) int cow, coh, clx, cly; XSetWindowAttributes att; - esd->k = 0; - esd->dk = 1024 * Conf.shading.speed * Conf.animation.step / 1000000; - esd->start.x = EoGetX(ewin); esd->start.y = EoGetY(ewin); esd->start.w = EoGetW(ewin); @@ -1150,24 +1138,16 @@ _EwinUnshadeEnd(_ewin_shade_data * esd) EwinStateUpdate(ewin); HintsSetWindowState(ewin); SnapshotEwinUpdate(ewin, SNAP_USE_SHADED); - - Efree(esd); } static int -_EwinUnshadeRun(void *data) +_EwinUnshadeRun(EObj * eobj, int remaining, void *state) { - _ewin_shade_data *esd = (_ewin_shade_data *) data; - EWin *ewin = esd->ewin; + _ewin_shade_data *esd = (_ewin_shade_data *) state; + EWin *ewin = (EWin *) eobj; int k, x, y, w, h, ww, hh, cow, coh, shx, shy; - if (!EwinFindByPtr(ewin)) /* Check, window may be gone */ - { - Efree(esd); - return 0; - } - - k = esd->k; + k = 1024 - remaining; x = esd->start.x; y = esd->start.y; @@ -1224,34 +1204,35 @@ _EwinUnshadeRun(void *data) EoMoveResize(ewin, x, y, w, h); EwinBorderCalcSizes(ewin, 1); - esd->k = k += esd->dk; - if (k < 1024) - return 1; + if (remaining == 0) + _EwinUnshadeEnd(esd); - _EwinUnshadeEnd(esd); return 0; } void EwinUnShade(EWin * ewin) { - _ewin_shade_data *esd; + Animator *an; + _ewin_shade_data esd; + int duration; if (ewin->state.zoomed) return; - TIMER_DEL(ewin->timer); if (!ewin->state.shaded || ewin->state.shading || ewin->state.iconified) return; - SoundPlay(SOUND_UNSHADE); - - esd = EMALLOC(_ewin_shade_data, 1); - esd->ewin = ewin; - _EwinUnshadeStart(esd); + esd.ewin = ewin; + _EwinUnshadeStart(&esd); if ((Conf.shading.animate) || (ewin->type == EWIN_TYPE_MENU)) - AnimatorAdd(_EwinUnshadeRun, esd); + { + duration = 1000000 / Conf.shading.speed; + an = AnimatorAdd(&ewin->o, ANIM_SHADE, _EwinUnshadeRun, duration, 0, + sizeof(esd), &esd); + AnimatorSetSound(an, SOUND_UNSHADE, SOUND_NONE); + } else - _EwinUnshadeEnd(esd); + _EwinUnshadeEnd(&esd); } void @@ -1408,7 +1389,7 @@ EwinOpActivate(EWin * ewin, int source, int raise) unshade = ewin->state.shaded /* && !ewin->state.iconified */ ; - if (!ewin->state.animated && !ewin->state.iconified) + if (!ewin->state.sliding && !ewin->state.iconified) { /* If somehow lost outside desktop, move it to center */ if (!EwinIsOnDesktop(ewin)) diff --git a/src/ewins.c b/src/ewins.c index 0d6d11d2..ee0239a2 100644 --- a/src/ewins.c +++ b/src/ewins.c @@ -38,7 +38,6 @@ #include "screen.h" #include "slide.h" #include "snaps.h" -#include "timers.h" #include "windowmatch.h" #include "xwin.h" #include @@ -57,8 +56,6 @@ /* StructureNotifyMask | */ ResizeRedirectMask | \ PropertyChangeMask | ColormapChangeMask | VisibilityChangeMask) -static int EwinSlideIn(void *data); - static void EwinChangesStart(EWin * ewin); static void EwinChangesProcess(EWin * ewin); @@ -989,14 +986,15 @@ AddToFamily(EWin * ewin, Window xwin, int startup) fx = WinGetW(VROOT); fy = (rand() % (WinGetH(VROOT))) - EoGetH(ewin); } - ewin->state.animated = 1; - FocusEnable(0); EwinMoveToDesktopAt(ewin, dsk, fx, fy); EwinShow(ewin); ewin->req_x = x; ewin->req_y = y; - TIMER_ADD_NP(50, EwinSlideIn, ewin); + + EwinSlideTo(ewin, EoGetX(ewin), EoGetY(ewin), ewin->req_x, ewin->req_y, + Conf.place.slidespeedmap, Conf.place.slidemode, + SLIDE_FOCUS | SLIDE_WARP | SLIDE_SOUND); } else { @@ -1986,27 +1984,6 @@ EwinUpdateOpacity(EWin * ewin) EoChangeOpacity(ewin, opacity); } -/* - * Slidein - */ -static int -EwinSlideIn(void *data) -{ - EWin *ewin = (EWin *) data; - - /* May be gone */ - if (!EwinFindByPtr(ewin)) - goto done; - - EwinSlideTo(ewin, EoGetX(ewin), EoGetY(ewin), ewin->req_x, ewin->req_y, - Conf.place.slidespeedmap, Conf.place.slidemode, 0); - - done: - FocusEnable(1); - - return 0; -} - /* * Change requests */ diff --git a/src/ewins.h b/src/ewins.h index 584f13ee..5273102a 100644 --- a/src/ewins.h +++ b/src/ewins.h @@ -100,7 +100,7 @@ struct _ewin { unsigned attention:1; unsigned showingdesk:1; /* Iconified by show desktop */ - unsigned animated:1; + unsigned sliding:1; unsigned moving:1; unsigned resizing:1; unsigned show_coords:1; @@ -246,6 +246,7 @@ struct _ewin { int shape_x, shape_y, shape_w, shape_h; int req_x, req_y; + int trg_x, trg_y; /* Used during desk slides */ Snapshot *snap; int head; /* Unused? */ diff --git a/src/fx.c b/src/fx.c index 77d88a90..1f7bced2 100644 --- a/src/fx.c +++ b/src/fx.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2011 Kim Woelders + * Copyright (C) 2004-2012 Kim Woelders * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -22,13 +22,13 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "desktops.h" #include "dialog.h" #include "ecompmgr.h" #include "eimage.h" #include "emodule.h" #include "settings.h" -#include "timers.h" #include "xwin.h" #include @@ -69,10 +69,10 @@ typedef struct { static Pixmap fx_ripple_above = None; static Win fx_ripple_win = NULL; static int fx_ripple_count = 0; -static Timer *fx_ripple_timer = NULL; static int -FX_ripple_timeout(void *data __UNUSED__) +FX_ripple_timeout(EObj * eo __UNUSED__, int remaining __UNUSED__, + void *state __UNUSED__) { static double incv = 0, inch = 0; static GC gc1 = 0, gc = 0; @@ -131,14 +131,14 @@ FX_ripple_timeout(void *data __UNUSED__) WinGetH(VROOT) - fx_ripple_waterh + y); } - return 1; + return 4; } static void FX_Ripple_Init(const char *name __UNUSED__) { fx_ripple_count = 0; - TIMER_ADD(fx_ripple_timer, 66, FX_ripple_timeout, NULL); + AnimatorAdd(NULL, ANIM_FX_RIPPLES, FX_ripple_timeout, -1, 0, 0, NULL); } static void @@ -152,7 +152,7 @@ FX_Ripple_Desk(void) static void FX_Ripple_Quit(void) { - TIMER_DEL(fx_ripple_timer); + AnimatorsDelCatAll(ANIM_FX_RIPPLES, 0); if (!fx_ripple_win) return; EClearArea(fx_ripple_win, 0, WinGetH(VROOT) - fx_ripple_waterh, @@ -172,10 +172,10 @@ FX_Ripple_Quit(void) static Pixmap fx_wave_above = None; static Win fx_wave_win = NULL; static int fx_wave_count = 0; -static Timer *fx_wave_timer = NULL; static int -FX_Wave_timeout(void *data __UNUSED__) +FX_Wave_timeout(EObj * eo __UNUSED__, int remaining __UNUSED__, + void *state __UNUSED__) { /* Variables */ static double incv = 0, inch = 0; @@ -282,14 +282,14 @@ FX_Wave_timeout(void *data __UNUSED__) } } - return 1; + return 4; } static void FX_Waves_Init(const char *name __UNUSED__) { fx_wave_count = 0; - TIMER_ADD(fx_wave_timer, 66, FX_Wave_timeout, NULL); + AnimatorAdd(NULL, ANIM_FX_WAVES, FX_Wave_timeout, -1, 0, 0, NULL); } static void @@ -303,7 +303,7 @@ FX_Waves_Desk(void) static void FX_Waves_Quit(void) { - TIMER_DEL(fx_wave_timer); + AnimatorsDelCatAll(ANIM_FX_WAVES, 0); if (!fx_wave_win) return; EClearArea(fx_wave_win, 0, WinGetH(VROOT) - FX_WAVE_WATERH, @@ -324,7 +324,6 @@ FX_Waves_Quit(void) static Win fx_raindrops_win = NULL; static int fx_raindrops_number = 4; static PixImg *fx_raindrops_draw = NULL; -static Timer *fx_raindrops_timer = NULL; typedef struct { int x, y; @@ -335,7 +334,8 @@ typedef struct { static DropContext fx_raindrops[4]; static int -FX_raindrops_timeout(void *data __UNUSED__) +FX_raindrops_timeout(EObj * eo __UNUSED__, int remaining __UNUSED__, + void *state __UNUSED__) { static GC gc1 = 0, gc = 0; int i, x, y, xx, yy; @@ -526,7 +526,7 @@ FX_raindrops_timeout(void *data __UNUSED__) ESync(0); } - return 1; + return 4; } static void @@ -541,7 +541,7 @@ FX_Raindrops_Init(const char *name __UNUSED__) fx_raindrops[i].x = rand() % (WinGetW(VROOT) - fx_raindrop_size); fx_raindrops[i].y = rand() % (WinGetH(VROOT) - fx_raindrop_size); } - TIMER_ADD(fx_raindrops_timer, 66, FX_raindrops_timeout, NULL); + AnimatorAdd(NULL, ANIM_FX_RAINDROPS, FX_raindrops_timeout, -1, 0, 0, NULL); } static void @@ -555,7 +555,7 @@ FX_Raindrops_Quit(void) { int i; - TIMER_DEL(fx_raindrops_timer); + AnimatorsDelCatAll(ANIM_FX_RAINDROPS, 0); for (i = 0; i < fx_raindrops_number; i++) { EClearArea(fx_raindrops_win, fx_raindrops[i].x, fx_raindrops[i].y, @@ -579,10 +579,10 @@ FX_Raindrops_Quit(void) static Win fx_imagespinner_win = NULL; static int fx_imagespinner_count = 3; static char *fx_imagespinner_params = NULL; -static Timer *fx_imagespinner_timer = NULL; static int -FX_imagespinner_timeout(void *data __UNUSED__) +FX_imagespinner_timeout(EObj * eo __UNUSED__, int remaining __UNUSED__, + void *state __UNUSED__) { char *string = NULL; EObj *bgeo; @@ -624,14 +624,14 @@ FX_imagespinner_timeout(void *data __UNUSED__) Efree(string); } - return 1; + return 4; } static void FX_ImageSpinner_Init(const char *name) { fx_imagespinner_count = 3; - TIMER_ADD(fx_imagespinner_timer, 66, FX_imagespinner_timeout, NULL); + AnimatorAdd(NULL, ANIM_FX_SPINNER, FX_imagespinner_timeout, -1, 0, 0, NULL); fx_imagespinner_params = Estrdup(name); } @@ -647,7 +647,7 @@ FX_ImageSpinner_Desk(void) static void FX_ImageSpinner_Quit(void) { - TIMER_DEL(fx_imagespinner_timer); + AnimatorsDelCatAll(ANIM_FX_SPINNER, 0); EClearArea(fx_imagespinner_win, 0, 0, WinGetW(VROOT), WinGetH(VROOT)); Efree(fx_imagespinner_params); fx_imagespinner_params = NULL; diff --git a/src/glwin.c b/src/glwin.c index fcef2f13..2e7a3283 100644 --- a/src/glwin.c +++ b/src/glwin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2011 Kim Woelders + * Copyright (C) 2007-2012 Kim Woelders * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -21,6 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "cursors.h" #include "desktops.h" #include "eimage.h" @@ -30,7 +31,6 @@ #include "events.h" #include "ewins.h" #include "grabs.h" -#include "timers.h" #include "util.h" #include @@ -464,7 +464,8 @@ SceneDraw(void) } static int -GlwinRun(void *data __UNUSED__) +GlwinRun(EObj * eobj __UNUSED__, int remaining __UNUSED__, + void *state __UNUSED__) { if (!GLWin.eo) return 0; @@ -606,7 +607,7 @@ GlwinEvent(Win win __UNUSED__, XEvent * ev, void *prm) #endif case MapNotify: GlwinKeyPress(gw, XK_g); - AnimatorAdd(GlwinRun, NULL); + AnimatorAdd(GLWin.eo, ANIM_GLWIN, GlwinRun, -1, 0, 0, NULL); break; #if 0 case ConfigureNotify: diff --git a/src/magwin.c b/src/magwin.c index be7fee3c..eeaf89d7 100644 --- a/src/magwin.c +++ b/src/magwin.c @@ -21,6 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "cursors.h" #include "ecompmgr.h" #include "eimage.h" @@ -31,7 +32,6 @@ #include "grabs.h" #include "hints.h" #include "tclass.h" -#include "timers.h" #include "util.h" #include @@ -193,10 +193,6 @@ _MagwinUpdate(MagWindow * mw) if (mw != MagWin) return 0; - /* Validate ewin */ - if (!EwinFindByPtr(mw->ewin)) - return 0; - /* When switching CM off do a delayed repaint. This will catch up on * at least some clients having processed expose events. */ if (Mode.events.damage_count == 0 && mw->damage_count != 0) @@ -221,11 +217,9 @@ _MagwinUpdate(MagWindow * mw) } static int -_MagwinAnimator(void *data) +_MagwinAnimator(EObj * eobj, int remaining __UNUSED__, void *state __UNUSED__) { - MagWindow *mw = (MagWindow *) data; - - return _MagwinUpdate(mw); + return _MagwinUpdate((MagWindow *) ((EWin *) eobj)->data); } static void @@ -408,7 +402,8 @@ MagwinEvent(Win win __UNUSED__, XEvent * ev, void *prm) break; mw->configured = 1; _MagwinGrabSet(mw); - AnimatorAdd(_MagwinAnimator, mw); + AnimatorAdd(EoObj(mw->ewin), ANIM_LAZY_MAGWIN, _MagwinAnimator, + -1, 0, 0, NULL); break; } diff --git a/src/menus.c b/src/menus.c index ee9950d7..0093912f 100644 --- a/src/menus.c +++ b/src/menus.c @@ -22,6 +22,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "borders.h" #include "desktops.h" #include "dialog.h" @@ -1415,6 +1416,37 @@ _SubmenuGetPlacement(Menu * m, int *xo, int *yo, int *mw, int *mh) *mh = mi->child->h + bt2 + bb2; } +static void +_SubmenuSlideDone(EObj * eo, void *data __UNUSED__) +{ + EWin *ewin, *ewin2; + Menu *m; + MenuItem *mi; + + MenusSetEvents(1); + + ewin = (EWin *) eo; + if (!EwinFindByPtr(ewin)) + return; + m = (Menu *) ewin->data; + if (!m) + return; + mi = m->sel_item; + if (!mi) + return; + + if (Conf.menus.warp) + EWarpPointer(mi->win, WinGetW(mi->win) / 2, WinGetH(mi->win) / 2); + + if (!mi->child) + return; + ewin2 = mi->child->ewin; + if (!EwinFindByPtr(ewin2)) + return; + + _MenuEwinShow(ewin2); +} + static void _MenusSlideCheck(Menu * m, int xo, int yo, int ww, int hh, int *pdx, int *pdy) { @@ -1457,7 +1489,7 @@ _MenusSlide(Menu * m, int xdist, int ydist) int fx[256], fy[256], tx[256], ty[256]; int i; Menu *mm; - MenuItem *mi; + Animator *an; i = 0; for (mm = Mode_menus.first; mm; mm = mm->child) @@ -1474,12 +1506,9 @@ _MenusSlide(Menu * m, int xdist, int ydist) } MenusSetEvents(0); /* Disable menu item events while sliding */ - EwinsSlideTo(menus, fx, fy, tx, ty, i, Conf.shading.speed, 0, 0); - MenusSetEvents(1); - - mi = m->sel_item; - if (mi && Conf.menus.warp) - EWarpPointer(mi->win, WinGetW(mi->win) / 2, WinGetH(mi->win) / 2); + an = EwinsSlideTo(menus, fx, fy, tx, ty, i, Conf.shading.speed, 0, + SLIDE_SOUND); + AnimatorSetDoneFunc(an, _SubmenuSlideDone); } static int @@ -1527,7 +1556,7 @@ SubmenuShowTimeout(void *data) MRF_NOCHECK_ONSCREEN); if (xdist != 0 || ydist != 0) _MenusSlide(m, xdist, ydist); - if (ewin2) + else if (ewin2) _MenuEwinShow(ewin2); done: diff --git a/src/misc.c b/src/misc.c index e9e890ba..78dc8a33 100644 --- a/src/misc.c +++ b/src/misc.c @@ -97,77 +97,6 @@ Quicksort(void **a, int l, int r, } } -/* - * Stuff to make loops for animated effects. - */ -static unsigned int etl_t_start; -static int etl_k1, etl_k2; -static double etl_k, etl_fac; - -#include - -static float -ETimeCurve(int k1, int k2, float k, int mode) -{ - float x, l; - - if (k >= k2 || mode == 0) - return k; - - l = k2 - k1; - x = k - k1; - - switch (mode) - { - case 1: /* Sinuoidal - half cycle */ - x = x / l - 0.5; /* x: -0.5 -> 0.5 */ - x = (float)(0.5 * (1. + sin(x * M_PI))); - break; - case 2: /* Sinuoidal - quarter cycle */ - x = x / l; /* x: 0 -> 1 */ - x = (float)sin(x * M_PI / 2); - break; - } - - return k1 + x * l; -} - -void -ETimedLoopInit(int k1, int k2, int speed) -{ - etl_k1 = k1; - etl_k2 = k2; - if (speed < 500) - speed = 500; - /* When speed is 1000 the loop will take one sec. */ - etl_fac = (k2 - k1) * (double)speed / 1000.; - - etl_t_start = GetTimeMs(); - - ESync(ESYNC_TLOOP); -} - -int -ETimedLoopNext(void) -{ - double tm, y; - - /* Is this portable? */ - usleep(5000); - - /* Find elapsed time since loop start */ - tm = 1e-3 * (GetTimeMs() - etl_t_start); - etl_k = etl_k1 + tm * etl_fac; -#if 0 - Eprintf("ETimedLoopNext k=%4f tm=%.3f\n", etl_k, tm); -#endif - y = ETimeCurve(etl_k1, etl_k2, (float)etl_k, 2); - - EobjsRepaint(); - - return (int)y; -} - /* * Debug/error message printing. */ diff --git a/src/slide.c b/src/slide.c index 29983e21..360a0c6f 100644 --- a/src/slide.c +++ b/src/slide.c @@ -21,6 +21,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "eobj.h" #include "ewins.h" #include "focus.h" @@ -31,172 +32,168 @@ * EObj sliding functions */ -void -EobjsSlideBy(EObj ** peo, int num, int dx, int dy, int speed) +typedef struct { + int fx, fy, fw, fh; + int tx, ty, tw, th; +} eobj_slide_params; + +static int +_EobjSlideSizeTo(EObj * eo, int remaining, void *state) { - int i, k, x, y; - struct _xy { - int x, y; - } *xy; + eobj_slide_params *params = (eobj_slide_params *) state; + int k = 1024 - remaining, x, y, w, h; - if (num <= 0) - return; + x = ((params->fx * (1024 - k)) + (params->tx * k)) >> 10; + y = ((params->fy * (1024 - k)) + (params->ty * k)) >> 10; + w = ((params->fw * (1024 - k)) + (params->tw * k)) >> 10; + h = ((params->fh * (1024 - k)) + (params->th * k)) >> 10; + EobjMoveResize(eo, x, y, w, h); - xy = EMALLOC(struct _xy, num); - if (!xy) - return; - - for (i = 0; i < num; i++) - { - xy[i].x = EobjGetX(peo[i]); - xy[i].y = EobjGetY(peo[i]); - } - - ETimedLoopInit(0, 1024, speed); - for (k = 0; k <= 1024;) - { - for (i = 0; i < num; i++) - { - x = ((xy[i].x * (1024 - k)) + ((xy[i].x + dx) * k)) >> 10; - y = ((xy[i].y * (1024 - k)) + ((xy[i].y + dy) * k)) >> 10; - EobjMove(peo[i], x, y); - } - - k = ETimedLoopNext(); - } - - for (i = 0; i < num; i++) - EobjMove(peo[i], xy[i].x + dx, xy[i].y + dy); - - Efree(xy); + return 0; } void EobjSlideSizeTo(EObj * eo, int fx, int fy, int tx, int ty, int fw, int fh, int tw, int th, int speed) { - int k, x, y, w, h; + eobj_slide_params params; + int duration; - ETimedLoopInit(0, 1024, speed); - for (k = 0; k <= 1024;) - { - x = ((fx * (1024 - k)) + (tx * k)) >> 10; - y = ((fy * (1024 - k)) + (ty * k)) >> 10; - w = ((fw * (1024 - k)) + (tw * k)) >> 10; - h = ((fh * (1024 - k)) + (th * k)) >> 10; - EobjMoveResize(eo, x, y, w, h); + params.fx = fx; + params.fy = fy; + params.fw = fw; + params.fh = fh; + params.tx = tx; + params.ty = ty; + params.tw = tw; + params.th = th; - k = ETimedLoopNext(); - } - EobjMoveResize(eo, tx, ty, tw, th); + if (speed <= 10) + speed = 10; + duration = 1000000 / speed; + + AnimatorAdd(eo, ANIM_SLIDE, _EobjSlideSizeTo, duration, 1, + sizeof(params), ¶ms); } /* * EWin sliding functions */ -void -EwinSlideSizeTo(EWin * ewin, int tx, int ty, int tw, int th, - int speed, int mode __UNUSED__, int flags __UNUSED__) +typedef struct { + int fx, fy, fw, fh; + int tx, ty, tw, th; + int mode; + char mouse_warp; + char give_focus; + int mouse_x; + int mouse_y; +} ewin_slide_params; + +static int +_EwinSlideSizeTo(EObj * eo, int remaining, void *state) { - int k, x, y, w, h; - int fx, fy, fw, fh, warp; + ewin_slide_params *params = (ewin_slide_params *) state; + EWin *ewin = (EWin *) eo; + int k = 1024 - remaining, x, y, w, h; - warp = (ewin == GetEwinPointerInClient()); + x = ((params->fx * (1024 - k)) + (params->tx * k)) >> 10; + y = ((params->fy * (1024 - k)) + (params->ty * k)) >> 10; + w = ((params->fw * (1024 - k)) + (params->tw * k)) >> 10; + h = ((params->fh * (1024 - k)) + (params->th * k)) >> 10; - if (Conf.movres.maximize_animate) - { - fx = EoGetX(ewin); - fy = EoGetY(ewin); - fw = ewin->client.w; - fh = ewin->client.h; + EwinMoveResize(ewin, x, y, w, h, MRF_KEEP_MAXIMIZED); + EwinShapeSet(ewin); - ETimedLoopInit(0, 1024, speed); - for (k = 0; k <= 1024;) - { - x = ((fx * (1024 - k)) + (tx * k)) >> 10; - y = ((fy * (1024 - k)) + (ty * k)) >> 10; - w = ((fw * (1024 - k)) + (tw * k)) >> 10; - h = ((fh * (1024 - k)) + (th * k)) >> 10; - EwinMoveResize(ewin, x, y, w, h, MRF_KEEP_MAXIMIZED); - - k = ETimedLoopNext(); - } - } - - EwinMoveResize(ewin, tx, ty, tw, th, MRF_KEEP_MAXIMIZED); - - if (warp && ewin != GetEwinPointerInClient()) + if (params->mouse_warp) { EwinWarpTo(ewin, 1); - FocusToEWin(ewin, FOCUS_SET); + EWarpPointer(EoGetWin(ewin), params->mouse_x, params->mouse_y); } + + if (!remaining) + { + ewin->state.sliding = 0; + if (params->give_focus) + { + FocusToEWin(ewin, FOCUS_SET); + } + } + + return 0; } -void -EwinSlideTo(EWin * ewin, int fx, int fy, int tx, int ty, +Animator * +EwinSlideSizeTo(EWin * ewin, int tx, int ty, int tw, int th, + int speed, int mode, int flags) +{ + Animator *an; + ewin_slide_params params; + int duration; + esound_e start_sound = SOUND_NONE; + esound_e end_sound = SOUND_NONE; + + ewin->state.sliding = 1; + + params.fx = EoGetX(ewin); + params.fy = EoGetY(ewin); + params.fw = ewin->client.w; + params.fh = ewin->client.h; + params.tx = tx; + params.ty = ty; + params.tw = tw; + params.th = th; + params.mode = mode; + params.give_focus = (flags & SLIDE_FOCUS) != 0; + params.mouse_warp = ((flags & SLIDE_WARP) != 0) && + ((params.fx != params.tx) || (params.fy != params.ty)) && + (ewin == GetEwinPointerInClient()); + EQueryPointer(EoGetWin(ewin), ¶ms.mouse_x, ¶ms.mouse_y, NULL, NULL); + + if (params.mouse_x > tw) + params.mouse_x = tw / 2; + if (params.mouse_y > th) + params.mouse_y = th / 2; + + if (flags & SLIDE_SOUND) + { + start_sound = SOUND_WINDOW_SLIDE; + end_sound = SOUND_WINDOW_SLIDE_END; + } + + if (speed <= 10) + speed = 10; + duration = 1000000 / speed; + + an = AnimatorAdd((EObj *) ewin, ANIM_SLIDE, _EwinSlideSizeTo, duration, 0, + sizeof(params), ¶ms); + AnimatorSetSound(an, start_sound, end_sound); + + return an; +} + +Animator * +EwinSlideTo(EWin * ewin, int fx __UNUSED__, int fy __UNUSED__, int tx, int ty, int speed, int mode, int flags) { - EwinsSlideTo(&ewin, &fx, &fy, &tx, &ty, 1, speed, mode, flags); +// EwinMove(ewin, fx, fy, 0); // FIXME - WHY? + return EwinSlideSizeTo(ewin, tx, ty, ewin->client.w, ewin->client.h, + speed, mode, flags); } -void +Animator * EwinsSlideTo(EWin ** ewin, int *fx, int *fy, int *tx, int *ty, int num_wins, - int speed, int mode, int flags __UNUSED__) + int speed, int mode, int flags) { - int k, x, y, w, h, i; - char firstlast, grab_server; - - if (num_wins <= 0) - return; - - firstlast = 0; - FocusEnable(0); - SoundPlay(SOUND_WINDOW_SLIDE); - - grab_server = DrawEwinShapeNeedsGrab(mode); - if (grab_server) - EGrabServer(); - - ETimedLoopInit(0, 1024, speed); - for (k = 0; k <= 1024;) - { - for (i = 0; i < num_wins; i++) - { - if (!ewin[i]) - continue; - - x = ((fx[i] * (1024 - k)) + (tx[i] * k)) >> 10; - y = ((fy[i] * (1024 - k)) + (ty[i] * k)) >> 10; - w = ewin[i]->client.w; - h = ewin[i]->client.h; - if (mode == 0) - EoMove(ewin[i], x, y); - else - DrawEwinShape(ewin[i], mode, x, y, w, h, firstlast, i); - firstlast = 1; - } - /* We may loop faster here than originally intended */ - k = ETimedLoopNext(); - } + Animator *an = NULL; + int i; for (i = 0; i < num_wins; i++) { - if (!ewin[i]) - continue; - - ewin[i]->state.animated = 0; - - if (mode > 0) - DrawEwinShape(ewin[i], mode, tx[i], ty[i], ewin[i]->client.w, - ewin[i]->client.h, 2, i); - EwinMove(ewin[i], tx[i], ty[i], MRF_NOCHECK_ONSCREEN); + an = + EwinSlideTo(ewin[i], fx[i], fy[i], tx[i], ty[i], speed, mode, flags); + flags |= SLIDE_SOUND; } - FocusEnable(1); - - if (grab_server) - EUngrabServer(); - - SoundPlay(SOUND_WINDOW_SLIDE_END); + return an; } diff --git a/src/slide.h b/src/slide.h index fd81a890..e2cb4bcc 100644 --- a/src/slide.h +++ b/src/slide.h @@ -28,19 +28,17 @@ void EobjSlideSizeTo(EObj * eo, int fx, int fy, int tx, int ty, int fw, int fh, int tw, int th, int speed); -void EobjsSlideBy(EObj ** peo, int num, int dx, int dy, - int speed); #define SLIDE_SOUND (1 << 0) #define SLIDE_FOCUS (1 << 1) #define SLIDE_WARP (1 << 2) -void EwinSlideSizeTo(EWin * ewin, int tx, int ty, +Animator *EwinSlideSizeTo(EWin * ewin, int tx, int ty, int tw, int th, int speed, int mode, int flags); -void EwinSlideTo(EWin * ewin, int fx, int fy, int tx, int ty, +Animator *EwinSlideTo(EWin * ewin, int fx, int fy, int tx, int ty, int speed, int mode, int flags); -void EwinsSlideTo(EWin ** ewin, int *fx, int *fy, +Animator *EwinsSlideTo(EWin ** ewin, int *fx, int *fy, int *tx, int *ty, int num_wins, int speed, int mode, int flags); diff --git a/src/startup.c b/src/startup.c index ba278ae1..22965217 100644 --- a/src/startup.c +++ b/src/startup.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2009 Kim Woelders + * Copyright (C) 2004-2012 Kim Woelders * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -22,10 +22,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" +#include "animation.h" #include "backgrounds.h" #include "eobj.h" #include "iclass.h" -#include "timers.h" #include "xwin.h" static EObj *init_win1 = NULL; @@ -122,12 +122,12 @@ StartupBackgroundsDestroy(void) } static int -doStartupWindowsOpen(void *data __UNUSED__) +doStartupWindowsOpen(EObj * eobj __UNUSED__, int remaining, + void *state __UNUSED__) { - static int kk = 0; int k, x, y, xOffset, yOffset; - k = kk; + k = 1024 - remaining; if (bg_sideways) { /* so we can have two different slide methods */ @@ -147,12 +147,8 @@ doStartupWindowsOpen(void *data __UNUSED__) EobjMove(init_win1, -x - xOffset, -y - yOffset); EobjMove(init_win2, x + xOffset, y + yOffset); - k = (int)(1e-3 * Conf.animation.step * Conf.desks.slidespeed / 2); - if (k <= 0) - k = 1; - kk += k; - if (kk < 1024) - return 1; + if (remaining > 0) + return 0; Mode.place.enable_features++; EobjWindowDestroy(init_win1); @@ -160,16 +156,22 @@ doStartupWindowsOpen(void *data __UNUSED__) init_win1 = NULL; init_win2 = NULL; - return 0; + return ANIM_RET_CANCEL_ANIM; } void StartupWindowsOpen(void) { + int speed, duration; + if (!init_win1 || !init_win2) return; Mode.place.enable_features--; ESync(ESYNC_STARTUP); - AnimatorAdd(doStartupWindowsOpen, NULL); + + speed = Conf.desks.slidespeed > 0 ? Conf.desks.slidespeed : 500; + duration = 2000000 / speed; + + AnimatorAdd(NULL, ANIM_STARTUP, doStartupWindowsOpen, duration, 0, 0, NULL); } diff --git a/src/timers.c b/src/timers.c index 30f08996..cd19e06d 100644 --- a/src/timers.c +++ b/src/timers.c @@ -273,115 +273,3 @@ IdlersRun(void) if (EDebug(EDBUG_TYPE_IDLERS)) Eprintf("%s E\n", __func__); } - -/* - * Animators - */ -#define DEBUG_ANIMATORS 0 -static Ecore_List *animator_list = NULL; -static Timer *animator_timer = NULL; - -typedef int (AnimatorFunc) (void *data); - -struct _animator { - AnimatorFunc *func; - void *data; -}; - -static void -_AnimatorRun(void *_an, void *prm __UNUSED__) -{ - Animator *an = (Animator *) _an; - int again; - -#if DEBUG_ANIMATORS > 2 - Eprintf("%s: %p\n", __func__, an); -#endif - again = an->func(an->data); - if (!again) - AnimatorDel(an); -} - -static int -AnimatorsRun(void *data __UNUSED__) -{ - static unsigned int tms_last = 0; - unsigned int dt_ms; - - dt_ms = Mode.events.time_ms - tms_last; - if (2 * dt_ms < Conf.animation.step) - { -#if DEBUG_ANIMATORS > 1 - Eprintf("%s: dt=%.3f - SKIP\n", __func__, 1e-3f * dt_ms); -#endif - return 1; - } - - ecore_list_for_each(animator_list, _AnimatorRun, NULL); - -#if DEBUG_ANIMATORS > 1 - Eprintf("%s: dt=%.3f run=%.3f\n", __func__, 1e-3f * dt_ms, - 1e-3f * (GetTimeMs() - Mode.events.time_ms)); -#endif - - tms_last = Mode.events.time_ms; - - if (ecore_list_count(animator_list)) - { - TimerSetInterval(animator_timer, Conf.animation.step); - return 1; - } - else - { - animator_timer = NULL; - return 0; - } -} - -Animator * -AnimatorAdd(AnimatorFunc * func, void *data) -{ - Animator *an; - - an = EMALLOC(Animator, 1); - if (!an) - return NULL; - -#if DEBUG_ANIMATORS - Eprintf("%s: %p func=%p data=%p\n", __func__, an, func, data); -#endif - an->func = func; - an->data = data; - - if (!animator_list) - animator_list = ecore_list_new(); - - ecore_list_append(animator_list, an); - - if (ecore_list_count(animator_list) == 1) - { - if (Conf.animation.step <= 0) - Conf.animation.step = 1; - /* Animator list was empty - Add to timer qeueue */ - TIMER_ADD(animator_timer, Conf.animation.step, AnimatorsRun, NULL); - } - - return an; -} - -void -AnimatorDel(Animator * an) -{ -#if DEBUG_ANIMATORS - Eprintf("%s: %p func=%p data=%p\n", __func__, an, an->func, an->data); -#endif - - ecore_list_node_remove(animator_list, an); - Efree(an); - - if (ecore_list_count(animator_list) == 0) - { - /* Animator list is empty - Remove from timer qeueue */ - TIMER_DEL(animator_timer); - } -} diff --git a/src/timers.h b/src/timers.h index ad386b72..74d713b0 100644 --- a/src/timers.h +++ b/src/timers.h @@ -43,7 +43,4 @@ Idler *IdlerAdd(void (*func) (void *data), void *data); void IdlerDel(Idler * id); void IdlersRun(void); -Animator *AnimatorAdd(int (*func) (void *data), void *data); -void AnimatorDel(Animator * an); - #endif /* _TIMERS_H_ */