summaryrefslogtreecommitdiff
path: root/ivi-shell/ivi-layout-transition.c
diff options
context:
space:
mode:
Diffstat (limited to 'ivi-shell/ivi-layout-transition.c')
-rw-r--r--ivi-shell/ivi-layout-transition.c948
1 files changed, 948 insertions, 0 deletions
diff --git a/ivi-shell/ivi-layout-transition.c b/ivi-shell/ivi-layout-transition.c
new file mode 100644
index 00000000..da05230c
--- /dev/null
+++ b/ivi-shell/ivi-layout-transition.c
@@ -0,0 +1,948 @@
+/*
+ * Copyright (C) 2014 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <time.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ivi-layout.h"
+#include "ivi-layout-export.h"
+#include "ivi-layout-transition.h"
+#include "ivi-layout-private.h"
+
+struct ivi_layout_transition;
+typedef void (*ivi_layout_transition_frame_func)(struct ivi_layout_transition *transition);
+typedef void (*ivi_layout_transition_destroy_func)(struct ivi_layout_transition* transition);
+typedef int32_t (*ivi_layout_transition_identifire_func)(void* private_data, void* id);
+
+enum layout_transition_type{
+ LAYOUT_TRANSITION_VIEW_MOVE_RESIZE,
+ LAYOUT_TRANSITION_VIEW_FADE,
+ LAYOUT_TRANSITION_LAYER_FADE,
+ LAYOUT_TRANSITION_LAYER_MOVE,
+ LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
+ LAYOUT_TRANSITION_MAX,
+};
+
+struct ivi_layout_transition {
+ enum layout_transition_type type;
+ void *private_data;
+ void *user_data;
+
+ uint32_t time_start;
+ uint32_t time_duration;
+ uint32_t time_elapsed;
+ uint32_t is_done;
+ ivi_layout_transition_identifire_func id_func;
+ ivi_layout_transition_frame_func frame_func;
+ ivi_layout_transition_destroy_func destroy_func;
+};
+
+struct transition_node {
+ struct ivi_layout_transition *transition;
+ struct wl_list link;
+};
+
+static void layout_transition_destroy(struct ivi_layout_transition* transition);
+
+static struct ivi_layout_transition*
+get_transition_from_type_and_id(enum layout_transition_type type, void* id_data)
+{
+ struct ivi_layout* layout = get_instance();
+ struct transition_node *node=NULL;
+ wl_list_for_each(node, &layout->transitions->transition_list, link){
+ if(node->transition->type == type)
+ if(node->transition->id_func(node->transition->private_data, id_data))
+ return node->transition;
+ }
+ return NULL;
+}
+
+static void
+tick_transition(struct ivi_layout_transition *transition, uint32_t timestamp)
+{
+ const double t = timestamp - transition->time_start;
+
+ if (transition->time_duration <= t) {
+ transition->time_elapsed = transition->time_duration;
+ transition->is_done = 1;
+ } else {
+ transition->time_elapsed = t;
+ }
+}
+
+static float time_to_nowpos(struct ivi_layout_transition* transition)
+{
+ return sin((float)transition->time_elapsed / (float)transition->time_duration * M_PI_2);
+}
+
+static void
+do_transition_frame(
+ struct ivi_layout_transition *transition, uint32_t timestamp)
+{
+ if (0 == transition->time_start) {
+ transition->time_start = timestamp;
+ }
+
+ tick_transition(transition, timestamp);
+ transition->frame_func(transition);
+
+ if(transition->is_done){
+ layout_transition_destroy(transition);
+ }
+}
+
+static int32_t
+layout_transition_frame(void* data)
+{
+ struct ivi_layout_transition_set *transitions = data;
+ uint32_t fps = 30;
+
+ if (wl_list_empty(&transitions->transition_list)) {
+ wl_event_source_timer_update(transitions->event_source, 0);
+ return 1;
+ }
+
+ wl_event_source_timer_update(transitions->event_source, 1000 / fps);
+
+ struct timespec timestamp = {0};
+ clock_gettime(CLOCK_MONOTONIC, &timestamp);
+ uint32_t msec = (1e+3 * timestamp.tv_sec + 1e-6 * timestamp.tv_nsec);
+
+ struct transition_node *node = NULL;
+ struct transition_node *next = NULL;
+
+ wl_list_for_each_safe(node, next, &transitions->transition_list, link) {
+ do_transition_frame(node->transition, msec);
+ }
+
+ ivi_layout_commitChanges();
+ return 1;
+}
+
+WL_EXPORT struct ivi_layout_transition_set *
+ivi_layout_transition_set_create(struct weston_compositor* ec)
+{
+ struct ivi_layout_transition_set *transitions = malloc(sizeof(*transitions));
+ assert(transitions);
+
+ wl_list_init(&transitions->transition_list);
+
+ struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);
+ transitions->event_source = wl_event_loop_add_timer(loop, layout_transition_frame, transitions);
+ wl_event_source_timer_update(transitions->event_source, 0);
+
+ return transitions;
+}
+
+static void
+layout_transition_register(struct ivi_layout_transition *trans)
+{
+ struct ivi_layout* layout = get_instance();
+ struct transition_node *node = NULL;
+
+ node = malloc(sizeof(*node));
+ assert(node);
+
+ node->transition = trans;
+ wl_list_insert(&layout->pending_transition_list, &node->link);
+}
+
+static void
+remove_transition(struct ivi_layout* layout,
+ struct ivi_layout_transition *trans)
+{
+ struct transition_node *node = NULL;
+ struct transition_node *next = NULL;
+
+ wl_list_for_each_safe(node, next, &layout->transitions->transition_list, link) {
+ if (node->transition == trans) {
+ wl_list_remove(&node->link);
+ free(node);
+ return;
+ }
+ }
+
+ wl_list_for_each_safe(node, next, &layout->pending_transition_list, link) {
+ if (node->transition == trans) {
+ wl_list_remove(&node->link);
+ free(node);
+ return;
+ }
+ }
+
+ return;
+}
+
+static void
+layout_transition_destroy(struct ivi_layout_transition *transition)
+{
+ struct ivi_layout* layout = get_instance();
+
+ remove_transition(layout, transition);
+ if(transition->destroy_func)
+ transition->destroy_func(transition);
+ free(transition);
+}
+
+static struct ivi_layout_transition*
+create_layout_transition(void)
+{
+ struct ivi_layout_transition* transition = malloc(sizeof(*transition));
+ assert(transition);
+
+ transition->type = LAYOUT_TRANSITION_MAX;
+ transition->time_start = 0;
+ transition->time_duration = 300; // 300ms
+ transition->time_elapsed = 0;
+
+ transition->is_done = 0;
+
+ transition->private_data = NULL;
+ transition->user_data = NULL;
+
+ transition->frame_func = NULL;
+ transition->destroy_func = NULL;
+
+ return transition;
+}
+
+/* move and resize view transition */
+
+struct move_resize_view_data {
+ struct ivi_layout_surface* surface;
+ int32_t start_x;
+ int32_t start_y;
+ int32_t end_x;
+ int32_t end_y;
+ uint32_t start_width;
+ uint32_t start_height;
+ uint32_t end_width;
+ uint32_t end_height;
+};
+
+static void
+transition_move_resize_view_destroy(struct ivi_layout_transition* transition)
+{
+ if(transition->private_data){
+ free(transition->private_data);
+ transition->private_data = NULL;
+ }
+}
+
+static void
+transition_move_resize_view_user_frame(struct ivi_layout_transition *transition)
+{
+ struct move_resize_view_data* private_data = transition->private_data;
+ struct ivi_layout_surface *surface = private_data->surface;
+
+ const double current = time_to_nowpos(transition);
+ const int32_t destx = private_data->start_x + (private_data->end_x - private_data->start_x)*current;
+ const int32_t desty = private_data->start_y + (private_data->end_y - private_data->start_y)*current;
+
+ const uint32_t dest_width = (int32_t)private_data->start_width +
+ ((int32_t)private_data->end_width - (int32_t)private_data->start_width) *current;
+
+ const uint32_t dest_height = (int32_t)private_data->start_height +
+ ((int32_t)private_data->end_height - (int32_t)private_data->start_height)*current;
+
+ ivi_layout_surfaceSetDestinationRectangle(surface,
+ destx, desty, dest_width, dest_height);
+
+}
+
+static int32_t
+transition_move_resize_view_identifire(struct move_resize_view_data* data,
+ struct ivi_layout_surface* view)
+{
+ return data->surface == view;
+}
+
+static struct ivi_layout_transition *
+create_move_resize_view_transition(
+ struct ivi_layout_surface* surface,
+ int32_t start_x, int32_t start_y,
+ int32_t end_x, int32_t end_y,
+ uint32_t start_width, uint32_t start_height,
+ uint32_t end_width, uint32_t end_height,
+ ivi_layout_transition_frame_func frame_func,
+ ivi_layout_transition_destroy_func destroy_func,
+ uint32_t duration)
+{
+ struct ivi_layout_transition* transition = create_layout_transition();
+ struct move_resize_view_data* data = malloc(sizeof(*data));
+
+ transition->type = LAYOUT_TRANSITION_VIEW_MOVE_RESIZE;
+ transition->id_func = (ivi_layout_transition_identifire_func)transition_move_resize_view_identifire;
+
+ transition->frame_func = frame_func;
+ transition->destroy_func = destroy_func;
+ transition->private_data = data;
+
+ if(duration != 0){
+ transition->time_duration = duration;
+ }
+
+ data->surface = surface;
+ data->start_x = start_x;
+ data->start_y = start_y;
+ data->end_x = end_x;
+ data->end_y = end_y;
+
+ data->start_width = start_width;
+ data->start_height = start_height;
+ data->end_width = end_width;
+ data->end_height = end_height;
+
+ return transition;
+}
+
+WL_EXPORT void
+ivi_layout_transition_move_resize_view(struct ivi_layout_surface* surface,
+ int32_t dest_x, int32_t dest_y,
+ uint32_t dest_width, uint32_t dest_height,
+ uint32_t duration)
+{
+ int32_t start_pos[2] = {};
+ ivi_layout_surfaceGetPosition(surface, start_pos);
+
+ uint32_t start_size[2] = {};
+ ivi_layout_surfaceGetDimension(surface, start_size);
+
+ struct ivi_layout_transition* transition = NULL;
+
+ transition = get_transition_from_type_and_id(LAYOUT_TRANSITION_VIEW_MOVE_RESIZE, surface);
+ if(transition){
+
+ transition->time_start = 0;
+ transition->time_duration = duration;
+
+ struct move_resize_view_data* data = transition->private_data;
+ data->start_x = start_pos[0];
+ data->start_y = start_pos[1];
+ data->end_x = dest_x;
+ data->end_y = dest_y;
+
+ data->start_width = start_size[0];
+ data->start_height = start_size[1];
+ data->end_width = dest_width;
+ data->end_height = dest_height;
+ return;
+ }
+
+ transition = create_move_resize_view_transition(
+ surface,
+ start_pos[0], start_pos[1],
+ dest_x, dest_y,
+ start_size[0], start_size[1],
+ dest_width, dest_height,
+ transition_move_resize_view_user_frame,
+ transition_move_resize_view_destroy,
+ duration);
+
+ layout_transition_register(transition);
+
+}
+
+/* fade transition */
+struct fade_view_data {
+ struct ivi_layout_surface* surface;
+ float start_alpha;
+ float end_alpha;
+};
+
+struct store_alpha{
+ float alpha;
+};
+
+static void
+fade_view_user_frame(struct ivi_layout_transition *transition)
+{
+ struct fade_view_data* private_data = transition->private_data;
+ struct ivi_layout_surface *surface = private_data->surface;
+
+ const double current = time_to_nowpos(transition);
+ const float alpha = private_data->start_alpha + (private_data->end_alpha - private_data->start_alpha)*current;
+
+ ivi_layout_surfaceSetOpacity(surface, wl_fixed_from_double(alpha));
+ ivi_layout_surfaceSetVisibility(surface, 1);
+
+}
+
+static int32_t
+transition_fade_view_identifire(struct fade_view_data* data,
+ struct ivi_layout_surface* view)
+{
+ return data->surface == view;
+}
+
+static struct ivi_layout_transition*
+create_fade_view_transition(
+ struct ivi_layout_surface* surface,
+ float start_alpha, float end_alpha,
+ ivi_layout_transition_frame_func frame_func,
+ void* user_data,
+ ivi_layout_transition_destroy_func destroy_func,
+ uint32_t duration)
+{
+ struct ivi_layout_transition* transition = create_layout_transition();
+ struct fade_view_data* data = malloc(sizeof(*data));
+ assert(data);
+
+ transition->type = LAYOUT_TRANSITION_VIEW_FADE;
+ transition->id_func = (ivi_layout_transition_identifire_func)transition_fade_view_identifire;
+
+ transition->user_data = user_data;
+ transition->private_data = data;
+ transition->frame_func = frame_func;
+ transition->destroy_func = destroy_func;
+
+ if(duration != 0){
+ transition->time_duration = duration;
+ }
+
+ data->surface = surface;
+ data->start_alpha = start_alpha;
+ data->end_alpha = end_alpha;
+
+ return transition;
+}
+
+static void
+create_visibility_transition(struct ivi_layout_surface* surface,
+ float start_alpha,
+ float dest_alpha,
+ void* user_data,
+ ivi_layout_transition_destroy_func destroy_func,
+ uint32_t duration)
+{
+ struct ivi_layout_transition* transition = NULL;
+
+ transition = create_fade_view_transition(
+ surface,
+ start_alpha, dest_alpha,
+ fade_view_user_frame,
+ user_data,
+ destroy_func,
+ duration);
+
+ layout_transition_register(transition);
+
+}
+
+static void
+visibility_on_transition_destroy(struct ivi_layout_transition* transition)
+{
+ struct fade_view_data *data = transition->private_data;
+ ivi_layout_surfaceSetVisibility(data->surface, 1);
+
+ free(data);
+ transition->private_data = NULL;
+
+ struct store_alpha *user_data = transition->user_data;
+
+ free(user_data);
+ transition->user_data = NULL;
+
+}
+
+WL_EXPORT void
+ivi_layout_transition_visibility_on(struct ivi_layout_surface* surface,
+ uint32_t duration)
+{
+
+ struct ivi_layout_transition* transition = NULL;
+
+ transition = get_transition_from_type_and_id(LAYOUT_TRANSITION_VIEW_FADE, surface);
+ if(transition){
+ transition->time_start = 0;
+ transition->time_duration = duration;
+ transition->destroy_func = visibility_on_transition_destroy;
+
+ float start_alpha=0.0;
+ ivi_layout_surfaceGetOpacity(surface, &start_alpha);
+
+ const struct store_alpha* user_data = transition->user_data;
+ struct fade_view_data* data = transition->private_data;
+ data->start_alpha = wl_fixed_to_double(start_alpha);
+ data->end_alpha = user_data->alpha;
+ return;
+ }
+
+ uint32_t is_visible = 0;
+ ivi_layout_surfaceGetVisibility(surface, &is_visible);
+ if(is_visible){
+ return;
+ }
+
+ float dest_alpha = 0;
+ ivi_layout_surfaceGetOpacity(surface, &dest_alpha);
+
+ struct store_alpha* user_data = malloc(sizeof(*user_data));
+ user_data->alpha = wl_fixed_to_double(dest_alpha);
+
+ create_visibility_transition(surface,
+ 0.0, // start_alpha
+ wl_fixed_to_double(dest_alpha),
+ user_data,
+ visibility_on_transition_destroy,
+ duration);
+}
+
+static void
+visibility_off_transition_destroy(struct ivi_layout_transition* transition)
+{
+ struct fade_view_data *data = transition->private_data;
+
+ ivi_layout_surfaceSetVisibility(data->surface, 0);
+
+ struct store_alpha* user_data = transition->user_data;
+ ivi_layout_surfaceSetOpacity(data->surface, wl_fixed_from_double(user_data->alpha));
+
+ free(data);
+ transition->private_data = NULL;
+
+ free(user_data);
+ transition->user_data= NULL;
+
+}
+
+WL_EXPORT void
+ivi_layout_transition_visibility_off(struct ivi_layout_surface* surface,
+ uint32_t duration)
+{
+
+ struct ivi_layout_transition* transition = NULL;
+
+ transition = get_transition_from_type_and_id(LAYOUT_TRANSITION_VIEW_FADE, surface);
+ if(transition){
+ transition->time_start = 0;
+ transition->time_duration = duration;
+ transition->destroy_func = visibility_off_transition_destroy;
+
+ float start_alpha=0.0;
+ ivi_layout_surfaceGetOpacity(surface, &start_alpha);
+
+ struct fade_view_data* data = transition->private_data;
+ data->start_alpha = wl_fixed_to_double(start_alpha);
+ data->end_alpha = 0;
+ return;
+ }
+
+ float start_alpha=0;
+ ivi_layout_surfaceGetOpacity(surface, &start_alpha);
+
+ struct store_alpha* user_data = malloc(sizeof(*user_data));
+ user_data->alpha = wl_fixed_to_double(start_alpha);
+
+ create_visibility_transition(surface,
+ wl_fixed_to_double(start_alpha),
+ 0.0f, // dest_alpha
+ user_data,
+ visibility_off_transition_destroy,
+ duration);
+}
+
+/* move layer transition */
+
+struct move_layer_data {
+ struct ivi_layout_layer* layer;
+ int32_t start_x;
+ int32_t start_y;
+ int32_t end_x;
+ int32_t end_y;
+ ivi_layout_transition_destroy_user_func destroy_func;
+};
+
+static void
+transition_move_layer_user_frame(struct ivi_layout_transition* transition)
+{
+ struct move_layer_data* data = transition->private_data;
+ struct ivi_layout_layer* layer = data->layer;
+
+ const float current = time_to_nowpos(transition);
+
+ const int32_t dest_x = data->start_x + (data->end_x - data->start_x) * current;
+ const int32_t dest_y = data->start_y + (data->end_y - data->start_y) * current;
+
+
+ int32_t pos[2] = {dest_x, dest_y};
+
+ ivi_layout_layerSetPosition(layer, pos);
+
+}
+
+static void
+transition_move_layer_destroy(struct ivi_layout_transition* transition)
+{
+
+ struct move_layer_data* data = transition->private_data;
+
+ if(data->destroy_func)
+ data->destroy_func(transition->user_data);
+
+ free(data);
+ transition->private_data = NULL;
+
+}
+
+static int32_t
+transition_move_layer_identifire(struct move_layer_data* data, struct ivi_layout_layer* layer)
+{
+ return data->layer == layer;
+}
+
+
+static struct ivi_layout_transition*
+create_move_layer_transition(
+ struct ivi_layout_layer* layer,
+ int32_t start_x, int32_t start_y,
+ int32_t end_x, int32_t end_y,
+ void* user_data,
+ ivi_layout_transition_destroy_user_func destroy_user_func,
+ uint32_t duration)
+{
+ struct ivi_layout_transition* transition = create_layout_transition();
+ struct move_layer_data* data = malloc(sizeof(*data));
+
+ transition->type = LAYOUT_TRANSITION_LAYER_MOVE;
+ transition->id_func = (ivi_layout_transition_identifire_func)transition_move_layer_identifire;
+
+ transition->frame_func = transition_move_layer_user_frame;
+ transition->destroy_func = transition_move_layer_destroy;
+ transition->private_data = data;
+ transition->user_data = user_data;
+
+ if(duration != 0)
+ transition->time_duration = duration;
+
+ data->layer = layer;
+ data->start_x = start_x;
+ data->start_y = start_y;
+ data->end_x = end_x;
+ data->end_y = end_y;
+ data->destroy_func = destroy_user_func;
+
+ return transition;
+}
+
+WL_EXPORT void
+ivi_layout_transition_move_layer(struct ivi_layout_layer* layer,
+ int32_t dest_x, int32_t dest_y,
+ uint32_t duration)
+{
+ int32_t start_pos[2] = {};
+ ivi_layout_layerGetPosition(layer, start_pos);
+
+ struct ivi_layout_transition* transition = NULL;
+ transition = create_move_layer_transition(
+ layer,
+ start_pos[0], start_pos[1],
+ dest_x, dest_y,
+ NULL, NULL,
+ duration);
+
+ layout_transition_register(transition);
+
+ return;
+}
+
+WL_EXPORT void
+ivi_layout_transition_move_layer_cancel(struct ivi_layout_layer* layer)
+{
+ struct ivi_layout_transition* transition =
+ get_transition_from_type_and_id(LAYOUT_TRANSITION_LAYER_MOVE, layer);
+ if(transition){
+ layout_transition_destroy(transition);
+ }
+}
+
+/* fade layer transition */
+struct fade_layer_data {
+ struct ivi_layout_layer* layer;
+ int32_t is_fade_in;
+ double start_alpha;
+ double end_alpha;
+ ivi_layout_transition_destroy_user_func destroy_func;
+};
+
+static void
+transition_fade_layer_destroy(struct ivi_layout_transition* transition)
+{
+ struct fade_layer_data* data = transition->private_data;
+ transition->private_data = NULL;
+
+ free(data);
+}
+
+static void
+transition_fade_layer_user_frame(struct ivi_layout_transition *transition)
+{
+ double current = time_to_nowpos(transition);
+ struct fade_layer_data* data = transition->private_data;
+ double alpha = data->start_alpha + (data->end_alpha - data->start_alpha) * current;
+ int32_t fixed_alpha = wl_fixed_from_double(alpha);
+
+ int32_t is_done = transition->is_done;
+ int32_t is_visible = !is_done || data->is_fade_in;
+
+ ivi_layout_layerSetOpacity(data->layer, fixed_alpha);
+ ivi_layout_layerSetVisibility(data->layer, is_visible);
+}
+
+static int32_t
+transition_fade_layer_identifire(struct fade_layer_data* data, struct ivi_layout_layer* layer)
+{
+ return data->layer == layer;
+}
+
+WL_EXPORT void
+ivi_layout_transition_fade_layer(struct ivi_layout_layer* layer,
+ int32_t is_fade_in,
+ double start_alpha, double end_alpha,
+ void* user_data,
+ ivi_layout_transition_destroy_user_func destroy_func,
+ uint32_t duration)
+{
+ struct ivi_layout_transition* transition = NULL;
+
+ transition = get_transition_from_type_and_id(LAYOUT_TRANSITION_LAYER_FADE, layer);
+
+ if(transition){
+ /* transition update */
+ struct fade_layer_data* data = transition->private_data;
+
+ float fixed_opacity=0.0; //FIXME
+ ivi_layout_layerGetOpacity(layer, &fixed_opacity);
+ const double now_opacity = wl_fixed_to_double(fixed_opacity);
+
+ data->is_fade_in = is_fade_in;
+ data->start_alpha = now_opacity;
+ data->end_alpha = end_alpha;
+
+ float remain = is_fade_in? 1.0 - now_opacity : now_opacity;
+ transition->time_start = 0;
+ transition->time_elapsed = 0;
+ transition->time_duration = duration * remain;
+
+ return;
+ }
+
+ transition = create_layout_transition();
+ struct fade_layer_data* data = malloc(sizeof(*data));
+ assert(data);
+
+ transition->type = LAYOUT_TRANSITION_LAYER_FADE;
+ transition->id_func = (ivi_layout_transition_identifire_func)transition_fade_layer_identifire;
+
+ transition->private_data = data;
+ transition->user_data = user_data;
+
+ transition->frame_func = transition_fade_layer_user_frame;
+ transition->destroy_func = transition_fade_layer_destroy;
+
+ if(duration != 0){
+ transition->time_duration = duration;
+ }
+
+ data->layer = layer;
+ data->is_fade_in = is_fade_in;
+ data->start_alpha = start_alpha;
+ data->end_alpha = end_alpha;
+ data->destroy_func = destroy_func;
+
+ layout_transition_register(transition);
+
+ return;
+}
+
+/* render order transition */
+struct surface_reorder{
+ uint32_t id_surface;
+ uint32_t new_index;
+};
+
+struct change_order_data{
+ struct ivi_layout_layer* layer;
+ uint32_t surface_num;
+ struct surface_reorder* reorder;
+};
+
+struct surf_with_index{
+ uint32_t id_surface;
+ float surface_index;
+};
+
+static int cmp_order_asc(const void* lhs, const void* rhs)
+{
+ return ((struct surf_with_index*)lhs)->surface_index > ((struct surf_with_index*)rhs)->surface_index;
+}
+
+/*
+render oerder transition
+
+index 0 1 2
+old surfA, surfB, surfC
+new surfB, surfC, surfA
+ (-1) (-1) (+2)
+
+after 10% of time elapsed
+ 0.2 0.9 1.9
+ surfA, surfB, surfC
+
+after 50% of time elapsed
+ 0.5 1.0 1.5
+ surfB, surfA, surfC
+*/
+
+static void
+transition_change_order_user_frame(struct ivi_layout_transition *transition)
+{
+ uint32_t i, old_index;
+ double current = time_to_nowpos(transition);
+ struct change_order_data* data = transition->private_data;
+
+ struct surf_with_index* swi = malloc(sizeof(*swi)*data->surface_num);
+
+ for(old_index=0; old_index<data->surface_num; old_index++){
+ swi[old_index].id_surface = data->reorder[old_index].id_surface;
+ swi[old_index].surface_index = (float)old_index +
+ ((float)data->reorder[old_index].new_index - (float)old_index) * current;
+ }
+
+ qsort(swi, data->surface_num, sizeof(*swi), cmp_order_asc);
+
+/*
+ fprintf(stderr, "=========\n");
+ for(i=0; i<data->surface_num;i++){
+ fprintf(stderr, "surface %d: %f\n", swi[i].id_surface, swi[i].surface_index);
+ }
+*/
+
+ struct ivi_layout_surface** new_surface_order =
+ malloc(sizeof(*new_surface_order) * data->surface_num);
+
+ uint32_t surface_num = 0;
+ for(i=0; i<data->surface_num; i++){
+ struct ivi_layout_surface* surf = ivi_layout_getSurfaceFromId(swi[i].id_surface);
+ if(surf)
+ new_surface_order[surface_num++] = surf;
+ }
+
+ ivi_layout_layerSetRenderOrder(data->layer, new_surface_order, surface_num);
+
+ free(new_surface_order);
+ free(swi);
+}
+
+static void
+transition_change_order_destroy(struct ivi_layout_transition* transition)
+{
+ struct change_order_data* data = transition->private_data;
+
+ free(data->reorder);
+ free(data);
+}
+
+static int32_t find_surface(struct ivi_layout_surface** surfaces,
+ uint32_t surface_num,
+ struct ivi_layout_surface* target)
+{
+ uint32_t i=0;
+ for(i=0; i<surface_num; i++){
+ if(surfaces[i] == target)
+ return i;
+ }
+
+ return -1;
+}
+
+static int32_t
+transition_change_order_identifire(struct change_order_data* data, struct ivi_layout_layer* layer)
+{
+ return data->layer == layer;
+}
+
+WL_EXPORT void
+ivi_layout_transition_layer_render_order(struct ivi_layout_layer* layer,
+ struct ivi_layout_surface** new_order,
+ uint32_t surface_num,
+ uint32_t duration)
+{
+ struct surface_reorder* reorder = malloc(sizeof(*reorder)*surface_num);
+ struct ivi_layout_surface* surf=NULL;
+ uint32_t old_index = 0;
+
+ wl_list_for_each(surf, &layer->order.list_surface, order.link){
+ int32_t new_index = find_surface(new_order, surface_num, surf);
+ if(new_index < 0){
+ fprintf(stderr, "invalid render order!!!\n");
+ return;
+ }
+
+ const uint32_t id = ivi_layout_getIdOfSurface(surf);
+
+ reorder[old_index].id_surface = id;
+ reorder[old_index].new_index = new_index;
+ old_index++;
+ }
+
+ struct ivi_layout_transition* transition = NULL;
+
+ transition = get_transition_from_type_and_id(LAYOUT_TRANSITION_LAYER_VIEW_ORDER, layer);
+ if(transition){
+ /* update transition */
+ transition->time_start = 0; /* timer reset */
+
+ if(duration != 0){
+ transition->time_duration = duration;
+ }
+
+ struct change_order_data* data = transition->private_data;
+ free(data->reorder);
+ data->reorder = reorder;
+ return;
+ }
+
+ transition = create_layout_transition();
+ struct change_order_data* data = malloc(sizeof(*data));
+ assert(data);
+
+ transition->type = LAYOUT_TRANSITION_LAYER_VIEW_ORDER;
+ transition->id_func = (ivi_layout_transition_identifire_func)transition_change_order_identifire;
+
+ transition->private_data = data;
+ transition->frame_func = transition_change_order_user_frame;
+ transition->destroy_func = transition_change_order_destroy;
+
+ if(duration != 0){
+ transition->time_duration = duration;
+ }
+
+ data->layer = layer;
+ data->reorder = reorder;
+ data->surface_num = old_index;
+
+ layout_transition_register(transition);
+
+}