ivi-shell: add IVI layout APIs
[profile/ivi/weston-ivi-shell.git] / ivi-shell / ivi-layout-transition.c
1 /*
2  * Copyright (C) 2014 DENSO CORPORATION
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include <time.h>
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27
28 #include "ivi-layout-export.h"
29 #include "ivi-layout-private.h"
30
31 struct ivi_layout_transition;
32
33 typedef void (*ivi_layout_transition_frame_func)(
34                         struct ivi_layout_transition *transition);
35 typedef void (*ivi_layout_transition_destroy_func)(
36                         struct ivi_layout_transition *transition);
37 typedef int32_t (*ivi_layout_is_transition_func)(void *private_data, void *id);
38
39 struct ivi_layout_transition {
40         enum ivi_layout_transition_type type;
41         void *private_data;
42         void *user_data;
43
44         uint32_t time_start;
45         uint32_t time_duration;
46         uint32_t time_elapsed;
47         uint32_t  is_done;
48         ivi_layout_is_transition_func is_transition_func;
49         ivi_layout_transition_frame_func frame_func;
50         ivi_layout_transition_destroy_func destroy_func;
51 };
52
53 struct transition_node {
54         struct ivi_layout_transition *transition;
55         struct wl_list link;
56 };
57
58 static void layout_transition_destroy(struct ivi_layout_transition *transition);
59
60 static struct ivi_layout_transition *
61 get_transition_from_type_and_id(enum ivi_layout_transition_type type,
62                                 void *id_data)
63 {
64         struct ivi_layout *layout = get_instance();
65         struct transition_node *node;
66         struct ivi_layout_transition *tran;
67
68         wl_list_for_each(node, &layout->transitions->transition_list, link) {
69                 tran = node->transition;
70
71                 if (tran->type == type &&
72                     tran->is_transition_func(tran->private_data, id_data))
73                         return tran;
74         }
75
76         return NULL;
77 }
78
79 WL_EXPORT int32_t
80 is_surface_transition(struct ivi_layout_surface *surface)
81 {
82         struct ivi_layout *layout = get_instance();
83         struct transition_node *node;
84         struct ivi_layout_transition *tran;
85
86         wl_list_for_each(node, &layout->transitions->transition_list, link) {
87                 tran = node->transition;
88
89                 if ((tran->type == IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE ||
90                      tran->type == IVI_LAYOUT_TRANSITION_VIEW_RESIZE) &&
91                     tran->is_transition_func(tran->private_data, surface))
92                         return 1;
93         }
94
95         return 0;
96 }
97
98 static void
99 tick_transition(struct ivi_layout_transition *transition, uint32_t timestamp)
100 {
101         const double t = timestamp - transition->time_start;
102
103         if (transition->time_duration <= t) {
104                 transition->time_elapsed = transition->time_duration;
105                 transition->is_done = 1;
106         } else {
107                 transition->time_elapsed = t;
108         }
109 }
110
111 static float time_to_nowpos(struct ivi_layout_transition *transition)
112 {
113         return sin((float)transition->time_elapsed /
114                    (float)transition->time_duration * M_PI_2);
115 }
116
117 static void
118 do_transition_frame(struct ivi_layout_transition *transition,
119                     uint32_t timestamp)
120 {
121         if (0 == transition->time_start)
122                 transition->time_start = timestamp;
123
124         tick_transition(transition, timestamp);
125         transition->frame_func(transition);
126
127         if (transition->is_done)
128                 layout_transition_destroy(transition);
129 }
130
131 static int32_t
132 layout_transition_frame(void *data)
133 {
134         struct ivi_layout_transition_set *transitions = data;
135         uint32_t fps = 30;
136         struct timespec timestamp = {};
137         uint32_t msec = 0;
138         struct transition_node *node = NULL;
139         struct transition_node *next = NULL;
140
141         if (wl_list_empty(&transitions->transition_list)) {
142                 wl_event_source_timer_update(transitions->event_source, 0);
143                 return 1;
144         }
145
146         wl_event_source_timer_update(transitions->event_source, 1000 / fps);
147
148         clock_gettime(CLOCK_MONOTONIC, &timestamp);/* FIXME */
149         msec = (1e+3 * timestamp.tv_sec + 1e-6 * timestamp.tv_nsec);
150
151         wl_list_for_each_safe(node, next, &transitions->transition_list, link) {
152                 do_transition_frame(node->transition, msec);
153         }
154
155         ivi_layout_commit_changes();
156         return 1;
157 }
158
159 WL_EXPORT struct ivi_layout_transition_set *
160 ivi_layout_transition_set_create(struct weston_compositor *ec)
161 {
162         struct ivi_layout_transition_set *transitions;
163         struct wl_event_loop *loop;
164
165         transitions = malloc(sizeof(*transitions));
166         if (transitions == NULL) {
167                 weston_log("%s: memory allocation fails\n", __func__);
168                 return NULL;
169         }
170
171         wl_list_init(&transitions->transition_list);
172
173         loop = wl_display_get_event_loop(ec->wl_display);
174         transitions->event_source =
175                 wl_event_loop_add_timer(loop, layout_transition_frame,
176                                         transitions);
177
178         return transitions;
179 }
180
181 static void
182 layout_transition_register(struct ivi_layout_transition *trans)
183 {
184         struct ivi_layout *layout = get_instance();
185         struct transition_node *node;
186
187         node = malloc(sizeof(*node));
188         if (node == NULL) {
189                 weston_log("%s: memory allocation fails\n", __func__);
190                 return;
191         }
192
193         node->transition = trans;
194         wl_list_insert(&layout->pending_transition_list, &node->link);
195 }
196
197 static void
198 remove_transition(struct ivi_layout *layout,
199                   struct ivi_layout_transition *trans)
200 {
201         struct transition_node *node;
202         struct transition_node *next;
203
204         wl_list_for_each_safe(node, next,
205                               &layout->transitions->transition_list, link) {
206                 if (node->transition == trans) {
207                         wl_list_remove(&node->link);
208                         free(node);
209                         return;
210                 }
211         }
212
213         wl_list_for_each_safe(node, next,
214                               &layout->pending_transition_list, link) {
215                 if (node->transition == trans) {
216                         wl_list_remove(&node->link);
217                         free(node);
218                         return;
219                 }
220         }
221 }
222
223 static void
224 layout_transition_destroy(struct ivi_layout_transition *transition)
225 {
226         struct ivi_layout *layout = get_instance();
227
228         remove_transition(layout, transition);
229         if(transition->destroy_func)
230                 transition->destroy_func(transition);
231         free(transition);
232 }
233
234 static struct ivi_layout_transition *
235 create_layout_transition(void)
236 {
237         struct ivi_layout_transition *transition = malloc(sizeof(*transition));
238
239         if (transition == NULL) {
240                 weston_log("%s: memory allocation fails\n", __func__);
241                 return NULL;
242         }
243
244         transition->type = IVI_LAYOUT_TRANSITION_MAX;
245         transition->time_start = 0;
246         transition->time_duration = 300; /* 300ms */
247         transition->time_elapsed = 0;
248
249         transition->is_done = 0;
250
251         transition->private_data = NULL;
252         transition->user_data = NULL;
253
254         transition->frame_func = NULL;
255         transition->destroy_func = NULL;
256
257         return transition;
258 }
259
260 /* move and resize view transition */
261
262 struct move_resize_view_data {
263         struct ivi_layout_surface *surface;
264         int32_t start_x;
265         int32_t start_y;
266         int32_t end_x;
267         int32_t end_y;
268         int32_t start_width;
269         int32_t start_height;
270         int32_t end_width;
271         int32_t end_height;
272 };
273
274 static void
275 transition_move_resize_view_destroy(struct ivi_layout_transition *transition)
276 {
277         struct move_resize_view_data *data =
278                 (struct move_resize_view_data *)transition->private_data;
279         struct ivi_layout_surface *layout_surface = data->surface;
280
281         wl_signal_emit(&layout_surface->configured, layout_surface);
282
283         if (transition->private_data) {
284                 free(transition->private_data);
285                 transition->private_data = NULL;
286         }
287 }
288
289 static void
290 transition_move_resize_view_user_frame(struct ivi_layout_transition *transition)
291 {
292         struct move_resize_view_data *mrv = transition->private_data;
293         const double current = time_to_nowpos(transition);
294
295         const int32_t destx = mrv->start_x +
296                 (mrv->end_x - mrv->start_x) * current;
297
298         const int32_t desty = mrv->start_y +
299                 (mrv->end_y - mrv->start_y) * current;
300
301         const int32_t dest_width = mrv->start_width  +
302                 (mrv->end_width - mrv->start_width) * current;
303
304         const int32_t dest_height = mrv->start_height +
305                 (mrv->end_height - mrv->start_height) * current;
306
307         ivi_layout_surface_set_destination_rectangle(mrv->surface,
308                                                      destx, desty,
309                                                      dest_width, dest_height);
310 }
311
312 static int32_t
313 is_transition_move_resize_view_func(struct move_resize_view_data *data,
314                                     struct ivi_layout_surface *view)
315 {
316         return data->surface == view;
317 }
318
319 static struct ivi_layout_transition *
320 create_move_resize_view_transition(
321                         struct ivi_layout_surface *surface,
322                         int32_t start_x, int32_t start_y,
323                         int32_t end_x, int32_t end_y,
324                         int32_t start_width, int32_t start_height,
325                         int32_t end_width, int32_t end_height,
326                         ivi_layout_transition_frame_func frame_func,
327                         ivi_layout_transition_destroy_func destroy_func,
328                         uint32_t duration)
329 {
330         struct ivi_layout_transition *transition = create_layout_transition();
331         struct move_resize_view_data *data = malloc(sizeof(*data));
332
333         if (data == NULL) {
334                 weston_log("%s: memory allocation fails\n", __func__);
335                 return NULL;
336         }
337
338         transition->type = IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE;
339         transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_move_resize_view_func;
340
341         transition->frame_func = frame_func;
342         transition->destroy_func = destroy_func;
343         transition->private_data = data;
344
345         if (duration != 0)
346                 transition->time_duration = duration;
347
348         data->surface = surface;
349         data->start_x = start_x;
350         data->start_y = start_y;
351         data->end_x   = end_x;
352         data->end_y   = end_y;
353
354         data->start_width  = start_width;
355         data->start_height = start_height;
356         data->end_width    = end_width;
357         data->end_height   = end_height;
358
359         return transition;
360 }
361
362 WL_EXPORT void
363 ivi_layout_transition_move_resize_view(struct ivi_layout_surface *surface,
364                                        int32_t dest_x, int32_t dest_y,
365                                        int32_t dest_width, int32_t dest_height,
366                                        uint32_t duration)
367 {
368         struct ivi_layout_transition *transition;
369         int32_t start_pos[2] = {
370                 surface->pending.prop.start_x,
371                 surface->pending.prop.start_y
372         };
373
374         int32_t start_size[2] = {
375                 surface->pending.prop.start_width,
376                 surface->pending.prop.start_height
377         };
378
379         transition = get_transition_from_type_and_id(
380                                         IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE,
381                                         surface);
382         if (transition) {
383                 struct move_resize_view_data *data = transition->private_data;
384                 transition->time_start = 0;
385                 transition->time_duration = duration;
386
387                 data->start_x = start_pos[0];
388                 data->start_y = start_pos[1];
389                 data->end_x   = dest_x;
390                 data->end_y   = dest_y;
391
392                 data->start_width  = start_size[0];
393                 data->start_height = start_size[1];
394                 data->end_width    = dest_width;
395                 data->end_height   = dest_height;
396                 return;
397         }
398
399         transition = create_move_resize_view_transition(
400                 surface,
401                 start_pos[0], start_pos[1],
402                 dest_x, dest_y,
403                 start_size[0], start_size[1],
404                 dest_width, dest_height,
405                 transition_move_resize_view_user_frame,
406                 transition_move_resize_view_destroy,
407                 duration);
408
409         layout_transition_register(transition);
410 }
411
412 /* fade transition */
413 struct fade_view_data {
414         struct ivi_layout_surface *surface;
415         double start_alpha;
416         double end_alpha;
417 };
418
419 struct store_alpha{
420         double alpha;
421 };
422
423 static void
424 fade_view_user_frame(struct ivi_layout_transition *transition)
425 {
426         struct fade_view_data *fade = transition->private_data;
427         struct ivi_layout_surface *surface = fade->surface;
428
429         const double current = time_to_nowpos(transition);
430         const double alpha = fade->start_alpha +
431                 (fade->end_alpha - fade->start_alpha) * current;
432
433         ivi_layout_surface_set_opacity(surface, wl_fixed_from_double(alpha));
434         ivi_layout_surface_set_visibility(surface, true);
435 }
436
437 static int32_t
438 is_transition_fade_view_func(struct fade_view_data *data,
439                              struct ivi_layout_surface *view)
440 {
441         return data->surface == view;
442 }
443
444 static struct ivi_layout_transition *
445 create_fade_view_transition(
446                         struct ivi_layout_surface *surface,
447                         double start_alpha, double end_alpha,
448                         ivi_layout_transition_frame_func frame_func,
449                         void *user_data,
450                         ivi_layout_transition_destroy_func destroy_func,
451                         uint32_t duration)
452 {
453         struct ivi_layout_transition *transition = create_layout_transition();
454         struct fade_view_data *data = malloc(sizeof(*data));
455
456         if (data == NULL) {
457                 weston_log("%s: memory allocation fails\n", __func__);
458                 return NULL;
459         }
460
461         transition->type = IVI_LAYOUT_TRANSITION_VIEW_FADE;
462         transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_fade_view_func;
463
464         transition->user_data = user_data;
465         transition->private_data = data;
466         transition->frame_func = frame_func;
467         transition->destroy_func = destroy_func;
468
469         if (duration != 0)
470                 transition->time_duration = duration;
471
472         data->surface = surface;
473         data->start_alpha = start_alpha;
474         data->end_alpha   = end_alpha;
475
476         return transition;
477 }
478
479 static void
480 create_visibility_transition(struct ivi_layout_surface *surface,
481                              double start_alpha,
482                              double dest_alpha,
483                              void *user_data,
484                              ivi_layout_transition_destroy_func destroy_func,
485                              uint32_t duration)
486 {
487         struct ivi_layout_transition *transition = NULL;
488
489         transition = create_fade_view_transition(
490                 surface,
491                 start_alpha, dest_alpha,
492                 fade_view_user_frame,
493                 user_data,
494                 destroy_func,
495                 duration);
496
497         layout_transition_register(transition);
498 }
499
500 static void
501 visibility_on_transition_destroy(struct ivi_layout_transition *transition)
502 {
503         struct fade_view_data *data = transition->private_data;
504         struct store_alpha *user_data = transition->user_data;
505
506         ivi_layout_surface_set_visibility(data->surface, true);
507
508         free(data);
509         transition->private_data = NULL;
510
511         free(user_data);
512         transition->user_data = NULL;
513 }
514
515 WL_EXPORT void
516 ivi_layout_transition_visibility_on(struct ivi_layout_surface *surface,
517                                     uint32_t duration)
518 {
519         struct ivi_layout_transition *transition;
520         bool is_visible = ivi_layout_surface_get_visibility(surface);
521         wl_fixed_t dest_alpha = ivi_layout_surface_get_opacity(surface);
522         struct store_alpha *user_data = NULL;
523         wl_fixed_t start_alpha = 0.0;
524         struct fade_view_data *data = NULL;
525
526         transition = get_transition_from_type_and_id(
527                                         IVI_LAYOUT_TRANSITION_VIEW_FADE,
528                                         surface);
529         if (transition) {
530                 start_alpha = ivi_layout_surface_get_opacity(surface);
531                 user_data = transition->user_data;
532                 data = transition->private_data;
533
534                 transition->time_start = 0;
535                 transition->time_duration = duration;
536                 transition->destroy_func = visibility_on_transition_destroy;
537
538                 data->start_alpha = wl_fixed_to_double(start_alpha);
539                 data->end_alpha = user_data->alpha;
540                 return;
541         }
542
543         if (is_visible)
544                 return;
545
546         user_data = malloc(sizeof(*user_data));
547         if (user_data == NULL) {
548                 weston_log("%s: memory allocation fails\n", __func__);
549                 return;
550         }
551
552         user_data->alpha = wl_fixed_to_double(dest_alpha);
553
554         create_visibility_transition(surface,
555                                      0.0, // start_alpha
556                                      wl_fixed_to_double(dest_alpha),
557                                      user_data,
558                                      visibility_on_transition_destroy,
559                                      duration);
560 }
561
562 static void
563 visibility_off_transition_destroy(struct ivi_layout_transition *transition)
564 {
565         struct fade_view_data *data = transition->private_data;
566         struct store_alpha *user_data = transition->user_data;
567
568         ivi_layout_surface_set_visibility(data->surface, false);
569
570         ivi_layout_surface_set_opacity(data->surface,
571                                        wl_fixed_from_double(user_data->alpha));
572
573         free(data);
574         transition->private_data = NULL;
575
576         free(user_data);
577         transition->user_data= NULL;
578 }
579
580 WL_EXPORT void
581 ivi_layout_transition_visibility_off(struct ivi_layout_surface *surface,
582                                      uint32_t duration)
583 {
584         struct ivi_layout_transition *transition;
585         wl_fixed_t start_alpha = ivi_layout_surface_get_opacity(surface);
586         struct store_alpha* user_data = NULL;
587         struct fade_view_data* data = NULL;
588
589         transition =
590                 get_transition_from_type_and_id(IVI_LAYOUT_TRANSITION_VIEW_FADE,
591                                                 surface);
592         if (transition) {
593                 data = transition->private_data;
594
595                 transition->time_start = 0;
596                 transition->time_duration = duration;
597                 transition->destroy_func = visibility_off_transition_destroy;
598
599                 data->start_alpha = wl_fixed_to_double(start_alpha);
600                 data->end_alpha = 0;
601                 return;
602         }
603
604         user_data = malloc(sizeof(*user_data));
605         if (user_data == NULL) {
606                 weston_log("%s: memory allocation fails\n", __func__);
607                 return;
608         }
609
610         user_data->alpha = wl_fixed_to_double(start_alpha);
611
612         create_visibility_transition(surface,
613                                      wl_fixed_to_double(start_alpha),
614                                      0.0, // dest_alpha
615                                      user_data,
616                                      visibility_off_transition_destroy,
617                                      duration);
618 }
619
620 /* move layer transition */
621
622 struct move_layer_data {
623         struct ivi_layout_layer *layer;
624         int32_t start_x;
625         int32_t start_y;
626         int32_t end_x;
627         int32_t end_y;
628         ivi_layout_transition_destroy_user_func destroy_func;
629 };
630
631 static void
632 transition_move_layer_user_frame(struct ivi_layout_transition *transition)
633 {
634         struct move_layer_data *data = transition->private_data;
635         struct ivi_layout_layer *layer = data->layer;
636
637         const float  current = time_to_nowpos(transition);
638
639         const int32_t dest_x = data->start_x +
640                 (data->end_x - data->start_x) * current;
641
642         const int32_t dest_y = data->start_y +
643                 (data->end_y - data->start_y) * current;
644
645         ivi_layout_layer_set_position(layer, dest_x, dest_y);
646 }
647
648 static void
649 transition_move_layer_destroy(struct ivi_layout_transition *transition)
650 {
651         struct move_layer_data *data = transition->private_data;
652
653         if(data->destroy_func)
654                 data->destroy_func(transition->user_data);
655
656         free(data);
657         transition->private_data = NULL;
658 }
659
660 static int32_t
661 is_transition_move_layer_func(struct move_layer_data *data,
662                               struct ivi_layout_layer *layer)
663 {
664         return data->layer == layer;
665 }
666
667
668 static struct ivi_layout_transition *
669 create_move_layer_transition(
670                 struct ivi_layout_layer *layer,
671                 int32_t start_x, int32_t start_y,
672                 int32_t end_x, int32_t end_y,
673                 void *user_data,
674                 ivi_layout_transition_destroy_user_func destroy_user_func,
675                 uint32_t duration)
676 {
677         struct ivi_layout_transition *transition = create_layout_transition();
678         struct move_layer_data *data = malloc(sizeof(*data));
679
680         if (data == NULL) {
681                 weston_log("%s: memory allocation fails\n", __func__);
682                 return NULL;
683         }
684
685         transition->type = IVI_LAYOUT_TRANSITION_LAYER_MOVE;
686         transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_move_layer_func;
687
688         transition->frame_func = transition_move_layer_user_frame;
689         transition->destroy_func = transition_move_layer_destroy;
690         transition->private_data = data;
691         transition->user_data = user_data;
692
693         if (duration != 0)
694                 transition->time_duration = duration;
695
696         data->layer = layer;
697         data->start_x = start_x;
698         data->start_y = start_y;
699         data->end_x   = end_x;
700         data->end_y   = end_y;
701         data->destroy_func = destroy_user_func;
702
703         return transition;
704 }
705
706 WL_EXPORT void
707 ivi_layout_transition_move_layer(struct ivi_layout_layer *layer,
708                                  int32_t dest_x, int32_t dest_y,
709                                  uint32_t duration)
710 {
711         int32_t start_pos_x = 0;
712         int32_t start_pos_y = 0;
713         struct ivi_layout_transition *transition = NULL;
714
715         ivi_layout_layer_get_position(layer, &start_pos_x, &start_pos_y);
716
717         transition = create_move_layer_transition(
718                 layer,
719                 start_pos_x, start_pos_y,
720                 dest_x, dest_y,
721                 NULL, NULL,
722                 duration);
723
724         layout_transition_register(transition);
725
726         return;
727 }
728
729 WL_EXPORT void
730 ivi_layout_transition_move_layer_cancel(struct ivi_layout_layer *layer)
731 {
732         struct ivi_layout_transition *transition =
733                 get_transition_from_type_and_id(
734                                         IVI_LAYOUT_TRANSITION_LAYER_MOVE,
735                                         layer);
736         if (transition) {
737                 layout_transition_destroy(transition);
738         }
739 }
740
741 /* fade layer transition */
742 struct fade_layer_data {
743         struct ivi_layout_layer *layer;
744         uint32_t is_fade_in;
745         double start_alpha;
746         double end_alpha;
747         ivi_layout_transition_destroy_user_func destroy_func;
748 };
749
750 static void
751 transition_fade_layer_destroy(struct ivi_layout_transition *transition)
752 {
753         struct fade_layer_data *data = transition->private_data;
754         transition->private_data = NULL;
755
756         free(data);
757 }
758
759 static void
760 transition_fade_layer_user_frame(struct ivi_layout_transition *transition)
761 {
762         double current = time_to_nowpos(transition);
763         struct fade_layer_data *data = transition->private_data;
764         double alpha = data->start_alpha +
765                 (data->end_alpha - data->start_alpha) * current;
766         wl_fixed_t fixed_alpha = wl_fixed_from_double(alpha);
767
768         int32_t is_done = transition->is_done;
769         bool is_visible = !is_done || data->is_fade_in;
770
771         ivi_layout_layer_set_opacity(data->layer, fixed_alpha);
772         ivi_layout_layer_set_visibility(data->layer, is_visible);
773 }
774
775 static int32_t
776 is_transition_fade_layer_func(struct fade_layer_data *data,
777                               struct ivi_layout_layer *layer)
778 {
779         return data->layer == layer;
780 }
781
782 WL_EXPORT void
783 ivi_layout_transition_fade_layer(
784                         struct ivi_layout_layer *layer,
785                         uint32_t is_fade_in,
786                         double start_alpha, double end_alpha,
787                         void* user_data,
788                         ivi_layout_transition_destroy_user_func destroy_func,
789                         uint32_t duration)
790 {
791         struct ivi_layout_transition *transition;
792         struct fade_layer_data *data = NULL;
793         wl_fixed_t fixed_opacity = 0.0;
794         double now_opacity = 0.0;
795         double remain = 0.0;
796
797         transition = get_transition_from_type_and_id(
798                                         IVI_LAYOUT_TRANSITION_LAYER_FADE,
799                                         layer);
800         if (transition) {
801                 /* transition update */
802                 data = transition->private_data;
803
804                 /* FIXME */
805                 fixed_opacity = ivi_layout_layer_get_opacity(layer);
806                 now_opacity = wl_fixed_to_double(fixed_opacity);
807                 remain = 0.0;
808
809                 data->is_fade_in = is_fade_in;
810                 data->start_alpha = now_opacity;
811                 data->end_alpha = end_alpha;
812
813                 remain = is_fade_in? 1.0 - now_opacity : now_opacity;
814                 transition->time_start = 0;
815                 transition->time_elapsed = 0;
816                 transition->time_duration = duration * remain;
817
818                 return;
819         }
820
821         transition = create_layout_transition();
822         data = malloc(sizeof(*data));
823
824         if (data == NULL) {
825                 weston_log("%s: memory allocation fails\n", __func__);
826                 return;
827         }
828
829         transition->type = IVI_LAYOUT_TRANSITION_LAYER_FADE;
830         transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_fade_layer_func;
831
832         transition->private_data = data;
833         transition->user_data = user_data;
834
835         transition->frame_func = transition_fade_layer_user_frame;
836         transition->destroy_func = transition_fade_layer_destroy;
837
838         if (duration != 0)
839                 transition->time_duration = duration;
840
841         data->layer = layer;
842         data->is_fade_in = is_fade_in;
843         data->start_alpha = start_alpha;
844         data->end_alpha = end_alpha;
845         data->destroy_func = destroy_func;
846
847         layout_transition_register(transition);
848
849         return;
850 }
851
852 /* render order transition */
853 struct surface_reorder {
854         uint32_t id_surface;
855         uint32_t new_index;
856 };
857
858 struct change_order_data {
859         struct ivi_layout_layer *layer;
860         uint32_t surface_num;
861         struct surface_reorder *reorder;
862 };
863
864 struct surf_with_index {
865         uint32_t id_surface;
866         float surface_index;
867 };
868
869 static int
870 cmp_order_asc(const void *lhs, const void *rhs)
871 {
872         const struct surf_with_index *l = lhs;
873         const struct surf_with_index *r = rhs;
874
875         return l->surface_index > r->surface_index;
876 }
877
878 /*
879 render oerder transition
880
881 index   0      1      2
882 old   surfA, surfB, surfC
883 new   surfB, surfC, surfA
884        (-1)  (-1)   (+2)
885
886 after 10% of time elapsed
887        0.2    0.9    1.9
888       surfA, surfB, surfC
889
890 after 50% of time elapsed
891        0.5    1.0    1.5
892       surfB, surfA, surfC
893 */
894
895 static void
896 transition_change_order_user_frame(struct ivi_layout_transition *transition)
897 {
898         uint32_t i, old_index;
899         double current = time_to_nowpos(transition);
900         struct change_order_data *data = transition->private_data;
901
902         struct surf_with_index *swi = malloc(sizeof(*swi) * data->surface_num);
903         struct ivi_layout_surface **new_surface_order = NULL;
904         uint32_t surface_num = 0;
905
906         if (swi == NULL) {
907                 weston_log("%s: memory allocation fails\n", __func__);
908                 return;
909         }
910
911         for (old_index = 0; old_index < data->surface_num; old_index++) {
912                 swi[old_index].id_surface = data->reorder[old_index].id_surface;
913                 swi[old_index].surface_index = (float)old_index +
914                         ((float)data->reorder[old_index].new_index - (float)old_index) * current;
915         }
916
917         qsort(swi, data->surface_num, sizeof(*swi), cmp_order_asc);
918
919         new_surface_order =
920                 malloc(sizeof(*new_surface_order) * data->surface_num);
921
922         if (new_surface_order == NULL) {
923                 weston_log("%s: memory allocation fails\n", __func__);
924                 return;
925         }
926
927         for (i = 0; i < data->surface_num; i++) {
928                 struct ivi_layout_surface *surf =
929                         ivi_layout_get_surface_from_id(swi[i].id_surface);
930                 if(surf)
931                         new_surface_order[surface_num++] = surf;
932         }
933
934         ivi_layout_layer_set_render_order(data->layer, new_surface_order,
935                                           surface_num);
936
937         free(new_surface_order);
938         free(swi);
939 }
940
941 static void
942 transition_change_order_destroy(struct ivi_layout_transition *transition)
943 {
944         struct change_order_data *data = transition->private_data;
945
946         free(data->reorder);
947         free(data);
948 }
949
950 static int32_t find_surface(struct ivi_layout_surface **surfaces,
951                             uint32_t surface_num,
952                             struct ivi_layout_surface *target)
953 {
954         uint32_t i = 0;
955
956         for(i = 0; i < surface_num; i++) {
957                 if (surfaces[i] == target)
958                         return i;
959         }
960
961         return -1;
962 }
963
964 static int32_t
965 is_transition_change_order_func(struct change_order_data *data,
966                                 struct ivi_layout_layer *layer)
967 {
968         return data->layer == layer;
969 }
970
971 WL_EXPORT void
972 ivi_layout_transition_layer_render_order(struct ivi_layout_layer *layer,
973                                          struct ivi_layout_surface **new_order,
974                                          uint32_t surface_num,
975                                          uint32_t duration)
976 {
977         struct surface_reorder *reorder;
978         struct ivi_layout_surface *surf;
979         uint32_t old_index = 0;
980         struct ivi_layout_transition *transition;
981         struct change_order_data *data = NULL;
982         int32_t new_index = 0;
983         uint32_t id = 0;
984
985         reorder = malloc(sizeof(*reorder) * surface_num);
986         if (reorder == NULL) {
987                 weston_log("%s: memory allocation fails\n", __func__);
988                 return;
989         }
990
991         wl_list_for_each(surf, &layer->order.surface_list, order.link) {
992                 new_index = find_surface(new_order, surface_num, surf);
993                 id = ivi_layout_get_id_of_surface(surf);
994                 if(new_index < 0){
995                         fprintf(stderr, "invalid render order!!!\n");
996                         return;
997                 }
998
999                 reorder[old_index].id_surface = id;
1000                 reorder[old_index].new_index = new_index;
1001                 old_index++;
1002         }
1003
1004         transition = get_transition_from_type_and_id(
1005                                         IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
1006                                         layer);
1007         if (transition) {
1008                 /* update transition */
1009                 struct change_order_data *data = transition->private_data;
1010                 transition->time_start = 0; /* timer reset */
1011
1012                 if (duration != 0) {
1013                         transition->time_duration = duration;
1014                 }
1015
1016                 free(data->reorder);
1017                 data->reorder = reorder;
1018                 return;
1019         }
1020
1021         transition = create_layout_transition();
1022         data = malloc(sizeof(*data));
1023
1024         if (data == NULL) {
1025                 weston_log("%s: memory allocation fails\n", __func__);
1026                 return;
1027         }
1028
1029         transition->type = IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER;
1030         transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_change_order_func;
1031
1032         transition->private_data = data;
1033         transition->frame_func = transition_change_order_user_frame;
1034         transition->destroy_func = transition_change_order_destroy;
1035
1036         if (duration != 0)
1037                 transition->time_duration = duration;
1038
1039         data->layer = layer;
1040         data->reorder = reorder;
1041         data->surface_num = old_index;
1042
1043         layout_transition_register(transition);
1044 }
1045
1046 WL_EXPORT int32_t
1047 ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf,
1048                                   enum ivi_layout_transition_type type,
1049                                   uint32_t duration)
1050 {
1051         struct ivi_layout_surface_properties *prop;
1052
1053         if (ivisurf == NULL) {
1054                 weston_log("%s: invalid argument\n", __func__);
1055                 return -1;
1056         }
1057
1058         prop = &ivisurf->pending.prop;
1059         prop->transition_type = type;
1060         prop->transition_duration = duration;
1061         return 0;
1062 }
1063
1064 int32_t
1065 ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf,
1066                                            uint32_t duration)
1067 {
1068         struct ivi_layout_surface_properties *prop;
1069
1070         if (ivisurf == NULL) {
1071                 weston_log("%s: invalid argument\n", __func__);
1072                 return -1;
1073         }
1074
1075         prop = &ivisurf->pending.prop;
1076         prop->transition_duration = duration*10;
1077         return 0;
1078 }
1079
1080 WL_EXPORT int32_t
1081 ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer,
1082                                 enum ivi_layout_transition_type type,
1083                                 uint32_t duration)
1084 {
1085         if (ivilayer == NULL) {
1086                 weston_log("%s: invalid argument\n", __func__);
1087                 return -1;
1088         }
1089
1090         ivilayer->pending.prop.transition_type = type;
1091         ivilayer->pending.prop.transition_duration = duration;
1092
1093         return 0;
1094 }
1095
1096 WL_EXPORT int32_t
1097 ivi_layout_layer_set_fade_info(struct ivi_layout_layer* ivilayer,
1098                                uint32_t is_fade_in,
1099                                double start_alpha, double end_alpha)
1100 {
1101         if (ivilayer == NULL) {
1102                 weston_log("%s: invalid argument\n", __func__);
1103                 return -1;
1104         }
1105
1106         ivilayer->pending.prop.is_fade_in = is_fade_in;
1107         ivilayer->pending.prop.start_alpha = start_alpha;
1108         ivilayer->pending.prop.end_alpha = end_alpha;
1109
1110         return 0;
1111 }