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
This commit is contained in:
Kim Woelders 2012-12-09 10:03:07 +00:00
parent 0543c3d9ae
commit 51a19d26e7
21 changed files with 1044 additions and 561 deletions

View File

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

View File

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

494
src/animation.c Normal file
View File

@ -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 <math.h>
#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;
}

94
src/animation.h Normal file
View File

@ -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_ */

View File

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

View File

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

View File

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

View File

@ -60,6 +60,7 @@ struct _eobj {
#if USE_GLX
struct _glhook *glhook;
#endif
Animator *animations; /* list of pending animations */
};
#define EOBJ_TYPE_EWIN 0

View File

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

View File

@ -38,7 +38,6 @@
#include "screen.h"
#include "slide.h"
#include "snaps.h"
#include "timers.h"
#include "windowmatch.h"
#include "xwin.h"
#include <X11/Xutil.h>
@ -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
*/

View File

@ -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? */

View File

@ -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 <math.h>
@ -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;

View File

@ -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 <math.h>
@ -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:

View File

@ -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 <math.h>
@ -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;
}

View File

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

View File

@ -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 <math.h>
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.
*/

View File

@ -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), &params);
}
/*
* 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), &params.mouse_x, &params.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), &params);
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;
}

View File

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

View File

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

View File

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

View File

@ -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_ */