aboutsummaryrefslogtreecommitdiffstats
path: root/meta-ivi-common/recipes-graphics/wayland
diff options
context:
space:
mode:
authorManuel Bachmann <manuel.bachmann@iot.bzh>2015-09-29 18:56:55 +0000
committerManuel Bachmann <mbc@iot.bzh>2015-09-30 03:47:01 +0000
commit06963e9e7e72e5bf730d08ed4b83bc12dcee4ad6 (patch)
tree45c7218aa64a5fdc07e0d2dbf84eb30e3730bd58 /meta-ivi-common/recipes-graphics/wayland
parente0cb14ae3f8eac1fb4c9c48b90e60115a0468985 (diff)
Provide Weston IVI-Shell, run it on demand
Weston IVI-Shell provides a shell plugin for Weston, mapping the GENIVI API (http://www.genivi.org) for In-Vehicle Infotainment. This is a code backport from Weston 1.9.0 "release". This patch makes sure that Weston IVI-Shell always gets built ; it will not be started, however, unless the builder specifies the following in his "conf/local.conf" file : IMAGE_INSTALL_append = " \ weston-ivi-shell-config \ " or manually overwrites the "/etc/xdg/weston/weston.ini" file with a correct one. Change-Id: I033094aaf8ac2c6299bd354b362b24ffc9ed8577 Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
Diffstat (limited to 'meta-ivi-common/recipes-graphics/wayland')
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell-config.bb14
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch10478
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/background.pngbin0 -> 245579 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/fullscreen.pngbin0 -> 3406 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/home.pngbin0 -> 4629 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_clickdot.pngbin0 -> 39523 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_flower.pngbin0 -> 24475 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-egl.pngbin0 -> 29316 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-shm.pngbin0 -> 71120 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_smoke.pngbin0 -> 46577 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/panel.pngbin0 -> 41955 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/random.pngbin0 -> 4891 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/sidebyside.pngbin0 -> 3929 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/tiling.pngbin0 -> 5620 bytes
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/weston.ini.ivi-shell98
-rw-r--r--meta-ivi-common/recipes-graphics/wayland/weston_1.5.0.bbappend23
16 files changed, 10613 insertions, 0 deletions
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell-config.bb b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell-config.bb
new file mode 100644
index 000000000..08921ef8e
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell-config.bb
@@ -0,0 +1,14 @@
+SUMMARY = "Configuration file for Weston IVI-Shell"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690"
+
+FILESEXTRAPATHS_prepend := ":${THISDIR}/weston-ivi-shell:"
+
+SRC_URI = "file://weston.ini.ivi-shell"
+
+do_install() {
+ install -d ${D}${sysconfdir}/xdg/weston
+ install -m644 ${WORKDIR}/weston.ini.ivi-shell ${D}${sysconfdir}/xdg/weston/weston.ini
+}
+
+RDEPENDS_${PN} = "weston"
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch
new file mode 100644
index 000000000..0e5a99f0b
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch
@@ -0,0 +1,10478 @@
+From 9e55f4f9c921782263b784e7f6e0e9b0fc9095ca Mon Sep 17 00:00:00 2001
+From: Manuel Bachmann <manuel.bachmann@iot.bzh>
+Date: Mon, 28 Sep 2015 04:45:19 +0200
+Subject: [PATCH] Backport IVI-Shell from Weston 1.9.0 to 1.5.0
+
+IVI-Shell is the alternative Weston shell implementing the
+eponymous protocol, and supported in client toolkits such
+as EFL, Qt...
+
+We backport only the necessary, without touching the core
+compositor if possible (was only necessary for surface
+copying logic which had a patch in Tizen IVI).
+
+Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
+---
+ Makefile.am | 113 +-
+ clients/ivi-shell-user-interface.c | 1312 ++++++++++++++++
+ clients/simple-egl.c | 78 +-
+ clients/simple-shm.c | 37 +
+ clients/window.c | 57 +-
+ configure.ac | 9 +
+ data/background.png | Bin 0 -> 245579 bytes
+ data/fullscreen.png | Bin 0 -> 3406 bytes
+ data/home.png | Bin 0 -> 4629 bytes
+ data/icon_ivi_clickdot.png | Bin 0 -> 39523 bytes
+ data/icon_ivi_flower.png | Bin 0 -> 24475 bytes
+ data/icon_ivi_simple-egl.png | Bin 0 -> 29316 bytes
+ data/icon_ivi_simple-shm.png | Bin 0 -> 71120 bytes
+ data/icon_ivi_smoke.png | Bin 0 -> 46577 bytes
+ data/panel.png | Bin 0 -> 41955 bytes
+ data/random.png | Bin 0 -> 4891 bytes
+ data/sidebyside.png | Bin 0 -> 3929 bytes
+ data/tiling.png | Bin 0 -> 5620 bytes
+ ivi-shell/hmi-controller.c | 1814 ++++++++++++++++++++++
+ ivi-shell/input-panel-ivi.c | 397 +++++
+ ivi-shell/ivi-layout-export.h | 813 ++++++++++
+ ivi-shell/ivi-layout-private.h | 229 +++
+ ivi-shell/ivi-layout-transition.c | 871 +++++++++++
+ ivi-shell/ivi-layout.c | 3011 ++++++++++++++++++++++++++++++++++++
+ ivi-shell/ivi-shell.c | 469 ++++++
+ ivi-shell/ivi-shell.h | 67 +
+ ivi-shell/weston.ini.in | 98 ++
+ protocol/ivi-application.xml | 100 ++
+ protocol/ivi-hmi-controller.xml | 98 ++
+ shared/helpers.h | 96 ++
+ src/compositor.c | 48 +
+ src/compositor.h | 20 +
+ src/gl-renderer.c | 150 ++
+ src/pixman-renderer.c | 51 +
+ 34 files changed, 9915 insertions(+), 23 deletions(-)
+ create mode 100644 clients/ivi-shell-user-interface.c
+ create mode 100644 data/background.png
+ create mode 100644 data/fullscreen.png
+ create mode 100644 data/home.png
+ create mode 100644 data/icon_ivi_clickdot.png
+ create mode 100644 data/icon_ivi_flower.png
+ create mode 100644 data/icon_ivi_simple-egl.png
+ create mode 100644 data/icon_ivi_simple-shm.png
+ create mode 100644 data/icon_ivi_smoke.png
+ create mode 100644 data/panel.png
+ create mode 100644 data/random.png
+ create mode 100644 data/sidebyside.png
+ create mode 100644 data/tiling.png
+ create mode 100644 ivi-shell/hmi-controller.c
+ create mode 100644 ivi-shell/input-panel-ivi.c
+ create mode 100644 ivi-shell/ivi-layout-export.h
+ create mode 100644 ivi-shell/ivi-layout-private.h
+ create mode 100644 ivi-shell/ivi-layout-transition.c
+ create mode 100644 ivi-shell/ivi-layout.c
+ create mode 100644 ivi-shell/ivi-shell.c
+ create mode 100644 ivi-shell/ivi-shell.h
+ create mode 100644 ivi-shell/weston.ini.in
+ create mode 100644 protocol/ivi-application.xml
+ create mode 100644 protocol/ivi-hmi-controller.xml
+ create mode 100644 shared/helpers.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 343adc6..7649d7d 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -8,7 +8,7 @@ BUILT_SOURCES =
+
+ DISTCHECK_CONFIGURE_FLAGS = --disable-setuid-install
+
+-EXTRA_DIST = weston.ini.in
++EXTRA_DIST = weston.ini.in ivi-shell/weston.ini.in
+
+ weston.ini : $(srcdir)/weston.ini.in
+ $(AM_V_GEN)$(SED) \
+@@ -17,7 +17,16 @@ weston.ini : $(srcdir)/weston.ini.in
+ -e 's|@libexecdir[@]|$(libexecdir)|g' \
+ $< > $@
+
+-all-local : weston.ini
++ivi-shell/weston.ini : $(srcdir)/ivi-shell/weston.ini.in
++ $(AM_V_GEN)$(SED) \
++ -e 's|@bindir[@]|$(bindir)|g' \
++ -e 's|@abs_top_builddir[@]|$(abs_top_builddir)|g' \
++ -e 's|@abs_top_srcdir[@]|$(abs_top_srcdir)|g' \
++ -e 's|@libexecdir[@]|$(libexecdir)|g' \
++ -e 's|@plugin_prefix[@]||g' \
++ $< > $@
++
++all-local : weston.ini ivi-shell/weston.ini
+
+ AM_CFLAGS = $(GCC_CFLAGS)
+
+@@ -33,7 +42,7 @@ AM_CPPFLAGS = \
+ -DLIBEXECDIR='"$(libexecdir)"' \
+ -DBINDIR='"$(bindir)"'
+
+-CLEANFILES = weston.ini $(BUILT_SOURCES)
++CLEANFILES = weston.ini ivi-shell/weston.ini $(BUILT_SOURCES)
+
+ bin_PROGRAMS += weston
+
+@@ -361,6 +370,11 @@ libexec_PROGRAMS += \
+ weston-keyboard \
+ weston-simple-im
+
++if ENABLE_IVI_SHELL
++libexec_PROGRAMS += \
++ weston-ivi-shell-user-interface
++endif
++
+ demo_clients = \
+ weston-flower \
+ weston-image \
+@@ -394,7 +408,9 @@ nodist_weston_simple_shm_SOURCES = \
+ protocol/xdg-shell-protocol.c \
+ protocol/xdg-shell-client-protocol.h \
+ protocol/fullscreen-shell-protocol.c \
+- protocol/fullscreen-shell-client-protocol.h
++ protocol/fullscreen-shell-client-protocol.h \
++ protocol/ivi-application-protocol.c \
++ protocol/ivi-application-client-protocol.h
+ weston_simple_shm_CFLAGS = $(AM_CFLAGS) $(SIMPLE_CLIENT_CFLAGS)
+ weston_simple_shm_LDADD = $(SIMPLE_CLIENT_LIBS) libshared.la
+
+@@ -412,7 +428,9 @@ demo_clients += weston-simple-egl
+ weston_simple_egl_SOURCES = clients/simple-egl.c
+ nodist_weston_simple_egl_SOURCES = \
+ protocol/xdg-shell-protocol.c \
+- protocol/xdg-shell-client-protocol.h
++ protocol/xdg-shell-client-protocol.h \
++ protocol/ivi-application-protocol.c \
++ protocol/ivi-application-client-protocol.h
+ weston_simple_egl_CFLAGS = $(AM_CFLAGS) $(SIMPLE_EGL_CLIENT_CFLAGS)
+ weston_simple_egl_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
+ endif
+@@ -431,7 +449,9 @@ nodist_libtoytoolkit_la_SOURCES = \
+ protocol/workspaces-protocol.c \
+ protocol/workspaces-client-protocol.h \
+ protocol/xdg-shell-protocol.c \
+- protocol/xdg-shell-client-protocol.h
++ protocol/xdg-shell-client-protocol.h \
++ protocol/ivi-application-protocol.c \
++ protocol/ivi-application-client-protocol.h
+
+ BUILT_SOURCES += $(nodist_libtoytoolkit_la_SOURCES)
+
+@@ -570,6 +590,19 @@ nodist_weston_desktop_shell_SOURCES = \
+ weston_desktop_shell_LDADD = libtoytoolkit.la
+ weston_desktop_shell_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+
++if ENABLE_IVI_SHELL
++weston_ivi_shell_user_interface_SOURCES = \
++ clients/ivi-shell-user-interface.c \
++ shared/helpers.h
++nodist_weston_ivi_shell_user_interface_SOURCES = \
++ protocol/ivi-hmi-controller-client-protocol.h \
++ protocol/ivi-hmi-controller-protocol.c \
++ protocol/ivi-application-client-protocol.h \
++ protocol/ivi-application-protocol.c
++weston_ivi_shell_user_interface_LDADD = libtoytoolkit.la
++weston_ivi_shell_user_interface_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
++endif
++
+ if BUILD_FULL_GL_CLIENTS
+ demo_clients += weston-gears
+ weston_gears_SOURCES = clients/gears.c
+@@ -616,8 +649,11 @@ BUILT_SOURCES += \
+ protocol/fullscreen-shell-protocol.c \
+ protocol/fullscreen-shell-client-protocol.h \
+ protocol/xdg-shell-protocol.c \
+- protocol/xdg-shell-client-protocol.h
+-
++ protocol/xdg-shell-client-protocol.h \
++ protocol/ivi-hmi-controller-protocol.c \
++ protocol/ivi-hmi-controller-client-protocol.h \
++ protocol/ivi-application-protocol.c \
++ protocol/ivi-application-client-protocol.h
+
+ westondatadir = $(datadir)/weston
+ dist_westondata_DATA = \
+@@ -631,6 +667,21 @@ dist_westondata_DATA = \
+ data/sign_maximize.png \
+ data/sign_minimize.png
+
++if ENABLE_IVI_SHELL
++dist_westondata_DATA += \
++ data/background.png \
++ data/tiling.png \
++ data/fullscreen.png \
++ data/panel.png \
++ data/random.png \
++ data/sidebyside.png \
++ data/home.png \
++ data/icon_ivi_clickdot.png \
++ data/icon_ivi_flower.png \
++ data/icon_ivi_simple-egl.png \
++ data/icon_ivi_simple-shm.png \
++ data/icon_ivi_smoke.png
++endif
+
+ if BUILD_WCAP_TOOLS
+ bin_PROGRAMS += wcap-decode
+@@ -700,6 +751,48 @@ nodist_fullscreen_shell_la_SOURCES = \
+ BUILT_SOURCES += $(nodist_fullscreen_shell_la_SOURCES)
+ endif
+
++if ENABLE_IVI_SHELL
++
++module_LTLIBRARIES += \
++ $(ivi_shell) \
++ $(hmi_controller)
++
++ivi_shell = ivi-shell.la
++ivi_shell_la_LDFLAGS = -module -avoid-version
++ivi_shell_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la
++ivi_shell_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS)
++ivi_shell_la_SOURCES = \
++ ivi-shell/ivi-layout-export.h \
++ ivi-shell/ivi-layout-private.h \
++ ivi-shell/ivi-layout.c \
++ ivi-shell/ivi-layout-transition.c \
++ ivi-shell/ivi-shell.h \
++ ivi-shell/ivi-shell.c \
++ ivi-shell/input-panel-ivi.c \
++ shared/helpers.h
++nodist_ivi_shell_la_SOURCES = \
++ protocol/ivi-application-protocol.c \
++ protocol/ivi-application-server-protocol.h
++
++BUILT_SOURCES += $(nodist_ivi_shell_la_SOURCES)
++
++hmi_controller = hmi-controller.la
++hmi_controller_la_LDFLAGS = -module -avoid-version
++hmi_controller_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la
++hmi_controller_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS)
++hmi_controller_la_SOURCES = \
++ ivi-shell/ivi-layout-export.h \
++ ivi-shell/hmi-controller.c \
++ shared/helpers.h
++nodist_hmi_controller_la_SOURCES = \
++ protocol/ivi-hmi-controller-protocol.c \
++ protocol/ivi-hmi-controller-server-protocol.h
++
++BUILT_SOURCES += $(nodist_hmi_controller_la_SOURCES)
++
++endif
++
++
+ if ENABLE_SCREEN_SHARING
+
+ module_LTLIBRARIES += screen-share.la
+@@ -969,7 +1062,9 @@ EXTRA_DIST += \
+ protocol/wayland-test.xml \
+ protocol/xdg-shell.xml \
+ protocol/fullscreen-shell.xml \
+- protocol/scaler.xml
++ protocol/scaler.xml \
++ protocol/ivi-application.xml \
++ protocol/ivi-hmi-controller.xml
+
+ man_MANS = weston.1 weston.ini.5
+
+diff --git a/clients/ivi-shell-user-interface.c b/clients/ivi-shell-user-interface.c
+new file mode 100644
+index 0000000..dbe7a88
+--- /dev/null
++++ b/clients/ivi-shell-user-interface.c
+@@ -0,0 +1,1312 @@
++/*
++ * Copyright (C) 2013 DENSO CORPORATION
++ *
++ * 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 (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS 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 <sys/wait.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <linux/input.h>
++#include <assert.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <sys/mman.h>
++#include <getopt.h>
++#include <wayland-cursor.h>
++#include <wayland-client-protocol.h>
++#include "shared/cairo-util.h"
++#include "shared/config-parser.h"
++#include "shared/helpers.h"
++#include "shared/os-compatibility.h"
++#include "ivi-application-client-protocol.h"
++#include "ivi-hmi-controller-client-protocol.h"
++
++/**
++ * A reference implementation how to use ivi-hmi-controller interface to
++ * interact with hmi-controller. This is launched from hmi-controller by using
++ * hmi_client_start and create a pthread.
++ *
++ * The basic flow is as followed,
++ * 1/ read configuration from weston.ini.
++ * 2/ draw png file to surface according to configuration of weston.ini
++ * 3/ set up UI by using ivi-hmi-controller protocol
++ * 4/ Enter event loop
++ * 5/ If a surface receives touch/pointer event, followings are invoked
++ * according to type of event and surface
++ * 5-1/ If a surface to launch ivi_application receive touch up, it execs
++ * ivi-application configured in weston.ini.
++ * 5-2/ If a surface to switch layout mode receive touch up, it sends a request,
++ * ivi_hmi_controller_switch_mode, to hmi-controller.
++ * 5-3/ If a surface to show workspace having launchers, it sends a request,
++ * ivi_hmi_controller_home, to hmi-controller.
++ * 5-4/ If touch down events happens in workspace,
++ * ivi_hmi_controller_workspace_control is sent to slide workspace.
++ * When control finished, event: ivi_hmi_controller_workspace_end_control
++ * is received.
++ */
++
++/*****************************************************************************
++ * structure, globals
++ ****************************************************************************/
++enum cursor_type {
++ CURSOR_BOTTOM_LEFT,
++ CURSOR_BOTTOM_RIGHT,
++ CURSOR_BOTTOM,
++ CURSOR_DRAGGING,
++ CURSOR_LEFT_PTR,
++ CURSOR_LEFT,
++ CURSOR_RIGHT,
++ CURSOR_TOP_LEFT,
++ CURSOR_TOP_RIGHT,
++ CURSOR_TOP,
++ CURSOR_IBEAM,
++ CURSOR_HAND1,
++ CURSOR_WATCH,
++
++ CURSOR_BLANK
++};
++struct wlContextCommon {
++ struct wl_display *wlDisplay;
++ struct wl_registry *wlRegistry;
++ struct wl_compositor *wlCompositor;
++ struct wl_shm *wlShm;
++ uint32_t formats;
++ struct wl_seat *wlSeat;
++ struct wl_pointer *wlPointer;
++ struct wl_touch *wlTouch;
++ struct ivi_application *iviApplication;
++ struct ivi_hmi_controller *hmiCtrl;
++ struct hmi_homescreen_setting *hmi_setting;
++ struct wl_list list_wlContextStruct;
++ struct wl_surface *enterSurface;
++ int32_t is_home_on;
++ struct wl_cursor_theme *cursor_theme;
++ struct wl_cursor **cursors;
++ struct wl_surface *pointer_surface;
++ enum cursor_type current_cursor;
++ uint32_t enter_serial;
++};
++
++struct wlContextStruct {
++ struct wlContextCommon *cmm;
++ struct wl_surface *wlSurface;
++ struct wl_buffer *wlBuffer;
++ cairo_surface_t *ctx_image;
++ void *data;
++ uint32_t id_surface;
++ struct wl_list link;
++};
++
++struct
++hmi_homescreen_srf {
++ uint32_t id;
++ char *filePath;
++ uint32_t color;
++};
++
++struct
++hmi_homescreen_workspace {
++ struct wl_array launcher_id_array;
++ struct wl_list link;
++};
++
++struct
++hmi_homescreen_launcher {
++ uint32_t icon_surface_id;
++ uint32_t workspace_id;
++ char *icon;
++ char *path;
++ struct wl_list link;
++};
++
++struct
++hmi_homescreen_setting {
++ struct hmi_homescreen_srf background;
++ struct hmi_homescreen_srf panel;
++ struct hmi_homescreen_srf tiling;
++ struct hmi_homescreen_srf sidebyside;
++ struct hmi_homescreen_srf fullscreen;
++ struct hmi_homescreen_srf random;
++ struct hmi_homescreen_srf home;
++ struct hmi_homescreen_srf workspace_background;
++
++ struct wl_list workspace_list;
++ struct wl_list launcher_list;
++
++ char *cursor_theme;
++ int32_t cursor_size;
++ uint32_t transition_duration;
++};
++
++static void *
++fail_on_null(void *p, size_t size, char *file, int32_t line)
++{
++ if (size && !p) {
++ fprintf(stderr, "%s(%d) %zd: out of memory\n",
++ file, line, size);
++ exit(EXIT_FAILURE);
++ }
++
++ return p;
++}
++
++static void *
++mem_alloc(size_t size, char *file, int32_t line)
++{
++ return fail_on_null(calloc(1, size), size, file, line);
++}
++
++#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
++
++/*****************************************************************************
++ * Event Handler
++ ****************************************************************************/
++
++static void
++shm_format(void *data, struct wl_shm *pWlShm, uint32_t format)
++{
++ struct wlContextCommon *pCtx = data;
++
++ pCtx->formats |= (1 << format);
++}
++
++static struct wl_shm_listener shm_listenter = {
++ shm_format
++};
++
++static int32_t
++getIdOfWlSurface(struct wlContextCommon *pCtx, struct wl_surface *wlSurface)
++{
++ struct wlContextStruct *pWlCtxSt = NULL;
++
++ if (NULL == pCtx || NULL == wlSurface )
++ return 0;
++
++ wl_list_for_each(pWlCtxSt, &pCtx->list_wlContextStruct, link) {
++ if (pWlCtxSt->wlSurface == wlSurface)
++ return pWlCtxSt->id_surface;
++ }
++
++ return -1;
++}
++
++static void
++set_pointer_image(struct wlContextCommon *pCtx, uint32_t index)
++{
++ struct wl_cursor *cursor = NULL;
++ struct wl_cursor_image *image = NULL;
++ struct wl_buffer *buffer = NULL;
++
++ if (!pCtx->wlPointer || !pCtx->cursors)
++ return;
++
++ if (CURSOR_BLANK == pCtx->current_cursor) {
++ wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,
++ NULL, 0, 0);
++ return;
++ }
++
++ cursor = pCtx->cursors[pCtx->current_cursor];
++ if (!cursor)
++ return;
++
++ if (cursor->image_count <= index) {
++ fprintf(stderr, "cursor index out of range\n");
++ return;
++ }
++
++ image = cursor->images[index];
++ buffer = wl_cursor_image_get_buffer(image);
++
++ if (!buffer)
++ return;
++
++ wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,
++ pCtx->pointer_surface,
++ image->hotspot_x, image->hotspot_y);
++
++ wl_surface_attach(pCtx->pointer_surface, buffer, 0, 0);
++
++ wl_surface_damage(pCtx->pointer_surface, 0, 0,
++ image->width, image->height);
++
++ wl_surface_commit(pCtx->pointer_surface);
++}
++
++static void
++PointerHandleEnter(void *data, struct wl_pointer *wlPointer, uint32_t serial,
++ struct wl_surface *wlSurface, wl_fixed_t sx, wl_fixed_t sy)
++{
++ struct wlContextCommon *pCtx = data;
++
++ pCtx->enter_serial = serial;
++ pCtx->enterSurface = wlSurface;
++ set_pointer_image(pCtx, 0);
++#ifdef _DEBUG
++ printf("ENTER PointerHandleEnter: x(%d), y(%d)\n", sx, sy);
++#endif
++}
++
++static void
++PointerHandleLeave(void *data, struct wl_pointer *wlPointer, uint32_t serial,
++ struct wl_surface *wlSurface)
++{
++ struct wlContextCommon *pCtx = data;
++
++ pCtx->enterSurface = NULL;
++
++#ifdef _DEBUG
++ printf("ENTER PointerHandleLeave: serial(%d)\n", serial);
++#endif
++}
++
++static void
++PointerHandleMotion(void *data, struct wl_pointer *wlPointer, uint32_t time,
++ wl_fixed_t sx, wl_fixed_t sy)
++{
++#ifdef _DEBUG
++ printf("ENTER PointerHandleMotion: x(%d), y(%d)\n", sx, sy);
++#endif
++}
++
++/**
++ * if a surface assigned as launcher receives touch-off event, invoking
++ * ivi-application which configured in weston.ini with path to binary.
++ */
++extern char **environ; /*defied by libc */
++
++static pid_t
++execute_process(char *path, char *argv[])
++{
++ pid_t pid = fork();
++ if (pid < 0)
++ fprintf(stderr, "Failed to fork\n");
++
++ if (pid)
++ return pid;
++
++ if (-1 == execve(path, argv, environ)) {
++ fprintf(stderr, "Failed to execve %s\n", path);
++ exit(1);
++ }
++
++ return pid;
++}
++
++static int32_t
++launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
++{
++ struct hmi_homescreen_launcher *launcher = NULL;
++
++ wl_list_for_each(launcher, launcher_list, link) {
++ char *argv[] = { NULL };
++
++ if (surfaceId != launcher->icon_surface_id)
++ continue;
++
++ execute_process(launcher->path, argv);
++
++ return 1;
++ }
++
++ return 0;
++}
++
++/**
++ * is-method to identify a surface set as launcher in workspace or workspace
++ * itself. This is-method is used to decide whether request;
++ * ivi_hmi_controller_workspace_control is sent or not.
++ */
++static int32_t
++isWorkspaceSurface(uint32_t id, struct hmi_homescreen_setting *hmi_setting)
++{
++ struct hmi_homescreen_launcher *launcher = NULL;
++
++ if (id == hmi_setting->workspace_background.id)
++ return 1;
++
++ wl_list_for_each(launcher, &hmi_setting->launcher_list, link) {
++ if (id == launcher->icon_surface_id)
++ return 1;
++ }
++
++ return 0;
++}
++
++/**
++ * Decide which request is sent to hmi-controller
++ */
++static void
++touch_up(struct ivi_hmi_controller *hmi_ctrl, uint32_t id_surface,
++ int32_t *is_home_on, struct hmi_homescreen_setting *hmi_setting)
++{
++ if (launcher_button(id_surface, &hmi_setting->launcher_list)) {
++ *is_home_on = 0;
++ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
++ } else if (id_surface == hmi_setting->tiling.id) {
++ ivi_hmi_controller_switch_mode(hmi_ctrl,
++ IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING);
++ } else if (id_surface == hmi_setting->sidebyside.id) {
++ ivi_hmi_controller_switch_mode(hmi_ctrl,
++ IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE);
++ } else if (id_surface == hmi_setting->fullscreen.id) {
++ ivi_hmi_controller_switch_mode(hmi_ctrl,
++ IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN);
++ } else if (id_surface == hmi_setting->random.id) {
++ ivi_hmi_controller_switch_mode(hmi_ctrl,
++ IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM);
++ } else if (id_surface == hmi_setting->home.id) {
++ *is_home_on = !(*is_home_on);
++ if (*is_home_on) {
++ ivi_hmi_controller_home(hmi_ctrl,
++ IVI_HMI_CONTROLLER_HOME_ON);
++ } else {
++ ivi_hmi_controller_home(hmi_ctrl,
++ IVI_HMI_CONTROLLER_HOME_OFF);
++ }
++ }
++}
++
++/**
++ * Even handler of Pointer event. IVI system is usually manipulated by touch
++ * screen. However, some systems also have pointer device.
++ * Release is the same behavior as touch off
++ * Pressed is the same behavior as touch on
++ */
++static void
++PointerHandleButton(void *data, struct wl_pointer *wlPointer, uint32_t serial,
++ uint32_t time, uint32_t button, uint32_t state)
++{
++ struct wlContextCommon *pCtx = data;
++ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
++ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
++
++ if (BTN_RIGHT == button)
++ return;
++
++ switch (state) {
++ case WL_POINTER_BUTTON_STATE_RELEASED:
++ touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on,
++ pCtx->hmi_setting);
++ break;
++
++ case WL_POINTER_BUTTON_STATE_PRESSED:
++
++ if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {
++ ivi_hmi_controller_workspace_control(hmi_ctrl,
++ pCtx->wlSeat,
++ serial);
++ }
++
++ break;
++ }
++#ifdef _DEBUG
++ printf("ENTER PointerHandleButton: button(%d), state(%d)\n",
++ button, state);
++#endif
++}
++
++static void
++PointerHandleAxis(void *data, struct wl_pointer *wlPointer, uint32_t time,
++ uint32_t axis, wl_fixed_t value)
++{
++#ifdef _DEBUG
++ printf("ENTER PointerHandleAxis: axis(%d), value(%d)\n", axis, value);
++#endif
++}
++
++static struct wl_pointer_listener pointer_listener = {
++ PointerHandleEnter,
++ PointerHandleLeave,
++ PointerHandleMotion,
++ PointerHandleButton,
++ PointerHandleAxis
++};
++
++/**
++ * Even handler of touch event
++ */
++static void
++TouchHandleDown(void *data, struct wl_touch *wlTouch, uint32_t serial,
++ uint32_t time, struct wl_surface *surface, int32_t id,
++ wl_fixed_t x_w, wl_fixed_t y_w)
++{
++ struct wlContextCommon *pCtx = data;
++ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
++ uint32_t id_surface = 0;
++
++ if (0 == id)
++ pCtx->enterSurface = surface;
++
++ id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
++
++ /**
++ * When touch down happens on surfaces of workspace, ask
++ * hmi-controller to start control workspace to select page of
++ * workspace. After sending seat to hmi-controller by
++ * ivi_hmi_controller_workspace_control,
++ * hmi-controller-homescreen doesn't receive any event till
++ * hmi-controller sends back it.
++ */
++ if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {
++ ivi_hmi_controller_workspace_control(hmi_ctrl, pCtx->wlSeat,
++ serial);
++ }
++}
++
++static void
++TouchHandleUp(void *data, struct wl_touch *wlTouch, uint32_t serial,
++ uint32_t time, int32_t id)
++{
++ struct wlContextCommon *pCtx = data;
++ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
++
++ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
++
++ /**
++ * triggering event according to touch-up happening on which surface.
++ */
++ if (id == 0){
++ touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on,
++ pCtx->hmi_setting);
++ }
++}
++
++static void
++TouchHandleMotion(void *data, struct wl_touch *wlTouch, uint32_t time,
++ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
++{
++}
++
++static void
++TouchHandleFrame(void *data, struct wl_touch *wlTouch)
++{
++}
++
++static void
++TouchHandleCancel(void *data, struct wl_touch *wlTouch)
++{
++}
++
++static struct wl_touch_listener touch_listener = {
++ TouchHandleDown,
++ TouchHandleUp,
++ TouchHandleMotion,
++ TouchHandleFrame,
++ TouchHandleCancel,
++};
++
++/**
++ * Handler of capabilities
++ */
++static void
++seat_handle_capabilities(void *data, struct wl_seat *seat, uint32_t caps)
++{
++ struct wlContextCommon *p_wlCtx = (struct wlContextCommon*)data;
++ struct wl_seat *wlSeat = p_wlCtx->wlSeat;
++ struct wl_pointer *wlPointer = p_wlCtx->wlPointer;
++ struct wl_touch *wlTouch = p_wlCtx->wlTouch;
++
++ if (p_wlCtx->hmi_setting->cursor_theme) {
++ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlPointer){
++ wlPointer = wl_seat_get_pointer(wlSeat);
++ wl_pointer_add_listener(wlPointer,
++ &pointer_listener, data);
++ } else
++ if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlPointer){
++ wl_pointer_destroy(wlPointer);
++ wlPointer = NULL;
++ }
++ p_wlCtx->wlPointer = wlPointer;
++ }
++
++ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wlTouch){
++ wlTouch = wl_seat_get_touch(wlSeat);
++ wl_touch_add_listener(wlTouch, &touch_listener, data);
++ } else
++ if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wlTouch){
++ wl_touch_destroy(wlTouch);
++ wlTouch = NULL;
++ }
++ p_wlCtx->wlTouch = wlTouch;
++}
++
++static struct wl_seat_listener seat_Listener = {
++ seat_handle_capabilities,
++};
++
++/**
++ * Registration of event
++ * This event is received when hmi-controller server finished controlling
++ * workspace.
++ */
++static void
++ivi_hmi_controller_workspace_end_control(void *data,
++ struct ivi_hmi_controller *hmi_ctrl,
++ int32_t is_controlled)
++{
++ struct wlContextCommon *pCtx = data;
++ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
++
++ if (is_controlled)
++ return;
++
++ /**
++ * During being controlled by hmi-controller, any input event is not
++ * notified. So when control ends with touch up, it invokes launcher
++ * if up event happens on a launcher surface.
++ *
++ */
++ if (launcher_button(id_surface, &pCtx->hmi_setting->launcher_list)) {
++ pCtx->is_home_on = 0;
++ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
++ }
++}
++
++static const struct ivi_hmi_controller_listener hmi_controller_listener = {
++ ivi_hmi_controller_workspace_end_control
++};
++
++/**
++ * Registration of interfaces
++ */
++static void
++registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
++ const char *interface, uint32_t version)
++{
++ struct wlContextCommon *p_wlCtx = (struct wlContextCommon*)data;
++
++ if (!strcmp(interface, "wl_compositor")) {
++ p_wlCtx->wlCompositor =
++ wl_registry_bind(registry, name,
++ &wl_compositor_interface, 1);
++ } else if (!strcmp(interface, "wl_shm")) {
++ p_wlCtx->wlShm =
++ wl_registry_bind(registry, name, &wl_shm_interface, 1);
++ wl_shm_add_listener(p_wlCtx->wlShm, &shm_listenter, p_wlCtx);
++ } else if (!strcmp(interface, "wl_seat")) {
++ p_wlCtx->wlSeat =
++ wl_registry_bind(registry, name, &wl_seat_interface, 1);
++ wl_seat_add_listener(p_wlCtx->wlSeat, &seat_Listener, data);
++ } else if (!strcmp(interface, "ivi_application")) {
++ p_wlCtx->iviApplication =
++ wl_registry_bind(registry, name,
++ &ivi_application_interface, 1);
++ } else if (!strcmp(interface, "ivi_hmi_controller")) {
++ p_wlCtx->hmiCtrl =
++ wl_registry_bind(registry, name,
++ &ivi_hmi_controller_interface, 1);
++
++ ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl,
++ &hmi_controller_listener, p_wlCtx);
++ }
++}
++
++static void
++registry_handle_global_remove(void *data, struct wl_registry *registry,
++ uint32_t name)
++{
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_global,
++ registry_handle_global_remove
++};
++
++static void
++frame_listener_func(void *data, struct wl_callback *callback, uint32_t time)
++{
++ if (callback)
++ wl_callback_destroy(callback);
++}
++
++static const struct wl_callback_listener frame_listener = {
++ frame_listener_func
++};
++
++/*
++ * The following correspondences between file names and cursors was copied
++ * from: https://bugs.kde.org/attachment.cgi?id=67313
++ */
++static const char *bottom_left_corners[] = {
++ "bottom_left_corner",
++ "sw-resize",
++ "size_bdiag"
++};
++
++static const char *bottom_right_corners[] = {
++ "bottom_right_corner",
++ "se-resize",
++ "size_fdiag"
++};
++
++static const char *bottom_sides[] = {
++ "bottom_side",
++ "s-resize",
++ "size_ver"
++};
++
++static const char *grabbings[] = {
++ "grabbing",
++ "closedhand",
++ "208530c400c041818281048008011002"
++};
++
++static const char *left_ptrs[] = {
++ "left_ptr",
++ "default",
++ "top_left_arrow",
++ "left-arrow"
++};
++
++static const char *left_sides[] = {
++ "left_side",
++ "w-resize",
++ "size_hor"
++};
++
++static const char *right_sides[] = {
++ "right_side",
++ "e-resize",
++ "size_hor"
++};
++
++static const char *top_left_corners[] = {
++ "top_left_corner",
++ "nw-resize",
++ "size_fdiag"
++};
++
++static const char *top_right_corners[] = {
++ "top_right_corner",
++ "ne-resize",
++ "size_bdiag"
++};
++
++static const char *top_sides[] = {
++ "top_side",
++ "n-resize",
++ "size_ver"
++};
++
++static const char *xterms[] = {
++ "xterm",
++ "ibeam",
++ "text"
++};
++
++static const char *hand1s[] = {
++ "hand1",
++ "pointer",
++ "pointing_hand",
++ "e29285e634086352946a0e7090d73106"
++};
++
++static const char *watches[] = {
++ "watch",
++ "wait",
++ "0426c94ea35c87780ff01dc239897213"
++};
++
++struct cursor_alternatives {
++ const char **names;
++ size_t count;
++};
++
++static const struct cursor_alternatives cursors[] = {
++ { bottom_left_corners, ARRAY_LENGTH(bottom_left_corners) },
++ { bottom_right_corners, ARRAY_LENGTH(bottom_right_corners) },
++ { bottom_sides, ARRAY_LENGTH(bottom_sides) },
++ { grabbings, ARRAY_LENGTH(grabbings) },
++ { left_ptrs, ARRAY_LENGTH(left_ptrs) },
++ { left_sides, ARRAY_LENGTH(left_sides) },
++ { right_sides, ARRAY_LENGTH(right_sides) },
++ { top_left_corners, ARRAY_LENGTH(top_left_corners) },
++ { top_right_corners, ARRAY_LENGTH(top_right_corners) },
++ { top_sides, ARRAY_LENGTH(top_sides) },
++ { xterms, ARRAY_LENGTH(xterms) },
++ { hand1s, ARRAY_LENGTH(hand1s) },
++ { watches, ARRAY_LENGTH(watches) },
++};
++
++static void
++create_cursors(struct wlContextCommon *cmm)
++{
++ uint32_t i = 0;
++ uint32_t j = 0;
++ struct wl_cursor *cursor = NULL;
++ char *cursor_theme = cmm->hmi_setting->cursor_theme;
++ int32_t cursor_size = cmm->hmi_setting->cursor_size;
++
++ cmm->cursor_theme = wl_cursor_theme_load(cursor_theme, cursor_size,
++ cmm->wlShm);
++
++ cmm->cursors =
++ MEM_ALLOC(ARRAY_LENGTH(cursors) * sizeof(cmm->cursors[0]));
++
++ for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
++ cursor = NULL;
++
++ for (j = 0; !cursor && j < cursors[i].count; ++j) {
++ cursor = wl_cursor_theme_get_cursor(
++ cmm->cursor_theme, cursors[i].names[j]);
++ }
++
++ if (!cursor) {
++ fprintf(stderr, "could not load cursor '%s'\n",
++ cursors[i].names[0]);
++ }
++
++ cmm->cursors[i] = cursor;
++ }
++}
++
++static void
++destroy_cursors(struct wlContextCommon *cmm)
++{
++ if (cmm->cursor_theme)
++ wl_cursor_theme_destroy(cmm->cursor_theme);
++
++ free(cmm->cursors);
++}
++
++/**
++ * Internal method to prepare parts of UI
++ */
++static void
++createShmBuffer(struct wlContextStruct *p_wlCtx)
++{
++ struct wl_shm_pool *pool;
++
++ int fd = -1;
++ int size = 0;
++ int width = 0;
++ int height = 0;
++ int stride = 0;
++
++ width = cairo_image_surface_get_width(p_wlCtx->ctx_image);
++ height = cairo_image_surface_get_height(p_wlCtx->ctx_image);
++ stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);
++
++ size = stride * height;
++
++ fd = os_create_anonymous_file(size);
++ if (fd < 0) {
++ fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
++ size);
++ return ;
++ }
++
++ p_wlCtx->data =
++ mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
++
++ if (MAP_FAILED == p_wlCtx->data) {
++ fprintf(stderr, "mmap failed: %m\n");
++ close(fd);
++ return;
++ }
++
++ pool = wl_shm_create_pool(p_wlCtx->cmm->wlShm, fd, size);
++ p_wlCtx->wlBuffer = wl_shm_pool_create_buffer(pool, 0,
++ width,
++ height,
++ stride,
++ WL_SHM_FORMAT_ARGB8888);
++
++ if (NULL == p_wlCtx->wlBuffer) {
++ fprintf(stderr, "wl_shm_create_buffer failed: %m\n");
++ close(fd);
++ return;
++ }
++
++ wl_shm_pool_destroy(pool);
++ close(fd);
++}
++
++static void
++destroyWLContextCommon(struct wlContextCommon *p_wlCtx)
++{
++ destroy_cursors(p_wlCtx);
++
++ if (p_wlCtx->pointer_surface)
++ wl_surface_destroy(p_wlCtx->pointer_surface);
++
++ if (p_wlCtx->wlCompositor)
++ wl_compositor_destroy(p_wlCtx->wlCompositor);
++}
++
++static void
++destroyWLContextStruct(struct wlContextStruct *p_wlCtx)
++{
++ if (p_wlCtx->wlSurface)
++ wl_surface_destroy(p_wlCtx->wlSurface);
++
++ if (p_wlCtx->ctx_image) {
++ cairo_surface_destroy(p_wlCtx->ctx_image);
++ p_wlCtx->ctx_image = NULL;
++ }
++}
++
++static int
++createSurface(struct wlContextStruct *p_wlCtx)
++{
++ p_wlCtx->wlSurface =
++ wl_compositor_create_surface(p_wlCtx->cmm->wlCompositor);
++ if (NULL == p_wlCtx->wlSurface) {
++ printf("Error: wl_compositor_create_surface failed.\n");
++ destroyWLContextCommon(p_wlCtx->cmm);
++ abort();
++ }
++
++ return 0;
++}
++
++static void
++drawImage(struct wlContextStruct *p_wlCtx)
++{
++ struct wl_callback *callback;
++
++ int width = 0;
++ int height = 0;
++ int stride = 0;
++ void *data = NULL;
++
++ width = cairo_image_surface_get_width(p_wlCtx->ctx_image);
++ height = cairo_image_surface_get_height(p_wlCtx->ctx_image);
++ stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);
++ data = cairo_image_surface_get_data(p_wlCtx->ctx_image);
++
++ memcpy(p_wlCtx->data, data, stride * height);
++
++ wl_surface_attach(p_wlCtx->wlSurface, p_wlCtx->wlBuffer, 0, 0);
++ wl_surface_damage(p_wlCtx->wlSurface, 0, 0, width, height);
++
++ callback = wl_surface_frame(p_wlCtx->wlSurface);
++ wl_callback_add_listener(callback, &frame_listener, NULL);
++
++ wl_surface_commit(p_wlCtx->wlSurface);
++}
++
++static void
++create_ivisurface(struct wlContextStruct *p_wlCtx,
++ uint32_t id_surface,
++ cairo_surface_t *surface)
++{
++ struct ivi_surface *ivisurf = NULL;
++
++ p_wlCtx->ctx_image = surface;
++
++ p_wlCtx->id_surface = id_surface;
++ wl_list_init(&p_wlCtx->link);
++ wl_list_insert(&p_wlCtx->cmm->list_wlContextStruct, &p_wlCtx->link);
++
++ createSurface(p_wlCtx);
++ createShmBuffer(p_wlCtx);
++
++ ivisurf = ivi_application_surface_create(p_wlCtx->cmm->iviApplication,
++ id_surface,
++ p_wlCtx->wlSurface);
++ if (ivisurf == NULL) {
++ fprintf(stderr, "Failed to create ivi_client_surface\n");
++ return;
++ }
++
++ drawImage(p_wlCtx);
++}
++
++static void
++create_ivisurfaceFromFile(struct wlContextStruct *p_wlCtx,
++ uint32_t id_surface,
++ const char *imageFile)
++{
++ cairo_surface_t *surface = load_cairo_surface(imageFile);
++
++ if (NULL == surface) {
++ fprintf(stderr, "Failed to load_cairo_surface %s\n", imageFile);
++ return;
++ }
++
++ create_ivisurface(p_wlCtx, id_surface, surface);
++}
++
++static void
++set_hex_color(cairo_t *cr, uint32_t color)
++{
++ cairo_set_source_rgba(cr,
++ ((color >> 16) & 0xff) / 255.0,
++ ((color >> 8) & 0xff) / 255.0,
++ ((color >> 0) & 0xff) / 255.0,
++ ((color >> 24) & 0xff) / 255.0);
++}
++
++static void
++create_ivisurfaceFromColor(struct wlContextStruct *p_wlCtx,
++ uint32_t id_surface,
++ uint32_t width, uint32_t height,
++ uint32_t color)
++{
++ cairo_surface_t *surface = NULL;
++ cairo_t *cr = NULL;
++
++ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
++ width, height);
++
++ cr = cairo_create(surface);
++ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
++ cairo_rectangle(cr, 0, 0, width, height);
++ set_hex_color(cr, color);
++ cairo_fill(cr);
++ cairo_destroy(cr);
++
++ create_ivisurface(p_wlCtx, id_surface, surface);
++}
++
++static void
++UI_ready(struct ivi_hmi_controller *controller)
++{
++ ivi_hmi_controller_UI_ready(controller);
++}
++
++/**
++ * Internal method to set up UI by using ivi-hmi-controller
++ */
++static void
++create_background(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
++ const char *imageFile)
++{
++ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
++}
++
++static void
++create_panel(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
++ const char *imageFile)
++{
++ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
++}
++
++static void
++create_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
++ const char *imageFile, uint32_t number)
++{
++ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
++}
++
++static void
++create_home_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
++ const char *imageFile)
++{
++ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
++}
++
++static void
++create_workspace_background(struct wlContextStruct *p_wlCtx,
++ struct hmi_homescreen_srf *srf)
++{
++ create_ivisurfaceFromColor(p_wlCtx, srf->id, 1, 1, srf->color);
++}
++
++static void
++create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
++{
++ struct hmi_homescreen_launcher **launchers;
++ struct hmi_homescreen_launcher *launcher = NULL;
++
++ int launcher_count = wl_list_length(launcher_list);
++ int ii = 0;
++ int start = 0;
++
++ if (0 == launcher_count)
++ return;
++
++ launchers = MEM_ALLOC(launcher_count * sizeof(*launchers));
++
++ wl_list_for_each(launcher, launcher_list, link) {
++ launchers[ii] = launcher;
++ ii++;
++ }
++
++ for (ii = 0; ii < launcher_count; ii++) {
++ int jj = 0;
++
++ if (ii != launcher_count - 1 &&
++ launchers[ii]->workspace_id ==
++ launchers[ii + 1]->workspace_id)
++ continue;
++
++ for (jj = start; jj <= ii; jj++) {
++ struct wlContextStruct *p_wlCtx;
++
++ p_wlCtx = MEM_ALLOC(sizeof(*p_wlCtx));
++ p_wlCtx->cmm = cmm;
++ create_ivisurfaceFromFile(p_wlCtx,
++ launchers[jj]->icon_surface_id,
++ launchers[jj]->icon);
++ }
++
++ start = ii + 1;
++ }
++
++ free(launchers);
++}
++
++/**
++ * Internal method to read out weston.ini to get configuration
++ */
++static struct hmi_homescreen_setting *
++hmi_homescreen_setting_create(void)
++{
++ struct weston_config *config = NULL;
++ struct weston_config_section *shellSection = NULL;
++ struct hmi_homescreen_setting *setting = MEM_ALLOC(sizeof(*setting));
++ struct weston_config_section *section = NULL;
++ const char *name = NULL;
++ uint32_t workspace_layer_id;
++ uint32_t icon_surface_id = 0;
++
++ wl_list_init(&setting->workspace_list);
++ wl_list_init(&setting->launcher_list);
++
++ config = weston_config_parse("weston.ini");
++
++ shellSection =
++ weston_config_get_section(config, "ivi-shell", NULL, NULL);
++
++ weston_config_section_get_string(
++ shellSection, "cursor-theme", &setting->cursor_theme, NULL);
++
++ weston_config_section_get_int(
++ shellSection, "cursor-size", &setting->cursor_size, 32);
++
++ weston_config_section_get_uint(
++ shellSection, "workspace-layer-id", &workspace_layer_id, 3000);
++
++ weston_config_section_get_string(
++ shellSection, "background-image", &setting->background.filePath,
++ DATADIR "/weston/background.png");
++
++ weston_config_section_get_uint(
++ shellSection, "background-id", &setting->background.id, 1001);
++
++ weston_config_section_get_string(
++ shellSection, "panel-image", &setting->panel.filePath,
++ DATADIR "/weston/panel.png");
++
++ weston_config_section_get_uint(
++ shellSection, "panel-id", &setting->panel.id, 1002);
++
++ weston_config_section_get_string(
++ shellSection, "tiling-image", &setting->tiling.filePath,
++ DATADIR "/weston/tiling.png");
++
++ weston_config_section_get_uint(
++ shellSection, "tiling-id", &setting->tiling.id, 1003);
++
++ weston_config_section_get_string(
++ shellSection, "sidebyside-image", &setting->sidebyside.filePath,
++ DATADIR "/weston/sidebyside.png");
++
++ weston_config_section_get_uint(
++ shellSection, "sidebyside-id", &setting->sidebyside.id, 1004);
++
++ weston_config_section_get_string(
++ shellSection, "fullscreen-image", &setting->fullscreen.filePath,
++ DATADIR "/weston/fullscreen.png");
++
++ weston_config_section_get_uint(
++ shellSection, "fullscreen-id", &setting->fullscreen.id, 1005);
++
++ weston_config_section_get_string(
++ shellSection, "random-image", &setting->random.filePath,
++ DATADIR "/weston/random.png");
++
++ weston_config_section_get_uint(
++ shellSection, "random-id", &setting->random.id, 1006);
++
++ weston_config_section_get_string(
++ shellSection, "home-image", &setting->home.filePath,
++ DATADIR "/weston/home.png");
++
++ weston_config_section_get_uint(
++ shellSection, "home-id", &setting->home.id, 1007);
++
++ weston_config_section_get_uint(
++ shellSection, "workspace-background-color",
++ &setting->workspace_background.color, 0x99000000);
++
++ weston_config_section_get_uint(
++ shellSection, "workspace-background-id",
++ &setting->workspace_background.id, 2001);
++
++ icon_surface_id = workspace_layer_id + 1;
++
++ while (weston_config_next_section(config, &section, &name)) {
++ struct hmi_homescreen_launcher *launcher;
++
++ if (strcmp(name, "ivi-launcher") != 0)
++ continue;
++
++ launcher = MEM_ALLOC(sizeof(*launcher));
++ wl_list_init(&launcher->link);
++
++ weston_config_section_get_string(section, "icon",
++ &launcher->icon, NULL);
++ weston_config_section_get_string(section, "path",
++ &launcher->path, NULL);
++ weston_config_section_get_uint(section, "workspace-id",
++ &launcher->workspace_id, 0);
++ weston_config_section_get_uint(section, "icon-id",
++ &launcher->icon_surface_id,
++ icon_surface_id);
++ icon_surface_id++;
++
++ wl_list_insert(setting->launcher_list.prev, &launcher->link);
++ }
++
++ weston_config_destroy(config);
++ return setting;
++}
++
++/**
++ * Main thread
++ *
++ * The basic flow are as followed,
++ * 1/ read configuration from weston.ini by hmi_homescreen_setting_create
++ * 2/ draw png file to surface according to configuration of weston.ini and
++ * set up UI by using ivi-hmi-controller protocol by each create_* method
++ */
++int main(int argc, char **argv)
++{
++ struct wlContextCommon wlCtxCommon;
++ struct wlContextStruct wlCtx_BackGround;
++ struct wlContextStruct wlCtx_Panel;
++ struct wlContextStruct wlCtx_Button_1;
++ struct wlContextStruct wlCtx_Button_2;
++ struct wlContextStruct wlCtx_Button_3;
++ struct wlContextStruct wlCtx_Button_4;
++ struct wlContextStruct wlCtx_HomeButton;
++ struct wlContextStruct wlCtx_WorkSpaceBackGround;
++ struct wl_list launcher_wlCtxList;
++ int ret = 0;
++ struct hmi_homescreen_setting *hmi_setting;
++ struct wlContextStruct *pWlCtxSt = NULL;
++
++ hmi_setting = hmi_homescreen_setting_create();
++
++ memset(&wlCtxCommon, 0x00, sizeof(wlCtxCommon));
++ memset(&wlCtx_BackGround, 0x00, sizeof(wlCtx_BackGround));
++ memset(&wlCtx_Panel, 0x00, sizeof(wlCtx_Panel));
++ memset(&wlCtx_Button_1, 0x00, sizeof(wlCtx_Button_1));
++ memset(&wlCtx_Button_2, 0x00, sizeof(wlCtx_Button_2));
++ memset(&wlCtx_Button_3, 0x00, sizeof(wlCtx_Button_3));
++ memset(&wlCtx_Button_4, 0x00, sizeof(wlCtx_Button_4));
++ memset(&wlCtx_HomeButton, 0x00, sizeof(wlCtx_HomeButton));
++ memset(&wlCtx_WorkSpaceBackGround, 0x00,
++ sizeof(wlCtx_WorkSpaceBackGround));
++ wl_list_init(&launcher_wlCtxList);
++ wl_list_init(&wlCtxCommon.list_wlContextStruct);
++
++ wlCtxCommon.hmi_setting = hmi_setting;
++
++ wlCtxCommon.wlDisplay = wl_display_connect(NULL);
++ if (NULL == wlCtxCommon.wlDisplay) {
++ printf("Error: wl_display_connect failed.\n");
++ return -1;
++ }
++
++ /* get wl_registry */
++ wlCtxCommon.formats = 0;
++ wlCtxCommon.wlRegistry = wl_display_get_registry(wlCtxCommon.wlDisplay);
++ wl_registry_add_listener(wlCtxCommon.wlRegistry,
++ &registry_listener, &wlCtxCommon);
++ wl_display_roundtrip(wlCtxCommon.wlDisplay);
++
++ if (wlCtxCommon.wlShm == NULL) {
++ fprintf(stderr, "No wl_shm global\n");
++ exit(1);
++ }
++
++ wl_display_roundtrip(wlCtxCommon.wlDisplay);
++
++ if (!(wlCtxCommon.formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
++ fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
++ exit(1);
++ }
++
++ if (wlCtxCommon.hmi_setting->cursor_theme) {
++ create_cursors(&wlCtxCommon);
++
++ wlCtxCommon.pointer_surface =
++ wl_compositor_create_surface(wlCtxCommon.wlCompositor);
++
++ wlCtxCommon.current_cursor = CURSOR_LEFT_PTR;
++ }
++
++ wlCtx_BackGround.cmm = &wlCtxCommon;
++ wlCtx_Panel.cmm = &wlCtxCommon;
++ wlCtx_Button_1.cmm = &wlCtxCommon;
++ wlCtx_Button_2.cmm = &wlCtxCommon;
++ wlCtx_Button_3.cmm = &wlCtxCommon;
++ wlCtx_Button_4.cmm = &wlCtxCommon;
++ wlCtx_HomeButton.cmm = &wlCtxCommon;
++ wlCtx_WorkSpaceBackGround.cmm = &wlCtxCommon;
++
++ /* create desktop widgets */
++ create_background(&wlCtx_BackGround, hmi_setting->background.id,
++ hmi_setting->background.filePath);
++
++ create_panel(&wlCtx_Panel, hmi_setting->panel.id,
++ hmi_setting->panel.filePath);
++
++ create_button(&wlCtx_Button_1, hmi_setting->tiling.id,
++ hmi_setting->tiling.filePath, 0);
++
++ create_button(&wlCtx_Button_2, hmi_setting->sidebyside.id,
++ hmi_setting->sidebyside.filePath, 1);
++
++ create_button(&wlCtx_Button_3, hmi_setting->fullscreen.id,
++ hmi_setting->fullscreen.filePath, 2);
++
++ create_button(&wlCtx_Button_4, hmi_setting->random.id,
++ hmi_setting->random.filePath, 3);
++
++ create_workspace_background(&wlCtx_WorkSpaceBackGround,
++ &hmi_setting->workspace_background);
++
++ create_launchers(&wlCtxCommon, &hmi_setting->launcher_list);
++
++ create_home_button(&wlCtx_HomeButton, hmi_setting->home.id,
++ hmi_setting->home.filePath);
++
++ UI_ready(wlCtxCommon.hmiCtrl);
++
++ while (ret != -1)
++ ret = wl_display_dispatch(wlCtxCommon.wlDisplay);
++
++ wl_list_for_each(pWlCtxSt, &wlCtxCommon.list_wlContextStruct, link) {
++ destroyWLContextStruct(pWlCtxSt);
++ }
++
++ destroyWLContextCommon(&wlCtxCommon);
++
++ return 0;
++}
+diff --git a/clients/simple-egl.c b/clients/simple-egl.c
+index 0d4673b..8634075 100644
+--- a/clients/simple-egl.c
++++ b/clients/simple-egl.c
+@@ -28,6 +28,7 @@
+ #include <stdbool.h>
+ #include <math.h>
+ #include <assert.h>
++#include <unistd.h>
+ #include <signal.h>
+
+ #include <linux/input.h>
+@@ -41,6 +42,8 @@
+ #include <EGL/eglext.h>
+
+ #include "xdg-shell-client-protocol.h"
++#include "ivi-application-client-protocol.h"
++#define IVI_SURFACE_ID 9000
+
+ #ifndef EGL_EXT_swap_buffers_with_damage
+ #define EGL_EXT_swap_buffers_with_damage 1
+@@ -74,6 +77,7 @@ struct display {
+ EGLConfig conf;
+ } egl;
+ struct window *window;
++ struct ivi_application *ivi_application;
+
+ PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
+ };
+@@ -95,6 +99,7 @@ struct window {
+ struct wl_egl_window *native;
+ struct wl_surface *surface;
+ struct xdg_surface *xdg_surface;
++ struct ivi_surface *ivi_surface;
+ EGLSurface egl_surface;
+ struct wl_callback *callback;
+ int fullscreen, opaque, buffer_size, frame_sync;
+@@ -329,18 +334,61 @@ static const struct xdg_surface_listener xdg_surface_listener = {
+ };
+
+ static void
+-create_surface(struct window *window)
++handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
++ int32_t width, int32_t height)
++{
++ struct window *window = data;
++
++ wl_egl_window_resize(window->native, width, height, 0, 0);
++
++ window->geometry.width = width;
++ window->geometry.height = height;
++
++ if (!window->fullscreen)
++ window->window_size = window->geometry;
++}
++
++static const struct ivi_surface_listener ivi_surface_listener = {
++ handle_ivi_surface_configure,
++};
++
++static void
++create_xdg_surface(struct window *window, struct display *display)
+ {
+- struct display *display = window->display;
+- EGLBoolean ret;
+-
+- window->surface = wl_compositor_create_surface(display->compositor);
+ window->xdg_surface = xdg_shell_get_xdg_surface(display->shell,
+ window->surface);
+
+ xdg_surface_add_listener(window->xdg_surface,
+ &xdg_surface_listener, window);
+
++ xdg_surface_set_title(window->xdg_surface, "simple-egl");
++}
++
++static void
++create_ivi_surface(struct window *window, struct display *display)
++{
++ uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
++ window->ivi_surface =
++ ivi_application_surface_create(display->ivi_application,
++ id_ivisurf, window->surface);
++
++ if (window->ivi_surface == NULL) {
++ fprintf(stderr, "Failed to create ivi_client_surface\n");
++ abort();
++ }
++
++ ivi_surface_add_listener(window->ivi_surface,
++ &ivi_surface_listener, window);
++}
++
++static void
++create_surface(struct window *window)
++{
++ struct display *display = window->display;
++ EGLBoolean ret;
++
++ window->surface = wl_compositor_create_surface(display->compositor);
++
+ window->native =
+ wl_egl_window_create(window->surface,
+ window->window_size.width,
+@@ -350,7 +398,13 @@ create_surface(struct window *window)
+ display->egl.conf,
+ window->native, NULL);
+
+- xdg_surface_set_title(window->xdg_surface, "simple-egl");
++ if (display->shell) {
++ create_xdg_surface(window, display);
++ } else if (display->ivi_application) {
++ create_ivi_surface(window, display);
++ } else {
++ assert(0);
++ }
+
+ ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
+ window->egl_surface, window->display->egl.ctx);
+@@ -375,7 +429,10 @@ destroy_surface(struct window *window)
+ eglDestroySurface(window->display->egl.dpy, window->egl_surface);
+ wl_egl_window_destroy(window->native);
+
+- xdg_surface_destroy(window->xdg_surface);
++ if (window->xdg_surface)
++ xdg_surface_destroy(window->xdg_surface);
++ if (window->display->ivi_application)
++ ivi_surface_destroy(window->ivi_surface);
+ wl_surface_destroy(window->surface);
+
+ if (window->callback)
+@@ -729,6 +786,10 @@ registry_handle_global(void *data, struct wl_registry *registry,
+ fprintf(stderr, "unable to load default left pointer\n");
+ // TODO: abort ?
+ }
++ } else if (strcmp(interface, "ivi_application") == 0) {
++ d->ivi_application =
++ wl_registry_bind(registry, name,
++ &ivi_application_interface, 1);
+ }
+ }
+
+@@ -834,6 +895,9 @@ main(int argc, char **argv)
+ if (display.shell)
+ xdg_shell_destroy(display.shell);
+
++ if (display.ivi_application)
++ ivi_application_destroy(display.ivi_application);
++
+ if (display.compositor)
+ wl_compositor_destroy(display.compositor);
+
+diff --git a/clients/simple-shm.c b/clients/simple-shm.c
+index 2087a0e..97c2da5 100644
+--- a/clients/simple-shm.c
++++ b/clients/simple-shm.c
+@@ -36,6 +36,8 @@
+ #include "../shared/os-compatibility.h"
+ #include "xdg-shell-client-protocol.h"
+ #include "fullscreen-shell-client-protocol.h"
++#include "ivi-application-client-protocol.h"
++#define IVI_SURFACE_ID 9000
+
+ struct display {
+ struct wl_display *display;
+@@ -45,6 +47,7 @@ struct display {
+ struct _wl_fullscreen_shell *fshell;
+ struct wl_shm *shm;
+ uint32_t formats;
++ struct ivi_application *ivi_application;
+ };
+
+ struct buffer {
+@@ -58,6 +61,7 @@ struct window {
+ int width, height;
+ struct wl_surface *surface;
+ struct xdg_surface *xdg_surface;
++ struct ivi_surface *ivi_surface;
+ struct buffer buffers[2];
+ struct buffer *prev_buffer;
+ struct wl_callback *callback;
+@@ -153,6 +157,17 @@ static const struct xdg_surface_listener xdg_surface_listener = {
+ handle_delete,
+ };
+
++static void
++handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
++ int32_t width, int32_t height)
++{
++ /* Simple-shm is resizable */
++}
++
++static const struct ivi_surface_listener ivi_surface_listener = {
++ handle_ivi_surface_configure,
++};
++
+ static struct window *
+ create_window(struct display *display, int width, int height)
+ {
+@@ -184,6 +199,18 @@ create_window(struct display *display, int width, int height)
+ window->surface,
+ _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT,
+ NULL);
++ } else if (display->ivi_application) {
++ uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
++ window->ivi_surface =
++ ivi_application_surface_create(display->ivi_application,
++ id_ivisurf, window->surface);
++ if (window->ivi_surface == NULL) {
++ fprintf(stderr, "Failed to create ivi_client_surface\n");
++ abort();
++ }
++
++ ivi_surface_add_listener(window->ivi_surface,
++ &ivi_surface_listener, window);
+ } else {
+ assert(0);
+ }
+@@ -368,6 +395,10 @@ registry_handle_global(void *data, struct wl_registry *registry,
+ d->shm = wl_registry_bind(registry,
+ id, &wl_shm_interface, 1);
+ wl_shm_add_listener(d->shm, &shm_listener, d);
++ } else if (strcmp(interface, "ivi_application") == 0) {
++ d->ivi_application =
++ wl_registry_bind(registry, id,
++ &ivi_application_interface, 1);
+ }
+ }
+
+@@ -472,6 +503,12 @@ main(int argc, char **argv)
+ ret = wl_display_dispatch(display->display);
+
+ fprintf(stderr, "simple-shm exiting\n");
++
++ if (window->display->ivi_application) {
++ ivi_surface_destroy(window->ivi_surface);
++ ivi_application_destroy(window->display->ivi_application);
++ }
++
+ destroy_window(window);
+ destroy_display(display);
+
+diff --git a/clients/window.c b/clients/window.c
+index 4592ef9..049093d 100644
+--- a/clients/window.c
++++ b/clients/window.c
+@@ -72,6 +72,9 @@ typedef void *EGLContext;
+
+ #include "window.h"
+
++#include "ivi-application-client-protocol.h"
++#define IVI_SURFACE_ID 9000
++
+ struct shm_pool;
+
+ struct global {
+@@ -91,6 +94,7 @@ struct display {
+ struct text_cursor_position *text_cursor_position;
+ struct workspace_manager *workspace_manager;
+ struct xdg_shell *xdg_shell;
++ struct ivi_application *ivi_application; /* ivi style shell */
+ EGLDisplay dpy;
+ EGLConfig argb_config;
+ EGLContext argb_ctx;
+@@ -246,6 +250,8 @@ struct window {
+
+ struct window *transient_for;
+
++ struct ivi_surface *ivi_surface;
++
+ struct window_frame *frame;
+
+ /* struct surface::link, contains also main_surface */
+@@ -1368,6 +1374,19 @@ window_get_display(struct window *window)
+ }
+
+ static void
++handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
++ int32_t width, int32_t height)
++{
++ struct window *window = data;
++
++ window_schedule_resize(window, width, height);
++}
++
++static const struct ivi_surface_listener ivi_surface_listener = {
++ handle_ivi_surface_configure,
++};
++
++static void
+ surface_create_surface(struct surface *surface, uint32_t flags)
+ {
+ struct display *display = surface->window->display;
+@@ -1515,6 +1534,9 @@ window_destroy(struct window *window)
+ if (window->xdg_popup)
+ xdg_popup_destroy(window->xdg_popup);
+
++ if (window->ivi_surface)
++ ivi_surface_destroy(window->ivi_surface);
++
+ surface_destroy(window->main_surface);
+
+ wl_list_remove(&window->link);
+@@ -4386,7 +4408,7 @@ window_create_internal(struct display *display, int custom)
+ surface = surface_create(window);
+ window->main_surface = surface;
+
+- assert(custom || display->xdg_shell);
++ assert(custom || display->xdg_shell || display->ivi_application);
+
+ window->custom = custom;
+ window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE;
+@@ -4406,17 +4428,31 @@ struct window *
+ window_create(struct display *display)
+ {
+ struct window *window;
++ uint32_t id_ivisurf;
+
+ window = window_create_internal(display, 0);
+
+- window->xdg_surface =
+- xdg_shell_get_xdg_surface(window->display->xdg_shell,
+- window->main_surface->surface);
+- fail_on_null(window->xdg_surface);
++ if (window->display->xdg_shell) {
++ window->xdg_surface =
++ xdg_shell_get_xdg_surface(window->display->xdg_shell,
++ window->main_surface->surface);
++ fail_on_null(window->xdg_surface);
+
+- xdg_surface_set_user_data(window->xdg_surface, window);
+- xdg_surface_add_listener(window->xdg_surface,
++ xdg_surface_set_user_data(window->xdg_surface, window);
++ xdg_surface_add_listener(window->xdg_surface,
+ &xdg_surface_listener, window);
++ } else if (display->ivi_application) {
++ /* auto generation of ivi_id based on process id + basement of id */
++ id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid();
++ window->ivi_surface =
++ ivi_application_surface_create(display->ivi_application,
++ id_ivisurf, window->main_surface->surface);
++
++ fail_on_null(window->ivi_surface);
++
++ ivi_surface_add_listener(window->ivi_surface,
++ &ivi_surface_listener, window);
++ }
+
+ return window;
+ }
+@@ -5090,6 +5126,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
+ d->subcompositor =
+ wl_registry_bind(registry, id,
+ &wl_subcompositor_interface, 1);
++ } else if (strcmp(interface, "ivi_application") == 0) {
++ d->ivi_application =
++ wl_registry_bind(registry, id,
++ &ivi_application_interface, 1);
+ }
+
+ if (d->global_handler)
+@@ -5389,6 +5429,9 @@ display_destroy(struct display *display)
+ if (display->xdg_shell)
+ xdg_shell_destroy(display->xdg_shell);
+
++ if (display->ivi_application)
++ ivi_application_destroy(display->ivi_application);
++
+ if (display->shm)
+ wl_shm_destroy(display->shm);
+
+diff --git a/configure.ac b/configure.ac
+index f55cea8..edaba3c 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -433,6 +433,13 @@ if test "x$enable_dbus" != "xno"; then
+ fi
+ AM_CONDITIONAL(ENABLE_DBUS, test "x$enable_dbus" = "xyes")
+
++# ivi-shell support
++AC_ARG_ENABLE(ivi-shell,
++ AS_HELP_STRING([--disable-ivi-shell],
++ [do not build ivi-shell server plugin and client]),,
++ enable_ivi_shell=yes)
++AM_CONDITIONAL(ENABLE_IVI_SHELL, test "x$enable_ivi_shell" = "xyes")
++
+ AC_ARG_ENABLE(wcap-tools, [ --disable-wcap-tools],, enable_wcap_tools=yes)
+ AM_CONDITIONAL(BUILD_WCAP_TOOLS, test x$enable_wcap_tools = xyes)
+ if test x$enable_wcap_tools = xyes; then
+@@ -522,6 +529,8 @@ AC_MSG_RESULT([
+ XWayland ${enable_xwayland}
+ dbus ${enable_dbus}
+
++ ivi-shell ${enable_ivi_shell}
++
+ Build wcap utility ${enable_wcap_tools}
+ Build Fullscreen Shell ${enable_fullscreen_shell}
+
+
+diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
+new file mode 100644
+index 0000000..7f3d5bf
+--- /dev/null
++++ b/ivi-shell/hmi-controller.c
+@@ -0,0 +1,1814 @@
++/*
++ * Copyright (C) 2014 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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.
++ */
++
++/**
++ * A reference implementation how to use ivi-layout APIs in order to manage
++ * layout of ivi_surfaces/ivi_layers. Layout change is triggered by
++ * ivi-hmi-controller protocol, ivi-hmi-controller.xml. A reference how to
++ * use the protocol, see hmi-controller-homescreen.
++ *
++ * In-Vehicle Infotainment system usually manage properties of
++ * ivi_surfaces/ivi_layers by only a central component which decide where
++ * ivi_surfaces/ivi_layers shall be. This reference show examples to
++ * implement the central component as a module of weston.
++ *
++ * Default Scene graph of UI is defined in hmi_controller_create. It
++ * consists of
++ * - In the bottom, a base ivi_layer to group ivi_surfaces of background,
++ * panel, and buttons
++ * - Next, a application ivi_layer to show application ivi_surfaces.
++ * - Workspace background ivi_layer to show a ivi_surface of background image.
++ * - Workspace ivi_layer to show launcher to launch application with icons.
++ * Paths to binary and icon are defined in weston.ini. The width of this
++ * ivi_layer is longer than the size of ivi_screen because a workspace has
++ * several pages and is controlled by motion of input.
++ *
++ * TODO: animation method shall be refined
++ * TODO: support fade-in when UI is ready
++ */
++
++#include <sys/wait.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <linux/input.h>
++#include <assert.h>
++#include <time.h>
++
++#include "ivi-layout-export.h"
++#include "ivi-hmi-controller-server-protocol.h"
++#include "shared/helpers.h"
++
++/*****************************************************************************
++ * structure, globals
++ ****************************************************************************/
++struct hmi_controller_layer {
++ struct ivi_layout_layer *ivilayer;
++ uint32_t id_layer;
++ int32_t x;
++ int32_t y;
++ int32_t width;
++ int32_t height;
++};
++
++struct link_layer {
++ struct ivi_layout_layer *layout_layer;
++ struct wl_list link;
++};
++
++struct hmi_controller_fade {
++ uint32_t is_fade_in;
++ struct wl_list layer_list;
++};
++
++struct hmi_server_setting {
++ uint32_t base_layer_id;
++ uint32_t application_layer_id;
++ uint32_t workspace_background_layer_id;
++ uint32_t workspace_layer_id;
++ int32_t panel_height;
++ uint32_t transition_duration;
++ char *ivi_homescreen;
++};
++
++struct ui_setting {
++ uint32_t background_id;
++ uint32_t panel_id;
++ uint32_t tiling_id;
++ uint32_t sidebyside_id;
++ uint32_t fullscreen_id;
++ uint32_t random_id;
++ uint32_t home_id;
++ uint32_t workspace_background_id;
++};
++
++struct hmi_controller {
++ struct hmi_server_setting *hmi_setting;
++ struct hmi_controller_layer base_layer;
++ struct hmi_controller_layer application_layer;
++ struct hmi_controller_layer workspace_background_layer;
++ struct hmi_controller_layer workspace_layer;
++ enum ivi_hmi_controller_layout_mode layout_mode;
++
++ struct hmi_controller_fade workspace_fade;
++
++ int32_t workspace_count;
++ struct wl_array ui_widgets;
++ int32_t is_initialized;
++
++ struct weston_compositor *compositor;
++ struct weston_process process;
++ struct wl_listener destroy_listener;
++
++ struct wl_client *user_interface;
++ struct ui_setting ui_setting;
++};
++
++struct launcher_info {
++ uint32_t surface_id;
++ uint32_t workspace_id;
++ int32_t index;
++};
++
++const struct ivi_controller_interface *ivi_controller_interface;
++
++int
++controller_module_init(struct weston_compositor *ec,
++ int *argc, char *argv[],
++ const struct ivi_controller_interface *interface,
++ size_t interface_version);
++
++/*****************************************************************************
++ * local functions
++ ****************************************************************************/
++static void *
++fail_on_null(void *p, size_t size, char *file, int32_t line)
++{
++ if (size && !p) {
++ weston_log("%s(%d) %zd: out of memory\n", file, line, size);
++ exit(EXIT_FAILURE);
++ }
++
++ return p;
++}
++
++static void *
++mem_alloc(size_t size, char *file, int32_t line)
++{
++ return fail_on_null(calloc(1, size), size, file, line);
++}
++
++#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)
++
++static int32_t
++is_surf_in_ui_widget(struct hmi_controller *hmi_ctrl,
++ struct ivi_layout_surface *ivisurf)
++{
++ uint32_t id = ivi_controller_interface->get_id_of_surface(ivisurf);
++
++ uint32_t *ui_widget_id = NULL;
++ wl_array_for_each(ui_widget_id, &hmi_ctrl->ui_widgets) {
++ if (*ui_widget_id == id)
++ return 1;
++ }
++
++ return 0;
++}
++
++static int
++compare_launcher_info(const void *lhs, const void *rhs)
++{
++ const struct launcher_info *left = lhs;
++ const struct launcher_info *right = rhs;
++
++ if (left->workspace_id < right->workspace_id)
++ return -1;
++
++ if (left->workspace_id > right->workspace_id)
++ return 1;
++
++ if (left->index < right->index)
++ return -1;
++
++ if (left->index > right->index)
++ return 1;
++
++ return 0;
++}
++
++/**
++ * Internal methods called by mainly ivi_hmi_controller_switch_mode
++ * This reference shows 4 examples how to use ivi_layout APIs.
++ */
++static void
++mode_divided_into_tiling(struct hmi_controller *hmi_ctrl,
++ struct ivi_layout_surface **pp_surface,
++ int32_t surface_length,
++ struct hmi_controller_layer *layer)
++{
++ const float surface_width = (float)layer->width * 0.25;
++ const float surface_height = (float)layer->height * 0.5;
++ int32_t surface_x = 0;
++ int32_t surface_y = 0;
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_surface **surfaces;
++ struct ivi_layout_surface **new_order;
++ const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
++
++ int32_t i = 0;
++ int32_t surf_num = 0;
++ uint32_t num = 1;
++
++ surfaces = MEM_ALLOC(sizeof(*surfaces) * surface_length);
++ new_order = MEM_ALLOC(sizeof(*surfaces) * surface_length);
++
++ for (i = 0; i < surface_length; i++) {
++ ivisurf = pp_surface[i];
++
++ /* skip ui widgets */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
++ continue;
++
++ surfaces[surf_num++] = ivisurf;
++ }
++
++ for (i = 0; i < surf_num; i++) {
++ ivisurf = surfaces[i];
++ new_order[i] = ivisurf;
++
++ if (num <= 8) {
++ if (num < 5) {
++ surface_x = (int32_t)((num - 1) * (surface_width));
++ surface_y = 0;
++ } else {
++ surface_x = (int32_t)((num - 5) * (surface_width));
++ surface_y = (int32_t)surface_height;
++ }
++
++ ivi_controller_interface->surface_set_transition(ivisurf,
++ IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
++ duration);
++ ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
++ surface_x, surface_y,
++ (int32_t)surface_width,
++ (int32_t)surface_height);
++
++ num++;
++ continue;
++ }
++ ivi_controller_interface->surface_set_visibility(ivisurf, false);
++ }
++
++ if (surf_num > 0) {
++ ivi_controller_interface->layer_set_transition(layer->ivilayer,
++ IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
++ duration);
++ }
++
++ free(surfaces);
++ free(new_order);
++}
++
++static void
++mode_divided_into_sidebyside(struct hmi_controller *hmi_ctrl,
++ struct ivi_layout_surface **pp_surface,
++ int32_t surface_length,
++ struct hmi_controller_layer *layer)
++{
++ int32_t surface_width = layer->width / 2;
++ int32_t surface_height = layer->height;
++ struct ivi_layout_surface *ivisurf = NULL;
++
++ const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
++ int32_t i = 0;
++ int32_t num = 1;
++
++ for (i = 0; i < surface_length; i++) {
++ ivisurf = pp_surface[i];
++
++ /* skip ui widgets */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
++ continue;
++
++ if (num == 1) {
++ ivi_controller_interface->surface_set_transition(ivisurf,
++ IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
++ duration);
++ ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
++ 0, 0,
++ surface_width,
++ surface_height);
++
++ num++;
++ continue;
++ } else if (num == 2) {
++ ivi_controller_interface->surface_set_transition(ivisurf,
++ IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
++ duration);
++ ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
++ surface_width, 0,
++ surface_width,
++ surface_height);
++
++ num++;
++ continue;
++ }
++ ivi_controller_interface->surface_set_transition(ivisurf,
++ IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
++ duration);
++ ivi_controller_interface->surface_set_visibility(ivisurf, false);
++ }
++}
++
++static void
++mode_fullscreen_someone(struct hmi_controller *hmi_ctrl,
++ struct ivi_layout_surface **pp_surface,
++ int32_t surface_length,
++ struct hmi_controller_layer *layer)
++{
++ const int32_t surface_width = layer->width;
++ const int32_t surface_height = layer->height;
++ struct ivi_layout_surface *ivisurf = NULL;
++ int32_t i = 0;
++ const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
++
++ for (i = 0; i < surface_length; i++) {
++ ivisurf = pp_surface[i];
++
++ /* skip ui widgets */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
++ continue;
++
++ ivi_controller_interface->surface_set_transition(ivisurf,
++ IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
++ duration);
++ ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ ivi_controller_interface->surface_set_destination_rectangle(ivisurf, 0, 0,
++ surface_width,
++ surface_height);
++ }
++}
++
++static void
++mode_random_replace(struct hmi_controller *hmi_ctrl,
++ struct ivi_layout_surface **pp_surface,
++ int32_t surface_length,
++ struct hmi_controller_layer *layer)
++{
++ const int32_t surface_width = (int32_t)(layer->width * 0.25f);
++ const int32_t surface_height = (int32_t)(layer->height * 0.25f);
++ int32_t surface_x = 0;
++ int32_t surface_y = 0;
++ struct ivi_layout_surface *ivisurf = NULL;
++ const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
++ int32_t i = 0;
++
++ for (i = 0; i < surface_length; i++) {
++ ivisurf = pp_surface[i];
++
++ /* skip ui widgets */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
++ continue;
++
++ ivi_controller_interface->surface_set_transition(ivisurf,
++ IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
++ duration);
++ ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ surface_x = rand() % (layer->width - surface_width);
++ surface_y = rand() % (layer->height - surface_height);
++
++ ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
++ surface_x,
++ surface_y,
++ surface_width,
++ surface_height);
++ }
++}
++
++static int32_t
++has_application_surface(struct hmi_controller *hmi_ctrl,
++ struct ivi_layout_surface **pp_surface,
++ int32_t surface_length)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ int32_t i = 0;
++
++ for (i = 0; i < surface_length; i++) {
++ ivisurf = pp_surface[i];
++
++ /* skip ui widgets */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
++ continue;
++
++ return 1;
++ }
++
++ return 0;
++}
++
++/**
++ * Supports 4 example to layout of application ivi_surfaces;
++ * tiling, side by side, fullscreen, and random.
++ */
++static void
++switch_mode(struct hmi_controller *hmi_ctrl,
++ enum ivi_hmi_controller_layout_mode layout_mode)
++{
++ struct hmi_controller_layer *layer = &hmi_ctrl->application_layer;
++ struct ivi_layout_surface **pp_surface = NULL;
++ int32_t surface_length = 0;
++ int32_t ret = 0;
++
++ if (!hmi_ctrl->is_initialized)
++ return;
++
++ hmi_ctrl->layout_mode = layout_mode;
++
++ ret = ivi_controller_interface->get_surfaces(&surface_length, &pp_surface);
++ assert(!ret);
++
++ if (!has_application_surface(hmi_ctrl, pp_surface, surface_length)) {
++ free(pp_surface);
++ pp_surface = NULL;
++ return;
++ }
++
++ switch (layout_mode) {
++ case IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING:
++ mode_divided_into_tiling(hmi_ctrl, pp_surface, surface_length,
++ layer);
++ break;
++ case IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE:
++ mode_divided_into_sidebyside(hmi_ctrl, pp_surface,
++ surface_length, layer);
++ break;
++ case IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN:
++ mode_fullscreen_someone(hmi_ctrl, pp_surface, surface_length,
++ layer);
++ break;
++ case IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM:
++ mode_random_replace(hmi_ctrl, pp_surface, surface_length,
++ layer);
++ break;
++ }
++
++ ivi_controller_interface->commit_changes();
++ free(pp_surface);
++}
++
++/**
++ * Internal method for transition
++ */
++static void
++hmi_controller_fade_run(struct hmi_controller *hmi_ctrl, uint32_t is_fade_in,
++ struct hmi_controller_fade *fade)
++{
++ double tint = is_fade_in ? 1.0 : 0.0;
++ struct link_layer *linklayer = NULL;
++ const uint32_t duration = hmi_ctrl->hmi_setting->transition_duration;
++
++ fade->is_fade_in = is_fade_in;
++
++ wl_list_for_each(linklayer, &fade->layer_list, link) {
++ ivi_controller_interface->layer_set_transition(linklayer->layout_layer,
++ IVI_LAYOUT_TRANSITION_LAYER_FADE,
++ duration);
++ ivi_controller_interface->layer_set_fade_info(linklayer->layout_layer,
++ is_fade_in, 1.0 - tint, tint);
++ }
++}
++
++/**
++ * Internal method to create ivi_layer with hmi_controller_layer and
++ * add to a ivi_screen
++ */
++static void
++create_layer(struct ivi_layout_screen *iviscrn,
++ struct hmi_controller_layer *layer)
++{
++ int32_t ret = 0;
++
++ layer->ivilayer =
++ ivi_controller_interface->layer_create_with_dimension(layer->id_layer,
++ layer->width,
++ layer->height);
++ assert(layer->ivilayer != NULL);
++
++ ret = ivi_controller_interface->screen_add_layer(iviscrn, layer->ivilayer);
++ assert(!ret);
++
++ ret = ivi_controller_interface->layer_set_destination_rectangle(layer->ivilayer,
++ layer->x, layer->y,
++ layer->width,
++ layer->height);
++ assert(!ret);
++
++ ret = ivi_controller_interface->layer_set_visibility(layer->ivilayer, true);
++ assert(!ret);
++}
++
++/**
++ * Internal set notification
++ */
++static void
++set_notification_create_surface(struct ivi_layout_surface *ivisurf,
++ void *userdata)
++{
++ struct hmi_controller *hmi_ctrl = userdata;
++ struct ivi_layout_layer *application_layer =
++ hmi_ctrl->application_layer.ivilayer;
++ int32_t ret = 0;
++
++ /* skip ui widgets */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf))
++ return;
++
++ ret = ivi_controller_interface->layer_add_surface(application_layer, ivisurf);
++ assert(!ret);
++}
++
++static void
++set_notification_remove_surface(struct ivi_layout_surface *ivisurf,
++ void *userdata)
++{
++ struct hmi_controller *hmi_ctrl = userdata;
++
++ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
++}
++
++static void
++set_notification_configure_surface(struct ivi_layout_surface *ivisurf,
++ void *userdata)
++{
++ struct hmi_controller *hmi_ctrl = userdata;
++ struct ivi_layout_layer *application_layer =
++ hmi_ctrl->application_layer.ivilayer;
++ struct weston_surface *surface;
++ struct ivi_layout_surface **ivisurfs;
++ int32_t length = 0;
++ int32_t i;
++
++ /* return if the surface is not application content */
++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) {
++ return;
++ }
++
++ /*
++ * if application changes size of wl_buffer. The source rectangle shall be
++ * fit to the size.
++ */
++ surface = ivi_controller_interface->surface_get_weston_surface(ivisurf);
++ if (surface) {
++ ivi_controller_interface->surface_set_source_rectangle(
++ ivisurf, 0, 0, surface->width,
++ surface->height);
++ }
++
++ /*
++ * search if the surface is already added to layer.
++ * If not yet, it is newly invoded application to go to switch_mode.
++ */
++ ivi_controller_interface->get_surfaces_on_layer(application_layer,
++ &length, &ivisurfs);
++ for (i = 0; i < length; i++) {
++ if (ivisurf == ivisurfs[i]) {
++ /*
++ * if it is non new invoked application, just call
++ * commit_changes to apply source_rectangle.
++ */
++ ivi_controller_interface->commit_changes();
++ return;
++ }
++ }
++
++ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode);
++}
++
++/**
++ * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of
++ * corresponding ivi_layer are defined in weston.ini. Default scene graph
++ * of ivi_layers are initialized in hmi_controller_create
++ */
++static struct hmi_server_setting *
++hmi_server_setting_create(struct weston_compositor *ec)
++{
++ struct hmi_server_setting *setting = MEM_ALLOC(sizeof(*setting));
++ struct weston_config *config = ec->config;
++ struct weston_config_section *shell_section = NULL;
++
++ shell_section = weston_config_get_section(config, "ivi-shell",
++ NULL, NULL);
++
++ weston_config_section_get_uint(shell_section, "base-layer-id",
++ &setting->base_layer_id, 1000);
++
++ weston_config_section_get_uint(shell_section,
++ "workspace-background-layer-id",
++ &setting->workspace_background_layer_id,
++ 2000);
++
++ weston_config_section_get_uint(shell_section, "workspace-layer-id",
++ &setting->workspace_layer_id, 3000);
++
++ weston_config_section_get_uint(shell_section, "application-layer-id",
++ &setting->application_layer_id, 4000);
++
++ weston_config_section_get_uint(shell_section, "transition-duration",
++ &setting->transition_duration, 300);
++
++ setting->panel_height = 70;
++
++ weston_config_section_get_string(shell_section,
++ "ivi-shell-user-interface",
++ &setting->ivi_homescreen, NULL);
++
++ return setting;
++}
++
++static void
++hmi_controller_destroy(struct wl_listener *listener, void *data)
++{
++ struct link_layer *link = NULL;
++ struct link_layer *next = NULL;
++ struct hmi_controller *hmi_ctrl =
++ container_of(listener, struct hmi_controller, destroy_listener);
++
++ wl_list_for_each_safe(link, next,
++ &hmi_ctrl->workspace_fade.layer_list, link) {
++ wl_list_remove(&link->link);
++ free(link);
++ }
++
++ wl_array_release(&hmi_ctrl->ui_widgets);
++ free(hmi_ctrl->hmi_setting);
++ free(hmi_ctrl);
++}
++
++/**
++ * This is a starting method called from module_init.
++ * This sets up scene graph of ivi_layers; base, application, workspace
++ * background, and workspace. These ivi_layers are created/added to
++ * ivi_screen in create_layer
++ *
++ * base: to group ivi_surfaces of panel and background
++ * application: to group ivi_surfaces of ivi_applications
++ * workspace background: to group a ivi_surface of background in workspace
++ * workspace: to group ivi_surfaces for launching ivi_applications
++ *
++ * ivi_layers of workspace background and workspace is set to invisible at
++ * first. The properties of it is updated with animation when
++ * ivi_hmi_controller_home is requested.
++ */
++static struct hmi_controller *
++hmi_controller_create(struct weston_compositor *ec)
++{
++ struct ivi_layout_screen **pp_screen = NULL;
++ struct ivi_layout_screen *iviscrn = NULL;
++ int32_t screen_length = 0;
++ int32_t screen_width = 0;
++ int32_t screen_height = 0;
++ struct link_layer *tmp_link_layer = NULL;
++ int32_t panel_height = 0;
++ struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl));
++
++ wl_array_init(&hmi_ctrl->ui_widgets);
++ hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING;
++ hmi_ctrl->hmi_setting = hmi_server_setting_create(ec);
++ hmi_ctrl->compositor = ec;
++
++ ivi_controller_interface->get_screens(&screen_length, &pp_screen);
++
++ iviscrn = pp_screen[0];
++
++ ivi_controller_interface->get_screen_resolution(iviscrn, &screen_width,
++ &screen_height);
++
++ /* init base ivi_layer*/
++ hmi_ctrl->base_layer.x = 0;
++ hmi_ctrl->base_layer.y = 0;
++ hmi_ctrl->base_layer.width = screen_width;
++ hmi_ctrl->base_layer.height = screen_height;
++ hmi_ctrl->base_layer.id_layer = hmi_ctrl->hmi_setting->base_layer_id;
++
++ create_layer(iviscrn, &hmi_ctrl->base_layer);
++
++ panel_height = hmi_ctrl->hmi_setting->panel_height;
++
++ /* init application ivi_layer */
++ hmi_ctrl->application_layer.x = 0;
++ hmi_ctrl->application_layer.y = 0;
++ hmi_ctrl->application_layer.width = screen_width;
++ hmi_ctrl->application_layer.height = screen_height - panel_height;
++ hmi_ctrl->application_layer.id_layer =
++ hmi_ctrl->hmi_setting->application_layer_id;
++
++ create_layer(iviscrn, &hmi_ctrl->application_layer);
++
++ /* init workspace background ivi_layer */
++ hmi_ctrl->workspace_background_layer.x = 0;
++ hmi_ctrl->workspace_background_layer.y = 0;
++ hmi_ctrl->workspace_background_layer.width = screen_width;
++ hmi_ctrl->workspace_background_layer.height =
++ screen_height - panel_height;
++
++ hmi_ctrl->workspace_background_layer.id_layer =
++ hmi_ctrl->hmi_setting->workspace_background_layer_id;
++
++ create_layer(iviscrn, &hmi_ctrl->workspace_background_layer);
++ ivi_controller_interface->layer_set_opacity(
++ hmi_ctrl->workspace_background_layer.ivilayer, 0);
++ ivi_controller_interface->layer_set_visibility(
++ hmi_ctrl->workspace_background_layer.ivilayer, false);
++
++
++ wl_list_init(&hmi_ctrl->workspace_fade.layer_list);
++ tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
++ tmp_link_layer->layout_layer =
++ hmi_ctrl->workspace_background_layer.ivilayer;
++ wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
++ &tmp_link_layer->link);
++
++ ivi_controller_interface->add_notification_create_surface(
++ set_notification_create_surface, hmi_ctrl);
++ ivi_controller_interface->add_notification_remove_surface(
++ set_notification_remove_surface, hmi_ctrl);
++ ivi_controller_interface->add_notification_configure_surface(
++ set_notification_configure_surface, hmi_ctrl);
++
++ hmi_ctrl->destroy_listener.notify = hmi_controller_destroy;
++ wl_signal_add(&hmi_ctrl->compositor->destroy_signal,
++ &hmi_ctrl->destroy_listener);
++
++ free(pp_screen);
++ pp_screen = NULL;
++
++ return hmi_ctrl;
++}
++
++/**
++ * Implementations of ivi-hmi-controller.xml
++ */
++
++/**
++ * A ivi_surface drawing background is identified by id_surface.
++ * Properties of the ivi_surface is set by using ivi_layout APIs according to
++ * the scene graph of UI defined in hmi_controller_create.
++ *
++ * UI ivi_layer is used to add this ivi_surface.
++ */
++static void
++ivi_hmi_controller_set_background(struct hmi_controller *hmi_ctrl,
++ uint32_t id_surface)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
++ const int32_t dstx = hmi_ctrl->application_layer.x;
++ const int32_t dsty = hmi_ctrl->application_layer.y;
++ const int32_t width = hmi_ctrl->application_layer.width;
++ const int32_t height = hmi_ctrl->application_layer.height;
++ int32_t ret = 0;
++
++ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
++ sizeof(*add_surface_id));
++ *add_surface_id = id_surface;
++
++ ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
++ assert(ivisurf != NULL);
++
++ ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
++ dstx, dsty, width, height);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ assert(!ret);
++}
++
++/**
++ * A ivi_surface drawing panel is identified by id_surface.
++ * Properties of the ivi_surface is set by using ivi_layout APIs according to
++ * the scene graph of UI defined in hmi_controller_create.
++ *
++ * UI ivi_layer is used to add this ivi_surface.
++ */
++static void
++ivi_hmi_controller_set_panel(struct hmi_controller *hmi_ctrl,
++ uint32_t id_surface)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
++ const int32_t width = hmi_ctrl->base_layer.width;
++ int32_t ret = 0;
++ int32_t panel_height = 0;
++ const int32_t dstx = 0;
++ int32_t dsty = 0;
++
++ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
++ sizeof(*add_surface_id));
++ *add_surface_id = id_surface;
++
++ ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
++ assert(ivisurf != NULL);
++
++ ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
++ assert(!ret);
++
++ panel_height = hmi_ctrl->hmi_setting->panel_height;
++
++ dsty = hmi_ctrl->base_layer.height - panel_height;
++
++ ret = ivi_controller_interface->surface_set_destination_rectangle(
++ ivisurf, dstx, dsty, width, panel_height);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ assert(!ret);
++}
++
++/**
++ * A ivi_surface drawing buttons in panel is identified by id_surface.
++ * It can set several buttons. Properties of the ivi_surface is set by
++ * using ivi_layout APIs according to the scene graph of UI defined in
++ * hmi_controller_create. Additionally, the position of it is shifted to
++ * right when new one is requested.
++ *
++ * UI ivi_layer is used to add these ivi_surfaces.
++ */
++static void
++ivi_hmi_controller_set_button(struct hmi_controller *hmi_ctrl,
++ uint32_t id_surface, int32_t number)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
++ const int32_t width = 48;
++ const int32_t height = 48;
++ int32_t ret = 0;
++ int32_t panel_height = 0;
++ int32_t dstx = 0;
++ int32_t dsty = 0;
++ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
++ sizeof(*add_surface_id));
++ *add_surface_id = id_surface;
++
++ ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
++ assert(ivisurf != NULL);
++
++ ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
++ assert(!ret);
++
++ panel_height = hmi_ctrl->hmi_setting->panel_height;
++
++ dstx = (60 * number) + 15;
++ dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
++
++ ret = ivi_controller_interface->surface_set_destination_rectangle(
++ ivisurf,dstx, dsty, width, height);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ assert(!ret);
++}
++
++/**
++ * A ivi_surface drawing home button in panel is identified by id_surface.
++ * Properties of the ivi_surface is set by using ivi_layout APIs according to
++ * the scene graph of UI defined in hmi_controller_create.
++ *
++ * UI ivi_layer is used to add these ivi_surfaces.
++ */
++static void
++ivi_hmi_controller_set_home_button(struct hmi_controller *hmi_ctrl,
++ uint32_t id_surface)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_layer *ivilayer = hmi_ctrl->base_layer.ivilayer;
++ int32_t ret = 0;
++ int32_t size = 48;
++ int32_t panel_height = hmi_ctrl->hmi_setting->panel_height;
++ const int32_t dstx = (hmi_ctrl->base_layer.width - size) / 2;
++ const int32_t dsty = (hmi_ctrl->base_layer.height - panel_height) + 5;
++
++ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
++ sizeof(*add_surface_id));
++ *add_surface_id = id_surface;
++
++ ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
++ assert(ivisurf != NULL);
++
++ ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_destination_rectangle(
++ ivisurf, dstx, dsty, size, size);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ assert(!ret);
++}
++
++/**
++ * A ivi_surface drawing background of workspace is identified by id_surface.
++ * Properties of the ivi_surface is set by using ivi_layout APIs according to
++ * the scene graph of UI defined in hmi_controller_create.
++ *
++ * A ivi_layer of workspace_background is used to add this ivi_surface.
++ */
++static void
++ivi_hmi_controller_set_workspacebackground(struct hmi_controller *hmi_ctrl,
++ uint32_t id_surface)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_layer *ivilayer = NULL;
++ const int32_t width = hmi_ctrl->workspace_background_layer.width;
++ const int32_t height = hmi_ctrl->workspace_background_layer.height;
++ int32_t ret = 0;
++
++ uint32_t *add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
++ sizeof(*add_surface_id));
++ *add_surface_id = id_surface;
++ ivilayer = hmi_ctrl->workspace_background_layer.ivilayer;
++
++ ivisurf = ivi_controller_interface->get_surface_from_id(id_surface);
++ assert(ivisurf != NULL);
++
++ ret = ivi_controller_interface->layer_add_surface(ivilayer, ivisurf);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_destination_rectangle(ivisurf,
++ 0, 0, width, height);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_visibility(ivisurf, true);
++ assert(!ret);
++}
++
++/**
++ * A list of ivi_surfaces drawing launchers in workspace is identified by
++ * id_surfaces. Properties of the ivi_surface is set by using ivi_layout
++ * APIs according to the scene graph of UI defined in hmi_controller_create.
++ *
++ * The workspace can have several pages to group ivi_surfaces of launcher.
++ * Each call of this interface increments a number of page to add a group
++ * of ivi_surfaces
++ */
++static void
++ivi_hmi_controller_add_launchers(struct hmi_controller *hmi_ctrl,
++ int32_t icon_size)
++{
++ int32_t minspace_x = 10;
++ int32_t minspace_y = minspace_x;
++
++ int32_t width = hmi_ctrl->workspace_background_layer.width;
++ int32_t height = hmi_ctrl->workspace_background_layer.height;
++
++ int32_t x_count = (width - minspace_x) / (minspace_x + icon_size);
++ int32_t space_x = (int32_t)((width - x_count * icon_size) / (1.0 + x_count));
++ float fcell_size_x = icon_size + space_x;
++
++ int32_t y_count = (height - minspace_y) / (minspace_y + icon_size);
++ int32_t space_y = (int32_t)((height - y_count * icon_size) / (1.0 + y_count));
++ float fcell_size_y = icon_size + space_y;
++
++ struct weston_config *config = NULL;
++ struct weston_config_section *section = NULL;
++ const char *name = NULL;
++ int launcher_count = 0;
++ struct wl_array launchers;
++ int32_t nx = 0;
++ int32_t ny = 0;
++ int32_t prev = -1;
++ struct launcher_info *data = NULL;
++
++ uint32_t surfaceid = 0;
++ uint32_t workspaceid = 0;
++ struct launcher_info *info = NULL;
++
++ int32_t x = 0;
++ int32_t y = 0;
++ int32_t ret = 0;
++ struct ivi_layout_surface* layout_surface = NULL;
++ uint32_t *add_surface_id = NULL;
++
++ struct ivi_layout_screen *iviscrn = NULL;
++ struct link_layer *tmp_link_layer = NULL;
++ struct ivi_layout_screen **pp_screen = NULL;
++ int32_t screen_length = 0;
++
++ if (0 == x_count)
++ x_count = 1;
++
++ if (0 == y_count)
++ y_count = 1;
++
++ config = hmi_ctrl->compositor->config;
++ if (!config)
++ return;
++
++ section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
++ if (!section)
++ return;
++
++ wl_array_init(&launchers);
++
++ while (weston_config_next_section(config, &section, &name)) {
++ surfaceid = 0;
++ workspaceid = 0;
++ info = NULL;
++ if (0 != strcmp(name, "ivi-launcher"))
++ continue;
++
++ if (0 != weston_config_section_get_uint(section, "icon-id",
++ &surfaceid, 0))
++ continue;
++
++ if (0 != weston_config_section_get_uint(section,
++ "workspace-id",
++ &workspaceid, 0))
++ continue;
++
++ info = wl_array_add(&launchers, sizeof(*info));
++
++ if (info) {
++ info->surface_id = surfaceid;
++ info->workspace_id = workspaceid;
++ info->index = launcher_count;
++ ++launcher_count;
++ }
++ }
++
++ qsort(launchers.data, launcher_count, sizeof(struct launcher_info),
++ compare_launcher_info);
++
++ wl_array_for_each(data, &launchers) {
++ x = 0;
++ y = 0;
++ ret = 0;
++ layout_surface = NULL;
++ add_surface_id = wl_array_add(&hmi_ctrl->ui_widgets,
++ sizeof(*add_surface_id));
++
++ *add_surface_id = data->surface_id;
++
++ if (0 > prev || (uint32_t)prev != data->workspace_id) {
++ nx = 0;
++ ny = 0;
++ prev = data->workspace_id;
++
++ if (0 <= prev)
++ hmi_ctrl->workspace_count++;
++ }
++
++ if (y_count == ny) {
++ ny = 0;
++ hmi_ctrl->workspace_count++;
++ }
++
++ x = nx * fcell_size_x + (hmi_ctrl->workspace_count - 1) * width + space_x;
++ y = ny * fcell_size_y + space_y;
++
++ layout_surface =
++ ivi_controller_interface->get_surface_from_id(data->surface_id);
++ assert(layout_surface);
++
++ ret = ivi_controller_interface->surface_set_destination_rectangle(
++ layout_surface, x, y, icon_size, icon_size);
++ assert(!ret);
++
++ nx++;
++
++ if (x_count == nx) {
++ ny++;
++ nx = 0;
++ }
++ }
++
++ /* init workspace ivi_layer */
++ hmi_ctrl->workspace_layer.x = hmi_ctrl->workspace_background_layer.x;
++ hmi_ctrl->workspace_layer.y = hmi_ctrl->workspace_background_layer.y;
++ hmi_ctrl->workspace_layer.width =
++ hmi_ctrl->workspace_background_layer.width * hmi_ctrl->workspace_count;
++ hmi_ctrl->workspace_layer.height =
++ hmi_ctrl->workspace_background_layer.height;
++ hmi_ctrl->workspace_layer.id_layer =
++ hmi_ctrl->hmi_setting->workspace_layer_id;
++
++ ivi_controller_interface->get_screens(&screen_length, &pp_screen);
++ iviscrn = pp_screen[0];
++ free(pp_screen);
++ create_layer(iviscrn, &hmi_ctrl->workspace_layer);
++ ivi_controller_interface->layer_set_opacity(hmi_ctrl->workspace_layer.ivilayer, 0);
++ ivi_controller_interface->layer_set_visibility(hmi_ctrl->workspace_layer.ivilayer,
++ false);
++
++ tmp_link_layer = MEM_ALLOC(sizeof(*tmp_link_layer));
++ tmp_link_layer->layout_layer = hmi_ctrl->workspace_layer.ivilayer;
++ wl_list_insert(&hmi_ctrl->workspace_fade.layer_list,
++ &tmp_link_layer->link);
++
++ /* Add surface to layer */
++ wl_array_for_each(data, &launchers) {
++ layout_surface =
++ ivi_controller_interface->get_surface_from_id(data->surface_id);
++ assert(layout_surface);
++
++ ret = ivi_controller_interface->layer_add_surface(hmi_ctrl->workspace_layer.ivilayer,
++ layout_surface);
++ assert(!ret);
++
++ ret = ivi_controller_interface->surface_set_visibility(layout_surface, true);
++ assert(!ret);
++ }
++
++ wl_array_release(&launchers);
++ ivi_controller_interface->commit_changes();
++}
++
++static void
++ivi_hmi_controller_UI_ready(struct wl_client *client,
++ struct wl_resource *resource)
++{
++ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
++
++ ivi_hmi_controller_set_background(hmi_ctrl, hmi_ctrl->ui_setting.background_id);
++ ivi_hmi_controller_set_panel(hmi_ctrl, hmi_ctrl->ui_setting.panel_id);
++ ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.tiling_id, 0);
++ ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.sidebyside_id, 1);
++ ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.fullscreen_id, 2);
++ ivi_hmi_controller_set_button(hmi_ctrl, hmi_ctrl->ui_setting.random_id, 3);
++ ivi_hmi_controller_set_home_button(hmi_ctrl, hmi_ctrl->ui_setting.home_id);
++ ivi_hmi_controller_set_workspacebackground(hmi_ctrl, hmi_ctrl->ui_setting.workspace_background_id);
++ ivi_controller_interface->commit_changes();
++
++ ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
++ hmi_ctrl->is_initialized = 1;
++}
++
++/**
++ * Implementation of request and event of ivi_hmi_controller_workspace_control
++ * and controlling workspace.
++ *
++ * When motion of input is detected in a ivi_surface of workspace background,
++ * ivi_hmi_controller_workspace_control shall be invoked and to start
++ * controlling of workspace. The workspace has several pages to show several
++ * groups of applications.
++ * The workspace is slid by using ivi-layout to select a a page in layer_set_pos
++ * according to motion. When motion finished, e.g. touch up detected, control is
++ * terminated and event:ivi_hmi_controller_workspace_control is notified.
++ */
++struct pointer_grab {
++ struct weston_pointer_grab grab;
++ struct ivi_layout_layer *layer;
++ struct wl_resource *resource;
++};
++
++struct touch_grab {
++ struct weston_touch_grab grab;
++ struct ivi_layout_layer *layer;
++ struct wl_resource *resource;
++};
++
++struct move_grab {
++ wl_fixed_t dst[2];
++ wl_fixed_t rgn[2][2];
++ double v[2];
++ struct timespec start_time;
++ struct timespec pre_time;
++ wl_fixed_t start_pos[2];
++ wl_fixed_t pos[2];
++ int32_t is_moved;
++};
++
++struct pointer_move_grab {
++ struct pointer_grab base;
++ struct move_grab move;
++};
++
++struct touch_move_grab {
++ struct touch_grab base;
++ struct move_grab move;
++ int32_t is_active;
++};
++
++static void
++pointer_grab_start(struct pointer_grab *grab,
++ struct ivi_layout_layer *layer,
++ const struct weston_pointer_grab_interface *interface,
++ struct weston_pointer *pointer)
++{
++ grab->grab.interface = interface;
++ grab->layer = layer;
++ weston_pointer_start_grab(pointer, &grab->grab);
++}
++
++static void
++touch_grab_start(struct touch_grab *grab,
++ struct ivi_layout_layer *layer,
++ const struct weston_touch_grab_interface *interface,
++ struct weston_touch* touch)
++{
++ grab->grab.interface = interface;
++ grab->layer = layer;
++ weston_touch_start_grab(touch, &grab->grab);
++}
++
++static int32_t
++clamp(int32_t val, int32_t min, int32_t max)
++{
++ if (val < min)
++ return min;
++
++ if (max < val)
++ return max;
++
++ return val;
++}
++
++static void
++move_workspace_grab_end(struct move_grab *move, struct wl_resource* resource,
++ wl_fixed_t grab_x, struct ivi_layout_layer *layer)
++{
++ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
++ int32_t width = hmi_ctrl->workspace_background_layer.width;
++
++ struct timespec time = {0};
++ double grab_time = 0.0;
++ double from_motion_time = 0.0;
++ double pointer_v = 0.0;
++ int32_t is_flick = 0;
++ int32_t pos_x = 0;
++ int32_t pos_y = 0;
++ int page_no = 0;
++ double end_pos = 0.0;
++ uint32_t duration = 0;
++
++ clock_gettime(CLOCK_MONOTONIC, &time);
++
++ grab_time = 1e+3 * (time.tv_sec - move->start_time.tv_sec) +
++ 1e-6 * (time.tv_nsec - move->start_time.tv_nsec);
++
++ from_motion_time = 1e+3 * (time.tv_sec - move->pre_time.tv_sec) +
++ 1e-6 * (time.tv_nsec - move->pre_time.tv_nsec);
++
++ pointer_v = move->v[0];
++
++ is_flick = grab_time < 400 && 0.4 < fabs(pointer_v);
++ if (200 < from_motion_time)
++ pointer_v = 0.0;
++
++ ivi_controller_interface->layer_get_position(layer, &pos_x, &pos_y);
++
++
++ if (is_flick) {
++ int orgx = wl_fixed_to_int(move->dst[0] + grab_x);
++ page_no = (-orgx + width / 2) / width;
++
++ if (pointer_v < 0.0)
++ page_no++;
++ else
++ page_no--;
++ } else {
++ page_no = (-pos_x + width / 2) / width;
++ }
++
++ page_no = clamp(page_no, 0, hmi_ctrl->workspace_count - 1);
++ end_pos = -page_no * width;
++
++ duration = hmi_ctrl->hmi_setting->transition_duration;
++ ivi_hmi_controller_send_workspace_end_control(resource, move->is_moved);
++ ivi_controller_interface->layer_set_transition(layer,
++ IVI_LAYOUT_TRANSITION_LAYER_MOVE,
++ duration);
++ ivi_controller_interface->layer_set_destination_rectangle(layer,
++ end_pos, pos_y,
++ hmi_ctrl->workspace_layer.width,
++ hmi_ctrl->workspace_layer.height);
++ ivi_controller_interface->commit_changes();
++}
++
++static void
++pointer_move_workspace_grab_end(struct pointer_grab *grab)
++{
++ struct pointer_move_grab *pnt_move_grab =
++ (struct pointer_move_grab *)grab;
++ struct ivi_layout_layer *layer = pnt_move_grab->base.layer;
++
++ move_workspace_grab_end(&pnt_move_grab->move, grab->resource,
++ grab->grab.pointer->grab_x, layer);
++
++ weston_pointer_end_grab(grab->grab.pointer);
++}
++
++static void
++touch_move_workspace_grab_end(struct touch_grab *grab)
++{
++ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
++ struct ivi_layout_layer *layer = tch_move_grab->base.layer;
++
++ move_workspace_grab_end(&tch_move_grab->move, grab->resource,
++ grab->grab.touch->grab_x, layer);
++
++ weston_touch_end_grab(grab->grab.touch);
++}
++
++static void
++pointer_noop_grab_focus(struct weston_pointer_grab *grab)
++{
++}
++
++static void
++move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
++{
++ struct timespec timestamp = {0};
++ int32_t ii = 0;
++ double dt = 0.0;
++
++ clock_gettime(CLOCK_MONOTONIC, &timestamp); //FIXME
++ dt = (1e+3 * (timestamp.tv_sec - move->pre_time.tv_sec) +
++ 1e-6 * (timestamp.tv_nsec - move->pre_time.tv_nsec));
++
++ if (dt < 1e-6)
++ dt = 1e-6;
++
++ move->pre_time = timestamp;
++
++ for (ii = 0; ii < 2; ii++) {
++ wl_fixed_t prepos = move->pos[ii];
++ move->pos[ii] = pointer[ii] + move->dst[ii];
++
++ if (move->pos[ii] < move->rgn[0][ii]) {
++ move->pos[ii] = move->rgn[0][ii];
++ move->dst[ii] = move->pos[ii] - pointer[ii];
++ } else if (move->rgn[1][ii] < move->pos[ii]) {
++ move->pos[ii] = move->rgn[1][ii];
++ move->dst[ii] = move->pos[ii] - pointer[ii];
++ }
++
++ move->v[ii] = wl_fixed_to_double(move->pos[ii] - prepos) / dt;
++
++ if (!move->is_moved &&
++ 0 < wl_fixed_to_int(move->pos[ii] - move->start_pos[ii]))
++ move->is_moved = 1;
++ }
++}
++
++static void
++layer_set_pos(struct ivi_layout_layer *layer, wl_fixed_t pos_x,
++ wl_fixed_t pos_y)
++{
++ int32_t layout_pos_x = 0;
++ int32_t layout_pos_y = 0;
++
++ layout_pos_x = wl_fixed_to_int(pos_x);
++ layout_pos_y = wl_fixed_to_int(pos_y);
++ ivi_controller_interface->layer_set_position(layer, layout_pos_x, layout_pos_y);
++ ivi_controller_interface->commit_changes();
++}
++
++static void
++pointer_move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
++ wl_fixed_t x, wl_fixed_t y)
++{
++ struct pointer_move_grab *pnt_move_grab =
++ (struct pointer_move_grab *)grab;
++ wl_fixed_t pointer_pos[2] = {x, y};
++
++ move_grab_update(&pnt_move_grab->move, pointer_pos);
++ layer_set_pos(pnt_move_grab->base.layer,
++ pnt_move_grab->move.pos[0], pnt_move_grab->move.pos[1]);
++ weston_pointer_move(pnt_move_grab->base.grab.pointer, x, y);
++}
++
++static void
++touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
++ int touch_id, wl_fixed_t x, wl_fixed_t y)
++{
++ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
++
++ if (!tch_move_grab->is_active)
++ return;
++
++ wl_fixed_t pointer_pos[2] = {
++ grab->touch->grab_x,
++ grab->touch->grab_y
++ };
++
++ move_grab_update(&tch_move_grab->move, pointer_pos);
++ layer_set_pos(tch_move_grab->base.layer,
++ tch_move_grab->move.pos[0], tch_move_grab->move.pos[1]);
++}
++
++static void
++pointer_move_workspace_grab_button(struct weston_pointer_grab *grab,
++ uint32_t time, uint32_t button,
++ uint32_t state_w)
++{
++ if (BTN_LEFT == button &&
++ WL_POINTER_BUTTON_STATE_RELEASED == state_w) {
++ struct pointer_grab *pg = (struct pointer_grab *)grab;
++
++ pointer_move_workspace_grab_end(pg);
++ free(grab);
++ }
++}
++
++static void
++touch_nope_grab_down(struct weston_touch_grab *grab, uint32_t time,
++ int touch_id, wl_fixed_t sx, wl_fixed_t sy)
++{
++}
++
++static void
++touch_move_workspace_grab_up(struct weston_touch_grab *grab, uint32_t time,
++ int touch_id)
++{
++ struct touch_move_grab *tch_move_grab = (struct touch_move_grab *)grab;
++
++ if (0 == touch_id)
++ tch_move_grab->is_active = 0;
++
++ if (0 == grab->touch->num_tp) {
++ touch_move_workspace_grab_end(&tch_move_grab->base);
++ free(grab);
++ }
++}
++
++static void
++pointer_move_workspace_grab_cancel(struct weston_pointer_grab *grab)
++{
++ struct pointer_grab *pg = (struct pointer_grab *)grab;
++
++ pointer_move_workspace_grab_end(pg);
++ free(grab);
++}
++
++static void
++touch_move_workspace_grab_frame(struct weston_touch_grab *grab)
++{
++}
++
++static void
++touch_move_workspace_grab_cancel(struct weston_touch_grab *grab)
++{
++ struct touch_grab *tg = (struct touch_grab *)grab;
++
++ touch_move_workspace_grab_end(tg);
++ free(grab);
++}
++
++static const struct weston_pointer_grab_interface pointer_move_grab_workspace_interface = {
++ pointer_noop_grab_focus,
++ pointer_move_grab_motion,
++ pointer_move_workspace_grab_button,
++ pointer_move_workspace_grab_cancel
++};
++
++static const struct weston_touch_grab_interface touch_move_grab_workspace_interface = {
++ touch_nope_grab_down,
++ touch_move_workspace_grab_up,
++ touch_move_grab_motion,
++ touch_move_workspace_grab_frame,
++ touch_move_workspace_grab_cancel
++};
++
++enum HMI_GRAB_DEVICE {
++ HMI_GRAB_DEVICE_NONE,
++ HMI_GRAB_DEVICE_POINTER,
++ HMI_GRAB_DEVICE_TOUCH
++};
++
++static enum HMI_GRAB_DEVICE
++get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
++{
++ struct weston_pointer *pointer = seat->pointer;
++ struct weston_touch *touch = seat->touch;
++
++ if (pointer &&
++ pointer->focus &&
++ pointer->button_count &&
++ pointer->grab_serial == serial)
++ return HMI_GRAB_DEVICE_POINTER;
++
++ if (touch &&
++ touch->focus &&
++ touch->grab_serial == serial)
++ return HMI_GRAB_DEVICE_TOUCH;
++
++ return HMI_GRAB_DEVICE_NONE;
++}
++
++static void
++move_grab_init(struct move_grab* move, wl_fixed_t start_pos[2],
++ wl_fixed_t grab_pos[2], wl_fixed_t rgn[2][2],
++ struct wl_resource* resource)
++{
++ clock_gettime(CLOCK_MONOTONIC, &move->start_time); //FIXME
++ move->pre_time = move->start_time;
++ move->pos[0] = start_pos[0];
++ move->pos[1] = start_pos[1];
++ move->start_pos[0] = start_pos[0];
++ move->start_pos[1] = start_pos[1];
++ move->dst[0] = start_pos[0] - grab_pos[0];
++ move->dst[1] = start_pos[1] - grab_pos[1];
++ memcpy(move->rgn, rgn, sizeof(move->rgn));
++}
++
++static void
++move_grab_init_workspace(struct move_grab* move,
++ wl_fixed_t grab_x, wl_fixed_t grab_y,
++ struct wl_resource *resource)
++{
++ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
++ struct ivi_layout_layer *layer = hmi_ctrl->workspace_layer.ivilayer;
++ int32_t workspace_count = hmi_ctrl->workspace_count;
++ int32_t workspace_width = hmi_ctrl->workspace_background_layer.width;
++ int32_t layer_pos_x = 0;
++ int32_t layer_pos_y = 0;
++ wl_fixed_t start_pos[2] = {0};
++ wl_fixed_t rgn[2][2] = {{0}};
++ wl_fixed_t grab_pos[2] = { grab_x, grab_y };
++
++ ivi_controller_interface->layer_get_position(layer, &layer_pos_x, &layer_pos_y);
++
++ start_pos[0] = wl_fixed_from_int(layer_pos_x);
++ start_pos[1] = wl_fixed_from_int(layer_pos_y);
++
++ rgn[0][0] = wl_fixed_from_int(-workspace_width * (workspace_count - 1));
++
++ rgn[0][1] = wl_fixed_from_int(0);
++ rgn[1][0] = wl_fixed_from_int(0);
++ rgn[1][1] = wl_fixed_from_int(0);
++
++ move_grab_init(move, start_pos, grab_pos, rgn, resource);
++}
++
++static struct pointer_move_grab *
++create_workspace_pointer_move(struct weston_pointer *pointer,
++ struct wl_resource* resource)
++{
++ struct pointer_move_grab *pnt_move_grab =
++ MEM_ALLOC(sizeof(*pnt_move_grab));
++
++ pnt_move_grab->base.resource = resource;
++ move_grab_init_workspace(&pnt_move_grab->move, pointer->grab_x,
++ pointer->grab_y, resource);
++
++ return pnt_move_grab;
++}
++
++static struct touch_move_grab *
++create_workspace_touch_move(struct weston_touch *touch,
++ struct wl_resource* resource)
++{
++ struct touch_move_grab *tch_move_grab =
++ MEM_ALLOC(sizeof(*tch_move_grab));
++
++ tch_move_grab->base.resource = resource;
++ tch_move_grab->is_active = 1;
++ move_grab_init_workspace(&tch_move_grab->move, touch->grab_x,
++ touch->grab_y, resource);
++
++ return tch_move_grab;
++}
++
++static void
++ivi_hmi_controller_workspace_control(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *seat_resource,
++ uint32_t serial)
++{
++ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
++ struct ivi_layout_layer *layer = NULL;
++ struct pointer_move_grab *pnt_move_grab = NULL;
++ struct touch_move_grab *tch_move_grab = NULL;
++ struct weston_seat *seat = NULL;
++ struct weston_pointer *pointer;
++ struct weston_touch *touch;
++
++ enum HMI_GRAB_DEVICE device;
++
++ if (hmi_ctrl->workspace_count < 2)
++ return;
++
++ seat = wl_resource_get_user_data(seat_resource);
++ device = get_hmi_grab_device(seat, serial);
++
++ if (HMI_GRAB_DEVICE_POINTER != device &&
++ HMI_GRAB_DEVICE_TOUCH != device)
++ return;
++
++ layer = hmi_ctrl->workspace_layer.ivilayer;
++
++ ivi_controller_interface->transition_move_layer_cancel(layer);
++
++ switch (device) {
++ case HMI_GRAB_DEVICE_POINTER:
++ pointer = seat->pointer;
++ pnt_move_grab = create_workspace_pointer_move(pointer,
++ resource);
++
++ pointer_grab_start(&pnt_move_grab->base, layer,
++ &pointer_move_grab_workspace_interface,
++ pointer);
++ break;
++
++ case HMI_GRAB_DEVICE_TOUCH:
++ touch = seat->touch;
++ tch_move_grab = create_workspace_touch_move(touch,
++ resource);
++
++ touch_grab_start(&tch_move_grab->base, layer,
++ &touch_move_grab_workspace_interface,
++ touch);
++ break;
++
++ default:
++ break;
++ }
++}
++
++/**
++ * Implementation of switch_mode
++ */
++static void
++ivi_hmi_controller_switch_mode(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t layout_mode)
++{
++ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
++
++ switch_mode(hmi_ctrl, layout_mode);
++}
++
++/**
++ * Implementation of on/off displaying workspace and workspace background
++ * ivi_layers.
++ */
++static void
++ivi_hmi_controller_home(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t home)
++{
++ struct hmi_controller *hmi_ctrl = wl_resource_get_user_data(resource);
++ uint32_t is_fade_in;
++
++ if ((IVI_HMI_CONTROLLER_HOME_ON == home &&
++ !hmi_ctrl->workspace_fade.is_fade_in) ||
++ (IVI_HMI_CONTROLLER_HOME_OFF == home &&
++ hmi_ctrl->workspace_fade.is_fade_in)) {
++ is_fade_in = !hmi_ctrl->workspace_fade.is_fade_in;
++ hmi_controller_fade_run(hmi_ctrl, is_fade_in,
++ &hmi_ctrl->workspace_fade);
++ }
++
++ ivi_controller_interface->commit_changes();
++}
++
++/**
++ * binding ivi-hmi-controller implementation
++ */
++static const struct ivi_hmi_controller_interface ivi_hmi_controller_implementation = {
++ ivi_hmi_controller_UI_ready,
++ ivi_hmi_controller_workspace_control,
++ ivi_hmi_controller_switch_mode,
++ ivi_hmi_controller_home
++};
++
++static void
++unbind_hmi_controller(struct wl_resource *resource)
++{
++}
++
++static void
++bind_hmi_controller(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct wl_resource *resource = NULL;
++ struct hmi_controller *hmi_ctrl = data;
++
++ if (hmi_ctrl->user_interface != client) {
++ struct wl_resource *res = wl_client_get_object(client, 1);
++ wl_resource_post_error(res,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "hmi-controller failed: permission denied");
++ return;
++ }
++
++ resource = wl_resource_create(
++ client, &ivi_hmi_controller_interface, 1, id);
++
++ wl_resource_set_implementation(
++ resource, &ivi_hmi_controller_implementation,
++ hmi_ctrl, unbind_hmi_controller);
++}
++
++static void
++handle_hmi_client_process_sigchld(struct weston_process *proc, int status)
++{
++ proc->pid = 0;
++}
++
++static int32_t
++initialize(struct hmi_controller *hmi_ctrl)
++{
++ struct config_command {
++ char *key;
++ uint32_t *dest;
++ };
++
++ struct weston_config *config = hmi_ctrl->compositor->config;
++ struct weston_config_section *section = NULL;
++ int result = 0;
++ int i = 0;
++
++ const struct config_command uint_commands[] = {
++ { "background-id", &hmi_ctrl->ui_setting.background_id },
++ { "panel-id", &hmi_ctrl->ui_setting.panel_id },
++ { "tiling-id", &hmi_ctrl->ui_setting.tiling_id },
++ { "sidebyside-id", &hmi_ctrl->ui_setting.sidebyside_id },
++ { "fullscreen-id", &hmi_ctrl->ui_setting.fullscreen_id },
++ { "random-id", &hmi_ctrl->ui_setting.random_id },
++ { "home-id", &hmi_ctrl->ui_setting.home_id },
++ { "workspace-background-id", &hmi_ctrl->ui_setting.workspace_background_id },
++ { NULL, NULL }
++ };
++
++ section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
++
++ for (i = 0; -1 != result; ++i) {
++ const struct config_command *command = &uint_commands[i];
++
++ if (!command->key)
++ break;
++
++ if (weston_config_section_get_uint(
++ section, command->key, command->dest, 0) != 0)
++ result = -1;
++ }
++
++ if (-1 == result) {
++ weston_log("Failed to initialize hmi-controller\n");
++ return 0;
++ }
++
++ return 1;
++}
++
++static void
++launch_hmi_client_process(void *data)
++{
++ struct hmi_controller *hmi_ctrl =
++ (struct hmi_controller *)data;
++
++ hmi_ctrl->user_interface =
++ weston_client_launch(hmi_ctrl->compositor,
++ &hmi_ctrl->process,
++ hmi_ctrl->hmi_setting->ivi_homescreen,
++ handle_hmi_client_process_sigchld);
++
++ free(hmi_ctrl->hmi_setting->ivi_homescreen);
++}
++
++/*****************************************************************************
++ * exported functions
++ ****************************************************************************/
++WL_EXPORT int
++controller_module_init(struct weston_compositor *ec,
++ int *argc, char *argv[],
++ const struct ivi_controller_interface *interface,
++ size_t interface_version)
++{
++ struct hmi_controller *hmi_ctrl = NULL;
++ struct wl_event_loop *loop = NULL;
++
++ if (interface_version < sizeof(struct ivi_controller_interface)) {
++ weston_log("ivi-shell: version mismatch of controller interface");
++ return -1;
++ }
++
++ ivi_controller_interface = interface;
++
++ hmi_ctrl = hmi_controller_create(ec);
++
++ if (!initialize(hmi_ctrl)) {
++ return -1;
++ }
++
++ if (wl_global_create(ec->wl_display,
++ &ivi_hmi_controller_interface, 1,
++ hmi_ctrl, bind_hmi_controller) == NULL) {
++ return -1;
++ }
++
++ loop = wl_display_get_event_loop(ec->wl_display);
++ wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
++
++ return 0;
++}
+diff --git a/ivi-shell/input-panel-ivi.c b/ivi-shell/input-panel-ivi.c
+new file mode 100644
+index 0000000..51d2b8a
+--- /dev/null
++++ b/ivi-shell/input-panel-ivi.c
+@@ -0,0 +1,397 @@
++/*
++ * Copyright © 2010-2012 Intel Corporation
++ * Copyright © 2011-2012 Collabora, Ltd.
++ * Copyright © 2013 Raspberry Pi Foundation
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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 "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++
++#include "ivi-shell.h"
++#include "input-method-server-protocol.h"
++#include "ivi-layout-private.h"
++#include "shared/helpers.h"
++
++struct input_panel_surface {
++ struct wl_resource *resource;
++ struct wl_signal destroy_signal;
++
++ struct ivi_shell *shell;
++
++ struct wl_list link;
++ struct weston_surface *surface;
++ struct weston_view *view;
++ struct wl_listener surface_destroy_listener;
++
++ struct weston_view_animation *anim;
++
++ struct weston_output *output;
++ uint32_t panel;
++};
++
++static void
++input_panel_slide_done(struct weston_view_animation *animation, void *data)
++{
++ struct input_panel_surface *ipsurf = data;
++
++ ipsurf->anim = NULL;
++}
++
++static void
++show_input_panel_surface(struct input_panel_surface *ipsurf)
++{
++ struct ivi_shell *shell = ipsurf->shell;
++ struct weston_seat *seat;
++ struct weston_surface *focus;
++ float x, y;
++
++ wl_list_for_each(seat, &shell->compositor->seat_list, link) {
++ struct weston_keyboard *keyboard = seat->keyboard;
++
++ if (!keyboard || !keyboard->focus)
++ continue;
++ focus = weston_surface_get_main_surface(keyboard->focus);
++ ipsurf->output = focus->output;
++ x = ipsurf->output->x + (ipsurf->output->width - ipsurf->surface->width) / 2;
++ y = ipsurf->output->y + ipsurf->output->height - ipsurf->surface->height;
++ weston_view_set_position(ipsurf->view, x, y);
++ }
++
++ wl_list_insert(&shell->input_panel_layer.view_list,
++ &ipsurf->view->layer_link);
++ weston_view_geometry_dirty(ipsurf->view);
++ weston_view_update_transform(ipsurf->view);
++ weston_surface_damage(ipsurf->surface);
++
++ if (ipsurf->anim)
++ weston_view_animation_destroy(ipsurf->anim);
++
++ ipsurf->anim =
++ weston_slide_run(ipsurf->view,
++ ipsurf->surface->height * 0.9, 0,
++ input_panel_slide_done, ipsurf);
++}
++
++static void
++show_input_panels(struct wl_listener *listener, void *data)
++{
++ struct ivi_shell *shell =
++ container_of(listener, struct ivi_shell,
++ show_input_panel_listener);
++ struct input_panel_surface *ipsurf, *next;
++
++ shell->text_input.surface = (struct weston_surface*)data;
++
++ if (shell->showing_input_panels)
++ return;
++
++ shell->showing_input_panels = true;
++
++ if (!shell->locked)
++ wl_list_insert(&shell->compositor->cursor_layer.link,
++ &shell->input_panel_layer.link);
++
++ wl_list_for_each_safe(ipsurf, next,
++ &shell->input_panel.surfaces, link) {
++ if (ipsurf->surface->width == 0)
++ continue;
++
++ show_input_panel_surface(ipsurf);
++ }
++}
++
++static void
++hide_input_panels(struct wl_listener *listener, void *data)
++{
++ struct ivi_shell *shell =
++ container_of(listener, struct ivi_shell,
++ hide_input_panel_listener);
++ struct weston_view *view, *next;
++
++ if (!shell->showing_input_panels)
++ return;
++
++ shell->showing_input_panels = false;
++
++ if (!shell->locked)
++ wl_list_remove(&shell->input_panel_layer.link);
++
++ wl_list_for_each_safe(view, next,
++ &shell->input_panel_layer.view_list,
++ layer_link)
++ weston_view_unmap(view);
++}
++
++static void
++update_input_panels(struct wl_listener *listener, void *data)
++{
++ struct ivi_shell *shell =
++ container_of(listener, struct ivi_shell,
++ update_input_panel_listener);
++
++ memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
++}
++
++static void
++input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
++{
++ struct input_panel_surface *ip_surface = surface->configure_private;
++ struct ivi_shell *shell = ip_surface->shell;
++ struct weston_view *view;
++ float x, y;
++
++ if (surface->width == 0)
++ return;
++
++ if (ip_surface->panel) {
++ view = get_default_view(shell->text_input.surface);
++ if (view == NULL)
++ return;
++ x = view->geometry.x + shell->text_input.cursor_rectangle.x2;
++ y = view->geometry.y + shell->text_input.cursor_rectangle.y2;
++ } else {
++ x = ip_surface->output->x + (ip_surface->output->width - surface->width) / 2;
++ y = ip_surface->output->y + ip_surface->output->height - surface->height;
++ }
++
++ weston_view_set_position(ip_surface->view, x, y);
++
++ if (!weston_surface_is_mapped(surface) && shell->showing_input_panels)
++ show_input_panel_surface(ip_surface);
++}
++
++static void
++destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
++{
++ wl_signal_emit(&input_panel_surface->destroy_signal, input_panel_surface);
++
++ wl_list_remove(&input_panel_surface->surface_destroy_listener.link);
++ wl_list_remove(&input_panel_surface->link);
++
++ input_panel_surface->surface->configure = NULL;
++ weston_view_destroy(input_panel_surface->view);
++
++ free(input_panel_surface);
++}
++
++static struct input_panel_surface *
++get_input_panel_surface(struct weston_surface *surface)
++{
++ if (surface->configure == input_panel_configure) {
++ return surface->configure_private;
++ } else {
++ return NULL;
++ }
++}
++
++static void
++input_panel_handle_surface_destroy(struct wl_listener *listener, void *data)
++{
++ struct input_panel_surface *ipsurface = container_of(listener,
++ struct input_panel_surface,
++ surface_destroy_listener);
++
++ if (ipsurface->resource) {
++ wl_resource_destroy(ipsurface->resource);
++ } else {
++ destroy_input_panel_surface(ipsurface);
++ }
++}
++
++static struct input_panel_surface *
++create_input_panel_surface(struct ivi_shell *shell,
++ struct weston_surface *surface)
++{
++ struct input_panel_surface *input_panel_surface;
++
++ input_panel_surface = calloc(1, sizeof *input_panel_surface);
++ if (!input_panel_surface)
++ return NULL;
++
++ surface->configure = input_panel_configure;
++ surface->configure_private = input_panel_surface;
++
++ input_panel_surface->shell = shell;
++
++ input_panel_surface->surface = surface;
++ input_panel_surface->view = weston_view_create(surface);
++
++ wl_signal_init(&input_panel_surface->destroy_signal);
++ input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy;
++ wl_signal_add(&surface->destroy_signal,
++ &input_panel_surface->surface_destroy_listener);
++
++ wl_list_init(&input_panel_surface->link);
++
++ return input_panel_surface;
++}
++
++static void
++input_panel_surface_set_toplevel(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *output_resource,
++ uint32_t position)
++{
++ struct input_panel_surface *input_panel_surface =
++ wl_resource_get_user_data(resource);
++ struct ivi_shell *shell = input_panel_surface->shell;
++
++ wl_list_insert(&shell->input_panel.surfaces,
++ &input_panel_surface->link);
++
++ input_panel_surface->output = wl_resource_get_user_data(output_resource);
++ input_panel_surface->panel = 0;
++}
++
++static void
++input_panel_surface_set_overlay_panel(struct wl_client *client,
++ struct wl_resource *resource)
++{
++ struct input_panel_surface *input_panel_surface =
++ wl_resource_get_user_data(resource);
++ struct ivi_shell *shell = input_panel_surface->shell;
++
++ wl_list_insert(&shell->input_panel.surfaces,
++ &input_panel_surface->link);
++
++ input_panel_surface->panel = 1;
++}
++
++static const struct wl_input_panel_surface_interface input_panel_surface_implementation = {
++ input_panel_surface_set_toplevel,
++ input_panel_surface_set_overlay_panel
++};
++
++static void
++destroy_input_panel_surface_resource(struct wl_resource *resource)
++{
++ struct input_panel_surface *ipsurf =
++ wl_resource_get_user_data(resource);
++
++ destroy_input_panel_surface(ipsurf);
++}
++
++static void
++input_panel_get_input_panel_surface(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id,
++ struct wl_resource *surface_resource)
++{
++ struct weston_surface *surface =
++ wl_resource_get_user_data(surface_resource);
++ struct ivi_shell *shell = wl_resource_get_user_data(resource);
++ struct input_panel_surface *ipsurf;
++
++ if (get_input_panel_surface(surface)) {
++ wl_resource_post_error(surface_resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "wl_input_panel::get_input_panel_surface already requested");
++ return;
++ }
++
++ ipsurf = create_input_panel_surface(shell, surface);
++ if (!ipsurf) {
++ wl_resource_post_error(surface_resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "surface->configure already set");
++ return;
++ }
++
++ ipsurf->resource =
++ wl_resource_create(client,
++ &wl_input_panel_surface_interface, 1, id);
++ wl_resource_set_implementation(ipsurf->resource,
++ &input_panel_surface_implementation,
++ ipsurf,
++ destroy_input_panel_surface_resource);
++}
++
++static const struct wl_input_panel_interface input_panel_implementation = {
++ input_panel_get_input_panel_surface
++};
++
++static void
++unbind_input_panel(struct wl_resource *resource)
++{
++ struct ivi_shell *shell = wl_resource_get_user_data(resource);
++
++ shell->input_panel.binding = NULL;
++}
++
++static void
++bind_input_panel(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct ivi_shell *shell = data;
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client,
++ &wl_input_panel_interface, 1, id);
++
++ if (shell->input_panel.binding == NULL) {
++ wl_resource_set_implementation(resource,
++ &input_panel_implementation,
++ shell, unbind_input_panel);
++ shell->input_panel.binding = resource;
++ return;
++ }
++
++ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "interface object already bound");
++}
++
++void
++input_panel_destroy(struct ivi_shell *shell)
++{
++ wl_list_remove(&shell->show_input_panel_listener.link);
++ wl_list_remove(&shell->hide_input_panel_listener.link);
++}
++
++int
++input_panel_setup(struct ivi_shell *shell)
++{
++ struct weston_compositor *ec = shell->compositor;
++
++ shell->show_input_panel_listener.notify = show_input_panels;
++ wl_signal_add(&ec->show_input_panel_signal,
++ &shell->show_input_panel_listener);
++ shell->hide_input_panel_listener.notify = hide_input_panels;
++ wl_signal_add(&ec->hide_input_panel_signal,
++ &shell->hide_input_panel_listener);
++ shell->update_input_panel_listener.notify = update_input_panels;
++ wl_signal_add(&ec->update_input_panel_signal,
++ &shell->update_input_panel_listener);
++
++ wl_list_init(&shell->input_panel.surfaces);
++
++ if (wl_global_create(shell->compositor->wl_display,
++ &wl_input_panel_interface, 1,
++ shell, bind_input_panel) == NULL)
++ return -1;
++
++ return 0;
++}
+diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h
+new file mode 100644
+index 0000000..8a92009
+--- /dev/null
++++ b/ivi-shell/ivi-layout-export.h
+@@ -0,0 +1,813 @@
++/*
++ * Copyright (C) 2013 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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.
++ */
++
++/**
++ * The ivi-layout library supports API set of controlling properties of
++ * surface and layer which groups surfaces. An unique ID whose type is integer
++ * is required to create surface and layer. With the unique ID, surface and
++ * layer are identified to control them. The API set consists of APIs to control
++ * properties of surface and layers about followings,
++ * - visibility.
++ * - opacity.
++ * - clipping (x,y,width,height).
++ * - position and size of it to be displayed.
++ * - orientation per 90 degree.
++ * - add or remove surfaces to a layer.
++ * - order of surfaces/layers in layer/screen to be displayed.
++ * - commit to apply property changes.
++ * - notifications of property change.
++ *
++ * Management of surfaces and layers grouping these surfaces are common
++ * way in In-Vehicle Infotainment system, which integrate several domains
++ * in one system. A layer is allocated to a domain in order to control
++ * application surfaces grouped to the layer all together.
++ *
++ * This API and ABI follow following specifications.
++ * http://projects.genivi.org/wayland-ivi-extension/layer-manager-apis
++ */
++
++#ifndef _IVI_LAYOUT_EXPORT_H_
++#define _IVI_LAYOUT_EXPORT_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++#include "stdbool.h"
++#include "compositor.h"
++
++#define IVI_SUCCEEDED (0)
++#define IVI_FAILED (-1)
++
++struct ivi_layout_layer;
++struct ivi_layout_screen;
++struct ivi_layout_surface;
++
++struct ivi_layout_surface_properties
++{
++ wl_fixed_t opacity;
++ int32_t source_x;
++ int32_t source_y;
++ int32_t source_width;
++ int32_t source_height;
++ int32_t start_x;
++ int32_t start_y;
++ int32_t start_width;
++ int32_t start_height;
++ int32_t dest_x;
++ int32_t dest_y;
++ int32_t dest_width;
++ int32_t dest_height;
++ enum wl_output_transform orientation;
++ bool visibility;
++ int32_t transition_type;
++ uint32_t transition_duration;
++};
++
++struct ivi_layout_layer_properties
++{
++ wl_fixed_t opacity;
++ int32_t source_x;
++ int32_t source_y;
++ int32_t source_width;
++ int32_t source_height;
++ int32_t dest_x;
++ int32_t dest_y;
++ int32_t dest_width;
++ int32_t dest_height;
++ enum wl_output_transform orientation;
++ uint32_t visibility;
++ int32_t transition_type;
++ uint32_t transition_duration;
++ double start_alpha;
++ double end_alpha;
++ uint32_t is_fade_in;
++};
++
++enum ivi_layout_notification_mask {
++ IVI_NOTIFICATION_NONE = 0,
++ IVI_NOTIFICATION_OPACITY = (1 << 1),
++ IVI_NOTIFICATION_SOURCE_RECT = (1 << 2),
++ IVI_NOTIFICATION_DEST_RECT = (1 << 3),
++ IVI_NOTIFICATION_DIMENSION = (1 << 4),
++ IVI_NOTIFICATION_POSITION = (1 << 5),
++ IVI_NOTIFICATION_ORIENTATION = (1 << 6),
++ IVI_NOTIFICATION_VISIBILITY = (1 << 7),
++ IVI_NOTIFICATION_PIXELFORMAT = (1 << 8),
++ IVI_NOTIFICATION_ADD = (1 << 9),
++ IVI_NOTIFICATION_REMOVE = (1 << 10),
++ IVI_NOTIFICATION_CONFIGURE = (1 << 11),
++ IVI_NOTIFICATION_ALL = 0xFFFF
++};
++
++enum ivi_layout_transition_type{
++ IVI_LAYOUT_TRANSITION_NONE,
++ IVI_LAYOUT_TRANSITION_VIEW_DEFAULT,
++ IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY,
++ IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY,
++ IVI_LAYOUT_TRANSITION_LAYER_FADE,
++ IVI_LAYOUT_TRANSITION_LAYER_MOVE,
++ IVI_LAYOUT_TRANSITION_LAYER_VIEW_ORDER,
++ IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE,
++ IVI_LAYOUT_TRANSITION_VIEW_RESIZE,
++ IVI_LAYOUT_TRANSITION_VIEW_FADE,
++ IVI_LAYOUT_TRANSITION_MAX,
++};
++
++typedef void (*layer_property_notification_func)(
++ struct ivi_layout_layer *ivilayer,
++ const struct ivi_layout_layer_properties *,
++ enum ivi_layout_notification_mask mask,
++ void *userdata);
++
++typedef void (*surface_property_notification_func)(
++ struct ivi_layout_surface *ivisurf,
++ const struct ivi_layout_surface_properties *,
++ enum ivi_layout_notification_mask mask,
++ void *userdata);
++
++typedef void (*layer_create_notification_func)(
++ struct ivi_layout_layer *ivilayer,
++ void *userdata);
++
++typedef void (*layer_remove_notification_func)(
++ struct ivi_layout_layer *ivilayer,
++ void *userdata);
++
++typedef void (*surface_create_notification_func)(
++ struct ivi_layout_surface *ivisurf,
++ void *userdata);
++
++typedef void (*surface_remove_notification_func)(
++ struct ivi_layout_surface *ivisurf,
++ void *userdata);
++
++typedef void (*surface_configure_notification_func)(
++ struct ivi_layout_surface *ivisurf,
++ void *userdata);
++
++typedef void (*ivi_controller_surface_content_callback)(
++ struct ivi_layout_surface *ivisurf,
++ int32_t content,
++ void *userdata);
++
++struct ivi_controller_interface {
++
++ /**
++ * \brief Commit all changes and execute all enqueued commands since
++ * last commit.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*commit_changes)(void);
++
++ /**
++ * surface controller interface
++ */
++
++ /**
++ * \brief register/unregister for notification when ivi_surface is created
++ */
++ int32_t (*add_notification_create_surface)(
++ surface_create_notification_func callback,
++ void *userdata);
++
++ void (*remove_notification_create_surface)(
++ surface_create_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief register/unregister for notification when ivi_surface is removed
++ */
++ int32_t (*add_notification_remove_surface)(
++ surface_remove_notification_func callback,
++ void *userdata);
++
++ void (*remove_notification_remove_surface)(
++ surface_remove_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief register/unregister for notification when ivi_surface is configured
++ */
++ int32_t (*add_notification_configure_surface)(
++ surface_configure_notification_func callback,
++ void *userdata);
++
++ void (*remove_notification_configure_surface)(
++ surface_configure_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief Get all ivi_surfaces which are currently registered and managed
++ * by the services
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_surfaces)(int32_t *pLength, struct ivi_layout_surface ***ppArray);
++
++ /**
++ * \brief get id of ivi_surface from ivi_layout_surface
++ *
++ * \return id of ivi_surface
++ */
++ uint32_t (*get_id_of_surface)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief get ivi_layout_surface from id of ivi_surface
++ *
++ * \return (struct ivi_layout_surface *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ struct ivi_layout_surface *
++ (*get_surface_from_id)(uint32_t id_surface);
++
++ /**
++ * \brief get ivi_layout_surface_properties from ivisurf
++ *
++ * \return (struct ivi_layout_surface_properties *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ const struct ivi_layout_surface_properties *
++ (*get_properties_of_surface)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief Get all Surfaces which are currently registered to a given
++ * layer and are managed by the services
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_surfaces_on_layer)(struct ivi_layout_layer *ivilayer,
++ int32_t *pLength,
++ struct ivi_layout_surface ***ppArray);
++
++ /**
++ * \brief Set the visibility of a ivi_surface.
++ *
++ * If a surface is not visible it will not be rendered.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_visibility)(struct ivi_layout_surface *ivisurf,
++ bool newVisibility);
++
++ /**
++ * \brief Get the visibility of a surface.
++ *
++ * If a surface is not visible it will not be rendered.
++ *
++ * \return true if surface is visible
++ * \return false if surface is invisible or the method call was failed
++ */
++ bool (*surface_get_visibility)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief Set the opacity of a surface.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_opacity)(struct ivi_layout_surface *ivisurf,
++ wl_fixed_t opacity);
++
++ /**
++ * \brief Get the opacity of a ivi_surface.
++ *
++ * \return opacity if the method call was successful
++ * \return wl_fixed_from_double(0.0) if the method call was failed
++ */
++ wl_fixed_t (*surface_get_opacity)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief Set the area of a ivi_surface which should be used for the rendering.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_source_rectangle)(struct ivi_layout_surface *ivisurf,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height);
++
++ /**
++ * \brief Set the destination area of a ivi_surface within a ivi_layer
++ * for rendering.
++ *
++ * The surface will be scaled to this rectangle for rendering.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_destination_rectangle)(struct ivi_layout_surface *ivisurf,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height);
++
++ /**
++ * \brief Sets the horizontal and vertical position of the surface.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_position)(struct ivi_layout_surface *ivisurf,
++ int32_t dest_x, int32_t dest_y);
++
++ /**
++ * \brief Get the horizontal and vertical position of the surface.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_get_position)(struct ivi_layout_surface *ivisurf,
++ int32_t *dest_x, int32_t *dest_y);
++
++ /**
++ * \brief Set the horizontal and vertical dimension of the surface.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_dimension)(struct ivi_layout_surface *ivisurf,
++ int32_t dest_width, int32_t dest_height);
++
++ /**
++ * \brief Get the horizontal and vertical dimension of the surface.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_get_dimension)(struct ivi_layout_surface *ivisurf,
++ int32_t *dest_width, int32_t *dest_height);
++
++ /**
++ * \brief Sets the orientation of a ivi_surface.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_orientation)(struct ivi_layout_surface *ivisurf,
++ enum wl_output_transform orientation);
++
++ /**
++ * \brief Gets the orientation of a surface.
++ *
++ * \return (enum wl_output_transform)
++ * if the method call was successful
++ * \return WL_OUTPUT_TRANSFORM_NORMAL if the method call was failed
++ */
++ enum wl_output_transform
++ (*surface_get_orientation)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief Set an observer callback for ivi_surface content status change.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_set_content_observer)(
++ struct ivi_layout_surface *ivisurf,
++ ivi_controller_surface_content_callback callback,
++ void* userdata);
++
++ /**
++ * \brief register for notification on property changes of ivi_surface
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*surface_add_notification)(struct ivi_layout_surface *ivisurf,
++ surface_property_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief remove notification on property changes of ivi_surface
++ */
++ void (*surface_remove_notification)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief get weston_surface of ivi_surface
++ */
++ struct weston_surface *
++ (*surface_get_weston_surface)(struct ivi_layout_surface *ivisurf);
++
++ /**
++ * \brief set type of transition animation
++ */
++ int32_t (*surface_set_transition)(struct ivi_layout_surface *ivisurf,
++ enum ivi_layout_transition_type type,
++ uint32_t duration);
++
++ /**
++ * \brief set duration of transition animation
++ */
++ int32_t (*surface_set_transition_duration)(
++ struct ivi_layout_surface *ivisurf,
++ uint32_t duration);
++
++ /**
++ * layer controller interface
++ */
++
++ /**
++ * \brief register/unregister for notification when ivi_layer is created
++ */
++ int32_t (*add_notification_create_layer)(
++ layer_create_notification_func callback,
++ void *userdata);
++
++ void (*remove_notification_create_layer)(
++ layer_create_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief register/unregister for notification when ivi_layer is removed
++ */
++ int32_t (*add_notification_remove_layer)(
++ layer_remove_notification_func callback,
++ void *userdata);
++
++ void (*remove_notification_remove_layer)(
++ layer_remove_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief Create a ivi_layer which should be managed by the service
++ *
++ * \return (struct ivi_layout_layer *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ struct ivi_layout_layer *
++ (*layer_create_with_dimension)(uint32_t id_layer,
++ int32_t width, int32_t height);
++
++ /**
++ * \brief Removes a ivi_layer which is currently managed by the service
++ */
++ void (*layer_destroy)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief Get all ivi_layers which are currently registered and managed
++ * by the services
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_layers)(int32_t *pLength, struct ivi_layout_layer ***ppArray);
++
++ /**
++ * \brief get id of ivi_layer from ivi_layout_layer
++ *
++ *
++ * \return id of ivi_layer
++ */
++ uint32_t (*get_id_of_layer)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief get ivi_layout_layer from id of layer
++ *
++ * \return (struct ivi_layout_layer *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ struct ivi_layout_layer * (*get_layer_from_id)(uint32_t id_layer);
++
++ /**
++ * \brief Get the ivi_layer properties
++ *
++ * \return (const struct ivi_layout_layer_properties *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ const struct ivi_layout_layer_properties *
++ (*get_properties_of_layer)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief Get all ivi_ayers under the given ivi_surface
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_layers_under_surface)(struct ivi_layout_surface *ivisurf,
++ int32_t *pLength,
++ struct ivi_layout_layer ***ppArray);
++
++ /**
++ * \brief Get all Layers of the given screen
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_layers_on_screen)(struct ivi_layout_screen *iviscrn,
++ int32_t *pLength,
++ struct ivi_layout_layer ***ppArray);
++
++ /**
++ * \brief Set the visibility of a ivi_layer. If a ivi_layer is not visible,
++ * the ivi_layer and its ivi_surfaces will not be rendered.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_visibility)(struct ivi_layout_layer *ivilayer,
++ bool newVisibility);
++
++ /**
++ * \brief Get the visibility of a layer. If a layer is not visible,
++ * the layer and its surfaces will not be rendered.
++ *
++ * \return true if layer is visible
++ * \return false if layer is invisible or the method call was failed
++ */
++ bool (*layer_get_visibility)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief Set the opacity of a ivi_layer.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_opacity)(struct ivi_layout_layer *ivilayer,
++ wl_fixed_t opacity);
++
++ /**
++ * \brief Get the opacity of a ivi_layer.
++ *
++ * \return opacity if the method call was successful
++ * \return wl_fixed_from_double(0.0) if the method call was failed
++ */
++ wl_fixed_t (*layer_get_opacity)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief Set the area of a ivi_layer which should be used for the rendering.
++ *
++ * Only this part will be visible.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_source_rectangle)(struct ivi_layout_layer *ivilayer,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height);
++
++ /**
++ * \brief Set the destination area on the display for a ivi_layer.
++ *
++ * The ivi_layer will be scaled and positioned to this rectangle
++ * for rendering
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_destination_rectangle)(struct ivi_layout_layer *ivilayer,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height);
++
++ /**
++ * \brief Sets the horizontal and vertical position of the ivi_layer.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_position)(struct ivi_layout_layer *ivilayer,
++ int32_t dest_x, int32_t dest_y);
++
++ /**
++ * \brief Get the horizontal and vertical position of the ivi_layer.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_get_position)(struct ivi_layout_layer *ivilayer,
++ int32_t *dest_x, int32_t *dest_y);
++
++ /**
++ * \brief Set the horizontal and vertical dimension of the layer.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_dimension)(struct ivi_layout_layer *ivilayer,
++ int32_t dest_width, int32_t dest_height);
++
++ /**
++ * \brief Get the horizontal and vertical dimension of the layer.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_get_dimension)(struct ivi_layout_layer *ivilayer,
++ int32_t *dest_width, int32_t *dest_height);
++
++ /**
++ * \brief Sets the orientation of a ivi_layer.
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_orientation)(struct ivi_layout_layer *ivilayer,
++ enum wl_output_transform orientation);
++
++ /**
++ * \brief Gets the orientation of a layer.
++ *
++ * \return (enum wl_output_transform)
++ * if the method call was successful
++ * \return WL_OUTPUT_TRANSFORM_NORMAL if the method call was failed
++ */
++ enum wl_output_transform
++ (*layer_get_orientation)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief Add a ivi_surface to a ivi_layer which is currently managed by the service
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_add_surface)(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *addsurf);
++
++ /**
++ * \brief Removes a surface from a layer which is currently managed by the service
++ */
++ void (*layer_remove_surface)(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *remsurf);
++
++ /**
++ * \brief Sets render order of ivi_surfaces within a ivi_layer
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_set_render_order)(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface **pSurface,
++ int32_t number);
++
++ /**
++ * \brief register for notification on property changes of ivi_layer
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*layer_add_notification)(struct ivi_layout_layer *ivilayer,
++ layer_property_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief remove notification on property changes of ivi_layer
++ */
++ void (*layer_remove_notification)(struct ivi_layout_layer *ivilayer);
++
++ /**
++ * \brief set type of transition animation
++ */
++ int32_t (*layer_set_transition)(struct ivi_layout_layer *ivilayer,
++ enum ivi_layout_transition_type type,
++ uint32_t duration);
++
++ /**
++ * screen controller interface
++ */
++
++ /**
++ * \brief get ivi_layout_screen from id of ivi_screen
++ *
++ * \return (struct ivi_layout_screen *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ struct ivi_layout_screen *
++ (*get_screen_from_id)(uint32_t id_screen);
++
++ /**
++ * \brief Get the screen resolution of a specific ivi_screen
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_screen_resolution)(struct ivi_layout_screen *iviscrn,
++ int32_t *pWidth,
++ int32_t *pHeight);
++
++ /**
++ * \brief Get the ivi_screens
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_screens)(int32_t *pLength, struct ivi_layout_screen ***ppArray);
++
++ /**
++ * \brief Get the ivi_screens under the given ivi_layer
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*get_screens_under_layer)(struct ivi_layout_layer *ivilayer,
++ int32_t *pLength,
++ struct ivi_layout_screen ***ppArray);
++
++ /**
++ * \brief Add a ivi_layer to a ivi_screen which is currently managed
++ * by the service
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*screen_add_layer)(struct ivi_layout_screen *iviscrn,
++ struct ivi_layout_layer *addlayer);
++
++ /**
++ * \brief Sets render order of ivi_layers on a ivi_screen
++ *
++ * \return IVI_SUCCEEDED if the method call was successful
++ * \return IVI_FAILED if the method call was failed
++ */
++ int32_t (*screen_set_render_order)(struct ivi_layout_screen *iviscrn,
++ struct ivi_layout_layer **pLayer,
++ const int32_t number);
++
++ /**
++ * \brief get weston_output from ivi_layout_screen.
++ *
++ * \return (struct weston_output *)
++ * if the method call was successful
++ * \return NULL if the method call was failed
++ */
++ struct weston_output *(*screen_get_output)(struct ivi_layout_screen *);
++
++
++ /**
++ * transision animation for layer
++ */
++ void (*transition_move_layer_cancel)(struct ivi_layout_layer *layer);
++ int32_t (*layer_set_fade_info)(struct ivi_layout_layer* ivilayer,
++ uint32_t is_fade_in,
++ double start_alpha, double end_alpha);
++
++ /**
++ * surface content dumping for debugging
++ */
++ int32_t (*surface_get_size)(struct ivi_layout_surface *ivisurf,
++ int32_t *width, int32_t *height,
++ int32_t *stride);
++
++ int32_t (*surface_dump)(struct weston_surface *surface,
++ void *target, size_t size,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height);
++
++ /**
++ * remove notification by callback on property changes of ivi_surface
++ */
++ void (*surface_remove_notification_by_callback)(struct ivi_layout_surface *ivisurf,
++ surface_property_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief remove notification by callback on property changes of ivi_layer
++ */
++ void (*layer_remove_notification_by_callback)(struct ivi_layout_layer *ivilayer,
++ layer_property_notification_func callback,
++ void *userdata);
++
++ /**
++ * \brief get id of ivi_screen from ivi_layout_screen
++ *
++ *
++ * \return id of ivi_screen
++ */
++ uint32_t (*get_id_of_screen)(struct ivi_layout_screen *iviscrn);
++};
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* _IVI_LAYOUT_EXPORT_H_ */
+diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h
+new file mode 100644
+index 0000000..074d598
+--- /dev/null
++++ b/ivi-shell/ivi-layout-private.h
+@@ -0,0 +1,229 @@
++/*
++ * Copyright (C) 2014 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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 _ivi_layout_PRIVATE_H_
++#define _ivi_layout_PRIVATE_H_
++
++#include "compositor.h"
++#include "ivi-layout-export.h"
++
++struct ivi_layout_surface {
++ struct wl_list link;
++ struct wl_signal property_changed;
++ struct wl_list layer_list;
++ int32_t update_count;
++ uint32_t id_surface;
++
++ struct ivi_layout *layout;
++ struct weston_surface *surface;
++
++ struct weston_transform transform;
++
++ struct ivi_layout_surface_properties prop;
++ uint32_t event_mask;
++
++ struct {
++ struct ivi_layout_surface_properties prop;
++ struct wl_list link;
++ } pending;
++
++ struct {
++ struct wl_list link;
++ struct wl_list layer_list;
++ } order;
++
++ struct {
++ ivi_controller_surface_content_callback callback;
++ void *userdata;
++ } content_observer;
++
++ struct wl_signal configured;
++};
++
++struct ivi_layout_layer {
++ struct wl_list link;
++ struct wl_signal property_changed;
++ struct wl_list screen_list;
++ struct wl_list link_to_surface;
++ uint32_t id_layer;
++
++ struct ivi_layout *layout;
++
++ struct ivi_layout_layer_properties prop;
++ uint32_t event_mask;
++
++ struct {
++ struct ivi_layout_layer_properties prop;
++ struct wl_list surface_list;
++ struct wl_list link;
++ } pending;
++
++ struct {
++ int dirty;
++ struct wl_list surface_list;
++ struct wl_list link;
++ } order;
++
++ int32_t ref_count;
++};
++
++struct ivi_layout {
++ struct weston_compositor *compositor;
++
++ struct wl_list surface_list;
++ struct wl_list layer_list;
++ struct wl_list screen_list;
++
++ struct {
++ struct wl_signal created;
++ struct wl_signal removed;
++ } layer_notification;
++
++ struct {
++ struct wl_signal created;
++ struct wl_signal removed;
++ struct wl_signal configure_changed;
++ } surface_notification;
++
++ struct weston_layer layout_layer;
++ struct wl_signal warning_signal;
++
++ struct ivi_layout_transition_set *transitions;
++ struct wl_list pending_transition_list;
++};
++
++struct ivi_layout *get_instance(void);
++
++struct ivi_layout_transition;
++
++struct ivi_layout_transition_set {
++ struct wl_event_source *event_source;
++ struct wl_list transition_list;
++};
++
++typedef void (*ivi_layout_transition_destroy_user_func)(void *user_data);
++
++struct ivi_layout_transition_set *
++ivi_layout_transition_set_create(struct weston_compositor *ec);
++
++void
++ivi_layout_transition_move_resize_view(struct ivi_layout_surface *surface,
++ int32_t dest_x, int32_t dest_y,
++ int32_t dest_width, int32_t dest_height,
++ uint32_t duration);
++
++void
++ivi_layout_transition_visibility_on(struct ivi_layout_surface *surface,
++ uint32_t duration);
++
++void
++ivi_layout_transition_visibility_off(struct ivi_layout_surface *surface,
++ uint32_t duration);
++
++
++void
++ivi_layout_transition_move_layer(struct ivi_layout_layer *layer,
++ int32_t dest_x, int32_t dest_y,
++ uint32_t duration);
++
++void
++ivi_layout_transition_fade_layer(struct ivi_layout_layer *layer,
++ uint32_t is_fade_in,
++ double start_alpha, double end_alpha,
++ void *user_data,
++ ivi_layout_transition_destroy_user_func destroy_func,
++ uint32_t duration);
++
++int32_t
++is_surface_transition(struct ivi_layout_surface *surface);
++
++/**
++ * methods of interaction between ivi-shell with ivi-layout
++ */
++struct weston_view *
++ivi_layout_get_weston_view(struct ivi_layout_surface *surface);
++void
++ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf,
++ int32_t width, int32_t height);
++struct ivi_layout_surface*
++ivi_layout_surface_create(struct weston_surface *wl_surface,
++ uint32_t id_surface);
++void
++ivi_layout_init_with_compositor(struct weston_compositor *ec);
++int32_t
++ivi_layout_surface_get_dimension(struct ivi_layout_surface *ivisurf,
++ int32_t *dest_width, int32_t *dest_height);
++void
++ivi_layout_surface_add_configured_listener(struct ivi_layout_surface* ivisurf,
++ struct wl_listener* listener);
++/**
++ * methods of interaction between transition animation with ivi-layout
++ */
++int32_t
++ivi_layout_commit_changes(void);
++uint32_t
++ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf);
++int32_t
++ivi_layout_surface_set_destination_rectangle(struct ivi_layout_surface *ivisurf,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height);
++int32_t
++ivi_layout_surface_set_opacity(struct ivi_layout_surface *ivisurf,
++ wl_fixed_t opacity);
++wl_fixed_t
++ivi_layout_surface_get_opacity(struct ivi_layout_surface *ivisurf);
++int32_t
++ivi_layout_surface_set_visibility(struct ivi_layout_surface *ivisurf,
++ bool newVisibility);
++bool
++ivi_layout_surface_get_visibility(struct ivi_layout_surface *ivisurf);
++struct ivi_layout_surface *
++ivi_layout_get_surface_from_id(uint32_t id_surface);
++int32_t
++ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer,
++ wl_fixed_t opacity);
++wl_fixed_t
++ivi_layout_layer_get_opacity(struct ivi_layout_layer *ivilayer);
++int32_t
++ivi_layout_layer_set_visibility(struct ivi_layout_layer *ivilayer,
++ bool newVisibility);
++int32_t
++ivi_layout_layer_set_position(struct ivi_layout_layer *ivilayer,
++ int32_t dest_x, int32_t dest_y);
++int32_t
++ivi_layout_layer_get_position(struct ivi_layout_layer *ivilayer,
++ int32_t *dest_x, int32_t *dest_y);
++int32_t
++ivi_layout_layer_set_render_order(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface **pSurface,
++ int32_t number);
++void
++ivi_layout_transition_move_layer_cancel(struct ivi_layout_layer *layer);
++int
++load_controller_modules(struct weston_compositor *compositor, const char *modules,
++ int *argc, char *argv[]);
++void
++ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf);
++#endif
+diff --git a/ivi-shell/ivi-layout-transition.c b/ivi-shell/ivi-layout-transition.c
+new file mode 100644
+index 0000000..d12a8f4
+--- /dev/null
++++ b/ivi-shell/ivi-layout-transition.c
+@@ -0,0 +1,871 @@
++/*
++ * Copyright (C) 2014 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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 <time.h>
++#include <assert.h>
++#include <stdlib.h>
++#include <stdio.h>
++
++#include "ivi-layout-export.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_is_transition_func)(void *private_data, void *id);
++
++struct ivi_layout_transition {
++ enum ivi_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_is_transition_func is_transition_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 ivi_layout_transition_type type,
++ void *id_data)
++{
++ struct ivi_layout *layout = get_instance();
++ struct transition_node *node;
++ struct ivi_layout_transition *tran;
++
++ wl_list_for_each(node, &layout->transitions->transition_list, link) {
++ tran = node->transition;
++
++ if (tran->type == type &&
++ tran->is_transition_func(tran->private_data, id_data))
++ return tran;
++ }
++
++ return NULL;
++}
++
++int32_t
++is_surface_transition(struct ivi_layout_surface *surface)
++{
++ struct ivi_layout *layout = get_instance();
++ struct transition_node *node;
++ struct ivi_layout_transition *tran;
++
++ wl_list_for_each(node, &layout->transitions->transition_list, link) {
++ tran = node->transition;
++
++ if ((tran->type == IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE ||
++ tran->type == IVI_LAYOUT_TRANSITION_VIEW_RESIZE) &&
++ tran->is_transition_func(tran->private_data, surface))
++ return 1;
++ }
++
++ return 0;
++}
++
++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;
++ struct timespec timestamp = {};
++ uint32_t msec = 0;
++ struct transition_node *node = NULL;
++ struct transition_node *next = NULL;
++
++ 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);
++
++ clock_gettime(CLOCK_MONOTONIC, &timestamp);/* FIXME */
++ msec = (1e+3 * timestamp.tv_sec + 1e-6 * timestamp.tv_nsec);
++
++ wl_list_for_each_safe(node, next, &transitions->transition_list, link) {
++ do_transition_frame(node->transition, msec);
++ }
++
++ ivi_layout_commit_changes();
++ return 1;
++}
++
++struct ivi_layout_transition_set *
++ivi_layout_transition_set_create(struct weston_compositor *ec)
++{
++ struct ivi_layout_transition_set *transitions;
++ struct wl_event_loop *loop;
++
++ transitions = malloc(sizeof(*transitions));
++ if (transitions == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return NULL;
++ }
++
++ wl_list_init(&transitions->transition_list);
++
++ loop = wl_display_get_event_loop(ec->wl_display);
++ transitions->event_source =
++ wl_event_loop_add_timer(loop, layout_transition_frame,
++ transitions);
++
++ return transitions;
++}
++
++static void
++layout_transition_register(struct ivi_layout_transition *trans)
++{
++ struct ivi_layout *layout = get_instance();
++ struct transition_node *node;
++
++ node = malloc(sizeof(*node));
++ if (node == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return;
++ }
++
++ 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;
++ struct transition_node *next;
++
++ 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;
++ }
++ }
++}
++
++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));
++
++ if (transition == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return NULL;
++ }
++
++ transition->type = IVI_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;
++ int32_t start_width;
++ int32_t start_height;
++ int32_t end_width;
++ int32_t end_height;
++};
++
++static void
++transition_move_resize_view_destroy(struct ivi_layout_transition *transition)
++{
++ struct move_resize_view_data *data =
++ (struct move_resize_view_data *)transition->private_data;
++ struct ivi_layout_surface *layout_surface = data->surface;
++
++ wl_signal_emit(&layout_surface->configured, layout_surface);
++
++ 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 *mrv = transition->private_data;
++ const double current = time_to_nowpos(transition);
++
++ const int32_t destx = mrv->start_x +
++ (mrv->end_x - mrv->start_x) * current;
++
++ const int32_t desty = mrv->start_y +
++ (mrv->end_y - mrv->start_y) * current;
++
++ const int32_t dest_width = mrv->start_width +
++ (mrv->end_width - mrv->start_width) * current;
++
++ const int32_t dest_height = mrv->start_height +
++ (mrv->end_height - mrv->start_height) * current;
++
++ ivi_layout_surface_set_destination_rectangle(mrv->surface,
++ destx, desty,
++ dest_width, dest_height);
++}
++
++static int32_t
++is_transition_move_resize_view_func(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,
++ int32_t start_width, int32_t start_height,
++ int32_t end_width, int32_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;
++ struct move_resize_view_data *data;
++
++ transition = create_layout_transition();
++ if (transition == NULL)
++ return NULL;
++
++ data = malloc(sizeof(*data));
++ if (data == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return NULL;
++ }
++
++ transition->type = IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE;
++ transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_move_resize_view_func;
++
++ 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;
++}
++
++void
++ivi_layout_transition_move_resize_view(struct ivi_layout_surface *surface,
++ int32_t dest_x, int32_t dest_y,
++ int32_t dest_width, int32_t dest_height,
++ uint32_t duration)
++{
++ struct ivi_layout_transition *transition;
++ int32_t start_pos[2] = {
++ surface->pending.prop.start_x,
++ surface->pending.prop.start_y
++ };
++
++ int32_t start_size[2] = {
++ surface->pending.prop.start_width,
++ surface->pending.prop.start_height
++ };
++
++ transition = get_transition_from_type_and_id(
++ IVI_LAYOUT_TRANSITION_VIEW_MOVE_RESIZE,
++ surface);
++ if (transition) {
++ struct move_resize_view_data *data = transition->private_data;
++ transition->time_start = 0;
++ transition->time_duration = duration;
++
++ 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;
++ double start_alpha;
++ double end_alpha;
++};
++
++struct store_alpha{
++ double alpha;
++};
++
++static void
++fade_view_user_frame(struct ivi_layout_transition *transition)
++{
++ struct fade_view_data *fade = transition->private_data;
++ struct ivi_layout_surface *surface = fade->surface;
++
++ const double current = time_to_nowpos(transition);
++ const double alpha = fade->start_alpha +
++ (fade->end_alpha - fade->start_alpha) * current;
++
++ ivi_layout_surface_set_opacity(surface, wl_fixed_from_double(alpha));
++ ivi_layout_surface_set_visibility(surface, true);
++}
++
++static int32_t
++is_transition_fade_view_func(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,
++ double start_alpha, double 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;
++ struct fade_view_data *data;
++
++ transition = create_layout_transition();
++ if (transition == NULL)
++ return NULL;
++
++ data = malloc(sizeof(*data));
++ if (data == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return NULL;
++ }
++
++ transition->type = IVI_LAYOUT_TRANSITION_VIEW_FADE;
++ transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_fade_view_func;
++
++ 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,
++ double start_alpha,
++ double 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;
++ struct store_alpha *user_data = transition->user_data;
++
++ ivi_layout_surface_set_visibility(data->surface, true);
++
++ free(data);
++ transition->private_data = NULL;
++
++ free(user_data);
++ transition->user_data = NULL;
++}
++
++void
++ivi_layout_transition_visibility_on(struct ivi_layout_surface *surface,
++ uint32_t duration)
++{
++ struct ivi_layout_transition *transition;
++ bool is_visible = ivi_layout_surface_get_visibility(surface);
++ wl_fixed_t dest_alpha = ivi_layout_surface_get_opacity(surface);
++ struct store_alpha *user_data = NULL;
++ wl_fixed_t start_alpha = 0.0;
++ struct fade_view_data *data = NULL;
++
++ transition = get_transition_from_type_and_id(
++ IVI_LAYOUT_TRANSITION_VIEW_FADE,
++ surface);
++ if (transition) {
++ start_alpha = ivi_layout_surface_get_opacity(surface);
++ user_data = transition->user_data;
++ data = transition->private_data;
++
++ transition->time_start = 0;
++ transition->time_duration = duration;
++ transition->destroy_func = visibility_on_transition_destroy;
++
++ data->start_alpha = wl_fixed_to_double(start_alpha);
++ data->end_alpha = user_data->alpha;
++ return;
++ }
++
++ if (is_visible)
++ return;
++
++ user_data = malloc(sizeof(*user_data));
++ if (user_data == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return;
++ }
++
++ 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;
++ struct store_alpha *user_data = transition->user_data;
++
++ ivi_layout_surface_set_visibility(data->surface, false);
++
++ ivi_layout_surface_set_opacity(data->surface,
++ wl_fixed_from_double(user_data->alpha));
++
++ free(data);
++ transition->private_data = NULL;
++
++ free(user_data);
++ transition->user_data= NULL;
++}
++
++void
++ivi_layout_transition_visibility_off(struct ivi_layout_surface *surface,
++ uint32_t duration)
++{
++ struct ivi_layout_transition *transition;
++ wl_fixed_t start_alpha = ivi_layout_surface_get_opacity(surface);
++ struct store_alpha* user_data = NULL;
++ struct fade_view_data* data = NULL;
++
++ transition =
++ get_transition_from_type_and_id(IVI_LAYOUT_TRANSITION_VIEW_FADE,
++ surface);
++ if (transition) {
++ data = transition->private_data;
++
++ transition->time_start = 0;
++ transition->time_duration = duration;
++ transition->destroy_func = visibility_off_transition_destroy;
++
++ data->start_alpha = wl_fixed_to_double(start_alpha);
++ data->end_alpha = 0;
++ return;
++ }
++
++ user_data = malloc(sizeof(*user_data));
++ if (user_data == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return;
++ }
++
++ user_data->alpha = wl_fixed_to_double(start_alpha);
++
++ create_visibility_transition(surface,
++ wl_fixed_to_double(start_alpha),
++ 0.0, // 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;
++
++ ivi_layout_layer_set_position(layer, dest_x, dest_y);
++}
++
++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
++is_transition_move_layer_func(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;
++ struct move_layer_data *data;
++
++ transition = create_layout_transition();
++ if (transition == NULL)
++ return NULL;
++
++ data = malloc(sizeof(*data));
++ if (data == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return NULL;
++ }
++
++ transition->type = IVI_LAYOUT_TRANSITION_LAYER_MOVE;
++ transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_move_layer_func;
++
++ 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;
++}
++
++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_x = 0;
++ int32_t start_pos_y = 0;
++ struct ivi_layout_transition *transition = NULL;
++
++ ivi_layout_layer_get_position(layer, &start_pos_x, &start_pos_y);
++
++ transition = create_move_layer_transition(
++ layer,
++ start_pos_x, start_pos_y,
++ dest_x, dest_y,
++ NULL, NULL,
++ duration);
++
++ layout_transition_register(transition);
++
++ return;
++}
++
++void
++ivi_layout_transition_move_layer_cancel(struct ivi_layout_layer *layer)
++{
++ struct ivi_layout_transition *transition =
++ get_transition_from_type_and_id(
++ IVI_LAYOUT_TRANSITION_LAYER_MOVE,
++ layer);
++ if (transition) {
++ layout_transition_destroy(transition);
++ }
++}
++
++/* fade layer transition */
++struct fade_layer_data {
++ struct ivi_layout_layer *layer;
++ uint32_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;
++ wl_fixed_t fixed_alpha = wl_fixed_from_double(alpha);
++
++ int32_t is_done = transition->is_done;
++ bool is_visible = !is_done || data->is_fade_in;
++
++ ivi_layout_layer_set_opacity(data->layer, fixed_alpha);
++ ivi_layout_layer_set_visibility(data->layer, is_visible);
++}
++
++static int32_t
++is_transition_fade_layer_func(struct fade_layer_data *data,
++ struct ivi_layout_layer *layer)
++{
++ return data->layer == layer;
++}
++
++void
++ivi_layout_transition_fade_layer(
++ struct ivi_layout_layer *layer,
++ uint32_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;
++ struct fade_layer_data *data = NULL;
++ wl_fixed_t fixed_opacity = 0.0;
++ double now_opacity = 0.0;
++ double remain = 0.0;
++
++ transition = get_transition_from_type_and_id(
++ IVI_LAYOUT_TRANSITION_LAYER_FADE,
++ layer);
++ if (transition) {
++ /* transition update */
++ data = transition->private_data;
++
++ /* FIXME */
++ fixed_opacity = ivi_layout_layer_get_opacity(layer);
++ now_opacity = wl_fixed_to_double(fixed_opacity);
++ remain = 0.0;
++
++ data->is_fade_in = is_fade_in;
++ data->start_alpha = now_opacity;
++ data->end_alpha = end_alpha;
++
++ 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();
++ if (transition == NULL)
++ return;
++
++ data = malloc(sizeof(*data));
++ if (data == NULL) {
++ weston_log("%s: memory allocation fails\n", __func__);
++ return;
++ }
++
++ transition->type = IVI_LAYOUT_TRANSITION_LAYER_FADE;
++ transition->is_transition_func = (ivi_layout_is_transition_func)is_transition_fade_layer_func;
++
++ 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;
++}
++
+diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
+new file mode 100644
+index 0000000..51d0a8d
+--- /dev/null
++++ b/ivi-shell/ivi-layout.c
+@@ -0,0 +1,3011 @@
++/*
++ * Copyright (C) 2013 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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.
++ */
++
++/**
++ * Implementation of ivi-layout library. The actual view on ivi_screen is
++ * not updated till calling ivi_layout_commit_changes. A overview from
++ * calling API for updating properties of ivi_surface/ivi_layer to asking
++ * compositor to compose them by using weston_compositor_schedule_repaint,
++ * 0/ initialize this library by ivi_layout_init_with_compositor
++ * with (struct weston_compositor *ec) from ivi-shell.
++ * 1/ When a API for updating properties of ivi_surface/ivi_layer, it updates
++ * pending prop of ivi_surface/ivi_layer/ivi_screen which are structure to
++ * store properties.
++ * 2/ Before calling commitChanges, in case of calling a API to get a property,
++ * return current property, not pending property.
++ * 3/ At the timing of calling ivi_layout_commitChanges, pending properties
++ * are applied to properties.
++ *
++ * *) ivi_layout_commitChanges is also called by transition animation
++ * per each frame. See ivi-layout-transition.c in details. Transition
++ * animation interpolates frames between previous properties of ivi_surface
++ * and new ones.
++ * For example, when a property of ivi_surface is changed from invisibility
++ * to visibility, it behaves like fade-in. When ivi_layout_commitChange is
++ * called during transition animation, it cancels the transition and
++ * re-start transition to new properties from current properties of final
++ * frame just before the the cancellation.
++ *
++ * 4/ According properties, set transformation by using weston_matrix and
++ * weston_view per ivi_surfaces and ivi_layers in while loop.
++ * 5/ Set damage and trigger transform by using weston_view_geometry_dirty.
++ * 6/ Notify update of properties.
++ * 7/ Trigger composition by weston_compositor_schedule_repaint.
++ *
++ */
++#include "config.h"
++
++#include <string.h>
++#include <assert.h>
++
++#include "compositor.h"
++#include "ivi-layout-export.h"
++#include "ivi-layout-private.h"
++
++#include "shared/helpers.h"
++#include "shared/os-compatibility.h"
++
++#define max(a, b) ((a) > (b) ? (a) : (b))
++
++struct link_layer {
++ struct ivi_layout_layer *ivilayer;
++ struct wl_list link;
++ struct wl_list link_to_layer;
++};
++
++struct link_screen {
++ struct ivi_layout_screen *iviscrn;
++ struct wl_list link;
++ struct wl_list link_to_screen;
++};
++
++struct listener_layout_notification {
++ void *userdata;
++ struct wl_listener listener;
++};
++
++struct ivi_layout;
++
++struct ivi_layout_screen {
++ struct wl_list link;
++ struct wl_list link_to_layer;
++ uint32_t id_screen;
++
++ struct ivi_layout *layout;
++ struct weston_output *output;
++
++ struct {
++ struct wl_list layer_list;
++ struct wl_list link;
++ } pending;
++
++ struct {
++ int dirty;
++ struct wl_list layer_list;
++ struct wl_list link;
++ } order;
++};
++
++struct ivi_layout_notification_callback {
++ void *callback;
++ void *data;
++};
++
++struct ivi_rectangle
++{
++ int32_t x;
++ int32_t y;
++ int32_t width;
++ int32_t height;
++};
++
++static void
++remove_notification(struct wl_list *listener_list, void *callback, void *userdata);
++
++static struct ivi_layout ivilayout = {0};
++
++struct ivi_layout *
++get_instance(void)
++{
++ return &ivilayout;
++}
++
++/**
++ * Internal API to add/remove a link to ivi_surface from ivi_layer.
++ */
++static void
++add_link_to_surface(struct ivi_layout_layer *ivilayer,
++ struct link_layer *link_layer)
++{
++ struct link_layer *link = NULL;
++
++ wl_list_for_each(link, &ivilayer->link_to_surface, link_to_layer) {
++ if (link == link_layer)
++ return;
++ }
++
++ wl_list_insert(&ivilayer->link_to_surface, &link_layer->link_to_layer);
++}
++
++static void
++remove_link_to_surface(struct ivi_layout_layer *ivilayer)
++{
++ struct link_layer *link = NULL;
++ struct link_layer *next = NULL;
++
++ wl_list_for_each_safe(link, next, &ivilayer->link_to_surface, link_to_layer) {
++ wl_list_remove(&link->link_to_layer);
++ wl_list_remove(&link->link);
++ free(link);
++ }
++
++ wl_list_init(&ivilayer->link_to_surface);
++}
++
++/**
++ * Internal API to add a link to ivi_layer from ivi_screen.
++ */
++static void
++add_link_to_layer(struct ivi_layout_screen *iviscrn,
++ struct link_screen *link_screen)
++{
++ wl_list_insert(&iviscrn->link_to_layer, &link_screen->link_to_screen);
++}
++
++/**
++ * Internal API to add/remove a ivi_surface from ivi_layer.
++ */
++static void
++add_ordersurface_to_layer(struct ivi_layout_surface *ivisurf,
++ struct ivi_layout_layer *ivilayer)
++{
++ struct link_layer *link_layer = NULL;
++
++ link_layer = malloc(sizeof *link_layer);
++ if (link_layer == NULL) {
++ weston_log("fails to allocate memory\n");
++ return;
++ }
++
++ link_layer->ivilayer = ivilayer;
++ wl_list_insert(&ivisurf->layer_list, &link_layer->link);
++ add_link_to_surface(ivilayer, link_layer);
++}
++
++static void
++remove_ordersurface_from_layer(struct ivi_layout_surface *ivisurf)
++{
++ struct link_layer *link_layer = NULL;
++ struct link_layer *next = NULL;
++
++ wl_list_for_each_safe(link_layer, next, &ivisurf->layer_list, link) {
++ wl_list_remove(&link_layer->link);
++ wl_list_remove(&link_layer->link_to_layer);
++ free(link_layer);
++ }
++ wl_list_init(&ivisurf->layer_list);
++}
++
++/**
++ * Internal API to add/remove a ivi_layer to/from ivi_screen.
++ */
++static void
++add_orderlayer_to_screen(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_screen *iviscrn)
++{
++ struct link_screen *link_scrn = NULL;
++
++ link_scrn = malloc(sizeof *link_scrn);
++ if (link_scrn == NULL) {
++ weston_log("fails to allocate memory\n");
++ return;
++ }
++
++ link_scrn->iviscrn = iviscrn;
++ wl_list_insert(&ivilayer->screen_list, &link_scrn->link);
++ add_link_to_layer(iviscrn, link_scrn);
++}
++
++static void
++remove_orderlayer_from_screen(struct ivi_layout_layer *ivilayer)
++{
++ struct link_screen *link_scrn = NULL;
++ struct link_screen *next = NULL;
++
++ wl_list_for_each_safe(link_scrn, next, &ivilayer->screen_list, link) {
++ wl_list_remove(&link_scrn->link);
++ wl_list_remove(&link_scrn->link_to_screen);
++ free(link_scrn);
++ }
++ wl_list_init(&ivilayer->screen_list);
++}
++
++/**
++ * Internal API to add/remove a ivi_layer to/from ivi_screen.
++ */
++static struct ivi_layout_surface *
++get_surface(struct wl_list *surf_list, uint32_t id_surface)
++{
++ struct ivi_layout_surface *ivisurf;
++
++ wl_list_for_each(ivisurf, surf_list, link) {
++ if (ivisurf->id_surface == id_surface) {
++ return ivisurf;
++ }
++ }
++
++ return NULL;
++}
++
++static struct ivi_layout_layer *
++get_layer(struct wl_list *layer_list, uint32_t id_layer)
++{
++ struct ivi_layout_layer *ivilayer;
++
++ wl_list_for_each(ivilayer, layer_list, link) {
++ if (ivilayer->id_layer == id_layer) {
++ return ivilayer;
++ }
++ }
++
++ return NULL;
++}
++
++static void
++remove_configured_listener(struct ivi_layout_surface *ivisurf)
++{
++ struct wl_listener *link = NULL;
++ struct wl_listener *next = NULL;
++
++ wl_list_for_each_safe(link, next, &ivisurf->configured.listener_list, link) {
++ wl_list_remove(&link->link);
++ }
++}
++
++static void
++remove_all_notification(struct wl_list *listener_list)
++{
++ struct wl_listener *listener = NULL;
++ struct wl_listener *next = NULL;
++
++ wl_list_for_each_safe(listener, next, listener_list, link) {
++ struct listener_layout_notification *notification = NULL;
++ wl_list_remove(&listener->link);
++
++ notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ free(notification->userdata);
++ free(notification);
++ }
++}
++
++static void
++ivi_layout_surface_remove_notification(struct ivi_layout_surface *ivisurf)
++{
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_remove_notification: invalid argument\n");
++ return;
++ }
++
++ remove_all_notification(&ivisurf->property_changed.listener_list);
++}
++
++static void
++ivi_layout_surface_remove_notification_by_callback(struct ivi_layout_surface *ivisurf,
++ surface_property_notification_func callback,
++ void *userdata)
++{
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_remove_notification_by_callback: invalid argument\n");
++ return;
++ }
++
++ remove_notification(&ivisurf->property_changed.listener_list, callback, userdata);
++}
++
++/**
++ * Called at destruction of wl_surface/ivi_surface
++ */
++void
++ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf)
++{
++ struct ivi_layout *layout = get_instance();
++
++ if (ivisurf == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return;
++ }
++
++ wl_list_remove(&ivisurf->transform.link);
++ wl_list_remove(&ivisurf->pending.link);
++ wl_list_remove(&ivisurf->order.link);
++ wl_list_remove(&ivisurf->link);
++ remove_ordersurface_from_layer(ivisurf);
++
++ wl_signal_emit(&layout->surface_notification.removed, ivisurf);
++
++ remove_configured_listener(ivisurf);
++
++ ivi_layout_surface_remove_notification(ivisurf);
++
++ free(ivisurf);
++}
++
++/**
++ * Internal API to check ivi_layer/ivi_surface already added in ivi_layer/ivi_screen.
++ * Called by ivi_layout_layer_add_surface/ivi_layout_screenAddLayer
++ */
++static int
++is_surface_in_layer(struct ivi_layout_surface *ivisurf,
++ struct ivi_layout_layer *ivilayer)
++{
++ struct ivi_layout_surface *surf = NULL;
++
++ wl_list_for_each(surf, &ivilayer->pending.surface_list, pending.link) {
++ if (surf->id_surface == ivisurf->id_surface) {
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++static int
++is_layer_in_screen(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_screen *iviscrn)
++{
++ struct ivi_layout_layer *layer = NULL;
++
++ wl_list_for_each(layer, &iviscrn->pending.layer_list, pending.link) {
++ if (layer->id_layer == ivilayer->id_layer) {
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * Internal API to initialize ivi_screens found from output_list of weston_compositor.
++ * Called by ivi_layout_init_with_compositor.
++ */
++static void
++create_screen(struct weston_compositor *ec)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_screen *iviscrn = NULL;
++ struct weston_output *output = NULL;
++ int32_t count = 0;
++
++ wl_list_for_each(output, &ec->output_list, link) {
++ iviscrn = calloc(1, sizeof *iviscrn);
++ if (iviscrn == NULL) {
++ weston_log("fails to allocate memory\n");
++ continue;
++ }
++
++ iviscrn->layout = layout;
++
++ iviscrn->id_screen = count;
++ count++;
++
++ iviscrn->output = output;
++
++ wl_list_init(&iviscrn->pending.layer_list);
++ wl_list_init(&iviscrn->pending.link);
++
++ wl_list_init(&iviscrn->order.layer_list);
++ wl_list_init(&iviscrn->order.link);
++
++ wl_list_init(&iviscrn->link_to_layer);
++
++ wl_list_insert(&layout->screen_list, &iviscrn->link);
++ }
++}
++
++/**
++ * Internal APIs to initialize properties of ivi_surface/ivi_layer when they are created.
++ */
++static void
++init_layer_properties(struct ivi_layout_layer_properties *prop,
++ int32_t width, int32_t height)
++{
++ memset(prop, 0, sizeof *prop);
++ prop->opacity = wl_fixed_from_double(1.0);
++ prop->source_width = width;
++ prop->source_height = height;
++ prop->dest_width = width;
++ prop->dest_height = height;
++}
++
++static void
++init_surface_properties(struct ivi_layout_surface_properties *prop)
++{
++ memset(prop, 0, sizeof *prop);
++ prop->opacity = wl_fixed_from_double(1.0);
++ /*
++ * FIXME: this shall be finxed by ivi-layout-transition.
++ */
++ prop->dest_width = 1;
++ prop->dest_height = 1;
++}
++
++/**
++ * Internal APIs to be called from ivi_layout_commit_changes.
++ */
++static void
++update_opacity(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *ivisurf)
++{
++ double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
++ double surf_alpha = wl_fixed_to_double(ivisurf->prop.opacity);
++
++ if ((ivilayer->event_mask & IVI_NOTIFICATION_OPACITY) ||
++ (ivisurf->event_mask & IVI_NOTIFICATION_OPACITY)) {
++ struct weston_view *tmpview = NULL;
++ wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) {
++ if (tmpview == NULL) {
++ continue;
++ }
++ tmpview->alpha = layer_alpha * surf_alpha;
++ }
++ }
++}
++
++static void
++get_rotate_values(enum wl_output_transform orientation,
++ float *v_sin,
++ float *v_cos)
++{
++ switch (orientation) {
++ case WL_OUTPUT_TRANSFORM_90:
++ *v_sin = 1.0f;
++ *v_cos = 0.0f;
++ break;
++ case WL_OUTPUT_TRANSFORM_180:
++ *v_sin = 0.0f;
++ *v_cos = -1.0f;
++ break;
++ case WL_OUTPUT_TRANSFORM_270:
++ *v_sin = -1.0f;
++ *v_cos = 0.0f;
++ break;
++ case WL_OUTPUT_TRANSFORM_NORMAL:
++ default:
++ *v_sin = 0.0f;
++ *v_cos = 1.0f;
++ break;
++ }
++}
++
++static void
++get_scale(enum wl_output_transform orientation,
++ float dest_width,
++ float dest_height,
++ float source_width,
++ float source_height,
++ float *scale_x,
++ float *scale_y)
++{
++ switch (orientation) {
++ case WL_OUTPUT_TRANSFORM_90:
++ *scale_x = dest_width / source_height;
++ *scale_y = dest_height / source_width;
++ break;
++ case WL_OUTPUT_TRANSFORM_180:
++ *scale_x = dest_width / source_width;
++ *scale_y = dest_height / source_height;
++ break;
++ case WL_OUTPUT_TRANSFORM_270:
++ *scale_x = dest_width / source_height;
++ *scale_y = dest_height / source_width;
++ break;
++ case WL_OUTPUT_TRANSFORM_NORMAL:
++ default:
++ *scale_x = dest_width / source_width;
++ *scale_y = dest_height / source_height;
++ break;
++ }
++}
++
++static void
++calc_transformation_matrix(struct ivi_rectangle *source_rect,
++ struct ivi_rectangle *dest_rect,
++ enum wl_output_transform orientation,
++ struct weston_matrix *m)
++{
++ float source_center_x;
++ float source_center_y;
++ float vsin;
++ float vcos;
++ float scale_x;
++ float scale_y;
++ float translate_x;
++ float translate_y;
++
++ source_center_x = source_rect->x + source_rect->width * 0.5f;
++ source_center_y = source_rect->y + source_rect->height * 0.5f;
++ weston_matrix_translate(m, -source_center_x, -source_center_y, 0.0f);
++
++ get_rotate_values(orientation, &vsin, &vcos);
++ weston_matrix_rotate_xy(m, vcos, vsin);
++
++ get_scale(orientation,
++ dest_rect->width,
++ dest_rect->height,
++ source_rect->width,
++ source_rect->height,
++ &scale_x,
++ &scale_y);
++ weston_matrix_scale(m, scale_x, scale_y, 1.0f);
++
++ translate_x = dest_rect->width * 0.5f + dest_rect->x;
++ translate_y = dest_rect->height * 0.5f + dest_rect->y;
++ weston_matrix_translate(m, translate_x, translate_y, 0.0f);
++}
++
++/*
++ * This computes intersected rect_output from two ivi_rectangles
++ */
++static void
++ivi_rectangle_intersect(const struct ivi_rectangle *rect1,
++ const struct ivi_rectangle *rect2,
++ struct ivi_rectangle *rect_output)
++{
++ int32_t rect1_right = rect1->x + rect1->width;
++ int32_t rect1_bottom = rect1->y + rect1->height;
++ int32_t rect2_right = rect2->x + rect2->width;
++ int32_t rect2_bottom = rect2->y + rect2->height;
++
++ rect_output->x = max(rect1->x, rect2->x);
++ rect_output->y = max(rect1->y, rect2->y);
++ rect_output->width = rect1_right < rect2_right ?
++ rect1_right - rect_output->x :
++ rect2_right - rect_output->x;
++ rect_output->height = rect1_bottom < rect2_bottom ?
++ rect1_bottom - rect_output->y :
++ rect2_bottom - rect_output->y;
++
++ if (rect_output->width < 0 || rect_output->height < 0) {
++ rect_output->width = 0;
++ rect_output->height = 0;
++ }
++}
++
++/*
++ * Transform rect_input by the inverse of matrix, intersect with boundingbox,
++ * and store the result in rect_output.
++ * The boundingbox must be given in the same coordinate space as rect_output.
++ * Additionally, there are the following restrictions on the matrix:
++ * - no projective transformations
++ * - no skew
++ * - only multiples of 90-degree rotations supported
++ *
++ * In failure case of weston_matrix_invert, rect_output is set to boundingbox
++ * as a fail-safe with log.
++ */
++static void
++calc_inverse_matrix_transform(const struct weston_matrix *matrix,
++ const struct ivi_rectangle *rect_input,
++ const struct ivi_rectangle *boundingbox,
++ struct ivi_rectangle *rect_output)
++{
++ struct weston_matrix m;
++ struct weston_vector top_left;
++ struct weston_vector bottom_right;
++
++ assert(boundingbox != rect_output);
++
++ if (weston_matrix_invert(&m, matrix) < 0) {
++ weston_log("ivi-shell: calc_inverse_matrix_transform fails to invert a matrix.\n");
++ weston_log("ivi-shell: boundingbox is set to the rect_output.\n");
++ rect_output->x = boundingbox->x;
++ rect_output->y = boundingbox->y;
++ rect_output->width = boundingbox->width;
++ rect_output->height = boundingbox->height;
++ }
++
++ /* The vectors and matrices involved will always produce f[3] == 1.0. */
++ top_left.f[0] = rect_input->x;
++ top_left.f[1] = rect_input->y;
++ top_left.f[2] = 0.0f;
++ top_left.f[3] = 1.0f;
++
++ bottom_right.f[0] = rect_input->x + rect_input->width;
++ bottom_right.f[1] = rect_input->y + rect_input->height;
++ bottom_right.f[2] = 0.0f;
++ bottom_right.f[3] = 1.0f;
++
++ weston_matrix_transform(&m, &top_left);
++ weston_matrix_transform(&m, &bottom_right);
++
++ if (top_left.f[0] < bottom_right.f[0]) {
++ rect_output->x = top_left.f[0];
++ rect_output->width = bottom_right.f[0] - rect_output->x;
++ } else {
++ rect_output->x = bottom_right.f[0];
++ rect_output->width = top_left.f[0] - rect_output->x;
++ }
++
++ if (top_left.f[1] < bottom_right.f[1]) {
++ rect_output->y = top_left.f[1];
++ rect_output->height = bottom_right.f[1] - rect_output->y;
++ } else {
++ rect_output->y = bottom_right.f[1];
++ rect_output->height = top_left.f[1] - rect_output->y;
++ }
++
++ ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
++}
++
++/**
++ * This computes the whole transformation matrix:m from surface-local
++ * coordinates to global coordinates. It is assumed that
++ * weston_view::geometry.{x,y} are zero.
++ *
++ * Additionally, this computes the mask on surface-local coordinates as a
++ * ivi_rectangle. This can be set to weston_view_set_mask.
++ *
++ * The mask is computed by following steps
++ * - destination rectangle of layer is inversed to surface-local cooodinates
++ * by inversed matrix:m.
++ * - the area is intersected by intersected area between weston_surface and
++ * source rectangle of ivi_surface.
++ */
++static void
++calc_surface_to_global_matrix_and_mask_to_weston_surface(
++ struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *ivisurf,
++ struct weston_matrix *m,
++ struct ivi_rectangle *result)
++{
++ const struct ivi_layout_surface_properties *sp = &ivisurf->prop;
++ const struct ivi_layout_layer_properties *lp = &ivilayer->prop;
++ struct ivi_rectangle weston_surface_rect = { 0,
++ 0,
++ ivisurf->surface->width,
++ ivisurf->surface->height };
++ struct ivi_rectangle surface_source_rect = { sp->source_x,
++ sp->source_y,
++ sp->source_width,
++ sp->source_height };
++ struct ivi_rectangle surface_dest_rect = { sp->dest_x,
++ sp->dest_y,
++ sp->dest_width,
++ sp->dest_height };
++ struct ivi_rectangle layer_source_rect = { lp->source_x,
++ lp->source_y,
++ lp->source_width,
++ lp->source_height };
++ struct ivi_rectangle layer_dest_rect = { lp->dest_x,
++ lp->dest_y,
++ lp->dest_width,
++ lp->dest_height };
++ struct ivi_rectangle surface_result;
++
++ /*
++ * the whole transformation matrix:m from surface-local
++ * coordinates to global coordinates, which is computed by
++ * two steps,
++ * - surface-local coordinates to layer-local coordinates
++ * - layer-local coordinates to global coordinates
++ */
++ calc_transformation_matrix(&surface_source_rect,
++ &surface_dest_rect,
++ sp->orientation, m);
++
++ calc_transformation_matrix(&layer_source_rect,
++ &layer_dest_rect,
++ lp->orientation, m);
++
++ /* this intersected ivi_rectangle would be used for masking
++ * weston_surface
++ */
++ ivi_rectangle_intersect(&surface_source_rect, &weston_surface_rect,
++ &surface_result);
++
++ /* calc masking area of weston_surface from m */
++ calc_inverse_matrix_transform(m,
++ &layer_dest_rect,
++ &surface_result,
++ result);
++}
++
++static void
++update_prop(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *ivisurf)
++{
++ struct weston_view *tmpview;
++ struct ivi_rectangle r;
++ bool can_calc = true;
++
++ if (!ivilayer->event_mask && !ivisurf->event_mask) {
++ return;
++ }
++
++ update_opacity(ivilayer, ivisurf);
++
++ wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) {
++ if (tmpview != NULL) {
++ break;
++ }
++ }
++
++ if (ivisurf->prop.source_width == 0 || ivisurf->prop.source_height == 0) {
++ weston_log("ivi-shell: source rectangle is not yet set by ivi_layout_surface_set_source_rectangle\n");
++ can_calc = false;
++ }
++
++ if (ivisurf->prop.dest_width == 0 || ivisurf->prop.dest_height == 0) {
++ weston_log("ivi-shell: destination rectangle is not yet set by ivi_layout_surface_set_destination_rectangle\n");
++ can_calc = false;
++ }
++
++ if (can_calc) {
++ wl_list_remove(&ivisurf->transform.link);
++ weston_matrix_init(&ivisurf->transform.matrix);
++
++ calc_surface_to_global_matrix_and_mask_to_weston_surface(
++ ivilayer, ivisurf, &ivisurf->transform.matrix, &r);
++
++ if (tmpview != NULL) {
++ wl_list_insert(&tmpview->geometry.transformation_list,
++ &ivisurf->transform.link);
++
++ weston_view_set_transform_parent(tmpview, NULL);
++ }
++ }
++
++ ivisurf->update_count++;
++
++ if (tmpview != NULL) {
++ weston_view_geometry_dirty(tmpview);
++ }
++
++ if (ivisurf->surface != NULL) {
++ weston_surface_damage(ivisurf->surface);
++ }
++}
++
++static void
++commit_changes(struct ivi_layout *layout)
++{
++ struct ivi_layout_screen *iviscrn = NULL;
++ struct ivi_layout_layer *ivilayer = NULL;
++ struct ivi_layout_surface *ivisurf = NULL;
++
++ wl_list_for_each(iviscrn, &layout->screen_list, link) {
++ wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
++ wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) {
++ update_prop(ivilayer, ivisurf);
++ }
++ }
++ }
++}
++
++static void
++commit_surface_list(struct ivi_layout *layout)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ int32_t dest_x = 0;
++ int32_t dest_y = 0;
++ int32_t dest_width = 0;
++ int32_t dest_height = 0;
++ int32_t configured = 0;
++
++ wl_list_for_each(ivisurf, &layout->surface_list, link) {
++ if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEFAULT) {
++ dest_x = ivisurf->prop.dest_x;
++ dest_y = ivisurf->prop.dest_y;
++ dest_width = ivisurf->prop.dest_width;
++ dest_height = ivisurf->prop.dest_height;
++
++ ivi_layout_transition_move_resize_view(ivisurf,
++ ivisurf->pending.prop.dest_x,
++ ivisurf->pending.prop.dest_y,
++ ivisurf->pending.prop.dest_width,
++ ivisurf->pending.prop.dest_height,
++ ivisurf->pending.prop.transition_duration);
++
++ if (ivisurf->pending.prop.visibility) {
++ ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration);
++ } else {
++ ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration);
++ }
++
++ ivisurf->prop = ivisurf->pending.prop;
++ ivisurf->prop.dest_x = dest_x;
++ ivisurf->prop.dest_y = dest_y;
++ ivisurf->prop.dest_width = dest_width;
++ ivisurf->prop.dest_height = dest_height;
++ ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++ ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++
++ } else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY) {
++ dest_x = ivisurf->prop.dest_x;
++ dest_y = ivisurf->prop.dest_y;
++ dest_width = ivisurf->prop.dest_width;
++ dest_height = ivisurf->prop.dest_height;
++
++ ivi_layout_transition_move_resize_view(ivisurf,
++ ivisurf->pending.prop.dest_x,
++ ivisurf->pending.prop.dest_y,
++ ivisurf->pending.prop.dest_width,
++ ivisurf->pending.prop.dest_height,
++ ivisurf->pending.prop.transition_duration);
++
++ ivisurf->prop = ivisurf->pending.prop;
++ ivisurf->prop.dest_x = dest_x;
++ ivisurf->prop.dest_y = dest_y;
++ ivisurf->prop.dest_width = dest_width;
++ ivisurf->prop.dest_height = dest_height;
++
++ ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++ ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++
++ } else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY) {
++ configured = 0;
++ if (ivisurf->pending.prop.visibility) {
++ ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration);
++ } else {
++ ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration);
++ }
++
++ if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width ||
++ ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) {
++ configured = 1;
++ }
++
++ ivisurf->prop = ivisurf->pending.prop;
++ ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++ ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++
++ if (configured && !is_surface_transition(ivisurf))
++ wl_signal_emit(&ivisurf->configured, ivisurf);
++ } else {
++ configured = 0;
++ if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width ||
++ ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) {
++ configured = 1;
++ }
++
++ ivisurf->prop = ivisurf->pending.prop;
++ ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++ ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++
++ if (configured && !is_surface_transition(ivisurf))
++ wl_signal_emit(&ivisurf->configured, ivisurf);
++ }
++ }
++}
++
++static void
++commit_layer_list(struct ivi_layout *layout)
++{
++ struct ivi_layout_layer *ivilayer = NULL;
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_surface *next = NULL;
++
++ wl_list_for_each(ivilayer, &layout->layer_list, link) {
++ if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_MOVE) {
++ ivi_layout_transition_move_layer(ivilayer, ivilayer->pending.prop.dest_x, ivilayer->pending.prop.dest_y, ivilayer->pending.prop.transition_duration);
++ } else if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_FADE) {
++ ivi_layout_transition_fade_layer(ivilayer,ivilayer->pending.prop.is_fade_in,
++ ivilayer->pending.prop.start_alpha,ivilayer->pending.prop.end_alpha,
++ NULL, NULL,
++ ivilayer->pending.prop.transition_duration);
++ }
++ ivilayer->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
++
++ ivilayer->prop = ivilayer->pending.prop;
++
++ if (!ivilayer->order.dirty) {
++ continue;
++ }
++
++ wl_list_for_each_safe(ivisurf, next, &ivilayer->order.surface_list,
++ order.link) {
++ remove_ordersurface_from_layer(ivisurf);
++ wl_list_remove(&ivisurf->order.link);
++ wl_list_init(&ivisurf->order.link);
++ ivisurf->event_mask |= IVI_NOTIFICATION_REMOVE;
++ }
++
++ assert(wl_list_empty(&ivilayer->order.surface_list));
++
++ wl_list_for_each(ivisurf, &ivilayer->pending.surface_list,
++ pending.link) {
++ wl_list_remove(&ivisurf->order.link);
++ wl_list_insert(&ivilayer->order.surface_list,
++ &ivisurf->order.link);
++ add_ordersurface_to_layer(ivisurf, ivilayer);
++ ivisurf->event_mask |= IVI_NOTIFICATION_ADD;
++ }
++
++ ivilayer->order.dirty = 0;
++ }
++}
++
++static void
++commit_screen_list(struct ivi_layout *layout)
++{
++ struct ivi_layout_screen *iviscrn = NULL;
++ struct ivi_layout_layer *ivilayer = NULL;
++ struct ivi_layout_layer *next = NULL;
++ struct ivi_layout_surface *ivisurf = NULL;
++
++ wl_list_for_each(iviscrn, &layout->screen_list, link) {
++ if (iviscrn->order.dirty) {
++ wl_list_for_each_safe(ivilayer, next,
++ &iviscrn->order.layer_list, order.link) {
++ remove_orderlayer_from_screen(ivilayer);
++ wl_list_remove(&ivilayer->order.link);
++ wl_list_init(&ivilayer->order.link);
++ ivilayer->event_mask |= IVI_NOTIFICATION_REMOVE;
++ }
++
++ assert(wl_list_empty(&iviscrn->order.layer_list));
++
++ wl_list_for_each(ivilayer, &iviscrn->pending.layer_list,
++ pending.link) {
++ wl_list_insert(&iviscrn->order.layer_list,
++ &ivilayer->order.link);
++ add_orderlayer_to_screen(ivilayer, iviscrn);
++ ivilayer->event_mask |= IVI_NOTIFICATION_ADD;
++ }
++
++ iviscrn->order.dirty = 0;
++ }
++
++ /* Clear view list of layout ivi_layer */
++ wl_list_init(&layout->layout_layer.view_list);
++
++ wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
++ if (ivilayer->prop.visibility == false)
++ continue;
++
++ wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) {
++ struct weston_view *tmpview = NULL;
++ wl_list_for_each(tmpview, &ivisurf->surface->views, surface_link) {
++ if (tmpview != NULL) {
++ break;
++ }
++ }
++
++ if (ivisurf->prop.visibility == false)
++ continue;
++ if (ivisurf->surface == NULL || tmpview == NULL)
++ continue;
++
++ wl_list_insert(&layout->layout_layer.view_list,
++ &tmpview->layer_link);
++
++ ivisurf->surface->output = iviscrn->output;
++ }
++ }
++
++ break;
++ }
++}
++
++static void
++commit_transition(struct ivi_layout* layout)
++{
++ if (wl_list_empty(&layout->pending_transition_list)) {
++ return;
++ }
++
++ wl_list_insert_list(&layout->transitions->transition_list,
++ &layout->pending_transition_list);
++
++ wl_list_init(&layout->pending_transition_list);
++
++ wl_event_source_timer_update(layout->transitions->event_source, 1);
++}
++
++static void
++send_surface_prop(struct ivi_layout_surface *ivisurf)
++{
++ wl_signal_emit(&ivisurf->property_changed, ivisurf);
++ ivisurf->event_mask = 0;
++}
++
++static void
++send_layer_prop(struct ivi_layout_layer *ivilayer)
++{
++ wl_signal_emit(&ivilayer->property_changed, ivilayer);
++ ivilayer->event_mask = 0;
++}
++
++static void
++send_prop(struct ivi_layout *layout)
++{
++ struct ivi_layout_layer *ivilayer = NULL;
++ struct ivi_layout_surface *ivisurf = NULL;
++
++ wl_list_for_each_reverse(ivilayer, &layout->layer_list, link) {
++ if (ivilayer->event_mask)
++ send_layer_prop(ivilayer);
++ }
++
++ wl_list_for_each_reverse(ivisurf, &layout->surface_list, link) {
++ if (ivisurf->event_mask)
++ send_surface_prop(ivisurf);
++ }
++}
++
++static void
++clear_surface_pending_list(struct ivi_layout_layer *ivilayer)
++{
++ struct ivi_layout_surface *surface_link = NULL;
++ struct ivi_layout_surface *surface_next = NULL;
++
++ wl_list_for_each_safe(surface_link, surface_next,
++ &ivilayer->pending.surface_list, pending.link) {
++ wl_list_remove(&surface_link->pending.link);
++ wl_list_init(&surface_link->pending.link);
++ }
++}
++
++static void
++clear_surface_order_list(struct ivi_layout_layer *ivilayer)
++{
++ struct ivi_layout_surface *surface_link = NULL;
++ struct ivi_layout_surface *surface_next = NULL;
++
++ wl_list_for_each_safe(surface_link, surface_next,
++ &ivilayer->order.surface_list, order.link) {
++ wl_list_remove(&surface_link->order.link);
++ wl_list_init(&surface_link->order.link);
++ }
++}
++
++static void
++layer_created(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_layer *ivilayer = data;
++
++ struct listener_layout_notification *notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *created_callback =
++ notification->userdata;
++
++ ((layer_create_notification_func)created_callback->callback)
++ (ivilayer, created_callback->data);
++}
++
++static void
++layer_removed(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_layer *ivilayer = data;
++
++ struct listener_layout_notification *notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *removed_callback =
++ notification->userdata;
++
++ ((layer_remove_notification_func)removed_callback->callback)
++ (ivilayer, removed_callback->data);
++}
++
++static void
++layer_prop_changed(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_layer *ivilayer = data;
++
++ struct listener_layout_notification *layout_listener =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *prop_callback =
++ layout_listener->userdata;
++
++ ((layer_property_notification_func)prop_callback->callback)
++ (ivilayer, &ivilayer->prop, ivilayer->event_mask, prop_callback->data);
++}
++
++static void
++surface_created(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_surface *ivisurface = data;
++
++ struct listener_layout_notification *notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *created_callback =
++ notification->userdata;
++
++ ((surface_create_notification_func)created_callback->callback)
++ (ivisurface, created_callback->data);
++}
++
++static void
++surface_removed(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_surface *ivisurface = data;
++
++ struct listener_layout_notification *notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *removed_callback =
++ notification->userdata;
++
++ ((surface_remove_notification_func)removed_callback->callback)
++ (ivisurface, removed_callback->data);
++}
++
++static void
++surface_prop_changed(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_surface *ivisurf = data;
++
++ struct listener_layout_notification *layout_listener =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *prop_callback =
++ layout_listener->userdata;
++
++ ((surface_property_notification_func)prop_callback->callback)
++ (ivisurf, &ivisurf->prop, ivisurf->event_mask, prop_callback->data);
++
++ ivisurf->event_mask = 0;
++}
++
++static void
++surface_configure_changed(struct wl_listener *listener,
++ void *data)
++{
++ struct ivi_layout_surface *ivisurface = data;
++
++ struct listener_layout_notification *notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *configure_changed_callback =
++ notification->userdata;
++
++ ((surface_configure_notification_func)configure_changed_callback->callback)
++ (ivisurface, configure_changed_callback->data);
++}
++
++static int32_t
++add_notification(struct wl_signal *signal,
++ wl_notify_func_t callback,
++ void *userdata)
++{
++ struct listener_layout_notification *notification = NULL;
++
++ notification = malloc(sizeof *notification);
++ if (notification == NULL) {
++ weston_log("fails to allocate memory\n");
++ free(userdata);
++ return IVI_FAILED;
++ }
++
++ notification->listener.notify = callback;
++ notification->userdata = userdata;
++
++ wl_signal_add(signal, &notification->listener);
++
++ return IVI_SUCCEEDED;
++}
++
++static void
++remove_notification(struct wl_list *listener_list, void *callback, void *userdata)
++{
++ struct wl_listener *listener = NULL;
++ struct wl_listener *next = NULL;
++
++ wl_list_for_each_safe(listener, next, listener_list, link) {
++ struct listener_layout_notification *notification =
++ container_of(listener,
++ struct listener_layout_notification,
++ listener);
++
++ struct ivi_layout_notification_callback *notification_callback =
++ notification->userdata;
++
++ if ((notification_callback->callback != callback) ||
++ (notification_callback->data != userdata)) {
++ continue;
++ }
++
++ wl_list_remove(&listener->link);
++
++ free(notification->userdata);
++ free(notification);
++ }
++}
++
++/**
++ * Exported APIs of ivi-layout library are implemented from here.
++ * Brief of APIs is described in ivi-layout-export.h.
++ */
++static int32_t
++ivi_layout_add_notification_create_layer(layer_create_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_notification_callback *created_callback = NULL;
++
++ if (callback == NULL) {
++ weston_log("ivi_layout_add_notification_create_layer: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ created_callback = malloc(sizeof *created_callback);
++ if (created_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ created_callback->callback = callback;
++ created_callback->data = userdata;
++
++ return add_notification(&layout->layer_notification.created,
++ layer_created,
++ created_callback);
++}
++
++static void
++ivi_layout_remove_notification_create_layer(layer_create_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ remove_notification(&layout->layer_notification.created.listener_list, callback, userdata);
++}
++
++static int32_t
++ivi_layout_add_notification_remove_layer(layer_remove_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_notification_callback *removed_callback = NULL;
++
++ if (callback == NULL) {
++ weston_log("ivi_layout_add_notification_remove_layer: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ removed_callback = malloc(sizeof *removed_callback);
++ if (removed_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ removed_callback->callback = callback;
++ removed_callback->data = userdata;
++ return add_notification(&layout->layer_notification.removed,
++ layer_removed,
++ removed_callback);
++}
++
++static void
++ivi_layout_remove_notification_remove_layer(layer_remove_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ remove_notification(&layout->layer_notification.removed.listener_list, callback, userdata);
++}
++
++static int32_t
++ivi_layout_add_notification_create_surface(surface_create_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_notification_callback *created_callback = NULL;
++
++ if (callback == NULL) {
++ weston_log("ivi_layout_add_notification_create_surface: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ created_callback = malloc(sizeof *created_callback);
++ if (created_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ created_callback->callback = callback;
++ created_callback->data = userdata;
++
++ return add_notification(&layout->surface_notification.created,
++ surface_created,
++ created_callback);
++}
++
++static void
++ivi_layout_remove_notification_create_surface(surface_create_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ remove_notification(&layout->surface_notification.created.listener_list, callback, userdata);
++}
++
++static int32_t
++ivi_layout_add_notification_remove_surface(surface_remove_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_notification_callback *removed_callback = NULL;
++
++ if (callback == NULL) {
++ weston_log("ivi_layout_add_notification_remove_surface: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ removed_callback = malloc(sizeof *removed_callback);
++ if (removed_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ removed_callback->callback = callback;
++ removed_callback->data = userdata;
++
++ return add_notification(&layout->surface_notification.removed,
++ surface_removed,
++ removed_callback);
++}
++
++static void
++ivi_layout_remove_notification_remove_surface(surface_remove_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ remove_notification(&layout->surface_notification.removed.listener_list, callback, userdata);
++}
++
++static int32_t
++ivi_layout_add_notification_configure_surface(surface_configure_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_notification_callback *configure_changed_callback = NULL;
++ if (callback == NULL) {
++ weston_log("ivi_layout_add_notification_configure_surface: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ configure_changed_callback = malloc(sizeof *configure_changed_callback);
++ if (configure_changed_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ configure_changed_callback->callback = callback;
++ configure_changed_callback->data = userdata;
++
++ return add_notification(&layout->surface_notification.configure_changed,
++ surface_configure_changed,
++ configure_changed_callback);
++}
++
++static void
++ivi_layout_remove_notification_configure_surface(surface_configure_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout *layout = get_instance();
++ remove_notification(&layout->surface_notification.configure_changed.listener_list, callback, userdata);
++}
++
++uint32_t
++ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf)
++{
++ return ivisurf->id_surface;
++}
++
++static uint32_t
++ivi_layout_get_id_of_layer(struct ivi_layout_layer *ivilayer)
++{
++ return ivilayer->id_layer;
++}
++
++static uint32_t
++ivi_layout_get_id_of_screen(struct ivi_layout_screen *iviscrn)
++{
++ return iviscrn->id_screen;
++}
++
++static struct ivi_layout_layer *
++ivi_layout_get_layer_from_id(uint32_t id_layer)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_layer *ivilayer = NULL;
++
++ wl_list_for_each(ivilayer, &layout->layer_list, link) {
++ if (ivilayer->id_layer == id_layer) {
++ return ivilayer;
++ }
++ }
++
++ return NULL;
++}
++
++struct ivi_layout_surface *
++ivi_layout_get_surface_from_id(uint32_t id_surface)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_surface *ivisurf = NULL;
++
++ wl_list_for_each(ivisurf, &layout->surface_list, link) {
++ if (ivisurf->id_surface == id_surface) {
++ return ivisurf;
++ }
++ }
++
++ return NULL;
++}
++
++static struct ivi_layout_screen *
++ivi_layout_get_screen_from_id(uint32_t id_screen)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_screen *iviscrn = NULL;
++
++ wl_list_for_each(iviscrn, &layout->screen_list, link) {
++/* FIXME : select iviscrn from screen_list by id_screen */
++ return iviscrn;
++ break;
++ }
++
++ return NULL;
++}
++
++static int32_t
++ivi_layout_get_screen_resolution(struct ivi_layout_screen *iviscrn,
++ int32_t *pWidth, int32_t *pHeight)
++{
++ struct weston_output *output = NULL;
++
++ if (iviscrn == NULL || pWidth == NULL || pHeight == NULL) {
++ weston_log("ivi_layout_get_screen_resolution: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ output = iviscrn->output;
++ *pWidth = output->current_mode->width;
++ *pHeight = output->current_mode->height;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_surface_add_notification(struct ivi_layout_surface *ivisurf,
++ surface_property_notification_func callback,
++ void *userdata)
++{
++ struct listener_layout_notification* notification = NULL;
++ struct ivi_layout_notification_callback *prop_callback = NULL;
++
++ if (ivisurf == NULL || callback == NULL) {
++ weston_log("ivi_layout_surface_add_notification: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ notification = malloc(sizeof *notification);
++ if (notification == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ prop_callback = malloc(sizeof *prop_callback);
++ if (prop_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ prop_callback->callback = callback;
++ prop_callback->data = userdata;
++
++ notification->listener.notify = surface_prop_changed;
++ notification->userdata = prop_callback;
++
++ wl_signal_add(&ivisurf->property_changed, &notification->listener);
++
++ return IVI_SUCCEEDED;
++}
++
++static const struct ivi_layout_layer_properties *
++ivi_layout_get_properties_of_layer(struct ivi_layout_layer *ivilayer)
++{
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_get_properties_of_layer: invalid argument\n");
++ return NULL;
++ }
++
++ return &ivilayer->prop;
++}
++
++static int32_t
++ivi_layout_get_screens(int32_t *pLength, struct ivi_layout_screen ***ppArray)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_screen *iviscrn = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_get_screens: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&layout->screen_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_screen *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(iviscrn, &layout->screen_list, link) {
++ (*ppArray)[n++] = iviscrn;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_get_screens_under_layer(struct ivi_layout_layer *ivilayer,
++ int32_t *pLength,
++ struct ivi_layout_screen ***ppArray)
++{
++ struct link_screen *link_scrn = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_get_screens_under_layer: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&ivilayer->screen_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_screen *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(link_scrn, &ivilayer->screen_list, link) {
++ (*ppArray)[n++] = link_scrn->iviscrn;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_get_layers(int32_t *pLength, struct ivi_layout_layer ***ppArray)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_layer *ivilayer = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_get_layers: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&layout->layer_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(ivilayer, &layout->layer_list, link) {
++ (*ppArray)[n++] = ivilayer;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_get_layers_on_screen(struct ivi_layout_screen *iviscrn,
++ int32_t *pLength,
++ struct ivi_layout_layer ***ppArray)
++{
++ struct ivi_layout_layer *ivilayer = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (iviscrn == NULL || pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_get_layers_on_screen: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&iviscrn->order.layer_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
++ (*ppArray)[n++] = ivilayer;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_get_layers_under_surface(struct ivi_layout_surface *ivisurf,
++ int32_t *pLength,
++ struct ivi_layout_layer ***ppArray)
++{
++ struct link_layer *link_layer = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (ivisurf == NULL || pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_getLayers: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&ivisurf->layer_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(link_layer, &ivisurf->layer_list, link) {
++ (*ppArray)[n++] = link_layer->ivilayer;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static
++int32_t
++ivi_layout_get_surfaces(int32_t *pLength, struct ivi_layout_surface ***ppArray)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_surface *ivisurf = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_get_surfaces: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&layout->surface_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(ivisurf, &layout->surface_list, link) {
++ (*ppArray)[n++] = ivisurf;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_get_surfaces_on_layer(struct ivi_layout_layer *ivilayer,
++ int32_t *pLength,
++ struct ivi_layout_surface ***ppArray)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ int32_t length = 0;
++ int32_t n = 0;
++
++ if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
++ weston_log("ivi_layout_getSurfaceIDsOnLayer: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ length = wl_list_length(&ivilayer->order.surface_list);
++
++ if (length != 0) {
++ /* the Array must be free by module which called this function */
++ *ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
++ if (*ppArray == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each(ivisurf, &ivilayer->order.surface_list, order.link) {
++ (*ppArray)[n++] = ivisurf;
++ }
++ }
++
++ *pLength = length;
++
++ return IVI_SUCCEEDED;
++}
++
++static struct ivi_layout_layer *
++ivi_layout_layer_create_with_dimension(uint32_t id_layer,
++ int32_t width, int32_t height)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_layer *ivilayer = NULL;
++
++ ivilayer = get_layer(&layout->layer_list, id_layer);
++ if (ivilayer != NULL) {
++ weston_log("id_layer is already created\n");
++ ++ivilayer->ref_count;
++ return ivilayer;
++ }
++
++ ivilayer = calloc(1, sizeof *ivilayer);
++ if (ivilayer == NULL) {
++ weston_log("fails to allocate memory\n");
++ return NULL;
++ }
++
++ ivilayer->ref_count = 1;
++ wl_signal_init(&ivilayer->property_changed);
++ wl_list_init(&ivilayer->screen_list);
++ wl_list_init(&ivilayer->link_to_surface);
++ ivilayer->layout = layout;
++ ivilayer->id_layer = id_layer;
++
++ init_layer_properties(&ivilayer->prop, width, height);
++ ivilayer->event_mask = 0;
++
++ wl_list_init(&ivilayer->pending.surface_list);
++ wl_list_init(&ivilayer->pending.link);
++ ivilayer->pending.prop = ivilayer->prop;
++
++ wl_list_init(&ivilayer->order.surface_list);
++ wl_list_init(&ivilayer->order.link);
++
++ wl_list_insert(&layout->layer_list, &ivilayer->link);
++
++ wl_signal_emit(&layout->layer_notification.created, ivilayer);
++
++ return ivilayer;
++}
++
++static void
++ivi_layout_layer_remove_notification(struct ivi_layout_layer *ivilayer)
++{
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_remove_notification: invalid argument\n");
++ return;
++ }
++
++ remove_all_notification(&ivilayer->property_changed.listener_list);
++}
++
++static void
++ivi_layout_layer_remove_notification_by_callback(struct ivi_layout_layer *ivilayer,
++ layer_property_notification_func callback,
++ void *userdata)
++{
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_remove_notification_by_callback: invalid argument\n");
++ return;
++ }
++
++ remove_notification(&ivilayer->property_changed.listener_list, callback, userdata);
++}
++
++static void
++ivi_layout_layer_destroy(struct ivi_layout_layer *ivilayer)
++{
++ struct ivi_layout *layout = get_instance();
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_remove: invalid argument\n");
++ return;
++ }
++
++ if (--ivilayer->ref_count > 0)
++ return;
++
++ wl_signal_emit(&layout->layer_notification.removed, ivilayer);
++
++ clear_surface_pending_list(ivilayer);
++ clear_surface_order_list(ivilayer);
++
++ wl_list_remove(&ivilayer->pending.link);
++ wl_list_remove(&ivilayer->order.link);
++ wl_list_remove(&ivilayer->link);
++
++ remove_orderlayer_from_screen(ivilayer);
++ remove_link_to_surface(ivilayer);
++ ivi_layout_layer_remove_notification(ivilayer);
++
++ free(ivilayer);
++}
++
++int32_t
++ivi_layout_layer_set_visibility(struct ivi_layout_layer *ivilayer,
++ bool newVisibility)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_visibility: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++ prop->visibility = newVisibility;
++
++ if (ivilayer->prop.visibility != newVisibility)
++ ivilayer->event_mask |= IVI_NOTIFICATION_VISIBILITY;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
++
++ return IVI_SUCCEEDED;
++}
++
++static bool
++ivi_layout_layer_get_visibility(struct ivi_layout_layer *ivilayer)
++{
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_get_visibility: invalid argument\n");
++ return false;
++ }
++
++ return ivilayer->prop.visibility;
++}
++
++int32_t
++ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer,
++ wl_fixed_t opacity)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL ||
++ opacity < wl_fixed_from_double(0.0) ||
++ wl_fixed_from_double(1.0) < opacity) {
++ weston_log("ivi_layout_layer_set_opacity: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++ prop->opacity = opacity;
++
++ if (ivilayer->prop.opacity != opacity)
++ ivilayer->event_mask |= IVI_NOTIFICATION_OPACITY;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_OPACITY;
++
++ return IVI_SUCCEEDED;
++}
++
++wl_fixed_t
++ivi_layout_layer_get_opacity(struct ivi_layout_layer *ivilayer)
++{
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_get_opacity: invalid argument\n");
++ return wl_fixed_from_double(0.0);
++ }
++
++ return ivilayer->prop.opacity;
++}
++
++static int32_t
++ivi_layout_layer_set_source_rectangle(struct ivi_layout_layer *ivilayer,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_source_rectangle: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++ prop->source_x = x;
++ prop->source_y = y;
++ prop->source_width = width;
++ prop->source_height = height;
++
++ if (ivilayer->prop.source_x != x || ivilayer->prop.source_y != y ||
++ ivilayer->prop.source_width != width ||
++ ivilayer->prop.source_height != height)
++ ivilayer->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_SOURCE_RECT;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_layer_set_destination_rectangle(struct ivi_layout_layer *ivilayer,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_destination_rectangle: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++ prop->dest_x = x;
++ prop->dest_y = y;
++ prop->dest_width = width;
++ prop->dest_height = height;
++
++ if (ivilayer->prop.dest_x != x || ivilayer->prop.dest_y != y ||
++ ivilayer->prop.dest_width != width ||
++ ivilayer->prop.dest_height != height)
++ ivilayer->event_mask |= IVI_NOTIFICATION_DEST_RECT;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_DEST_RECT;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_layer_get_dimension(struct ivi_layout_layer *ivilayer,
++ int32_t *dest_width, int32_t *dest_height)
++{
++ if (ivilayer == NULL || dest_width == NULL || dest_height == NULL) {
++ weston_log("ivi_layout_layer_get_dimension: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ *dest_width = ivilayer->prop.dest_width;
++ *dest_height = ivilayer->prop.dest_height;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_layer_set_dimension(struct ivi_layout_layer *ivilayer,
++ int32_t dest_width, int32_t dest_height)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_dimension: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++
++ prop->dest_width = dest_width;
++ prop->dest_height = dest_height;
++
++ if (ivilayer->prop.dest_width != dest_width ||
++ ivilayer->prop.dest_height != dest_height)
++ ivilayer->event_mask |= IVI_NOTIFICATION_DIMENSION;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_DIMENSION;
++
++ return IVI_SUCCEEDED;
++}
++
++int32_t
++ivi_layout_layer_get_position(struct ivi_layout_layer *ivilayer,
++ int32_t *dest_x, int32_t *dest_y)
++{
++ if (ivilayer == NULL || dest_x == NULL || dest_y == NULL) {
++ weston_log("ivi_layout_layer_get_position: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ *dest_x = ivilayer->prop.dest_x;
++ *dest_y = ivilayer->prop.dest_y;
++
++ return IVI_SUCCEEDED;
++}
++
++int32_t
++ivi_layout_layer_set_position(struct ivi_layout_layer *ivilayer,
++ int32_t dest_x, int32_t dest_y)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_position: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++ prop->dest_x = dest_x;
++ prop->dest_y = dest_y;
++
++ if (ivilayer->prop.dest_x != dest_x || ivilayer->prop.dest_y != dest_y)
++ ivilayer->event_mask |= IVI_NOTIFICATION_POSITION;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_POSITION;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_layer_set_orientation(struct ivi_layout_layer *ivilayer,
++ enum wl_output_transform orientation)
++{
++ struct ivi_layout_layer_properties *prop = NULL;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_orientation: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivilayer->pending.prop;
++ prop->orientation = orientation;
++
++ if (ivilayer->prop.orientation != orientation)
++ ivilayer->event_mask |= IVI_NOTIFICATION_ORIENTATION;
++ else
++ ivilayer->event_mask &= ~IVI_NOTIFICATION_ORIENTATION;
++
++ return IVI_SUCCEEDED;
++}
++
++static enum wl_output_transform
++ivi_layout_layer_get_orientation(struct ivi_layout_layer *ivilayer)
++{
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_get_orientation: invalid argument\n");
++ return 0;
++ }
++
++ return ivilayer->prop.orientation;
++}
++
++int32_t
++ivi_layout_layer_set_render_order(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface **pSurface,
++ int32_t number)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_surface *next = NULL;
++ uint32_t *id_surface = NULL;
++ int32_t i = 0;
++
++ if (ivilayer == NULL) {
++ weston_log("ivi_layout_layer_set_render_order: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ clear_surface_pending_list(ivilayer);
++
++ for (i = 0; i < number; i++) {
++ id_surface = &pSurface[i]->id_surface;
++
++ wl_list_for_each_safe(ivisurf, next, &layout->surface_list, link) {
++ if (*id_surface != ivisurf->id_surface) {
++ continue;
++ }
++
++ wl_list_remove(&ivisurf->pending.link);
++ wl_list_insert(&ivilayer->pending.surface_list,
++ &ivisurf->pending.link);
++ break;
++ }
++ }
++
++ ivilayer->order.dirty = 1;
++
++ return IVI_SUCCEEDED;
++}
++
++int32_t
++ivi_layout_surface_set_visibility(struct ivi_layout_surface *ivisurf,
++ bool newVisibility)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_set_visibility: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->visibility = newVisibility;
++
++ if (ivisurf->prop.visibility != newVisibility)
++ ivisurf->event_mask |= IVI_NOTIFICATION_VISIBILITY;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
++
++ return IVI_SUCCEEDED;
++}
++
++bool
++ivi_layout_surface_get_visibility(struct ivi_layout_surface *ivisurf)
++{
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_get_visibility: invalid argument\n");
++ return false;
++ }
++
++ return ivisurf->prop.visibility;
++}
++
++int32_t
++ivi_layout_surface_set_opacity(struct ivi_layout_surface *ivisurf,
++ wl_fixed_t opacity)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL ||
++ opacity < wl_fixed_from_double(0.0) ||
++ wl_fixed_from_double(1.0) < opacity) {
++ weston_log("ivi_layout_surface_set_opacity: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->opacity = opacity;
++
++ if (ivisurf->prop.opacity != opacity)
++ ivisurf->event_mask |= IVI_NOTIFICATION_OPACITY;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_OPACITY;
++
++ return IVI_SUCCEEDED;
++}
++
++wl_fixed_t
++ivi_layout_surface_get_opacity(struct ivi_layout_surface *ivisurf)
++{
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_get_opacity: invalid argument\n");
++ return wl_fixed_from_double(0.0);
++ }
++
++ return ivisurf->prop.opacity;
++}
++
++int32_t
++ivi_layout_surface_set_destination_rectangle(struct ivi_layout_surface *ivisurf,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_set_destination_rectangle: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->start_x = prop->dest_x;
++ prop->start_y = prop->dest_y;
++ prop->dest_x = x;
++ prop->dest_y = y;
++ prop->start_width = prop->dest_width;
++ prop->start_height = prop->dest_height;
++ prop->dest_width = width;
++ prop->dest_height = height;
++
++ if (ivisurf->prop.dest_x != x || ivisurf->prop.dest_y != y ||
++ ivisurf->prop.dest_width != width ||
++ ivisurf->prop.dest_height != height)
++ ivisurf->event_mask |= IVI_NOTIFICATION_DEST_RECT;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_DEST_RECT;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_surface_set_dimension(struct ivi_layout_surface *ivisurf,
++ int32_t dest_width, int32_t dest_height)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_set_dimension: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->dest_width = dest_width;
++ prop->dest_height = dest_height;
++
++ if (ivisurf->prop.dest_width != dest_width ||
++ ivisurf->prop.dest_height != dest_height)
++ ivisurf->event_mask |= IVI_NOTIFICATION_DIMENSION;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_DIMENSION;
++
++ return IVI_SUCCEEDED;
++}
++
++int32_t
++ivi_layout_surface_get_dimension(struct ivi_layout_surface *ivisurf,
++ int32_t *dest_width, int32_t *dest_height)
++{
++ if (ivisurf == NULL || dest_width == NULL || dest_height == NULL) {
++ weston_log("ivi_layout_surface_get_dimension: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ *dest_width = ivisurf->prop.dest_width;
++ *dest_height = ivisurf->prop.dest_height;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_surface_set_position(struct ivi_layout_surface *ivisurf,
++ int32_t dest_x, int32_t dest_y)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_set_position: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->dest_x = dest_x;
++ prop->dest_y = dest_y;
++
++ if (ivisurf->prop.dest_x != dest_x || ivisurf->prop.dest_y != dest_y)
++ ivisurf->event_mask |= IVI_NOTIFICATION_POSITION;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_POSITION;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_surface_get_position(struct ivi_layout_surface *ivisurf,
++ int32_t *dest_x, int32_t *dest_y)
++{
++ if (ivisurf == NULL || dest_x == NULL || dest_y == NULL) {
++ weston_log("ivi_layout_surface_get_position: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ *dest_x = ivisurf->prop.dest_x;
++ *dest_y = ivisurf->prop.dest_y;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_surface_set_orientation(struct ivi_layout_surface *ivisurf,
++ enum wl_output_transform orientation)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_set_orientation: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->orientation = orientation;
++
++ if (ivisurf->prop.orientation != orientation)
++ ivisurf->event_mask |= IVI_NOTIFICATION_ORIENTATION;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_ORIENTATION;
++
++ return IVI_SUCCEEDED;
++}
++
++static enum wl_output_transform
++ivi_layout_surface_get_orientation(struct ivi_layout_surface *ivisurf)
++{
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_get_orientation: invalid argument\n");
++ return 0;
++ }
++
++ return ivisurf->prop.orientation;
++}
++
++static int32_t
++ivi_layout_screen_add_layer(struct ivi_layout_screen *iviscrn,
++ struct ivi_layout_layer *addlayer)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_layer *ivilayer = NULL;
++ struct ivi_layout_layer *next = NULL;
++ int is_layer_in_scrn = 0;
++
++ if (iviscrn == NULL || addlayer == NULL) {
++ weston_log("ivi_layout_screen_add_layer: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ is_layer_in_scrn = is_layer_in_screen(addlayer, iviscrn);
++ if (is_layer_in_scrn == 1) {
++ weston_log("ivi_layout_screen_add_layer: addlayer is already available\n");
++ return IVI_SUCCEEDED;
++ }
++
++ wl_list_for_each_safe(ivilayer, next, &layout->layer_list, link) {
++ if (ivilayer->id_layer == addlayer->id_layer) {
++ wl_list_remove(&ivilayer->pending.link);
++ wl_list_insert(&iviscrn->pending.layer_list,
++ &ivilayer->pending.link);
++ break;
++ }
++ }
++
++ iviscrn->order.dirty = 1;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_screen_set_render_order(struct ivi_layout_screen *iviscrn,
++ struct ivi_layout_layer **pLayer,
++ const int32_t number)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_layer *ivilayer = NULL;
++ struct ivi_layout_layer *next = NULL;
++ uint32_t *id_layer = NULL;
++ int32_t i = 0;
++
++ if (iviscrn == NULL) {
++ weston_log("ivi_layout_screen_set_render_order: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ wl_list_for_each_safe(ivilayer, next,
++ &iviscrn->pending.layer_list, pending.link) {
++ wl_list_remove(&ivilayer->pending.link);
++ wl_list_init(&ivilayer->pending.link);
++ }
++
++ assert(wl_list_empty(&iviscrn->pending.layer_list));
++
++ for (i = 0; i < number; i++) {
++ id_layer = &pLayer[i]->id_layer;
++ wl_list_for_each(ivilayer, &layout->layer_list, link) {
++ if (*id_layer != ivilayer->id_layer) {
++ continue;
++ }
++
++ wl_list_remove(&ivilayer->pending.link);
++ wl_list_insert(&iviscrn->pending.layer_list,
++ &ivilayer->pending.link);
++ break;
++ }
++ }
++
++ iviscrn->order.dirty = 1;
++
++ return IVI_SUCCEEDED;
++}
++
++static struct weston_output *
++ivi_layout_screen_get_output(struct ivi_layout_screen *iviscrn)
++{
++ return iviscrn->output;
++}
++
++/**
++ * This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
++ * The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
++ * This function is used to get the result of drawing by clients.
++ */
++static struct weston_surface *
++ivi_layout_surface_get_weston_surface(struct ivi_layout_surface *ivisurf)
++{
++ return ivisurf != NULL ? ivisurf->surface : NULL;
++}
++
++static int32_t
++ivi_layout_surface_get_size(struct ivi_layout_surface *ivisurf,
++ int32_t *width, int32_t *height,
++ int32_t *stride)
++{
++ int32_t w;
++ int32_t h;
++ const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
++
++ if (ivisurf == NULL || ivisurf->surface == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return IVI_FAILED;
++ }
++
++ weston_surface_get_content_size(ivisurf->surface, &w, &h);
++
++ if (width != NULL)
++ *width = w;
++
++ if (height != NULL)
++ *height = h;
++
++ if (stride != NULL)
++ *stride = w * bytespp;
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_layer_add_notification(struct ivi_layout_layer *ivilayer,
++ layer_property_notification_func callback,
++ void *userdata)
++{
++ struct ivi_layout_notification_callback *prop_callback = NULL;
++
++ if (ivilayer == NULL || callback == NULL) {
++ weston_log("ivi_layout_layer_add_notification: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop_callback = malloc(sizeof *prop_callback);
++ if (prop_callback == NULL) {
++ weston_log("fails to allocate memory\n");
++ return IVI_FAILED;
++ }
++
++ prop_callback->callback = callback;
++ prop_callback->data = userdata;
++
++ return add_notification(&ivilayer->property_changed,
++ layer_prop_changed,
++ prop_callback);
++}
++
++static const struct ivi_layout_surface_properties *
++ivi_layout_get_properties_of_surface(struct ivi_layout_surface *ivisurf)
++{
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_get_properties_of_surface: invalid argument\n");
++ return NULL;
++ }
++
++ return &ivisurf->prop;
++}
++
++static int32_t
++ivi_layout_layer_add_surface(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *addsurf)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_surface *next = NULL;
++ int is_surf_in_layer = 0;
++
++ if (ivilayer == NULL || addsurf == NULL) {
++ weston_log("ivi_layout_layer_add_surface: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ is_surf_in_layer = is_surface_in_layer(addsurf, ivilayer);
++ if (is_surf_in_layer == 1) {
++ weston_log("ivi_layout_layer_add_surface: addsurf is already available\n");
++ return IVI_SUCCEEDED;
++ }
++
++ wl_list_for_each_safe(ivisurf, next, &layout->surface_list, link) {
++ if (ivisurf->id_surface == addsurf->id_surface) {
++ wl_list_remove(&ivisurf->pending.link);
++ wl_list_insert(&ivilayer->pending.surface_list,
++ &ivisurf->pending.link);
++ break;
++ }
++ }
++
++ ivilayer->order.dirty = 1;
++
++ return IVI_SUCCEEDED;
++}
++
++static void
++ivi_layout_layer_remove_surface(struct ivi_layout_layer *ivilayer,
++ struct ivi_layout_surface *remsurf)
++{
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct ivi_layout_surface *next = NULL;
++
++ if (ivilayer == NULL || remsurf == NULL) {
++ weston_log("ivi_layout_layer_remove_surface: invalid argument\n");
++ return;
++ }
++
++ wl_list_for_each_safe(ivisurf, next,
++ &ivilayer->pending.surface_list, pending.link) {
++ if (ivisurf->id_surface == remsurf->id_surface) {
++ wl_list_remove(&ivisurf->pending.link);
++ wl_list_init(&ivisurf->pending.link);
++ break;
++ }
++ }
++
++ ivilayer->order.dirty = 1;
++}
++
++static int32_t
++ivi_layout_surface_set_source_rectangle(struct ivi_layout_surface *ivisurf,
++ int32_t x, int32_t y,
++ int32_t width, int32_t height)
++{
++ struct ivi_layout_surface_properties *prop = NULL;
++
++ if (ivisurf == NULL) {
++ weston_log("ivi_layout_surface_set_source_rectangle: invalid argument\n");
++ return IVI_FAILED;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->source_x = x;
++ prop->source_y = y;
++ prop->source_width = width;
++ prop->source_height = height;
++
++ if (ivisurf->prop.source_x != x || ivisurf->prop.source_y != y ||
++ ivisurf->prop.source_width != width ||
++ ivisurf->prop.source_height != height)
++ ivisurf->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
++ else
++ ivisurf->event_mask &= ~IVI_NOTIFICATION_SOURCE_RECT;
++
++ return IVI_SUCCEEDED;
++}
++
++int32_t
++ivi_layout_commit_changes(void)
++{
++ struct ivi_layout *layout = get_instance();
++
++ commit_surface_list(layout);
++ commit_layer_list(layout);
++ commit_screen_list(layout);
++
++ commit_transition(layout);
++
++ commit_changes(layout);
++ send_prop(layout);
++ weston_compositor_schedule_repaint(layout->compositor);
++
++ return IVI_SUCCEEDED;
++}
++
++static int32_t
++ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer,
++ enum ivi_layout_transition_type type,
++ uint32_t duration)
++{
++ if (ivilayer == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return -1;
++ }
++
++ ivilayer->pending.prop.transition_type = type;
++ ivilayer->pending.prop.transition_duration = duration;
++
++ return 0;
++}
++
++static int32_t
++ivi_layout_layer_set_fade_info(struct ivi_layout_layer* ivilayer,
++ uint32_t is_fade_in,
++ double start_alpha, double end_alpha)
++{
++ if (ivilayer == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return -1;
++ }
++
++ ivilayer->pending.prop.is_fade_in = is_fade_in;
++ ivilayer->pending.prop.start_alpha = start_alpha;
++ ivilayer->pending.prop.end_alpha = end_alpha;
++
++ return 0;
++}
++
++static int32_t
++ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf,
++ uint32_t duration)
++{
++ struct ivi_layout_surface_properties *prop;
++
++ if (ivisurf == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return -1;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->transition_duration = duration*10;
++ return 0;
++}
++
++static int32_t
++ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf,
++ enum ivi_layout_transition_type type,
++ uint32_t duration)
++{
++ struct ivi_layout_surface_properties *prop;
++
++ if (ivisurf == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return -1;
++ }
++
++ prop = &ivisurf->pending.prop;
++ prop->transition_type = type;
++ prop->transition_duration = duration;
++ return 0;
++}
++
++static int32_t
++ivi_layout_surface_dump(struct weston_surface *surface,
++ void *target, size_t size,int32_t x, int32_t y,
++ int32_t width, int32_t height)
++{
++ int result = 0;
++
++ if (surface == NULL) {
++ weston_log("%s: invalid argument\n", __func__);
++ return IVI_FAILED;
++ }
++
++ result = weston_surface_copy_content(
++ surface, target, size,
++ x, y, width, height);
++
++ return result == 0 ? IVI_SUCCEEDED : IVI_FAILED;
++}
++
++/**
++ * methods of interaction between ivi-shell with ivi-layout
++ */
++struct weston_view *
++ivi_layout_get_weston_view(struct ivi_layout_surface *surface)
++{
++ struct weston_view *tmpview = NULL;
++
++ if (surface == NULL)
++ return NULL;
++
++ wl_list_for_each(tmpview, &surface->surface->views, surface_link)
++ {
++ if (tmpview != NULL) {
++ break;
++ }
++ }
++ return tmpview;
++}
++
++void
++ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf,
++ int32_t width, int32_t height)
++{
++ struct ivi_layout *layout = get_instance();
++
++ /* emit callback which is set by ivi-layout api user */
++ wl_signal_emit(&layout->surface_notification.configure_changed,
++ ivisurf);
++}
++
++static int32_t
++ivi_layout_surface_set_content_observer(struct ivi_layout_surface *ivisurf,
++ ivi_controller_surface_content_callback callback,
++ void* userdata)
++{
++ int32_t ret = IVI_FAILED;
++
++ if (ivisurf != NULL) {
++ ivisurf->content_observer.callback = callback;
++ ivisurf->content_observer.userdata = userdata;
++ ret = IVI_SUCCEEDED;
++ }
++ return ret;
++}
++
++struct ivi_layout_surface*
++ivi_layout_surface_create(struct weston_surface *wl_surface,
++ uint32_t id_surface)
++{
++ struct ivi_layout *layout = get_instance();
++ struct ivi_layout_surface *ivisurf = NULL;
++ struct weston_view *tmpview = NULL;
++
++ if (wl_surface == NULL) {
++ weston_log("ivi_layout_surface_create: invalid argument\n");
++ return NULL;
++ }
++
++ ivisurf = get_surface(&layout->surface_list, id_surface);
++ if (ivisurf != NULL) {
++ if (ivisurf->surface != NULL) {
++ weston_log("id_surface(%d) is already created\n", id_surface);
++ return NULL;
++ }
++ }
++
++ ivisurf = calloc(1, sizeof *ivisurf);
++ if (ivisurf == NULL) {
++ weston_log("fails to allocate memory\n");
++ return NULL;
++ }
++
++ wl_signal_init(&ivisurf->property_changed);
++ wl_signal_init(&ivisurf->configured);
++ wl_list_init(&ivisurf->layer_list);
++ ivisurf->id_surface = id_surface;
++ ivisurf->layout = layout;
++
++ ivisurf->surface = wl_surface;
++
++ tmpview = weston_view_create(wl_surface);
++ if (tmpview == NULL) {
++ weston_log("fails to allocate memory\n");
++ }
++
++ ivisurf->surface->width_from_buffer = 0;
++ ivisurf->surface->height_from_buffer = 0;
++
++ weston_matrix_init(&ivisurf->transform.matrix);
++ wl_list_init(&ivisurf->transform.link);
++
++ init_surface_properties(&ivisurf->prop);
++ ivisurf->event_mask = 0;
++
++ ivisurf->pending.prop = ivisurf->prop;
++ wl_list_init(&ivisurf->pending.link);
++
++ wl_list_init(&ivisurf->order.link);
++ wl_list_init(&ivisurf->order.layer_list);
++
++ wl_list_insert(&layout->surface_list, &ivisurf->link);
++
++ wl_signal_emit(&layout->surface_notification.created, ivisurf);
++
++ return ivisurf;
++}
++
++void
++ivi_layout_init_with_compositor(struct weston_compositor *ec)
++{
++ struct ivi_layout *layout = get_instance();
++
++ layout->compositor = ec;
++
++ wl_list_init(&layout->surface_list);
++ wl_list_init(&layout->layer_list);
++ wl_list_init(&layout->screen_list);
++
++ wl_signal_init(&layout->layer_notification.created);
++ wl_signal_init(&layout->layer_notification.removed);
++
++ wl_signal_init(&layout->surface_notification.created);
++ wl_signal_init(&layout->surface_notification.removed);
++ wl_signal_init(&layout->surface_notification.configure_changed);
++
++ /* Add layout_layer at the last of weston_compositor.layer_list */
++ weston_layer_init(&layout->layout_layer, ec->layer_list.prev);
++
++ create_screen(ec);
++
++ layout->transitions = ivi_layout_transition_set_create(ec);
++ wl_list_init(&layout->pending_transition_list);
++}
++
++
++void
++ivi_layout_surface_add_configured_listener(struct ivi_layout_surface* ivisurf,
++ struct wl_listener* listener)
++{
++ wl_signal_add(&ivisurf->configured, listener);
++}
++
++static struct ivi_controller_interface ivi_controller_interface = {
++ /**
++ * commit all changes
++ */
++ .commit_changes = ivi_layout_commit_changes,
++
++ /**
++ * surface controller interfaces
++ */
++ .add_notification_create_surface = ivi_layout_add_notification_create_surface,
++ .remove_notification_create_surface = ivi_layout_remove_notification_create_surface,
++ .add_notification_remove_surface = ivi_layout_add_notification_remove_surface,
++ .remove_notification_remove_surface = ivi_layout_remove_notification_remove_surface,
++ .add_notification_configure_surface = ivi_layout_add_notification_configure_surface,
++ .remove_notification_configure_surface = ivi_layout_remove_notification_configure_surface,
++ .get_surfaces = ivi_layout_get_surfaces,
++ .get_id_of_surface = ivi_layout_get_id_of_surface,
++ .get_surface_from_id = ivi_layout_get_surface_from_id,
++ .get_properties_of_surface = ivi_layout_get_properties_of_surface,
++ .get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
++ .surface_set_visibility = ivi_layout_surface_set_visibility,
++ .surface_get_visibility = ivi_layout_surface_get_visibility,
++ .surface_set_opacity = ivi_layout_surface_set_opacity,
++ .surface_get_opacity = ivi_layout_surface_get_opacity,
++ .surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
++ .surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
++ .surface_set_position = ivi_layout_surface_set_position,
++ .surface_get_position = ivi_layout_surface_get_position,
++ .surface_set_dimension = ivi_layout_surface_set_dimension,
++ .surface_get_dimension = ivi_layout_surface_get_dimension,
++ .surface_set_orientation = ivi_layout_surface_set_orientation,
++ .surface_get_orientation = ivi_layout_surface_get_orientation,
++ .surface_set_content_observer = ivi_layout_surface_set_content_observer,
++ .surface_add_notification = ivi_layout_surface_add_notification,
++ .surface_remove_notification = ivi_layout_surface_remove_notification,
++ .surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
++ .surface_set_transition = ivi_layout_surface_set_transition,
++ .surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
++
++ /**
++ * layer controller interfaces
++ */
++ .add_notification_create_layer = ivi_layout_add_notification_create_layer,
++ .remove_notification_create_layer = ivi_layout_remove_notification_create_layer,
++ .add_notification_remove_layer = ivi_layout_add_notification_remove_layer,
++ .remove_notification_remove_layer = ivi_layout_remove_notification_remove_layer,
++ .layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
++ .layer_destroy = ivi_layout_layer_destroy,
++ .get_layers = ivi_layout_get_layers,
++ .get_id_of_layer = ivi_layout_get_id_of_layer,
++ .get_layer_from_id = ivi_layout_get_layer_from_id,
++ .get_properties_of_layer = ivi_layout_get_properties_of_layer,
++ .get_layers_under_surface = ivi_layout_get_layers_under_surface,
++ .get_layers_on_screen = ivi_layout_get_layers_on_screen,
++ .layer_set_visibility = ivi_layout_layer_set_visibility,
++ .layer_get_visibility = ivi_layout_layer_get_visibility,
++ .layer_set_opacity = ivi_layout_layer_set_opacity,
++ .layer_get_opacity = ivi_layout_layer_get_opacity,
++ .layer_set_source_rectangle = ivi_layout_layer_set_source_rectangle,
++ .layer_set_destination_rectangle = ivi_layout_layer_set_destination_rectangle,
++ .layer_set_position = ivi_layout_layer_set_position,
++ .layer_get_position = ivi_layout_layer_get_position,
++ .layer_set_dimension = ivi_layout_layer_set_dimension,
++ .layer_get_dimension = ivi_layout_layer_get_dimension,
++ .layer_set_orientation = ivi_layout_layer_set_orientation,
++ .layer_get_orientation = ivi_layout_layer_get_orientation,
++ .layer_add_surface = ivi_layout_layer_add_surface,
++ .layer_remove_surface = ivi_layout_layer_remove_surface,
++ .layer_set_render_order = ivi_layout_layer_set_render_order,
++ .layer_add_notification = ivi_layout_layer_add_notification,
++ .layer_remove_notification = ivi_layout_layer_remove_notification,
++ .layer_set_transition = ivi_layout_layer_set_transition,
++
++ /**
++ * screen controller interfaces part1
++ */
++ .get_screen_from_id = ivi_layout_get_screen_from_id,
++ .get_screen_resolution = ivi_layout_get_screen_resolution,
++ .get_screens = ivi_layout_get_screens,
++ .get_screens_under_layer = ivi_layout_get_screens_under_layer,
++ .screen_add_layer = ivi_layout_screen_add_layer,
++ .screen_set_render_order = ivi_layout_screen_set_render_order,
++ .screen_get_output = ivi_layout_screen_get_output,
++
++ /**
++ * animation
++ */
++ .transition_move_layer_cancel = ivi_layout_transition_move_layer_cancel,
++ .layer_set_fade_info = ivi_layout_layer_set_fade_info,
++
++ /**
++ * surface content dumping for debugging
++ */
++ .surface_get_size = ivi_layout_surface_get_size,
++ .surface_dump = ivi_layout_surface_dump,
++
++ /**
++ * remove notification by callback on property changes of ivi_surface/layer
++ */
++ .surface_remove_notification_by_callback = ivi_layout_surface_remove_notification_by_callback,
++ .layer_remove_notification_by_callback = ivi_layout_layer_remove_notification_by_callback,
++
++ /**
++ * screen controller interfaces part2
++ */
++ .get_id_of_screen = ivi_layout_get_id_of_screen
++};
++
++int
++load_controller_modules(struct weston_compositor *compositor, const char *modules,
++ int *argc, char *argv[])
++{
++ const char *p, *end;
++ char buffer[256];
++ int (*controller_module_init)(struct weston_compositor *compositor,
++ int *argc, char *argv[],
++ const struct ivi_controller_interface *interface,
++ size_t interface_version);
++
++ if (modules == NULL)
++ return 0;
++
++ p = modules;
++ while (*p) {
++ end = strchrnul(p, ',');
++ snprintf(buffer, sizeof buffer, "%.*s", (int)(end - p), p);
++
++ controller_module_init = weston_load_module(buffer, "controller_module_init");
++ if (!controller_module_init)
++ return -1;
++
++ if (controller_module_init(compositor, argc, argv,
++ &ivi_controller_interface,
++ sizeof(struct ivi_controller_interface)) != 0) {
++ weston_log("ivi-shell: Initialization of controller module fails");
++ return -1;
++ }
++
++ p = end;
++ while (*p == ',')
++ p++;
++ }
++
++ return 0;
++}
+diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
+new file mode 100644
+index 0000000..220a508
+--- /dev/null
++++ b/ivi-shell/ivi-shell.c
+@@ -0,0 +1,469 @@
++/*
++ * Copyright (C) 2013 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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.
++ */
++
++/*
++ * ivi-shell supports a type of shell for In-Vehicle Infotainment system.
++ * In-Vehicle Infotainment system traditionally manages surfaces with global
++ * identification. A protocol, ivi_application, supports such a feature
++ * by implementing a request, ivi_application::surface_creation defined in
++ * ivi_application.xml.
++ *
++ * The ivi-shell explicitly loads a module to add business logic like how to
++ * layout surfaces by using internal ivi-layout APIs.
++ */
++#include "config.h"
++
++#include <string.h>
++#include <dlfcn.h>
++#include <limits.h>
++#include <assert.h>
++#include <linux/input.h>
++
++#include "ivi-shell.h"
++#include "ivi-application-server-protocol.h"
++#include "ivi-layout-export.h"
++#include "ivi-layout-private.h"
++#include "shared/helpers.h"
++
++/* Representation of ivi_surface protocol object. */
++struct ivi_shell_surface
++{
++ struct wl_resource* resource;
++ struct ivi_shell *shell;
++ struct ivi_layout_surface *layout_surface;
++
++ struct weston_surface *surface;
++ struct wl_listener surface_destroy_listener;
++
++ uint32_t id_surface;
++
++ int32_t width;
++ int32_t height;
++
++ struct wl_list link;
++
++ struct wl_listener configured_listener;
++};
++
++struct ivi_shell_setting
++{
++ char *ivi_module;
++ int developermode;
++};
++
++/*
++ * Implementation of ivi_surface
++ */
++
++static void
++surface_configure_notify(struct wl_listener *listener, void *data)
++{
++ struct ivi_layout_surface *layout_surf =
++ (struct ivi_layout_surface *)data;
++
++ struct ivi_shell_surface *shell_surf =
++ container_of(listener,
++ struct ivi_shell_surface,
++ configured_listener);
++
++ int32_t dest_width = 0;
++ int32_t dest_height = 0;
++
++ ivi_layout_surface_get_dimension(layout_surf,
++ &dest_width, &dest_height);
++
++ if (shell_surf->resource)
++ ivi_surface_send_configure(shell_surf->resource,
++ dest_width, dest_height);
++}
++
++static void
++ivi_shell_surface_configure(struct weston_surface *, int32_t, int32_t);
++
++static struct ivi_shell_surface *
++get_ivi_shell_surface(struct weston_surface *surface)
++{
++ if (surface->configure == ivi_shell_surface_configure)
++ return surface->configure_private;
++
++ return NULL;
++}
++
++static void
++ivi_shell_surface_configure(struct weston_surface *surface,
++ int32_t sx, int32_t sy)
++{
++ struct ivi_shell_surface *ivisurf = get_ivi_shell_surface(surface);
++
++ if (surface->width == 0 || surface->height == 0 || ivisurf == NULL)
++ return;
++
++ if (ivisurf->width != surface->width ||
++ ivisurf->height != surface->height) {
++ ivisurf->width = surface->width;
++ ivisurf->height = surface->height;
++
++ ivi_layout_surface_configure(ivisurf->layout_surface,
++ surface->width, surface->height);
++ }
++}
++
++static void
++layout_surface_cleanup(struct ivi_shell_surface *ivisurf)
++{
++ assert(ivisurf->layout_surface != NULL);
++
++ ivi_layout_surface_destroy(ivisurf->layout_surface);
++ ivisurf->layout_surface = NULL;
++
++ ivisurf->surface->configure = NULL;
++ ivisurf->surface->configure_private = NULL;
++ ivisurf->surface = NULL;
++
++ // destroy weston_surface destroy signal.
++ wl_list_remove(&ivisurf->surface_destroy_listener.link);
++}
++
++/*
++ * The ivi_surface wl_resource destructor.
++ *
++ * Gets called via ivi_surface.destroy request or automatic wl_client clean-up.
++ */
++static void
++shell_destroy_shell_surface(struct wl_resource *resource)
++{
++ struct ivi_shell_surface *ivisurf = wl_resource_get_user_data(resource);
++
++ if (ivisurf == NULL)
++ return;
++
++ assert(ivisurf->resource == resource);
++
++ if (ivisurf->layout_surface != NULL)
++ layout_surface_cleanup(ivisurf);
++
++ wl_list_remove(&ivisurf->link);
++
++ free(ivisurf);
++}
++
++/* Gets called through the weston_surface destroy signal. */
++static void
++shell_handle_surface_destroy(struct wl_listener *listener, void *data)
++{
++ struct ivi_shell_surface *ivisurf =
++ container_of(listener, struct ivi_shell_surface,
++ surface_destroy_listener);
++
++ assert(ivisurf != NULL);
++
++ if (ivisurf->layout_surface != NULL)
++ layout_surface_cleanup(ivisurf);
++}
++
++/* Gets called, when a client sends ivi_surface.destroy request. */
++static void
++surface_destroy(struct wl_client *client, struct wl_resource *resource)
++{
++ /*
++ * Fires the wl_resource destroy signal, and then calls
++ * ivi_surface wl_resource destructor: shell_destroy_shell_surface()
++ */
++ wl_resource_destroy(resource);
++}
++
++static const struct ivi_surface_interface surface_implementation = {
++ surface_destroy,
++};
++
++/**
++ * Request handler for ivi_application.surface_create.
++ *
++ * Creates an ivi_surface protocol object associated with the given wl_surface.
++ * ivi_surface protocol object is represented by struct ivi_shell_surface.
++ *
++ * \param client The client.
++ * \param resource The ivi_application protocol object.
++ * \param id_surface The IVI surface ID.
++ * \param surface_resource The wl_surface protocol object.
++ * \param id The protocol object id for the new ivi_surface protocol object.
++ *
++ * The wl_surface is given the ivi_surface role and associated with a unique
++ * IVI ID which is used to identify the surface in a controller
++ * (window manager).
++ */
++static void
++application_surface_create(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id_surface,
++ struct wl_resource *surface_resource,
++ uint32_t id)
++{
++ struct ivi_shell *shell = wl_resource_get_user_data(resource);
++ struct ivi_shell_surface *ivisurf;
++ struct ivi_layout_surface *layout_surface;
++ struct weston_surface *weston_surface =
++ wl_resource_get_user_data(surface_resource);
++ struct wl_resource *res;
++
++ /* check if a surface already has another role */
++ if (weston_surface->configure) {
++ wl_resource_post_error(weston_surface->resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "surface->configure already "
++ "set");
++ return;
++ }
++
++ layout_surface = ivi_layout_surface_create(weston_surface, id_surface);
++
++ /* check if id_ivi is already used for wl_surface*/
++ if (layout_surface == NULL) {
++ wl_resource_post_error(resource,
++ IVI_APPLICATION_ERROR_IVI_ID,
++ "surface_id is already assigned "
++ "by another app");
++ return;
++ }
++
++ ivisurf = zalloc(sizeof *ivisurf);
++ if (ivisurf == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ wl_list_init(&ivisurf->link);
++ wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
++
++ ivisurf->shell = shell;
++ ivisurf->id_surface = id_surface;
++
++ ivisurf->width = 0;
++ ivisurf->height = 0;
++ ivisurf->layout_surface = layout_surface;
++ ivisurf->configured_listener.notify = surface_configure_notify;
++ ivi_layout_surface_add_configured_listener(layout_surface,
++ &ivisurf->configured_listener);
++ /*
++ * The following code relies on wl_surface destruction triggering
++ * immediateweston_surface destruction
++ */
++ ivisurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
++ wl_signal_add(&weston_surface->destroy_signal,
++ &ivisurf->surface_destroy_listener);
++
++ ivisurf->surface = weston_surface;
++
++ weston_surface->configure = ivi_shell_surface_configure;
++ weston_surface->configure_private = ivisurf;
++
++ res = wl_resource_create(client, &ivi_surface_interface, 1, id);
++ if (res == NULL) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ ivisurf->resource = res;
++
++ wl_resource_set_implementation(res, &surface_implementation,
++ ivisurf, shell_destroy_shell_surface);
++}
++
++static const struct ivi_application_interface application_implementation = {
++ application_surface_create
++};
++
++/*
++ * Handle wl_registry.bind of ivi_application global singleton.
++ */
++static void
++bind_ivi_application(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct ivi_shell *shell = data;
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client, &ivi_application_interface,
++ 1, id);
++
++ wl_resource_set_implementation(resource,
++ &application_implementation,
++ shell, NULL);
++}
++
++struct weston_view *
++get_default_view(struct weston_surface *surface)
++{
++ struct ivi_shell_surface *shsurf;
++ struct weston_view *view;
++
++ if (!surface || wl_list_empty(&surface->views))
++ return NULL;
++
++ shsurf = get_ivi_shell_surface(surface);
++ if (shsurf && shsurf->layout_surface) {
++ view = ivi_layout_get_weston_view(shsurf->layout_surface);
++ if (view)
++ return view;
++ }
++
++ wl_list_for_each(view, &surface->views, surface_link) {
++ if (weston_view_is_mapped(view))
++ return view;
++ }
++
++ return container_of(surface->views.next,
++ struct weston_view, surface_link);
++}
++
++/*
++ * Called through the compositor's destroy signal.
++ */
++static void
++shell_destroy(struct wl_listener *listener, void *data)
++{
++ struct ivi_shell *shell =
++ container_of(listener, struct ivi_shell, destroy_listener);
++ struct ivi_shell_surface *ivisurf, *next;
++
++ input_panel_destroy(shell);
++
++ wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
++ wl_list_remove(&ivisurf->link);
++ free(ivisurf);
++ }
++
++ free(shell);
++}
++
++static void
++terminate_binding(struct weston_seat *seat, uint32_t time,
++ uint32_t key, void *data)
++{
++ struct weston_compositor *compositor = data;
++
++ wl_display_terminate(compositor->wl_display);
++}
++
++static void
++init_ivi_shell(struct weston_compositor *compositor, struct ivi_shell *shell,
++ const struct ivi_shell_setting *setting)
++{
++ shell->compositor = compositor;
++
++ wl_list_init(&shell->ivi_surface_list);
++
++ weston_layer_init(&shell->input_panel_layer, NULL);
++
++ if (setting->developermode) {
++#if 0
++ weston_install_debug_key_binding(compositor, MODIFIER_SUPER);
++#endif
++
++ weston_compositor_add_key_binding(compositor, KEY_BACKSPACE,
++ MODIFIER_CTRL | MODIFIER_ALT,
++ terminate_binding,
++ compositor);
++ }
++}
++
++static int
++ivi_shell_setting_create(struct ivi_shell_setting *dest,
++ struct weston_compositor *compositor,
++ int *argc, char *argv[])
++{
++ int result = 0;
++ struct weston_config *config = compositor->config;
++ struct weston_config_section *section;
++
++ const struct weston_option ivi_shell_options[] = {
++ { WESTON_OPTION_STRING, "ivi-module", 0, &dest->ivi_module },
++ };
++
++ parse_options(ivi_shell_options, ARRAY_LENGTH(ivi_shell_options),
++ argc, argv);
++
++ section = weston_config_get_section(config, "ivi-shell", NULL, NULL);
++
++ if (!dest->ivi_module &&
++ weston_config_section_get_string(section, "ivi-module",
++ &dest->ivi_module, NULL) < 0) {
++ weston_log("Error: ivi-shell: No ivi-module set\n");
++ result = -1;
++ }
++
++ weston_config_section_get_bool(section, "developermode",
++ &dest->developermode, 0);
++
++ return result;
++}
++
++/*
++ * Initialization of ivi-shell.
++ */
++WL_EXPORT int
++module_init(struct weston_compositor *compositor,
++ int *argc, char *argv[])
++{
++ struct ivi_shell *shell;
++ struct ivi_shell_setting setting = { };
++ int retval = -1;
++
++ shell = zalloc(sizeof *shell);
++ if (shell == NULL)
++ return -1;
++
++ if (ivi_shell_setting_create(&setting, compositor, argc, argv) != 0)
++ return -1;
++
++ init_ivi_shell(compositor, shell, &setting);
++
++ shell->destroy_listener.notify = shell_destroy;
++ wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener);
++
++ if (input_panel_setup(shell) < 0)
++ goto out_settings;
++
++ text_backend_init(compositor);
++
++ if (wl_global_create(compositor->wl_display,
++ &ivi_application_interface, 1,
++ shell, bind_ivi_application) == NULL)
++ goto out_settings;
++
++ ivi_layout_init_with_compositor(compositor);
++
++ /* Call module_init of ivi-modules which are defined in weston.ini */
++ if (load_controller_modules(compositor, setting.ivi_module,
++ argc, argv) < 0)
++ goto out_settings;
++
++ retval = 0;
++
++out_settings:
++ free(setting.ivi_module);
++
++ return retval;
++}
+diff --git a/ivi-shell/ivi-shell.h b/ivi-shell/ivi-shell.h
+new file mode 100644
+index 0000000..9a05eb2
+--- /dev/null
++++ b/ivi-shell/ivi-shell.h
+@@ -0,0 +1,67 @@
++/*
++ * Copyright (C) 2013 DENSO CORPORATION
++ *
++ * 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 (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * 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 OR COPYRIGHT HOLDERS
++ * 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 <stdbool.h>
++
++#include "compositor.h"
++
++struct ivi_shell
++{
++ struct wl_listener destroy_listener;
++
++ struct weston_compositor *compositor;
++
++ struct wl_list ivi_surface_list; /* struct ivi_shell_surface::link */
++
++ struct text_backend *text_backend;
++
++ struct wl_listener show_input_panel_listener;
++ struct wl_listener hide_input_panel_listener;
++ struct wl_listener update_input_panel_listener;
++
++ struct weston_layer input_panel_layer;
++
++ bool locked;
++ bool showing_input_panels;
++
++ struct {
++ struct weston_surface *surface;
++ pixman_box32_t cursor_rectangle;
++ } text_input;
++
++ struct {
++ struct wl_resource *binding;
++ struct wl_list surfaces;
++ } input_panel;
++};
++
++struct weston_view *
++get_default_view(struct weston_surface *surface);
++
++int
++input_panel_setup(struct ivi_shell *shell);
++
++void
++input_panel_destroy(struct ivi_shell *shell);
+diff --git a/ivi-shell/weston.ini.in b/ivi-shell/weston.ini.in
+new file mode 100644
+index 0000000..6c22633
+--- /dev/null
++++ b/ivi-shell/weston.ini.in
+@@ -0,0 +1,98 @@
++[core]
++shell=@plugin_prefix@ivi-shell.so
++
++[ivi-shell]
++ivi-module=@plugin_prefix@hmi-controller.so
++ivi-shell-user-interface=@abs_top_builddir@/weston-ivi-shell-user-interface
++
++#developermode=true
++
++cursor-theme=default
++cursor-size=32
++
++base-layer-id=1000
++workspace-background-layer-id=2000
++workspace-layer-id=3000
++application-layer-id=4000
++
++transition-duration=300
++
++background-image=@abs_top_srcdir@/data/background.png
++background-id=1001
++panel-image=@abs_top_srcdir@/data/panel.png
++panel-id=1002
++tiling-image=@abs_top_srcdir@/data/tiling.png
++tiling-id=1003
++sidebyside-image=@abs_top_srcdir@/data/sidebyside.png
++sidebyside-id=1004
++fullscreen-image=@abs_top_srcdir@/data/fullscreen.png
++fullscreen-id=1005
++random-image=@abs_top_srcdir@/data/random.png
++random-id=1006
++home-image=@abs_top_srcdir@/data/home.png
++home-id=1007
++workspace-background-color=0x99000000
++workspace-background-id=2001
++
++[input-method]
++path=@libexecdir@/weston-keyboard
++
++[ivi-launcher]
++workspace-id=0
++icon-id=4001
++icon=@abs_top_srcdir@/data/icon_ivi_flower.png
++path=@abs_top_builddir@/weston-flower
++
++[ivi-launcher]
++workspace-id=0
++icon-id=4002
++icon=@abs_top_srcdir@/data/icon_ivi_clickdot.png
++path=@abs_top_builddir@/weston-clickdot
++
++[ivi-launcher]
++workspace-id=1
++icon-id=4003
++icon=@abs_top_srcdir@/data/icon_ivi_simple-egl.png
++path=@abs_top_builddir@/weston-simple-egl
++
++[ivi-launcher]
++workspace-id=1
++icon-id=4004
++icon=@abs_top_srcdir@/data/icon_ivi_simple-shm.png
++path=@abs_top_builddir@/weston-simple-shm
++
++[ivi-launcher]
++workspace-id=2
++icon-id=4005
++icon=@abs_top_srcdir@/data/icon_ivi_smoke.png
++path=@abs_top_builddir@/weston-smoke
++
++[ivi-launcher]
++workspace-id=3
++icon-id=4006
++icon=@abs_top_srcdir@/data/icon_ivi_flower.png
++path=@abs_top_builddir@/weston-flower
++
++[ivi-launcher]
++workspace-id=3
++icon-id=4007
++icon=@abs_top_srcdir@/data/icon_ivi_clickdot.png
++path=@abs_top_builddir@/weston-clickdot
++
++[ivi-launcher]
++workspace-id=3
++icon-id=4008
++icon=@abs_top_srcdir@/data/icon_ivi_simple-egl.png
++path=@abs_top_builddir@/weston-simple-egl
++
++[ivi-launcher]
++workspace-id=3
++icon-id=4009
++icon=@abs_top_srcdir@/data/icon_ivi_simple-shm.png
++path=@abs_top_builddir@/weston-simple-shm
++
++[ivi-launcher]
++workspace-id=3
++icon-id=4010
++icon=@abs_top_srcdir@/data/icon_ivi_smoke.png
++path=@abs_top_builddir@/weston-smoke
+diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml
+new file mode 100644
+index 0000000..8f24226
+--- /dev/null
++++ b/protocol/ivi-application.xml
+@@ -0,0 +1,100 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="ivi_application">
++
++ <copyright>
++ Copyright (C) 2013 DENSO CORPORATION
++ Copyright (c) 2013 BMW Car IT GmbH
++
++ 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 (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ 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 OR COPYRIGHT HOLDERS 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.
++ </copyright>
++
++ <interface name="ivi_surface" version="1">
++ <description summary="application interface to surface in ivi compositor"/>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy ivi_surface">
++ This removes link from ivi_id to wl_surface and destroys ivi_surface.
++ The ID, ivi_id, is free and can be used for surface_create again.
++ </description>
++ </request>
++
++ <event name="configure">
++ <description summary="suggest resize">
++ The configure event asks the client to resize its surface.
++
++ The size is a hint, in the sense that the client is free to
++ ignore it if it doesn't resize, pick a smaller size (to
++ satisfy aspect ratio or resize in steps of NxM pixels).
++
++ The client is free to dismiss all but the last configure
++ event it received.
++
++ The width and height arguments specify the size of the window
++ in surface local coordinates.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </event>
++ </interface>
++
++ <interface name="ivi_application" version="1">
++ <description summary="create ivi-style surfaces">
++ This interface is exposed as a global singleton.
++ This interface is implemented by servers that provide IVI-style user interfaces.
++ It allows clients to associate a ivi_surface with wl_surface.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ <entry name="ivi_id" value="1" summary="given ivi_id is assigned to another wl_surface"/>
++ </enum>
++
++ <request name="surface_create">
++ <description summary="create ivi_surface with numeric ID in ivi compositor">
++ This request gives the wl_surface the role of an IVI Surface. Creating more than
++ one ivi_surface for a wl_surface is not allowed. Note, that this still allows the
++ following example:
++
++ 1. create a wl_surface
++ 2. create ivi_surface for the wl_surface
++ 3. destroy the ivi_surface
++ 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before)
++
++ surface_create will create a interface:ivi_surface with numeric ID; ivi_id in
++ ivi compositor. These ivi_ids are defined as unique in the system to identify
++ it inside of ivi compositor. The ivi compositor implements business logic how to
++ set properties of the surface with ivi_id according to status of the system.
++ E.g. a unique ID for Car Navigation application is used for implementing special
++ logic of the application about where it shall be located.
++ The server regards following cases as protocol errors and disconnects the client.
++ - wl_surface already has an nother role.
++ - ivi_id is already assigned to an another wl_surface.
++
++ If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface,
++ ivi_id which is assigned to the ivi_surface is free for reuse.
++ </description>
++ <arg name="ivi_id" type="uint"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="id" type="new_id" interface="ivi_surface"/>
++ </request>
++
++ </interface>
++
++</protocol>
+diff --git a/protocol/ivi-hmi-controller.xml b/protocol/ivi-hmi-controller.xml
+new file mode 100644
+index 0000000..826763c
+--- /dev/null
++++ b/protocol/ivi-hmi-controller.xml
+@@ -0,0 +1,98 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="ivi_hmi_controller">
++
++ <copyright>
++ Copyright (C) 2013 DENSO CORPORATION
++ Copyright (c) 2013 BMW Car IT GmbH
++
++ 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 (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ 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 OR COPYRIGHT HOLDERS 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.
++ </copyright>
++
++ <interface name="ivi_hmi_controller" version="1">
++ <description summary="set up and control IVI style UI"/>
++
++ <request name="UI_ready">
++ <description summary="inform the ready for drawing desktop." />
++ </request>
++
++ <request name="workspace_control">
++ <description summary="start controlling a surface by server">
++ Reference protocol to control a surface by server.
++ To control a surface by server, it gives seat to the server
++ to e.g. control Home screen. Home screen has several workspaces
++ to group launchers of wayland application. These workspaces
++ are drawn on a horizontally long surface to be controlled
++ by motion of input device. E.g. A motion from right to left
++ happens, the viewport of surface is controlled in the ivi-shell
++ by using ivi-layout. client can recognizes the end of controlling
++ by event "workspace_end_control".
++ </description>
++ <arg name="seat" type="object" interface="wl_seat"/>
++ <arg name="serial" type="uint"/>
++ </request>
++
++ <enum name="layout_mode">
++ <entry name="tiling" value="0"/>
++ <entry name="side_by_side" value="1"/>
++ <entry name="full_screen" value="2"/>
++ <entry name="random" value="3" />
++ </enum>
++
++ <request name="switch_mode">
++ <description summary="request mode switch of application layout">
++ hmi-controller loaded to ivi-shall implements 4 types of layout
++ as a reference; tiling, side by side, full_screen, and random.
++ </description>
++ <arg name="layout_mode" type="uint"/>
++ </request>
++
++ <enum name="home">
++ <entry name="off" value="0"/>
++ <entry name="on" value="1"/>
++ </enum>
++
++ <request name="home">
++ <description summary="request displaying/undisplaying home screen">
++ home screen is a reference implementation of launcher to launch
++ wayland applications. The home screen has several workspaces to
++ group wayland applications. By defining the following keys in
++ weston.ini, user can add launcher icon to launch a wayland application
++ to a workspace.
++ [ivi-launcher]
++ workspace-id=0
++ : id of workspace to add a launcher
++ icon-id=4001
++ : ivi id of ivi_surface to draw a icon
++ icon=/home/user/review/build-ivi-shell/data/icon_ivi_flower.png
++ : path to icon image
++ path=/home/user/review/build-ivi-shell/weston-dnd
++ : path to wayland application
++ </description>
++ <arg name="home" type="uint"/>
++ </request>
++
++ <event name="workspace_end_control">
++ <description summary="notify controlling workspace end"/>
++ <arg name="is_controlled" type="int"/>
++ </event>
++
++ </interface>
++
++</protocol>
+diff --git a/shared/helpers.h b/shared/helpers.h
+new file mode 100644
+index 0000000..1d1e458
+--- /dev/null
++++ b/shared/helpers.h
+@@ -0,0 +1,96 @@
++/*
++ * Copyright © 2015 Samsung Electronics Co., Ltd
++ *
++ * 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 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 OR COPYRIGHT HOLDERS
++ * 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 WESTON_HELPERS_H
++#define WESTON_HELPERS_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @file
++ * Simple misc helper macros.
++ */
++
++/**
++ * Compile-time computation of number of items in a hardcoded array.
++ *
++ * @param a the array being measured.
++ * @return the number of items hardcoded into the array.
++ */
++#ifndef ARRAY_LENGTH
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++#endif
++
++/**
++ * Returns the smaller of two values.
++ *
++ * @param x the first item to compare.
++ * @param y the second item to compare.
++ * @return the value that evaluates to lesser than the other.
++ */
++#ifndef MIN
++#define MIN(x,y) (((x) < (y)) ? (x) : (y))
++#endif
++
++/**
++ * Returns a pointer the the containing struct of a given member item.
++ *
++ * To demonstrate, the following example retrieves a pointer to
++ * `example_container` given only its `destroy_listener` member:
++ *
++ * @code
++ * struct example_container {
++ * struct wl_listener destroy_listener;
++ * // other members...
++ * };
++ *
++ * void example_container_destroy(struct wl_listener *listener, void *data)
++ * {
++ * struct example_container *ctr;
++ *
++ * ctr = wl_container_of(listener, ctr, destroy_listener);
++ * // destroy ctr...
++ * }
++ * @endcode
++ *
++ * @param ptr A valid pointer to the contained item.
++ *
++ * @param type A pointer to the type of content that the list item
++ * stores. Type does not need be a valid pointer; a null or
++ * an uninitialised pointer will suffice.
++ *
++ * @param member The named location of ptr within the sample type.
++ *
++ * @return The container for the specified pointer.
++ */
++#ifndef container_of
++#define container_of(ptr, type, member) ({ \
++ const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
++ (type *)( (char *)__mptr - offsetof(type,member) );})
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* WESTON_HELPERS_H */
+diff --git a/src/compositor.c b/src/compositor.c
+index 574db2d..e9c46a4 100644
+--- a/src/compositor.c
++++ b/src/compositor.c
+@@ -2503,6 +2503,54 @@ weston_surface_get_main_surface(struct weston_surface *surface)
+ return surface;
+ }
+
++/** Get the size of surface contents */
++WL_EXPORT void
++weston_surface_get_content_size(struct weston_surface *surface,
++ int *width, int *height)
++{
++ struct weston_renderer *rer = surface->compositor->renderer;
++
++ if (!rer->surface_get_content_size) {
++ *width = 0;
++ *height = 0;
++ return;
++ }
++
++ rer->surface_get_content_size(surface, width, height);
++}
++
++/** Copy surface contents to system memory */
++WL_EXPORT int
++weston_surface_copy_content(struct weston_surface *surface,
++ void *target, size_t size,
++ int src_x, int src_y,
++ int width, int height)
++{
++ struct weston_renderer *rer = surface->compositor->renderer;
++ int cw, ch;
++ const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
++
++ if (!rer->surface_copy_content)
++ return -1;
++
++ weston_surface_get_content_size(surface, &cw, &ch);
++
++ if (src_x < 0 || src_y < 0)
++ return -1;
++
++ if (width <= 0 || height <= 0)
++ return -1;
++
++ if (src_x + width > cw || src_y + height > ch)
++ return -1;
++
++ if (width * bytespp * height > size)
++ return -1;
++
++ return rer->surface_copy_content(surface, target, size,
++ src_x, src_y, width, height);
++}
++
+ static void
+ subsurface_set_position(struct wl_client *client,
+ struct wl_resource *resource, int32_t x, int32_t y)
+diff --git a/src/compositor.h b/src/compositor.h
+index 057f8be..2a8da6b 100644
+--- a/src/compositor.h
++++ b/src/compositor.h
+@@ -552,6 +552,16 @@ struct weston_renderer {
+ float red, float green,
+ float blue, float alpha);
+ void (*destroy)(struct weston_compositor *ec);
++
++ /** See weston_surface_get_content_size() */
++ void (*surface_get_content_size)(struct weston_surface *surface,
++ int *width, int *height);
++
++ /** See weston_surface__copy_content() */
++ int (*surface_copy_content)(struct weston_surface *surface,
++ void *target, size_t size,
++ int src_x, int src_y,
++ int width, int height);
+ };
+
+ enum weston_capability {
+@@ -1205,6 +1215,16 @@ weston_surface_unmap(struct weston_surface *surface);
+ struct weston_surface *
+ weston_surface_get_main_surface(struct weston_surface *surface);
+
++void
++weston_surface_get_content_size(struct weston_surface *surface,
++ int *width, int *height);
++
++int
++weston_surface_copy_content(struct weston_surface *surface,
++ void *target, size_t size,
++ int src_x, int src_y,
++ int width, int height);
++
+ struct weston_buffer *
+ weston_buffer_from_resource(struct wl_resource *resource);
+
+diff --git a/src/gl-renderer.c b/src/gl-renderer.c
+index 63af75d..55b612c 100644
+--- a/src/gl-renderer.c
++++ b/src/gl-renderer.c
+@@ -77,6 +77,7 @@ struct gl_output_state {
+
+ enum buffer_type {
+ BUFFER_TYPE_NULL,
++ BUFFER_TYPE_SOLID, /* internal solid color surfaces without a buffer */
+ BUFFER_TYPE_SHM,
+ BUFFER_TYPE_EGL
+ };
+@@ -1297,11 +1298,157 @@ gl_renderer_surface_set_color(struct weston_surface *surface,
+ gs->color[1] = green;
+ gs->color[2] = blue;
+ gs->color[3] = alpha;
++ gs->buffer_type = BUFFER_TYPE_SOLID;
+
+ gs->shader = &gr->solid_shader;
+ }
+
+ static void
++gl_renderer_surface_get_content_size(struct weston_surface *surface,
++ int *width, int *height)
++{
++ struct gl_surface_state *gs = get_surface_state(surface);
++
++ if (gs->buffer_type == BUFFER_TYPE_NULL) {
++ *width = 0;
++ *height = 0;
++ } else {
++ *width = gs->pitch;
++ *height = gs->height;
++ }
++}
++
++static uint32_t
++pack_color(pixman_format_code_t format, float *c)
++{
++ uint8_t r = round(c[0] * 255.0f);
++ uint8_t g = round(c[1] * 255.0f);
++ uint8_t b = round(c[2] * 255.0f);
++ uint8_t a = round(c[3] * 255.0f);
++
++ switch (format) {
++ case PIXMAN_a8b8g8r8:
++ return (a << 24) | (b << 16) | (g << 8) | r;
++ default:
++ assert(0);
++ return 0;
++ }
++}
++
++static int
++gl_renderer_surface_copy_content(struct weston_surface *surface,
++ void *target, size_t size,
++ int src_x, int src_y,
++ int width, int height)
++{
++ static const GLfloat verts[4 * 2] = {
++ 0.0f, 0.0f,
++ 1.0f, 0.0f,
++ 1.0f, 1.0f,
++ 0.0f, 1.0f
++ };
++ static const GLfloat projmat_normal[16] = { /* transpose */
++ 2.0f, 0.0f, 0.0f, 0.0f,
++ 0.0f, 2.0f, 0.0f, 0.0f,
++ 0.0f, 0.0f, 1.0f, 0.0f,
++ -1.0f, -1.0f, 0.0f, 1.0f
++ };
++ static const GLfloat projmat_yinvert[16] = { /* transpose */
++ 2.0f, 0.0f, 0.0f, 0.0f,
++ 0.0f, -2.0f, 0.0f, 0.0f,
++ 0.0f, 0.0f, 1.0f, 0.0f,
++ -1.0f, 1.0f, 0.0f, 1.0f
++ };
++ const pixman_format_code_t format = PIXMAN_a8b8g8r8;
++ const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
++ const GLenum gl_format = GL_RGBA; /* PIXMAN_a8b8g8r8 little-endian */
++ struct gl_renderer *gr = get_renderer(surface->compositor);
++ struct gl_surface_state *gs = get_surface_state(surface);
++ int cw, ch;
++ GLuint fbo;
++ GLuint tex;
++ GLenum status;
++ const GLfloat *proj;
++ int i;
++
++ gl_renderer_surface_get_content_size(surface, &cw, &ch);
++
++ switch (gs->buffer_type) {
++ case BUFFER_TYPE_NULL:
++ return -1;
++ case BUFFER_TYPE_SOLID:
++ *(uint32_t *)target = pack_color(format, gs->color);
++ return 0;
++ case BUFFER_TYPE_SHM:
++ gl_renderer_flush_damage(surface);
++ /* fall through */
++ case BUFFER_TYPE_EGL:
++ break;
++ }
++
++ glGenTextures(1, &tex);
++ glBindTexture(GL_TEXTURE_2D, tex);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cw, ch,
++ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
++ glBindTexture(GL_TEXTURE_2D, 0);
++
++ glGenFramebuffers(1, &fbo);
++ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
++ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
++ GL_TEXTURE_2D, tex, 0);
++
++ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
++ if (status != GL_FRAMEBUFFER_COMPLETE) {
++ weston_log("%s: fbo error: %#x\n", __func__, status);
++ glDeleteFramebuffers(1, &fbo);
++ glDeleteTextures(1, &tex);
++ return -1;
++ }
++
++ glViewport(0, 0, cw, ch);
++ glDisable(GL_BLEND);
++ use_shader(gr, gs->shader);
++ if (gs->y_inverted)
++ proj = projmat_normal;
++ else
++ proj = projmat_yinvert;
++
++ glUniformMatrix4fv(gs->shader->proj_uniform, 1, GL_FALSE, proj);
++ glUniform1f(gs->shader->alpha_uniform, 1.0f);
++
++ for (i = 0; i < gs->num_textures; i++) {
++ glUniform1i(gs->shader->tex_uniforms[i], i);
++
++ glActiveTexture(GL_TEXTURE0 + i);
++ glBindTexture(gs->target, gs->textures[i]);
++ glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
++ glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
++ }
++
++ /* position: */
++ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
++ glEnableVertexAttribArray(0);
++
++ /* texcoord: */
++ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, verts);
++ glEnableVertexAttribArray(1);
++
++ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
++
++ glDisableVertexAttribArray(1);
++ glDisableVertexAttribArray(0);
++
++ glPixelStorei(GL_PACK_ALIGNMENT, bytespp);
++ glReadPixels(src_x, src_y, width, height, gl_format,
++ GL_UNSIGNED_BYTE, target);
++
++ glDeleteFramebuffers(1, &fbo);
++ glDeleteTextures(1, &tex);
++
++ return 0;
++}
++
++static void
+ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
+ {
+ int i;
+@@ -1932,6 +2079,9 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
+ gr->base.attach = gl_renderer_attach;
+ gr->base.surface_set_color = gl_renderer_surface_set_color;
+ gr->base.destroy = gl_renderer_destroy;
++ gr->base.surface_get_content_size =
++ gl_renderer_surface_get_content_size;
++ gr->base.surface_copy_content = gl_renderer_surface_copy_content;
+
+ gr->egl_display = eglGetDisplay(display);
+ if (gr->egl_display == EGL_NO_DISPLAY) {
+diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
+index 93be968..c9d5038 100644
+--- a/src/pixman-renderer.c
++++ b/src/pixman-renderer.c
+@@ -674,6 +674,53 @@ pixman_renderer_destroy(struct weston_compositor *ec)
+ }
+
+ static void
++pixman_renderer_surface_get_content_size(struct weston_surface *surface,
++ int *width, int *height)
++{
++ struct pixman_surface_state *ps = get_surface_state(surface);
++
++ if (ps->image) {
++ *width = pixman_image_get_width(ps->image);
++ *height = pixman_image_get_height(ps->image);
++ } else {
++ *width = 0;
++ *height = 0;
++ }
++}
++
++static int
++pixman_renderer_surface_copy_content(struct weston_surface *surface,
++ void *target, size_t size,
++ int src_x, int src_y,
++ int width, int height)
++{
++ const pixman_format_code_t format = PIXMAN_a8b8g8r8;
++ const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
++ struct pixman_surface_state *ps = get_surface_state(surface);
++ pixman_image_t *out_buf;
++
++ if (!ps->image)
++ return -1;
++
++ out_buf = pixman_image_create_bits(format, width, height,
++ target, width * bytespp);
++
++ pixman_image_set_transform(ps->image, NULL);
++ pixman_image_composite32(PIXMAN_OP_SRC,
++ ps->image, /* src */
++ NULL, /* mask */
++ out_buf, /* dest */
++ src_x, src_y, /* src_x, src_y */
++ 0, 0, /* mask_x, mask_y */
++ 0, 0, /* dest_x, dest_y */
++ width, height);
++
++ pixman_image_unref(out_buf);
++
++ return 0;
++}
++
++static void
+ debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
+ void *data)
+ {
+@@ -711,6 +758,10 @@ pixman_renderer_init(struct weston_compositor *ec)
+ renderer->base.attach = pixman_renderer_attach;
+ renderer->base.surface_set_color = pixman_renderer_surface_set_color;
+ renderer->base.destroy = pixman_renderer_destroy;
++ renderer->base.surface_get_content_size =
++ pixman_renderer_surface_get_content_size;
++ renderer->base.surface_copy_content =
++ pixman_renderer_surface_copy_content;
+ ec->renderer = &renderer->base;
+ ec->capabilities |= WESTON_CAP_ROTATION_ANY;
+ ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
+--
+1.8.3.1
+
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/background.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/background.png
new file mode 100644
index 000000000..60c317c94
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/background.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/fullscreen.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/fullscreen.png
new file mode 100644
index 000000000..dc5a302d5
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/fullscreen.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/home.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/home.png
new file mode 100644
index 000000000..af9f60372
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/home.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_clickdot.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_clickdot.png
new file mode 100644
index 000000000..711bcfcbd
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_clickdot.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_flower.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_flower.png
new file mode 100644
index 000000000..0a71479c6
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_flower.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-egl.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-egl.png
new file mode 100644
index 000000000..025395033
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-egl.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-shm.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-shm.png
new file mode 100644
index 000000000..6aacaaa87
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_simple-shm.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_smoke.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_smoke.png
new file mode 100644
index 000000000..0dbe20ea0
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/icon_ivi_smoke.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/panel.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/panel.png
new file mode 100644
index 000000000..0fd72b87f
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/panel.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/random.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/random.png
new file mode 100644
index 000000000..7640aa052
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/random.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/sidebyside.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/sidebyside.png
new file mode 100644
index 000000000..98ea7803b
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/sidebyside.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/tiling.png b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/tiling.png
new file mode 100644
index 000000000..dd3e02c0f
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/data/tiling.png
Binary files differ
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/weston.ini.ivi-shell b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/weston.ini.ivi-shell
new file mode 100644
index 000000000..ad6f19a77
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/weston.ini.ivi-shell
@@ -0,0 +1,98 @@
+[core]
+shell=ivi-shell.so
+
+[ivi-shell]
+ivi-module=hmi-controller.so
+ivi-shell-user-interface=/usr/lib/weston/weston-ivi-shell-user-interface
+
+#developermode=true
+
+cursor-theme=default
+cursor-size=32
+
+base-layer-id=1000
+workspace-background-layer-id=2000
+workspace-layer-id=3000
+application-layer-id=4000
+
+transition-duration=300
+
+background-icon=/usr/share/weston/background.png
+background-id=1001
+panel-icon=/usr/share/weston/panel.png
+panel-id=1002
+tiling-icon=/usr/share/weston/tiling.png
+tiling-id=1003
+sidebyside-icon=/usr/share/weston/sidebyside.png
+sidebyside-id=1004
+fullscreen-icon=/usr/share/weston/fullscreen.png
+fullscreen-id=1005
+random-icon=/usr/share/weston/random.png
+random-id=1006
+home-icon=/usr/share/weston/home.png
+home-id=1007
+workspace-background-color=0x99000000
+workspace-background-id=2001
+
+[input-method]
+path=/usr/lib/weston/weston-keyboard
+
+[ivi-launcher]
+workspace-id=0
+icon-id=4001
+icon=/usr/share/weston/icon_ivi_flower.png
+path=/usr/bin/weston-flower
+
+[ivi-launcher]
+workspace-id=0
+icon-id=4002
+icon=/usr/share/weston/icon_ivi_clickdot.png
+path=/usr/bin/weston-clickdot
+
+[ivi-launcher]
+workspace-id=1
+icon-id=4003
+icon=/usr/share/weston/icon_ivi_simple-egl.png
+path=/usr/bin/weston-simple-egl
+
+[ivi-launcher]
+workspace-id=1
+icon-id=4004
+icon=/usr/share/weston/icon_ivi_simple-shm.png
+path=/usr/bin/weston-simple-shm
+
+[ivi-launcher]
+workspace-id=2
+icon-id=4005
+icon=/usr/share/weston/icon_ivi_smoke.png
+path=/usr/bin/weston-smoke
+
+[ivi-launcher]
+workspace-id=3
+icon-id=4006
+icon=/usr/share/weston/icon_ivi_flower.png
+path=/usr/bin/weston-flower
+
+[ivi-launcher]
+workspace-id=3
+icon-id=4007
+icon=/usr/share/weston/icon_ivi_clickdot.png
+path=/usr/bin/weston-clickdot
+
+[ivi-launcher]
+workspace-id=3
+icon-id=4008
+icon=/usr/share/weston/icon_ivi_simple-egl.png
+path=/usr/bin/weston-simple-egl
+
+[ivi-launcher]
+workspace-id=3
+icon-id=4009
+icon=/usr/share/weston/icon_ivi_simple-shm.png
+path=/usr/bin/weston-simple-shm
+
+[ivi-launcher]
+workspace-id=3
+icon-id=4010
+icon=/usr/share/weston/icon_ivi_smoke.png
+path=/usr/bin/weston-smoke
diff --git a/meta-ivi-common/recipes-graphics/wayland/weston_1.5.0.bbappend b/meta-ivi-common/recipes-graphics/wayland/weston_1.5.0.bbappend
new file mode 100644
index 000000000..264b6ab6d
--- /dev/null
+++ b/meta-ivi-common/recipes-graphics/wayland/weston_1.5.0.bbappend
@@ -0,0 +1,23 @@
+FILESEXTRAPATHS_prepend := ":${THISDIR}/weston-ivi-shell:"
+
+SRC_URI_append = " \
+ file://Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch \
+ file://data/background.png \
+ file://data/fullscreen.png \
+ file://data/home.png \
+ file://data/icon_ivi_clickdot.png \
+ file://data/icon_ivi_flower.png \
+ file://data/icon_ivi_simple-egl.png \
+ file://data/icon_ivi_simple-shm.png \
+ file://data/icon_ivi_smoke.png \
+ file://data/panel.png \
+ file://data/random.png \
+ file://data/sidebyside.png \
+ file://data/tiling.png \
+ "
+
+EXTRA_OECONF_append = " --enable-ivi-shell"
+
+do_compile_prepend() {
+ cp -f ${WORKDIR}/data/* ${S}/data
+}