From e873ca6bed7996d9ee7593651808b94fa8f68e0f Mon Sep 17 00:00:00 2001 From: Manuel Bachmann Date: Thu, 5 Nov 2015 10:17:00 +0000 Subject: Fix Weston IVI-Shell layout on Renesas R-Car E2 Silk On Renesas Silk boards, when running weston ivi-shell, layout is too small and black borders are visible. This is due to the presence of a VGA adapter, which ivi-shell wrongly queries for resolution size values. Work around this ; this patch is not upstreamed due to current work being done on ivi-shell multiscreen support (https://github.com/ntanibata/weston-ivi-shell/commits/ multiscreen_feature_03). PS : although this patch is primarily intended for Silk, we put it into "meta-agl" because it is a general-purpose fix. It would also fix the issue on laptops having VGA adapters, e.g.. Change-Id: I25447b54d53eb8f8b7261903c0699a53c81790f8 Signed-off-by: Manuel Bachmann --- ...Shell-Backport-from-Weston-1.9.0-to-1.5.0.patch | 10478 +++++++++++++++++++ ...I-Shell-use-primary-screen-for-resolution.patch | 49 + ...port-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch | 10478 ------------------- 3 files changed, 10527 insertions(+), 10478 deletions(-) create mode 100644 meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/0001-IVI-Shell-Backport-from-Weston-1.9.0-to-1.5.0.patch create mode 100644 meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/0002-IVI-Shell-use-primary-screen-for-resolution.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch (limited to 'meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell') diff --git a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/0001-IVI-Shell-Backport-from-Weston-1.9.0-to-1.5.0.patch b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/0001-IVI-Shell-Backport-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/0001-IVI-Shell-Backport-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 +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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, §ion, &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, ++ ®istry_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 + #include + #include ++#include + #include + + #include +@@ -41,6 +42,8 @@ + #include + + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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, §ion, &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, ×tamp); //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 ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++ ++#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, ×tamp);/* 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 ++#include ++ ++#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, ¬ification->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, ¬ification->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 ++#include ++#include ++#include ++#include ++ ++#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 ++ ++#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 @@ ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ ++ ++ ++ +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 @@ ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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". ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ hmi-controller loaded to ivi-shall implements 4 types of layout ++ as a reference; tiling, side by side, full_screen, and random. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +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/0002-IVI-Shell-use-primary-screen-for-resolution.patch b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/0002-IVI-Shell-use-primary-screen-for-resolution.patch new file mode 100644 index 000000000..2df9f4aed --- /dev/null +++ b/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/0002-IVI-Shell-use-primary-screen-for-resolution.patch @@ -0,0 +1,49 @@ +From: Manuel Bachmann +Date: Thu, Nov 5 10:17:00 2015 +0000 +Subject: ivi-shell: use primary screen for resolution values + +Screen resolution values (width, height) are always grabbed +from the first screen, n.0, which can be a bad choice if it +is not the one really used as main display. + +This mostly happens on hardware with a VGA adapter, such as +laptops or Renesas R-Car E2 "Silk", and prevents correct +layout stretching (black borders). + +Discover the primary screen and use its values. + +Signed-off-by: Manuel Bachmann +--- + +--- a/ivi-shell/hmi-controller.c 2015-11-05 09:57:55.740942450 +0000 ++++ b/ivi-shell/hmi-controller.c 2015-11-05 10:00:23.545912494 +0000 +@@ -676,6 +676,8 @@ + struct link_layer *tmp_link_layer = NULL; + int32_t panel_height = 0; + struct hmi_controller *hmi_ctrl = MEM_ALLOC(sizeof(*hmi_ctrl)); ++ struct weston_output *output = NULL; ++ int i = 0; + + wl_array_init(&hmi_ctrl->ui_widgets); + hmi_ctrl->layout_mode = IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING; +@@ -684,11 +686,19 @@ + + ivi_controller_interface->get_screens(&screen_length, &pp_screen); + +- iviscrn = pp_screen[0]; ++ /* find primary screen */ ++ for (i = 0; i < screen_length; i++) { ++ iviscrn = pp_screen[i]; ++ output = ivi_controller_interface->screen_get_output(iviscrn); ++ if (output->x == 0) ++ break; ++ } + + ivi_controller_interface->get_screen_resolution(iviscrn, &screen_width, + &screen_height); + ++ iviscrn = pp_screen[0]; ++ + /* init base ivi_layer*/ + hmi_ctrl->base_layer.x = 0; + hmi_ctrl->base_layer.y = 0; 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 deleted file mode 100644 index 0e5a99f0b..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/weston-ivi-shell/Backport-IVI-Shell-from-Weston-1.9.0-to-1.5.0.patch +++ /dev/null @@ -1,10478 +0,0 @@ -From 9e55f4f9c921782263b784e7f6e0e9b0fc9095ca Mon Sep 17 00:00:00 2001 -From: Manuel Bachmann -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 ---- - 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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, §ion, &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, -+ ®istry_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 - #include - #include -+#include - #include - - #include -@@ -41,6 +42,8 @@ - #include - - #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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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, §ion, &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, ×tamp); //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 -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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, ×tamp);/* 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 -+#include -+ -+#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, ¬ification->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, ¬ification->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 -+#include -+#include -+#include -+#include -+ -+#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 -+ -+#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 @@ -+ -+ -+ -+ -+ 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. -+ -+ -+ -+ -+ -+ -+ -+ 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. -+ -+ -+ -+ -+ -+ 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. -+ -+ -+ -+ -+ -+ -+ -+ -+ 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. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 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. -+ -+ -+ -+ -+ -+ -+ -+ -+ -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 @@ -+ -+ -+ -+ -+ 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. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 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". -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ hmi-controller loaded to ivi-shall implements 4 types of layout -+ as a reference; tiling, side by side, full_screen, and random. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 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 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -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 - -- cgit 1.2.3-korg