Rudimentary animation system
This is actually the same as the animation system from the old compositor, but with some added bits for damage rects.
This commit is contained in:
parent
e8bd8fa6fa
commit
48e0ddd99e
@ -297,6 +297,8 @@ static yutani_server_window_t * server_window_create(yutani_globals_t * yg, int
|
||||
win->rotation = 0;
|
||||
win->newbufid = 0;
|
||||
win->name = NULL;
|
||||
win->anim_mode = YUTANI_EFFECT_FADE_IN;
|
||||
win->anim_start = yg->tick_count;
|
||||
|
||||
char key[1024];
|
||||
YUTANI_SHMKEY(key, 1024, win);
|
||||
@ -534,10 +536,51 @@ static int yutani_blit_window(yutani_globals_t * yg, yutani_server_window_t * wi
|
||||
cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_FAST);
|
||||
}
|
||||
}
|
||||
if (window->anim_mode) {
|
||||
int frame = yg->tick_count - window->anim_start;
|
||||
if (frame >= yutani_animation_lengths[window->anim_mode]) {
|
||||
/* XXX handle animation-end things like cleanup of closing windows */
|
||||
if (window->anim_mode == YUTANI_EFFECT_FADE_OUT) {
|
||||
window_actually_close(yg, window);
|
||||
goto draw_finish;
|
||||
}
|
||||
window->anim_mode = 0;
|
||||
window->anim_start = 0;
|
||||
goto draw_window;
|
||||
} else {
|
||||
switch (window->anim_mode) {
|
||||
case YUTANI_EFFECT_FADE_OUT:
|
||||
{
|
||||
frame = 256 - frame;
|
||||
}
|
||||
case YUTANI_EFFECT_FADE_IN:
|
||||
{
|
||||
double x = 0.75 + ((double)frame / 256.0) * 0.25;
|
||||
int t_x = (window->width * (1.0 - x)) / 2;
|
||||
int t_y = (window->height * (1.0 - x)) / 2;
|
||||
|
||||
/* Paint window */
|
||||
cairo_set_source_surface(cr, surf, 0, 0);
|
||||
cairo_paint(cr);
|
||||
if (!window_is_top(yg, window) && !window_is_bottom(yg, window)) {
|
||||
cairo_translate(cr, t_x, t_y);
|
||||
cairo_scale(cr, x, x);
|
||||
}
|
||||
|
||||
cairo_set_source_surface(cr, surf, 0, 0);
|
||||
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);
|
||||
cairo_paint_with_alpha(cr, (double)frame/256.0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
draw_window:
|
||||
/* Paint window */
|
||||
cairo_set_source_surface(cr, surf, 0, 0);
|
||||
cairo_paint(cr);
|
||||
}
|
||||
|
||||
draw_finish:
|
||||
|
||||
/* Clean up */
|
||||
cairo_surface_destroy(surf);
|
||||
@ -636,6 +679,17 @@ static void redraw_windows(yutani_globals_t * yg) {
|
||||
yg->last_mouse_x = tmp_mouse_x;
|
||||
yg->last_mouse_y = tmp_mouse_y;
|
||||
|
||||
yg->tick_count += 10;
|
||||
|
||||
for (unsigned int i = 0; i <= YUTANI_ZORDER_MAX; ++i) {
|
||||
yutani_server_window_t * w = yg->zlist[i];
|
||||
if (w) {
|
||||
if (w->anim_mode > 0) {
|
||||
mark_window(yg,w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate damage regions from currently queued updates */
|
||||
spin_lock(&yg->update_list_lock);
|
||||
while (yg->update_list->length) {
|
||||
@ -823,6 +877,28 @@ static void mark_region(yutani_globals_t * yg, int x, int y, int width, int heig
|
||||
spin_unlock(&yg->update_list_lock);
|
||||
}
|
||||
|
||||
static void window_mark_for_close(yutani_globals_t * yg, yutani_server_window_t * w) {
|
||||
w->anim_mode = YUTANI_EFFECT_FADE_OUT;
|
||||
w->anim_start = yg->tick_count;
|
||||
}
|
||||
|
||||
static void window_actually_close(yutani_globals_t * yg, yutani_server_window_t * w) {
|
||||
/* XXX free window */
|
||||
hashmap_remove(yg->wids_to_windows, (void *)w->wid);
|
||||
list_remove(yg->windows, list_index_of(yg->windows, w));
|
||||
mark_window(yg, w);
|
||||
unorder_window(yg, w);
|
||||
if (w == yg->focused_window) {
|
||||
yg->focused_window = NULL;
|
||||
}
|
||||
yutani_msg_t * response = yutani_msg_build_notify();
|
||||
foreach(node, yg->window_subscribers) {
|
||||
uint32_t subscriber = (uint32_t)node->value;
|
||||
pex_send(yg->server, subscriber, response->size, (char *)response);
|
||||
}
|
||||
free(response);
|
||||
}
|
||||
|
||||
static void handle_key_event(yutani_globals_t * yg, struct yutani_msg_key_event * ke) {
|
||||
yutani_server_window_t * focused = get_focused(yg);
|
||||
memcpy(&yg->kbd_state, &ke->state, sizeof(key_event_state_t));
|
||||
@ -1159,20 +1235,7 @@ int main(int argc, char * argv[]) {
|
||||
struct yutani_msg_window_close * wc = (void *)m->data;
|
||||
yutani_server_window_t * w = hashmap_get(yg->wids_to_windows, (void *)wc->wid);
|
||||
if (w) {
|
||||
/* XXX free window */
|
||||
hashmap_remove(yg->wids_to_windows, (void *)wc->wid);
|
||||
list_remove(yg->windows, list_index_of(yg->windows, w));
|
||||
mark_window(yg, w);
|
||||
unorder_window(yg, w);
|
||||
if (w == yg->focused_window) {
|
||||
yg->focused_window = NULL;
|
||||
}
|
||||
yutani_msg_t * response = yutani_msg_build_notify();
|
||||
foreach(node, yg->window_subscribers) {
|
||||
uint32_t subscriber = (uint32_t)node->value;
|
||||
pex_send(server, subscriber, response->size, (char *)response);
|
||||
}
|
||||
free(response);
|
||||
window_mark_for_close(yg, w);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -22,6 +22,14 @@ typedef enum {
|
||||
YUTANI_EFFECT_UNMINIMIZE,
|
||||
} yutani_effect;
|
||||
|
||||
static int yutani_animation_lengths[] = {
|
||||
0,
|
||||
256,
|
||||
256,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
yutani_wid_t wid;
|
||||
|
||||
@ -43,6 +51,9 @@ typedef struct {
|
||||
uint8_t * newbuffer;
|
||||
|
||||
char * name;
|
||||
|
||||
int anim_mode;
|
||||
int anim_start;
|
||||
} yutani_server_window_t;
|
||||
|
||||
typedef struct {
|
||||
@ -103,7 +114,11 @@ typedef struct {
|
||||
|
||||
list_t * window_subscribers;
|
||||
|
||||
int tick_count;
|
||||
|
||||
} yutani_globals_t;
|
||||
|
||||
static void mark_window(yutani_globals_t * yg, yutani_server_window_t * window);
|
||||
static void window_actually_close(yutani_globals_t * yg, yutani_server_window_t * w);
|
||||
|
||||
#endif /* _YUTANI_INTERNAL_H */
|
||||
|
Loading…
Reference in New Issue
Block a user