summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>2014-03-20 09:28:52 +0900
committerNobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>2014-05-20 12:35:52 +0900
commit496aa3b565e1ecf67460c4f5c4965d824af8aac1 (patch)
treecfd93f6e59a0fb115bda65f2fe621c2ef3991c8a
parentf77596fb44a8f34a9a11b4bbafad73d01118ca6b (diff)
downloadweston-496aa3b565e1ecf67460c4f5c4965d824af8aac1.tar.gz
clients: a reference implementation of UI client how to use ivi-hmi-controller.
This is launched from hmi-controller by launch_hmi_client_process and invoke a client process. The basic flow is as followed, 1/ process invoked 2/ read configuration from weston.ini. 3/ draw png file to surface according to configuration of weston.ini 4/ all parts of UI are ready. request "UI_ready" to draw UI. 5/ Enter event loop 6/ If a surface receives touch/pointer event, followings are invoked according to type of event and surface 6-1/ If a surface to launch ivi_application receive touch up, it execs ivi-application configured in weston.ini. 6-2/ If a surface to switch layout mode receive touch up, it sends a request, ivi_hmi_controller_switch_mode, to hmi-controller. 6-3/ If a surface to show workspace having launchers, it sends a request, ivi_hmi_controller_home, to hmi-controller. 6-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. Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>
-rw-r--r--Makefile.am10
-rw-r--r--clients/ivi-shell-user-interface.c1332
-rw-r--r--ivi-shell/hmi-controller.c42
3 files changed, 1380 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 1f75cc36..46c5e3d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -359,7 +359,8 @@ libexec_PROGRAMS += \
weston-desktop-shell \
weston-screenshooter \
weston-keyboard \
- weston-simple-im
+ weston-simple-im \
+ weston-ivi-shell-user-interface
demo_clients = \
weston-flower \
@@ -570,6 +571,13 @@ nodist_weston_desktop_shell_SOURCES = \
weston_desktop_shell_LDADD = libtoytoolkit.la
weston_desktop_shell_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+weston_ivi_shell_user_interface_SOURCES = clients/ivi-shell-user-interface.c
+nodist_weston_ivi_shell_user_interface_SOURCES = \
+ protocol/ivi-hmi-controller-client-protocol.h \
+ protocol/ivi-hmi-controller-protocol.c
+weston_ivi_shell_user_interface_LDADD = libtoytoolkit.la
+weston_ivi_shell_user_interface_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+
if BUILD_FULL_GL_CLIENTS
demo_clients += weston-gears
weston_gears_SOURCES = clients/gears.c
diff --git a/clients/ivi-shell-user-interface.c b/clients/ivi-shell-user-interface.c
new file mode 100644
index 00000000..70b854b9
--- /dev/null
+++ b/clients/ivi-shell-user-interface.c
@@ -0,0 +1,1332 @@
+/*
+ * Copyright (C) 2013 DENSO CORPORATION
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/input.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <getopt.h>
+#include <pthread.h>
+#include <wayland-cursor.h>
+#include "../shared/cairo-util.h"
+#include "../shared/config-parser.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/ create pthread
+ * 2/ read configuration from weston.ini.
+ * 3/ draw png file to surface according to configuration of weston.ini
+ * 4/ set up UI by using ivi-hmi-controller protocol
+ * 5/ Enter event loop
+ * 6/ If a surface receives touch/pointer event, followings are invoked according
+ * to type of event and surface
+ * 6-1/ If a surface to launch ivi_application receive touch up, it execs
+ * ivi-application configured in weston.ini.
+ * 6-2/ If a surface to switch layout mode receive touch up, it sends a request,
+ * ivi_hmi_controller_switch_mode, to hmi-controller.
+ * 6-3/ If a surface to show workspace having launchers, it sends a request,
+ * ivi_hmi_controller_home, to hmi-controller.
+ * 6-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;
+ 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;
+ uint32_t formats;
+ 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;
+};
+
+volatile int gRun = 0;
+
+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__)
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+/*****************************************************************************
+ * Event Handler
+ ****************************************************************************/
+
+static void
+shm_format(void* data, struct wl_shm* pWlShm, uint32_t format)
+{
+ struct wlContextStruct* pDsp = data;
+ pDsp->formats |= (1 << format);
+}
+
+static struct wl_shm_listener shm_listenter = {
+ shm_format
+};
+
+static int32_t
+getIdOfWlSurface(struct wlContextCommon *pCtx, struct wl_surface *wlSurface)
+{
+ if (NULL == pCtx ||
+ NULL == wlSurface ) {
+ return 0;
+ }
+
+ struct wlContextStruct* pWlCtxSt = NULL;
+ wl_list_for_each(pWlCtxSt, pCtx->list_wlContextStruct, link) {
+ if (pWlCtxSt->wlSurface == wlSurface) {
+ return pWlCtxSt->id_surface;
+ }
+ continue;
+ }
+ return -1;
+}
+
+static void
+set_pointer_image(struct wlContextCommon *pCtx, uint32_t index)
+{
+ 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;
+ }
+
+ struct wl_cursor *cursor = pCtx->cursors[pCtx->current_cursor];
+ if (!cursor) {
+ return;
+ }
+
+ if (cursor->image_count <= index) {
+ fprintf(stderr, "cursor index out of range\n");
+ return;
+ }
+
+ struct wl_cursor_image *image = cursor->images[index];
+ struct wl_buffer *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)
+{
+ (void)wlPointer;
+ (void)serial;
+
+ 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)
+{
+ (void)wlPointer;
+ (void)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)
+{
+ (void)data;
+ (void)wlPointer;
+ (void)time;
+
+#ifdef _DEBUG
+ printf("ENTER PointerHandleMotion: x(%d), y(%d)\n", gPointerX, gPointerY);
+#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) {
+ if (surfaceId != launcher->icon_surface_id) {
+ continue;
+ }
+
+ char *argv[] = {NULL};
+ 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)
+{
+ if (id == hmi_setting->workspace_background.id) {
+ return 1;
+ }
+
+ struct hmi_homescreen_launcher *launcher = NULL;
+ 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)
+{
+ (void)wlPointer;
+ (void)serial;
+ (void)time;
+ struct wlContextCommon *pCtx = data;
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
+
+ if (BTN_RIGHT == button) {
+ return;
+ }
+
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
+
+ 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)
+{
+ (void)data;
+ (void)wlPointer;
+ (void)time;
+#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;
+
+ if (0 == id){
+ pCtx->enterSurface = surface;
+ }
+
+ const uint32_t 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)
+{
+ (void)serial;
+ (void)time;
+ 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)
+{
+ (void)seat;
+ 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_set_user_data(wlPointer, data);
+ 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_set_user_data(wlTouch, data);
+ 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)
+{
+ if (is_controlled) {
+ return;
+ }
+
+ struct wlContextCommon *pCtx = data;
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
+
+ /**
+ * 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)
+{
+ (void)version;
+ struct wlContextCommon* p_wlCtx = (struct wlContextCommon*)data;
+
+ do {
+ if (!strcmp(interface, "wl_compositor")) {
+ p_wlCtx->wlCompositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
+ break;
+ }
+ 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);
+ break;
+ }
+ 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);
+ break;
+ }
+ if (!strcmp(interface, "ivi_application")) {
+ p_wlCtx->iviApplication = wl_registry_bind(registry, name, &ivi_application_interface, 1);
+ break;
+ }
+ if (!strcmp(interface, "ivi_hmi_controller")) {
+ p_wlCtx->hmiCtrl = wl_registry_bind(registry, name, &ivi_hmi_controller_interface, 1);
+
+ if (p_wlCtx->hmiCtrl) {
+ ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl, &hmi_controller_listener, p_wlCtx);
+ }
+ break;
+ }
+
+ } while(0);
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ NULL
+};
+
+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;
+
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ int fd = -1;
+ int size = 0;
+ int width = 0;
+ int height = 0;
+ int stride = 0;
+
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ fprintf(stderr, "open %s failed: %m\n", filename);
+ return;
+ }
+
+ 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;
+ if (ftruncate(fd, size) < 0) {
+ fprintf(stderr, "ftruncate failed: %m\n");
+ close(fd);
+ 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);
+
+ return;
+}
+
+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
+createWLContext(struct wlContextStruct *p_wlCtx)
+{
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+
+ 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();
+ }
+
+
+ createShmBuffer(p_wlCtx);
+
+ wl_display_flush(p_wlCtx->cmm.wlDisplay);
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+
+ 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);
+
+ wl_display_flush(p_wlCtx->cmm.wlDisplay);
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+}
+
+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);
+
+ createWLContext(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);
+
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);
+}
+
+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)
+{
+ int launcher_count = wl_list_length(launcher_list);
+
+ if (0 == launcher_count) {
+ return;
+ }
+
+ struct hmi_homescreen_launcher** launchers;
+ launchers = MEM_ALLOC(launcher_count * sizeof(*launchers));
+
+ int ii = 0;
+ struct hmi_homescreen_launcher *launcher = NULL;
+
+ wl_list_for_each(launcher, launcher_list, link) {
+ launchers[ii] = launcher;
+ ii++;
+ }
+
+ int start = 0;
+
+ for (ii = 0; ii < launcher_count; ii++) {
+
+ if (ii != launcher_count -1 &&
+ launchers[ii]->workspace_id == launchers[ii + 1]->workspace_id) {
+ continue;
+ }
+
+ int jj = 0;
+ for (jj = start; jj <= ii; jj++) {
+ struct wlContextStruct *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);
+}
+
+static void sigFunc(int signum)
+{
+ gRun = 0;
+}
+
+/**
+ * Internal method to read out weston.ini to get configuration
+ */
+static struct hmi_homescreen_setting*
+hmi_homescreen_setting_create(void)
+{
+ struct hmi_homescreen_setting* setting = MEM_ALLOC(sizeof(*setting));
+
+ wl_list_init(&setting->workspace_list);
+ wl_list_init(&setting->launcher_list);
+
+ struct weston_config *config = NULL;
+ config = weston_config_parse("weston.ini");
+
+ struct weston_config_section *shellSection = NULL;
+ 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);
+
+ uint32_t workspace_layer_id;
+ 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);
+
+ struct weston_config_section *section = NULL;
+ const char *name = NULL;
+
+ uint32_t icon_surface_id = workspace_layer_id + 1;
+
+ while (weston_config_next_section(config, &section, &name)) {
+
+ if (0 == strcmp(name, "ivi-launcher")) {
+
+ struct hmi_homescreen_launcher *launcher = NULL;
+ 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;
+
+ 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);
+ wlCtxCommon.list_wlContextStruct = MEM_ALLOC(sizeof(struct wl_list));
+ assert(wlCtxCommon.list_wlContextStruct);
+ wl_list_init(wlCtxCommon.list_wlContextStruct);
+
+ struct hmi_homescreen_setting *hmi_setting = hmi_homescreen_setting_create();
+ wlCtxCommon.hmi_setting = hmi_setting;
+
+ gRun = 1;
+
+ wlCtxCommon.wlDisplay = wl_display_connect(NULL);
+ if (NULL == wlCtxCommon.wlDisplay) {
+ printf("Error: wl_display_connect failed.\n");
+ return -1;
+ }
+
+ /* get wl_registry */
+ wlCtxCommon.wlRegistry = wl_display_get_registry(wlCtxCommon.wlDisplay);
+ wl_registry_add_listener(wlCtxCommon.wlRegistry,
+ &registry_listener, &wlCtxCommon);
+ wl_display_dispatch(wlCtxCommon.wlDisplay);
+ wl_display_roundtrip(wlCtxCommon.wlDisplay);
+
+ 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);
+
+ /* signal handling */
+ signal(SIGINT, sigFunc);
+ signal(SIGKILL, sigFunc);
+
+ while(gRun) {
+ wl_display_dispatch(wlCtxCommon.wlDisplay);
+ }
+
+ struct wlContextStruct* pWlCtxSt = NULL;
+ wl_list_for_each(pWlCtxSt, wlCtxCommon.list_wlContextStruct, link) {
+ destroyWLContextStruct(pWlCtxSt);
+ }
+
+ destroyWLContextCommon(&wlCtxCommon);
+ free(wlCtxCommon.list_wlContextStruct);
+
+ return 0;
+}
diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
index 67179908..ab37ae93 100644
--- a/ivi-shell/hmi-controller.c
+++ b/ivi-shell/hmi-controller.c
@@ -134,6 +134,7 @@ hmi_server_setting {
uint32_t workspace_background_layer_id;
uint32_t workspace_layer_id;
uint32_t panel_height;
+ char *ivi_homescreen;
};
struct hmi_controller
@@ -151,6 +152,10 @@ struct hmi_controller
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 launcher_info
@@ -830,6 +835,9 @@ hmi_server_setting_create(void)
setting->panel_height = 70;
+ weston_config_section_get_string(
+ shellSection, "ivi-shell-user-interface", &setting->ivi_homescreen, NULL);
+
weston_config_destroy(config);
return setting;
@@ -1896,9 +1904,36 @@ bind_hmi_controller(struct wl_client *client,
}
static void
-launch_hmi_client(void *data)
+handle_hmi_client_process_sigchld(struct weston_process *proc, int status)
+{
+ proc->pid = 0;
+}
+
+static void
+hmi_client_destroy(struct wl_listener *listener, void *data)
+{
+ struct hmi_controller *hmi_ctrl =
+ container_of(listener, struct hmi_controller, destroy_listener);
+
+ kill(hmi_ctrl->process.pid, SIGTERM);
+ hmi_ctrl->process.pid = 0;
+}
+
+static void
+launch_hmi_client_process(void *data)
{
- /*Nothing to do here*/
+ struct hmi_controller *hmi_ctrl =
+ (struct hmi_controller *)data;
+
+ weston_client_launch(hmi_ctrl->compositor,
+ &hmi_ctrl->process,
+ hmi_ctrl->hmi_setting->ivi_homescreen,
+ handle_hmi_client_process_sigchld);
+
+ hmi_ctrl->destroy_listener.notify = hmi_client_destroy;
+ wl_signal_add(&hmi_ctrl->compositor->destroy_signal, &hmi_ctrl->destroy_listener);
+
+ free(hmi_ctrl->hmi_setting->ivi_homescreen);
}
/*****************************************************************************
@@ -1910,6 +1945,7 @@ module_init(struct weston_compositor *ec,
int *argc, char *argv[])
{
struct hmi_controller *hmi_ctrl = hmi_controller_create(ec);
+ hmi_ctrl->compositor = ec;
if (wl_global_create(ec->wl_display,
&ivi_hmi_controller_interface, 1,
@@ -1918,7 +1954,7 @@ module_init(struct weston_compositor *ec,
}
struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);
- wl_event_loop_add_idle(loop, launch_hmi_client, ec);
+ wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);
return 0;
}