<div dir="ltr"><div>Hello Tanibata-San,<br><br>I am currently testing your patches against the latest Weston 1.5 release.<br><br>For this particular patch, I had to modify this section in order to compile :<br><br>nodist_weston_ivi_shell_user_interface_SOURCES = \<br>
protocol/ivi-hmi-controller-client-protocol.h \<br> protocol/ivi-hmi-controller-protocol.c \<br> protocol/ivi-application-protocol.c<br><br></div>Notice the "protocol/ivi-application-protocol.c" line at the end. WIthout it, the build process failed when linking the binary.<br>
<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-05-20 6:30 GMT+02:00 Nobuhiko Tanibata <span dir="ltr"><<a href="mailto:NOBUHIKO_TANIBATA@xddp.denso.co.jp" target="_blank">NOBUHIKO_TANIBATA@xddp.denso.co.jp</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This is launched from hmi-controller by launch_hmi_client_process and invoke a<br>
client process.<br>
<br>
The basic flow is as followed,<br>
1/ process invoked<br>
2/ read configuration from weston.ini.<br>
3/ draw png file to surface according to configuration of weston.ini<br>
4/ all parts of UI are ready. request "UI_ready" to draw UI.<br>
5/ Enter event loop<br>
6/ If a surface receives touch/pointer event, followings are invoked according<br>
to type of event and surface<br>
6-1/ If a surface to launch ivi_application receive touch up, it execs<br>
ivi-application configured in weston.ini.<br>
6-2/ If a surface to switch layout mode receive touch up, it sends a request,<br>
ivi_hmi_controller_switch_mode, to hmi-controller.<br>
6-3/ If a surface to show workspace having launchers, it sends a request,<br>
ivi_hmi_controller_home, to hmi-controller.<br>
6-4/ If touch down events happens in workspace,<br>
ivi_hmi_controller_workspace_control is sent to slide workspace.<br>
When control finished, event: ivi_hmi_controller_workspace_end_control<br>
is received.<br>
<br>
Signed-off-by: Nobuhiko Tanibata <<a href="mailto:NOBUHIKO_TANIBATA@xddp.denso.co.jp">NOBUHIKO_TANIBATA@xddp.denso.co.jp</a>><br>
---<br>
<br>
Changes for v2:<br>
- squash Makefile to this patch<br>
<br>
Changes for v3 and v4<br>
- nothing. Version number aligned to the first patch<br>
<br>
Changes for v5:<br>
- rebase weston v1.5 branch<br>
- apply review comments from mailing list<br>
<br>
Makefile.am | 10 +-<br>
clients/ivi-shell-user-interface.c | 1332 ++++++++++++++++++++++++++++++++++++<br>
ivi-shell/hmi-controller.c | 42 +-<br>
3 files changed, 1380 insertions(+), 4 deletions(-)<br>
create mode 100644 clients/ivi-shell-user-interface.c<br>
<br>
diff --git a/Makefile.am b/Makefile.am<br>
index 1f75cc3..46c5e3d 100644<br>
--- a/Makefile.am<br>
+++ b/Makefile.am<br>
@@ -359,7 +359,8 @@ libexec_PROGRAMS += \<br>
weston-desktop-shell \<br>
weston-screenshooter \<br>
weston-keyboard \<br>
- weston-simple-im<br>
+ weston-simple-im \<br>
+ weston-ivi-shell-user-interface<br>
<br>
demo_clients = \<br>
weston-flower \<br>
@@ -570,6 +571,13 @@ nodist_weston_desktop_shell_SOURCES = \<br>
weston_desktop_shell_LDADD = <a href="http://libtoytoolkit.la" target="_blank">libtoytoolkit.la</a><br>
weston_desktop_shell_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)<br>
<br>
+weston_ivi_shell_user_interface_SOURCES = clients/ivi-shell-user-interface.c<br>
+nodist_weston_ivi_shell_user_interface_SOURCES = \<br>
+ protocol/ivi-hmi-controller-client-protocol.h \<br>
+ protocol/ivi-hmi-controller-protocol.c<br>
+weston_ivi_shell_user_interface_LDADD = <a href="http://libtoytoolkit.la" target="_blank">libtoytoolkit.la</a><br>
+weston_ivi_shell_user_interface_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)<br>
+<br>
if BUILD_FULL_GL_CLIENTS<br>
demo_clients += weston-gears<br>
weston_gears_SOURCES = clients/gears.c<br>
diff --git a/clients/ivi-shell-user-interface.c b/clients/ivi-shell-user-interface.c<br>
new file mode 100644<br>
index 0000000..70b854b<br>
--- /dev/null<br>
+++ b/clients/ivi-shell-user-interface.c<br>
@@ -0,0 +1,1332 @@<br>
+/*<br>
+ * Copyright (C) 2013 DENSO CORPORATION<br>
+ *<br>
+ * Permission to use, copy, modify, distribute, and sell this software and<br>
+ * its documentation for any purpose is hereby granted without fee, provided<br>
+ * that the above copyright notice appear in all copies and that both that<br>
+ * copyright notice and this permission notice appear in supporting<br>
+ * documentation, and that the name of the copyright holders not be used in<br>
+ * advertising or publicity pertaining to distribution of the software<br>
+ * without specific, written prior permission. The copyright holders make<br>
+ * no representations about the suitability of this software for any<br>
+ * purpose. It is provided "as is" without express or implied warranty.<br>
+ *<br>
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS<br>
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND<br>
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY<br>
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER<br>
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF<br>
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN<br>
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.<br>
+ */<br>
+<br>
+#include <sys/wait.h><br>
+#include <unistd.h><br>
+#include <stdlib.h><br>
+#include <stdio.h><br>
+#include <string.h><br>
+#include <linux/input.h><br>
+#include <assert.h><br>
+#include <fcntl.h><br>
+#include <signal.h><br>
+#include <sys/mman.h><br>
+#include <getopt.h><br>
+#include <pthread.h><br>
+#include <wayland-cursor.h><br>
+#include "../shared/cairo-util.h"<br>
+#include "../shared/config-parser.h"<br>
+#include "ivi-application-client-protocol.h"<br>
+#include "ivi-hmi-controller-client-protocol.h"<br>
+<br>
+/**<br>
+ * A reference implementation how to use ivi-hmi-controller interface to interact<br>
+ * with hmi-controller. This is launched from hmi-controller by using<br>
+ * hmi_client_start and create a pthread.<br>
+ *<br>
+ * The basic flow is as followed,<br>
+ * 1/ create pthread<br>
+ * 2/ read configuration from weston.ini.<br>
+ * 3/ draw png file to surface according to configuration of weston.ini<br>
+ * 4/ set up UI by using ivi-hmi-controller protocol<br>
+ * 5/ Enter event loop<br>
+ * 6/ If a surface receives touch/pointer event, followings are invoked according<br>
+ * to type of event and surface<br>
+ * 6-1/ If a surface to launch ivi_application receive touch up, it execs<br>
+ * ivi-application configured in weston.ini.<br>
+ * 6-2/ If a surface to switch layout mode receive touch up, it sends a request,<br>
+ * ivi_hmi_controller_switch_mode, to hmi-controller.<br>
+ * 6-3/ If a surface to show workspace having launchers, it sends a request,<br>
+ * ivi_hmi_controller_home, to hmi-controller.<br>
+ * 6-4/ If touch down events happens in workspace,<br>
+ * ivi_hmi_controller_workspace_control is sent to slide workspace.<br>
+ * When control finished, event: ivi_hmi_controller_workspace_end_control<br>
+ * is received.<br>
+ */<br>
+<br>
+/*****************************************************************************<br>
+ * structure, globals<br>
+ ****************************************************************************/<br>
+enum cursor_type {<br>
+ CURSOR_BOTTOM_LEFT,<br>
+ CURSOR_BOTTOM_RIGHT,<br>
+ CURSOR_BOTTOM,<br>
+ CURSOR_DRAGGING,<br>
+ CURSOR_LEFT_PTR,<br>
+ CURSOR_LEFT,<br>
+ CURSOR_RIGHT,<br>
+ CURSOR_TOP_LEFT,<br>
+ CURSOR_TOP_RIGHT,<br>
+ CURSOR_TOP,<br>
+ CURSOR_IBEAM,<br>
+ CURSOR_HAND1,<br>
+ CURSOR_WATCH,<br>
+<br>
+ CURSOR_BLANK<br>
+};<br>
+struct wlContextCommon {<br>
+ struct wl_display *wlDisplay;<br>
+ struct wl_registry *wlRegistry;<br>
+ struct wl_compositor *wlCompositor;<br>
+ struct wl_shm *wlShm;<br>
+ struct wl_seat *wlSeat;<br>
+ struct wl_pointer *wlPointer;<br>
+ struct wl_touch *wlTouch;<br>
+ struct ivi_application *iviApplication;<br>
+ struct ivi_hmi_controller *hmiCtrl;<br>
+ struct hmi_homescreen_setting *hmi_setting;<br>
+ struct wl_list *list_wlContextStruct;<br>
+ struct wl_surface *enterSurface;<br>
+ int32_t is_home_on;<br>
+ struct wl_cursor_theme *cursor_theme;<br>
+ struct wl_cursor **cursors;<br>
+ struct wl_surface *pointer_surface;<br>
+ enum cursor_type current_cursor;<br>
+ uint32_t enter_serial;<br>
+};<br>
+<br>
+struct wlContextStruct {<br>
+ struct wlContextCommon cmm;<br>
+ struct wl_surface *wlSurface;<br>
+ struct wl_buffer *wlBuffer;<br>
+ uint32_t formats;<br>
+ cairo_surface_t *ctx_image;<br>
+ void *data;<br>
+ uint32_t id_surface;<br>
+ struct wl_list link;<br>
+};<br>
+<br>
+struct<br>
+hmi_homescreen_srf {<br>
+ uint32_t id;<br>
+ char *filePath;<br>
+ uint32_t color;<br>
+};<br>
+<br>
+struct<br>
+hmi_homescreen_workspace {<br>
+ struct wl_array launcher_id_array;<br>
+ struct wl_list link;<br>
+};<br>
+<br>
+struct<br>
+hmi_homescreen_launcher {<br>
+ uint32_t icon_surface_id;<br>
+ uint32_t workspace_id;<br>
+ char* icon;<br>
+ char* path;<br>
+ struct wl_list link;<br>
+};<br>
+<br>
+struct<br>
+hmi_homescreen_setting {<br>
+ struct hmi_homescreen_srf background;<br>
+ struct hmi_homescreen_srf panel;<br>
+ struct hmi_homescreen_srf tiling;<br>
+ struct hmi_homescreen_srf sidebyside;<br>
+ struct hmi_homescreen_srf fullscreen;<br>
+ struct hmi_homescreen_srf random;<br>
+ struct hmi_homescreen_srf home;<br>
+ struct hmi_homescreen_srf workspace_background;<br>
+<br>
+ struct wl_list workspace_list;<br>
+ struct wl_list launcher_list;<br>
+<br>
+ char *cursor_theme;<br>
+ int32_t cursor_size;<br>
+};<br>
+<br>
+volatile int gRun = 0;<br>
+<br>
+static void *<br>
+fail_on_null(void *p, size_t size, char* file, int32_t line)<br>
+{<br>
+ if (size && !p) {<br>
+ fprintf(stderr, "%s(%d) %zd: out of memory\n", file, line, size);<br>
+ exit(EXIT_FAILURE);<br>
+ }<br>
+<br>
+ return p;<br>
+}<br>
+<br>
+static void *<br>
+mem_alloc(size_t size, char* file, int32_t line)<br>
+{<br>
+ return fail_on_null(calloc(1, size), size, file, line);<br>
+}<br>
+<br>
+#define MEM_ALLOC(s) mem_alloc((s),__FILE__,__LINE__)<br>
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])<br>
+<br>
+/*****************************************************************************<br>
+ * Event Handler<br>
+ ****************************************************************************/<br>
+<br>
+static void<br>
+shm_format(void* data, struct wl_shm* pWlShm, uint32_t format)<br>
+{<br>
+ struct wlContextStruct* pDsp = data;<br>
+ pDsp->formats |= (1 << format);<br>
+}<br>
+<br>
+static struct wl_shm_listener shm_listenter = {<br>
+ shm_format<br>
+};<br>
+<br>
+static int32_t<br>
+getIdOfWlSurface(struct wlContextCommon *pCtx, struct wl_surface *wlSurface)<br>
+{<br>
+ if (NULL == pCtx ||<br>
+ NULL == wlSurface ) {<br>
+ return 0;<br>
+ }<br>
+<br>
+ struct wlContextStruct* pWlCtxSt = NULL;<br>
+ wl_list_for_each(pWlCtxSt, pCtx->list_wlContextStruct, link) {<br>
+ if (pWlCtxSt->wlSurface == wlSurface) {<br>
+ return pWlCtxSt->id_surface;<br>
+ }<br>
+ continue;<br>
+ }<br>
+ return -1;<br>
+}<br>
+<br>
+static void<br>
+set_pointer_image(struct wlContextCommon *pCtx, uint32_t index)<br>
+{<br>
+ if (!pCtx->wlPointer ||<br>
+ !pCtx->cursors) {<br>
+ return;<br>
+ }<br>
+<br>
+ if (CURSOR_BLANK == pCtx->current_cursor) {<br>
+ wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,<br>
+ NULL, 0, 0);<br>
+ return;<br>
+ }<br>
+<br>
+ struct wl_cursor *cursor = pCtx->cursors[pCtx->current_cursor];<br>
+ if (!cursor) {<br>
+ return;<br>
+ }<br>
+<br>
+ if (cursor->image_count <= index) {<br>
+ fprintf(stderr, "cursor index out of range\n");<br>
+ return;<br>
+ }<br>
+<br>
+ struct wl_cursor_image *image = cursor->images[index];<br>
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);<br>
+<br>
+ if (!buffer) {<br>
+ return;<br>
+ }<br>
+<br>
+ wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,<br>
+ pCtx->pointer_surface,<br>
+ image->hotspot_x, image->hotspot_y);<br>
+<br>
+ wl_surface_attach(pCtx->pointer_surface, buffer, 0, 0);<br>
+<br>
+ wl_surface_damage(pCtx->pointer_surface, 0, 0,<br>
+ image->width, image->height);<br>
+<br>
+ wl_surface_commit(pCtx->pointer_surface);<br>
+}<br>
+<br>
+static void<br>
+PointerHandleEnter(void* data, struct wl_pointer* wlPointer, uint32_t serial,<br>
+ struct wl_surface* wlSurface, wl_fixed_t sx, wl_fixed_t sy)<br>
+{<br>
+ (void)wlPointer;<br>
+ (void)serial;<br>
+<br>
+ struct wlContextCommon *pCtx = data;<br>
+ pCtx->enter_serial = serial;<br>
+ pCtx->enterSurface = wlSurface;<br>
+ set_pointer_image(pCtx, 0);<br>
+#ifdef _DEBUG<br>
+ printf("ENTER PointerHandleEnter: x(%d), y(%d)\n", sx, sy);<br>
+#endif<br>
+}<br>
+<br>
+static void<br>
+PointerHandleLeave(void* data, struct wl_pointer* wlPointer, uint32_t serial,<br>
+ struct wl_surface* wlSurface)<br>
+{<br>
+ (void)wlPointer;<br>
+ (void)wlSurface;<br>
+<br>
+ struct wlContextCommon *pCtx = data;<br>
+ pCtx->enterSurface = NULL;<br>
+<br>
+#ifdef _DEBUG<br>
+ printf("ENTER PointerHandleLeave: serial(%d)\n", serial);<br>
+#endif<br>
+}<br>
+<br>
+static void<br>
+PointerHandleMotion(void* data, struct wl_pointer* wlPointer, uint32_t time,<br>
+ wl_fixed_t sx, wl_fixed_t sy)<br>
+{<br>
+ (void)data;<br>
+ (void)wlPointer;<br>
+ (void)time;<br>
+<br>
+#ifdef _DEBUG<br>
+ printf("ENTER PointerHandleMotion: x(%d), y(%d)\n", gPointerX, gPointerY);<br>
+#endif<br>
+}<br>
+<br>
+/**<br>
+ * if a surface assigned as launcher receives touch-off event, invoking<br>
+ * ivi-application which configured in weston.ini with path to binary.<br>
+ */<br>
+extern char **environ; /*defied by libc */<br>
+<br>
+static pid_t execute_process(char* path, char *argv[])<br>
+{<br>
+ pid_t pid = fork();<br>
+ if (pid < 0) {<br>
+ fprintf(stderr, "Failed to fork\n");<br>
+ }<br>
+<br>
+ if (pid) {<br>
+ return pid;<br>
+ }<br>
+<br>
+ if (-1 == execve(path, argv, environ)) {<br>
+ fprintf(stderr, "Failed to execve %s\n", path);<br>
+ exit(1);<br>
+ }<br>
+<br>
+ return pid;<br>
+}<br>
+<br>
+static int32_t<br>
+launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)<br>
+{<br>
+ struct hmi_homescreen_launcher *launcher = NULL;<br>
+<br>
+ wl_list_for_each(launcher, launcher_list, link) {<br>
+ if (surfaceId != launcher->icon_surface_id) {<br>
+ continue;<br>
+ }<br>
+<br>
+ char *argv[] = {NULL};<br>
+ execute_process(launcher->path, argv);<br>
+<br>
+ return 1;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+/**<br>
+ * is-method to identify a surface set as launcher in workspace or workspace<br>
+ * itself. This is-method is used to decide whether request;<br>
+ * ivi_hmi_controller_workspace_control is sent or not.<br>
+ */<br>
+static int32_t<br>
+isWorkspaceSurface(uint32_t id, struct hmi_homescreen_setting *hmi_setting)<br>
+{<br>
+ if (id == hmi_setting-><a href="http://workspace_background.id" target="_blank">workspace_background.id</a>) {<br>
+ return 1;<br>
+ }<br>
+<br>
+ struct hmi_homescreen_launcher *launcher = NULL;<br>
+ wl_list_for_each(launcher, &hmi_setting->launcher_list, link) {<br>
+ if (id == launcher->icon_surface_id) {<br>
+ return 1;<br>
+ }<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+/**<br>
+ * Decide which request is sent to hmi-controller<br>
+ */<br>
+static void<br>
+touch_up(struct ivi_hmi_controller *hmi_ctrl, uint32_t id_surface,<br>
+ int32_t *is_home_on, struct hmi_homescreen_setting* hmi_setting)<br>
+{<br>
+ if (launcher_button(id_surface, &hmi_setting->launcher_list)) {<br>
+ *is_home_on = 0;<br>
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);<br>
+ } else if (id_surface == hmi_setting-><a href="http://tiling.id" target="_blank">tiling.id</a>) {<br>
+ ivi_hmi_controller_switch_mode(<br>
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING);<br>
+ } else if (id_surface == hmi_setting-><a href="http://sidebyside.id" target="_blank">sidebyside.id</a>) {<br>
+ ivi_hmi_controller_switch_mode(<br>
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE);<br>
+ } else if (id_surface == hmi_setting-><a href="http://fullscreen.id" target="_blank">fullscreen.id</a>) {<br>
+ ivi_hmi_controller_switch_mode(<br>
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN);<br>
+ } else if (id_surface == hmi_setting-><a href="http://random.id" target="_blank">random.id</a>) {<br>
+ ivi_hmi_controller_switch_mode(<br>
+ hmi_ctrl, IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM);<br>
+ } else if (id_surface == hmi_setting-><a href="http://home.id" target="_blank">home.id</a>) {<br>
+ *is_home_on = !(*is_home_on);<br>
+ if (*is_home_on) {<br>
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_ON);<br>
+ } else {<br>
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);<br>
+ }<br>
+ }<br>
+}<br>
+<br>
+/**<br>
+ * Even handler of Pointer event. IVI system is usually manipulated by touch<br>
+ * screen. However, some systems also have pointer device.<br>
+ * Release is the same behavior as touch off<br>
+ * Pressed is the same behavior as touch on<br>
+ */<br>
+static void<br>
+PointerHandleButton(void* data, struct wl_pointer* wlPointer, uint32_t serial,<br>
+ uint32_t time, uint32_t button, uint32_t state)<br>
+{<br>
+ (void)wlPointer;<br>
+ (void)serial;<br>
+ (void)time;<br>
+ struct wlContextCommon *pCtx = data;<br>
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;<br>
+<br>
+ if (BTN_RIGHT == button) {<br>
+ return;<br>
+ }<br>
+<br>
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);<br>
+<br>
+ switch (state) {<br>
+ case WL_POINTER_BUTTON_STATE_RELEASED:<br>
+ touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on, pCtx->hmi_setting);<br>
+ break;<br>
+<br>
+ case WL_POINTER_BUTTON_STATE_PRESSED:<br>
+<br>
+ if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {<br>
+ ivi_hmi_controller_workspace_control(hmi_ctrl, pCtx->wlSeat, serial);<br>
+ }<br>
+<br>
+ break;<br>
+ }<br>
+#ifdef _DEBUG<br>
+ printf("ENTER PointerHandleButton: button(%d), state(%d)\n", button, state);<br>
+#endif<br>
+}<br>
+<br>
+static void<br>
+PointerHandleAxis(void* data, struct wl_pointer* wlPointer, uint32_t time,<br>
+ uint32_t axis, wl_fixed_t value)<br>
+{<br>
+ (void)data;<br>
+ (void)wlPointer;<br>
+ (void)time;<br>
+#ifdef _DEBUG<br>
+ printf("ENTER PointerHandleAxis: axis(%d), value(%d)\n", axis, value);<br>
+#endif<br>
+}<br>
+<br>
+static struct wl_pointer_listener pointer_listener = {<br>
+ PointerHandleEnter,<br>
+ PointerHandleLeave,<br>
+ PointerHandleMotion,<br>
+ PointerHandleButton,<br>
+ PointerHandleAxis<br>
+};<br>
+<br>
+/**<br>
+ * Even handler of touch event<br>
+ */<br>
+static void<br>
+TouchHandleDown(void *data, struct wl_touch *wlTouch, uint32_t serial, uint32_t time,<br>
+ struct wl_surface *surface, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)<br>
+{<br>
+ struct wlContextCommon *pCtx = data;<br>
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;<br>
+<br>
+ if (0 == id){<br>
+ pCtx->enterSurface = surface;<br>
+ }<br>
+<br>
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);<br>
+<br>
+ /**<br>
+ * When touch down happens on surfaces of workspace, ask hmi-controller to start<br>
+ * control workspace to select page of workspace.<br>
+ * After sending seat to hmi-controller by ivi_hmi_controller_workspace_control,<br>
+ * hmi-controller-homescreen doesn't receive any event till hmi-controller sends<br>
+ * back it.<br>
+ */<br>
+ if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {<br>
+ ivi_hmi_controller_workspace_control(hmi_ctrl, pCtx->wlSeat, serial);<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+TouchHandleUp(void *data, struct wl_touch *wlTouch, uint32_t serial, uint32_t time,<br>
+ int32_t id)<br>
+{<br>
+ (void)serial;<br>
+ (void)time;<br>
+ struct wlContextCommon *pCtx = data;<br>
+ struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;<br>
+<br>
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);<br>
+<br>
+ /**<br>
+ * triggering event according to touch-up happening on which surface.<br>
+ */<br>
+ if (id == 0){<br>
+ touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on, pCtx->hmi_setting);<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+TouchHandleMotion(void *data, struct wl_touch *wlTouch, uint32_t time,<br>
+ int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)<br>
+{<br>
+}<br>
+<br>
+static void<br>
+TouchHandleFrame(void *data, struct wl_touch *wlTouch)<br>
+{<br>
+}<br>
+<br>
+static void<br>
+TouchHandleCancel(void *data, struct wl_touch *wlTouch)<br>
+{<br>
+}<br>
+<br>
+static struct wl_touch_listener touch_listener = {<br>
+ TouchHandleDown,<br>
+ TouchHandleUp,<br>
+ TouchHandleMotion,<br>
+ TouchHandleFrame,<br>
+ TouchHandleCancel,<br>
+};<br>
+<br>
+/**<br>
+ * Handler of capabilities<br>
+ */<br>
+static void<br>
+seat_handle_capabilities(void* data, struct wl_seat* seat, uint32_t caps)<br>
+{<br>
+ (void)seat;<br>
+ struct wlContextCommon* p_wlCtx = (struct wlContextCommon*)data;<br>
+ struct wl_seat* wlSeat = p_wlCtx->wlSeat;<br>
+ struct wl_pointer* wlPointer = p_wlCtx->wlPointer;<br>
+ struct wl_touch* wlTouch = p_wlCtx->wlTouch;<br>
+<br>
+ if (p_wlCtx->hmi_setting->cursor_theme) {<br>
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlPointer){<br>
+ wlPointer = wl_seat_get_pointer(wlSeat);<br>
+ wl_pointer_set_user_data(wlPointer, data);<br>
+ wl_pointer_add_listener(wlPointer, &pointer_listener, data);<br>
+ } else<br>
+ if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlPointer){<br>
+ wl_pointer_destroy(wlPointer);<br>
+ wlPointer = NULL;<br>
+ }<br>
+ p_wlCtx->wlPointer = wlPointer;<br>
+ }<br>
+<br>
+ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wlTouch){<br>
+ wlTouch = wl_seat_get_touch(wlSeat);<br>
+ wl_touch_set_user_data(wlTouch, data);<br>
+ wl_touch_add_listener(wlTouch, &touch_listener, data);<br>
+ } else<br>
+ if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wlTouch){<br>
+ wl_touch_destroy(wlTouch);<br>
+ wlTouch = NULL;<br>
+ }<br>
+ p_wlCtx->wlTouch = wlTouch;<br>
+}<br>
+<br>
+static struct wl_seat_listener seat_Listener = {<br>
+ seat_handle_capabilities,<br>
+};<br>
+<br>
+/**<br>
+ * Registration of event<br>
+ * This event is received when hmi-controller server finished controlling<br>
+ * workspace.<br>
+ */<br>
+static void<br>
+ivi_hmi_controller_workspace_end_control(void *data,<br>
+ struct ivi_hmi_controller *hmi_ctrl,<br>
+ int32_t is_controlled)<br>
+{<br>
+ if (is_controlled) {<br>
+ return;<br>
+ }<br>
+<br>
+ struct wlContextCommon *pCtx = data;<br>
+ const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);<br>
+<br>
+ /**<br>
+ * During being controlled by hmi-controller, any input event is not<br>
+ * notified. So when control ends with touch up, it invokes launcher<br>
+ * if up event happens on a launcher surface.<br>
+ *<br>
+ */<br>
+ if (launcher_button(id_surface, &pCtx->hmi_setting->launcher_list)) {<br>
+ pCtx->is_home_on = 0;<br>
+ ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);<br>
+ }<br>
+}<br>
+<br>
+static const struct ivi_hmi_controller_listener hmi_controller_listener = {<br>
+ ivi_hmi_controller_workspace_end_control<br>
+};<br>
+<br>
+/**<br>
+ * Registration of interfaces<br>
+ */<br>
+static void<br>
+registry_handle_global(void* data, struct wl_registry* registry, uint32_t name,<br>
+ const char *interface, uint32_t version)<br>
+{<br>
+ (void)version;<br>
+ struct wlContextCommon* p_wlCtx = (struct wlContextCommon*)data;<br>
+<br>
+ do {<br>
+ if (!strcmp(interface, "wl_compositor")) {<br>
+ p_wlCtx->wlCompositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);<br>
+ break;<br>
+ }<br>
+ if (!strcmp(interface, "wl_shm")) {<br>
+ p_wlCtx->wlShm = wl_registry_bind(registry, name, &wl_shm_interface, 1);<br>
+ wl_shm_add_listener(p_wlCtx->wlShm, &shm_listenter, p_wlCtx);<br>
+ break;<br>
+ }<br>
+ if (!strcmp(interface, "wl_seat")) {<br>
+ p_wlCtx->wlSeat = wl_registry_bind(registry, name, &wl_seat_interface, 1);<br>
+ wl_seat_add_listener(p_wlCtx->wlSeat, &seat_Listener, data);<br>
+ break;<br>
+ }<br>
+ if (!strcmp(interface, "ivi_application")) {<br>
+ p_wlCtx->iviApplication = wl_registry_bind(registry, name, &ivi_application_interface, 1);<br>
+ break;<br>
+ }<br>
+ if (!strcmp(interface, "ivi_hmi_controller")) {<br>
+ p_wlCtx->hmiCtrl = wl_registry_bind(registry, name, &ivi_hmi_controller_interface, 1);<br>
+<br>
+ if (p_wlCtx->hmiCtrl) {<br>
+ ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl, &hmi_controller_listener, p_wlCtx);<br>
+ }<br>
+ break;<br>
+ }<br>
+<br>
+ } while(0);<br>
+}<br>
+<br>
+static const struct wl_registry_listener registry_listener = {<br>
+ registry_handle_global,<br>
+ NULL<br>
+};<br>
+<br>
+static void<br>
+frame_listener_func(void *data, struct wl_callback *callback, uint32_t time)<br>
+{<br>
+ if (callback) {<br>
+ wl_callback_destroy(callback);<br>
+ }<br>
+}<br>
+<br>
+static const struct wl_callback_listener frame_listener = {<br>
+ frame_listener_func<br>
+};<br>
+<br>
+/*<br>
+ * The following correspondences between file names and cursors was copied<br>
+ * from: <a href="https://bugs.kde.org/attachment.cgi?id=67313" target="_blank">https://bugs.kde.org/attachment.cgi?id=67313</a><br>
+ */<br>
+static const char *bottom_left_corners[] = {<br>
+ "bottom_left_corner",<br>
+ "sw-resize",<br>
+ "size_bdiag"<br>
+};<br>
+<br>
+static const char *bottom_right_corners[] = {<br>
+ "bottom_right_corner",<br>
+ "se-resize",<br>
+ "size_fdiag"<br>
+};<br>
+<br>
+static const char *bottom_sides[] = {<br>
+ "bottom_side",<br>
+ "s-resize",<br>
+ "size_ver"<br>
+};<br>
+<br>
+static const char *grabbings[] = {<br>
+ "grabbing",<br>
+ "closedhand",<br>
+ "208530c400c041818281048008011002"<br>
+};<br>
+<br>
+static const char *left_ptrs[] = {<br>
+ "left_ptr",<br>
+ "default",<br>
+ "top_left_arrow",<br>
+ "left-arrow"<br>
+};<br>
+<br>
+static const char *left_sides[] = {<br>
+ "left_side",<br>
+ "w-resize",<br>
+ "size_hor"<br>
+};<br>
+<br>
+static const char *right_sides[] = {<br>
+ "right_side",<br>
+ "e-resize",<br>
+ "size_hor"<br>
+};<br>
+<br>
+static const char *top_left_corners[] = {<br>
+ "top_left_corner",<br>
+ "nw-resize",<br>
+ "size_fdiag"<br>
+};<br>
+<br>
+static const char *top_right_corners[] = {<br>
+ "top_right_corner",<br>
+ "ne-resize",<br>
+ "size_bdiag"<br>
+};<br>
+<br>
+static const char *top_sides[] = {<br>
+ "top_side",<br>
+ "n-resize",<br>
+ "size_ver"<br>
+};<br>
+<br>
+static const char *xterms[] = {<br>
+ "xterm",<br>
+ "ibeam",<br>
+ "text"<br>
+};<br>
+<br>
+static const char *hand1s[] = {<br>
+ "hand1",<br>
+ "pointer",<br>
+ "pointing_hand",<br>
+ "e29285e634086352946a0e7090d73106"<br>
+};<br>
+<br>
+static const char *watches[] = {<br>
+ "watch",<br>
+ "wait",<br>
+ "0426c94ea35c87780ff01dc239897213"<br>
+};<br>
+<br>
+struct cursor_alternatives {<br>
+ const char **names;<br>
+ size_t count;<br>
+};<br>
+<br>
+static const struct cursor_alternatives cursors[] = {<br>
+ {bottom_left_corners, ARRAY_LENGTH(bottom_left_corners)},<br>
+ {bottom_right_corners, ARRAY_LENGTH(bottom_right_corners)},<br>
+ {bottom_sides, ARRAY_LENGTH(bottom_sides)},<br>
+ {grabbings, ARRAY_LENGTH(grabbings)},<br>
+ {left_ptrs, ARRAY_LENGTH(left_ptrs)},<br>
+ {left_sides, ARRAY_LENGTH(left_sides)},<br>
+ {right_sides, ARRAY_LENGTH(right_sides)},<br>
+ {top_left_corners, ARRAY_LENGTH(top_left_corners)},<br>
+ {top_right_corners, ARRAY_LENGTH(top_right_corners)},<br>
+ {top_sides, ARRAY_LENGTH(top_sides)},<br>
+ {xterms, ARRAY_LENGTH(xterms)},<br>
+ {hand1s, ARRAY_LENGTH(hand1s)},<br>
+ {watches, ARRAY_LENGTH(watches)},<br>
+};<br>
+<br>
+static void<br>
+create_cursors(struct wlContextCommon *cmm)<br>
+{<br>
+ uint32_t i = 0;<br>
+ uint32_t j = 0;<br>
+ struct wl_cursor *cursor = NULL;<br>
+ char* cursor_theme = cmm->hmi_setting->cursor_theme;<br>
+ int32_t cursor_size = cmm->hmi_setting->cursor_size;<br>
+<br>
+ cmm->cursor_theme = wl_cursor_theme_load(cursor_theme, cursor_size, cmm->wlShm);<br>
+<br>
+ cmm->cursors = MEM_ALLOC(ARRAY_LENGTH(cursors) * sizeof(cmm->cursors[0]));<br>
+<br>
+ for (i = 0; i < ARRAY_LENGTH(cursors); i++) {<br>
+ cursor = NULL;<br>
+<br>
+ for (j = 0; !cursor && j < cursors[i].count; ++j) {<br>
+ cursor = wl_cursor_theme_get_cursor(<br>
+ cmm->cursor_theme, cursors[i].names[j]);<br>
+ }<br>
+<br>
+ if (!cursor) {<br>
+ fprintf(stderr, "could not load cursor '%s'\n",<br>
+ cursors[i].names[0]);<br>
+ }<br>
+<br>
+ cmm->cursors[i] = cursor;<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+destroy_cursors(struct wlContextCommon *cmm)<br>
+{<br>
+ if (cmm->cursor_theme) {<br>
+ wl_cursor_theme_destroy(cmm->cursor_theme);<br>
+ }<br>
+<br>
+ free(cmm->cursors);<br>
+}<br>
+<br>
+/**<br>
+ * Internal method to prepare parts of UI<br>
+ */<br>
+static void<br>
+createShmBuffer(struct wlContextStruct *p_wlCtx)<br>
+{<br>
+ struct wl_shm_pool *pool;<br>
+<br>
+ char filename[] = "/tmp/wayland-shm-XXXXXX";<br>
+ int fd = -1;<br>
+ int size = 0;<br>
+ int width = 0;<br>
+ int height = 0;<br>
+ int stride = 0;<br>
+<br>
+ fd = mkstemp(filename);<br>
+ if (fd < 0) {<br>
+ fprintf(stderr, "open %s failed: %m\n", filename);<br>
+ return;<br>
+ }<br>
+<br>
+ width = cairo_image_surface_get_width(p_wlCtx->ctx_image);<br>
+ height = cairo_image_surface_get_height(p_wlCtx->ctx_image);<br>
+ stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);<br>
+<br>
+ size = stride * height;<br>
+ if (ftruncate(fd, size) < 0) {<br>
+ fprintf(stderr, "ftruncate failed: %m\n");<br>
+ close(fd);<br>
+ return;<br>
+ }<br>
+<br>
+ p_wlCtx->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);<br>
+<br>
+ if (MAP_FAILED == p_wlCtx->data) {<br>
+ fprintf(stderr, "mmap failed: %m\n");<br>
+ close(fd);<br>
+ return;<br>
+ }<br>
+<br>
+ pool = wl_shm_create_pool(p_wlCtx->cmm.wlShm, fd, size);<br>
+ p_wlCtx->wlBuffer = wl_shm_pool_create_buffer(pool, 0,<br>
+ width,<br>
+ height,<br>
+ stride,<br>
+ WL_SHM_FORMAT_ARGB8888);<br>
+<br>
+ if (NULL == p_wlCtx->wlBuffer) {<br>
+ fprintf(stderr, "wl_shm_create_buffer failed: %m\n");<br>
+ close(fd);<br>
+ return;<br>
+ }<br>
+ wl_shm_pool_destroy(pool);<br>
+ close(fd);<br>
+<br>
+ return;<br>
+}<br>
+<br>
+static void<br>
+destroyWLContextCommon(struct wlContextCommon *p_wlCtx)<br>
+{<br>
+ destroy_cursors(p_wlCtx);<br>
+<br>
+ if (p_wlCtx->pointer_surface) {<br>
+ wl_surface_destroy(p_wlCtx->pointer_surface);<br>
+ }<br>
+<br>
+ if (p_wlCtx->wlCompositor) {<br>
+ wl_compositor_destroy(p_wlCtx->wlCompositor);<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+destroyWLContextStruct(struct wlContextStruct *p_wlCtx)<br>
+{<br>
+ if (p_wlCtx->wlSurface) {<br>
+ wl_surface_destroy(p_wlCtx->wlSurface);<br>
+ }<br>
+<br>
+ if (p_wlCtx->ctx_image) {<br>
+ cairo_surface_destroy(p_wlCtx->ctx_image);<br>
+ p_wlCtx->ctx_image = NULL;<br>
+ }<br>
+}<br>
+<br>
+static int<br>
+createWLContext(struct wlContextStruct *p_wlCtx)<br>
+{<br>
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);<br>
+<br>
+ p_wlCtx->wlSurface = wl_compositor_create_surface(p_wlCtx->cmm.wlCompositor);<br>
+ if (NULL == p_wlCtx->wlSurface) {<br>
+ printf("Error: wl_compositor_create_surface failed.\n");<br>
+ destroyWLContextCommon(&p_wlCtx->cmm);<br>
+ abort();<br>
+ }<br>
+<br>
+<br>
+ createShmBuffer(p_wlCtx);<br>
+<br>
+ wl_display_flush(p_wlCtx->cmm.wlDisplay);<br>
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static void<br>
+drawImage(struct wlContextStruct *p_wlCtx)<br>
+{<br>
+ struct wl_callback *callback;<br>
+<br>
+ int width = 0;<br>
+ int height = 0;<br>
+ int stride = 0;<br>
+ void *data = NULL;<br>
+<br>
+ width = cairo_image_surface_get_width(p_wlCtx->ctx_image);<br>
+ height = cairo_image_surface_get_height(p_wlCtx->ctx_image);<br>
+ stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);<br>
+ data = cairo_image_surface_get_data(p_wlCtx->ctx_image);<br>
+<br>
+ memcpy(p_wlCtx->data, data, stride * height);<br>
+<br>
+ wl_surface_attach(p_wlCtx->wlSurface, p_wlCtx->wlBuffer, 0, 0);<br>
+ wl_surface_damage(p_wlCtx->wlSurface, 0, 0, width, height);<br>
+<br>
+ callback = wl_surface_frame(p_wlCtx->wlSurface);<br>
+ wl_callback_add_listener(callback, &frame_listener, NULL);<br>
+<br>
+ wl_surface_commit(p_wlCtx->wlSurface);<br>
+<br>
+ wl_display_flush(p_wlCtx->cmm.wlDisplay);<br>
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);<br>
+}<br>
+<br>
+static void<br>
+create_ivisurface(struct wlContextStruct *p_wlCtx,<br>
+ uint32_t id_surface,<br>
+ cairo_surface_t* surface)<br>
+{<br>
+ struct ivi_surface *ivisurf = NULL;<br>
+<br>
+ p_wlCtx->ctx_image = surface;<br>
+<br>
+ p_wlCtx->id_surface = id_surface;<br>
+ wl_list_init(&p_wlCtx->link);<br>
+ wl_list_insert(p_wlCtx->cmm.list_wlContextStruct, &p_wlCtx->link);<br>
+<br>
+ createWLContext(p_wlCtx);<br>
+<br>
+ ivisurf = ivi_application_surface_create(p_wlCtx->cmm.iviApplication,<br>
+ id_surface, p_wlCtx->wlSurface);<br>
+ if (ivisurf == NULL) {<br>
+ fprintf(stderr, "Failed to create ivi_client_surface\n");<br>
+ return;<br>
+ }<br>
+<br>
+ drawImage(p_wlCtx);<br>
+<br>
+ wl_display_roundtrip(p_wlCtx->cmm.wlDisplay);<br>
+}<br>
+<br>
+static void<br>
+create_ivisurfaceFromFile(struct wlContextStruct *p_wlCtx,<br>
+ uint32_t id_surface,<br>
+ const char* imageFile)<br>
+{<br>
+ cairo_surface_t* surface = load_cairo_surface(imageFile);<br>
+<br>
+ if (NULL == surface) {<br>
+ fprintf(stderr, "Failed to load_cairo_surface %s\n", imageFile);<br>
+ return;<br>
+ }<br>
+<br>
+ create_ivisurface(p_wlCtx, id_surface, surface);<br>
+}<br>
+<br>
+static void<br>
+set_hex_color(cairo_t *cr, uint32_t color)<br>
+{<br>
+ cairo_set_source_rgba(cr,<br>
+ ((color >> 16) & 0xff) / 255.0,<br>
+ ((color >> 8) & 0xff) / 255.0,<br>
+ ((color >> 0) & 0xff) / 255.0,<br>
+ ((color >> 24) & 0xff) / 255.0);<br>
+}<br>
+<br>
+static void<br>
+create_ivisurfaceFromColor(struct wlContextStruct *p_wlCtx,<br>
+ uint32_t id_surface,<br>
+ uint32_t width, uint32_t height,<br>
+ uint32_t color)<br>
+{<br>
+ cairo_surface_t *surface = NULL;<br>
+ cairo_t *cr = NULL;<br>
+<br>
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);<br>
+<br>
+ cr = cairo_create(surface);<br>
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);<br>
+ cairo_rectangle(cr, 0, 0, width, height);<br>
+ set_hex_color(cr, color);<br>
+ cairo_fill(cr);<br>
+ cairo_destroy(cr);<br>
+<br>
+ create_ivisurface(p_wlCtx, id_surface, surface);<br>
+}<br>
+<br>
+static void<br>
+UI_ready(struct ivi_hmi_controller *controller)<br>
+{<br>
+ ivi_hmi_controller_UI_ready(controller);<br>
+}<br>
+<br>
+/**<br>
+ * Internal method to set up UI by using ivi-hmi-controller<br>
+ */<br>
+static void<br>
+create_background(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,<br>
+ const char* imageFile)<br>
+{<br>
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);<br>
+}<br>
+<br>
+static void<br>
+create_panel(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,<br>
+ const char* imageFile)<br>
+{<br>
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);<br>
+}<br>
+<br>
+static void<br>
+create_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,<br>
+ const char* imageFile, uint32_t number)<br>
+{<br>
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);<br>
+}<br>
+<br>
+static void<br>
+create_home_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,<br>
+ const char* imageFile)<br>
+{<br>
+ create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);<br>
+}<br>
+<br>
+static void<br>
+create_workspace_background(<br>
+ struct wlContextStruct *p_wlCtx, struct hmi_homescreen_srf *srf)<br>
+{<br>
+ create_ivisurfaceFromColor(p_wlCtx, srf->id, 1, 1, srf->color);<br>
+}<br>
+<br>
+static void<br>
+create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)<br>
+{<br>
+ int launcher_count = wl_list_length(launcher_list);<br>
+<br>
+ if (0 == launcher_count) {<br>
+ return;<br>
+ }<br>
+<br>
+ struct hmi_homescreen_launcher** launchers;<br>
+ launchers = MEM_ALLOC(launcher_count * sizeof(*launchers));<br>
+<br>
+ int ii = 0;<br>
+ struct hmi_homescreen_launcher *launcher = NULL;<br>
+<br>
+ wl_list_for_each(launcher, launcher_list, link) {<br>
+ launchers[ii] = launcher;<br>
+ ii++;<br>
+ }<br>
+<br>
+ int start = 0;<br>
+<br>
+ for (ii = 0; ii < launcher_count; ii++) {<br>
+<br>
+ if (ii != launcher_count -1 &&<br>
+ launchers[ii]->workspace_id == launchers[ii + 1]->workspace_id) {<br>
+ continue;<br>
+ }<br>
+<br>
+ int jj = 0;<br>
+ for (jj = start; jj <= ii; jj++) {<br>
+ struct wlContextStruct *p_wlCtx = MEM_ALLOC(sizeof(*p_wlCtx));<br>
+ p_wlCtx->cmm = *cmm;<br>
+ create_ivisurfaceFromFile(p_wlCtx,launchers[jj]->icon_surface_id, launchers[jj]->icon);<br>
+ }<br>
+<br>
+ start = ii + 1;<br>
+ }<br>
+<br>
+ free(launchers);<br>
+}<br>
+<br>
+static void sigFunc(int signum)<br>
+{<br>
+ gRun = 0;<br>
+}<br>
+<br>
+/**<br>
+ * Internal method to read out weston.ini to get configuration<br>
+ */<br>
+static struct hmi_homescreen_setting*<br>
+hmi_homescreen_setting_create(void)<br>
+{<br>
+ struct hmi_homescreen_setting* setting = MEM_ALLOC(sizeof(*setting));<br>
+<br>
+ wl_list_init(&setting->workspace_list);<br>
+ wl_list_init(&setting->launcher_list);<br>
+<br>
+ struct weston_config *config = NULL;<br>
+ config = weston_config_parse("weston.ini");<br>
+<br>
+ struct weston_config_section *shellSection = NULL;<br>
+ shellSection = weston_config_get_section(config, "ivi-shell", NULL, NULL);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "cursor-theme", &setting->cursor_theme, NULL);<br>
+<br>
+ weston_config_section_get_int(shellSection, "cursor-size", &setting->cursor_size, 32);<br>
+<br>
+ uint32_t workspace_layer_id;<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "workspace-layer-id", &workspace_layer_id, 3000);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "background-image", &setting->background.filePath,<br>
+ DATADIR "/weston/background.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "background-id", &setting-><a href="http://background.id" target="_blank">background.id</a>, 1001);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "panel-image", &setting->panel.filePath,<br>
+ DATADIR "/weston/panel.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "panel-id", &setting-><a href="http://panel.id" target="_blank">panel.id</a>, 1002);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "tiling-image", &setting->tiling.filePath,<br>
+ DATADIR "/weston/tiling.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "tiling-id", &setting-><a href="http://tiling.id" target="_blank">tiling.id</a>, 1003);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "sidebyside-image", &setting->sidebyside.filePath,<br>
+ DATADIR "/weston/sidebyside.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "sidebyside-id", &setting-><a href="http://sidebyside.id" target="_blank">sidebyside.id</a>, 1004);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "fullscreen-image", &setting->fullscreen.filePath,<br>
+ DATADIR "/weston/fullscreen.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "fullscreen-id", &setting-><a href="http://fullscreen.id" target="_blank">fullscreen.id</a>, 1005);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "random-image", &setting->random.filePath,<br>
+ DATADIR "/weston/random.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "random-id", &setting-><a href="http://random.id" target="_blank">random.id</a>, 1006);<br>
+<br>
+ weston_config_section_get_string(<br>
+ shellSection, "home-image", &setting->home.filePath,<br>
+ DATADIR "/weston/home.png");<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "home-id", &setting-><a href="http://home.id" target="_blank">home.id</a>, 1007);<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "workspace-background-color",<br>
+ &setting->workspace_background.color, 0x99000000);<br>
+<br>
+ weston_config_section_get_uint(<br>
+ shellSection, "workspace-background-id",<br>
+ &setting-><a href="http://workspace_background.id" target="_blank">workspace_background.id</a>, 2001);<br>
+<br>
+ struct weston_config_section *section = NULL;<br>
+ const char *name = NULL;<br>
+<br>
+ uint32_t icon_surface_id = workspace_layer_id + 1;<br>
+<br>
+ while (weston_config_next_section(config, §ion, &name)) {<br>
+<br>
+ if (0 == strcmp(name, "ivi-launcher")) {<br>
+<br>
+ struct hmi_homescreen_launcher *launcher = NULL;<br>
+ launcher = MEM_ALLOC(sizeof(*launcher));<br>
+ wl_list_init(&launcher->link);<br>
+<br>
+ weston_config_section_get_string(section, "icon", &launcher->icon, NULL);<br>
+ weston_config_section_get_string(section, "path", &launcher->path, NULL);<br>
+ weston_config_section_get_uint(section, "workspace-id", &launcher->workspace_id, 0);<br>
+ weston_config_section_get_uint(section, "icon-id", &launcher->icon_surface_id, icon_surface_id);<br>
+ icon_surface_id++;<br>
+<br>
+ wl_list_insert(setting->launcher_list.prev, &launcher->link);<br>
+ }<br>
+ }<br>
+<br>
+ weston_config_destroy(config);<br>
+ return setting;<br>
+}<br>
+<br>
+/**<br>
+ * Main thread<br>
+ *<br>
+ * The basic flow are as followed,<br>
+ * 1/ read configuration from weston.ini by hmi_homescreen_setting_create<br>
+ * 2/ draw png file to surface according to configuration of weston.ini and<br>
+ * set up UI by using ivi-hmi-controller protocol by each create_* method<br>
+ */<br>
+int main(int argc, char **argv)<br>
+{<br>
+ struct wlContextCommon wlCtxCommon;<br>
+ struct wlContextStruct wlCtx_BackGround;<br>
+ struct wlContextStruct wlCtx_Panel;<br>
+ struct wlContextStruct wlCtx_Button_1;<br>
+ struct wlContextStruct wlCtx_Button_2;<br>
+ struct wlContextStruct wlCtx_Button_3;<br>
+ struct wlContextStruct wlCtx_Button_4;<br>
+ struct wlContextStruct wlCtx_HomeButton;<br>
+ struct wlContextStruct wlCtx_WorkSpaceBackGround;<br>
+ struct wl_list launcher_wlCtxList;<br>
+<br>
+ memset(&wlCtxCommon, 0x00, sizeof(wlCtxCommon));<br>
+ memset(&wlCtx_BackGround, 0x00, sizeof(wlCtx_BackGround));<br>
+ memset(&wlCtx_Panel, 0x00, sizeof(wlCtx_Panel));<br>
+ memset(&wlCtx_Button_1, 0x00, sizeof(wlCtx_Button_1));<br>
+ memset(&wlCtx_Button_2, 0x00, sizeof(wlCtx_Button_2));<br>
+ memset(&wlCtx_Button_3, 0x00, sizeof(wlCtx_Button_3));<br>
+ memset(&wlCtx_Button_4, 0x00, sizeof(wlCtx_Button_4));<br>
+ memset(&wlCtx_HomeButton, 0x00, sizeof(wlCtx_HomeButton));<br>
+ memset(&wlCtx_WorkSpaceBackGround, 0x00, sizeof(wlCtx_WorkSpaceBackGround));<br>
+ wl_list_init(&launcher_wlCtxList);<br>
+ wlCtxCommon.list_wlContextStruct = MEM_ALLOC(sizeof(struct wl_list));<br>
+ assert(wlCtxCommon.list_wlContextStruct);<br>
+ wl_list_init(wlCtxCommon.list_wlContextStruct);<br>
+<br>
+ struct hmi_homescreen_setting *hmi_setting = hmi_homescreen_setting_create();<br>
+ wlCtxCommon.hmi_setting = hmi_setting;<br>
+<br>
+ gRun = 1;<br>
+<br>
+ wlCtxCommon.wlDisplay = wl_display_connect(NULL);<br>
+ if (NULL == wlCtxCommon.wlDisplay) {<br>
+ printf("Error: wl_display_connect failed.\n");<br>
+ return -1;<br>
+ }<br>
+<br>
+ /* get wl_registry */<br>
+ wlCtxCommon.wlRegistry = wl_display_get_registry(wlCtxCommon.wlDisplay);<br>
+ wl_registry_add_listener(wlCtxCommon.wlRegistry,<br>
+ ®istry_listener, &wlCtxCommon);<br>
+ wl_display_dispatch(wlCtxCommon.wlDisplay);<br>
+ wl_display_roundtrip(wlCtxCommon.wlDisplay);<br>
+<br>
+ if (wlCtxCommon.hmi_setting->cursor_theme) {<br>
+ create_cursors(&wlCtxCommon);<br>
+<br>
+ wlCtxCommon.pointer_surface =<br>
+ wl_compositor_create_surface(wlCtxCommon.wlCompositor);<br>
+<br>
+ wlCtxCommon.current_cursor = CURSOR_LEFT_PTR;<br>
+ }<br>
+<br>
+ wlCtx_BackGround.cmm = wlCtxCommon;<br>
+ wlCtx_Panel.cmm = wlCtxCommon;<br>
+ wlCtx_Button_1.cmm = wlCtxCommon;<br>
+ wlCtx_Button_2.cmm = wlCtxCommon;<br>
+ wlCtx_Button_3.cmm = wlCtxCommon;<br>
+ wlCtx_Button_4.cmm = wlCtxCommon;<br>
+ wlCtx_HomeButton.cmm = wlCtxCommon;<br>
+ wlCtx_WorkSpaceBackGround.cmm = wlCtxCommon;<br>
+<br>
+ /* create desktop widgets */<br>
+ create_background(&wlCtx_BackGround, hmi_setting-><a href="http://background.id" target="_blank">background.id</a>,<br>
+ hmi_setting->background.filePath);<br>
+<br>
+ create_panel(&wlCtx_Panel, hmi_setting-><a href="http://panel.id" target="_blank">panel.id</a>,<br>
+ hmi_setting->panel.filePath);<br>
+<br>
+ create_button(&wlCtx_Button_1, hmi_setting-><a href="http://tiling.id" target="_blank">tiling.id</a>,<br>
+ hmi_setting->tiling.filePath, 0);<br>
+<br>
+ create_button(&wlCtx_Button_2, hmi_setting-><a href="http://sidebyside.id" target="_blank">sidebyside.id</a>,<br>
+ hmi_setting->sidebyside.filePath, 1);<br>
+<br>
+ create_button(&wlCtx_Button_3, hmi_setting-><a href="http://fullscreen.id" target="_blank">fullscreen.id</a>,<br>
+ hmi_setting->fullscreen.filePath, 2);<br>
+<br>
+ create_button(&wlCtx_Button_4, hmi_setting-><a href="http://random.id" target="_blank">random.id</a>,<br>
+ hmi_setting->random.filePath, 3);<br>
+<br>
+ create_workspace_background(&wlCtx_WorkSpaceBackGround,<br>
+ &hmi_setting->workspace_background);<br>
+<br>
+ create_launchers(&wlCtxCommon, &hmi_setting->launcher_list);<br>
+<br>
+ create_home_button(&wlCtx_HomeButton, hmi_setting-><a href="http://home.id" target="_blank">home.id</a>,<br>
+ hmi_setting->home.filePath);<br>
+<br>
+ UI_ready(wlCtxCommon.hmiCtrl);<br>
+<br>
+ /* signal handling */<br>
+ signal(SIGINT, sigFunc);<br>
+ signal(SIGKILL, sigFunc);<br>
+<br>
+ while(gRun) {<br>
+ wl_display_dispatch(wlCtxCommon.wlDisplay);<br>
+ }<br>
+<br>
+ struct wlContextStruct* pWlCtxSt = NULL;<br>
+ wl_list_for_each(pWlCtxSt, wlCtxCommon.list_wlContextStruct, link) {<br>
+ destroyWLContextStruct(pWlCtxSt);<br>
+ }<br>
+<br>
+ destroyWLContextCommon(&wlCtxCommon);<br>
+ free(wlCtxCommon.list_wlContextStruct);<br>
+<br>
+ return 0;<br>
+}<br>
diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c<br>
index 4e4e7c0..86db700 100644<br>
--- a/ivi-shell/hmi-controller.c<br>
+++ b/ivi-shell/hmi-controller.c<br>
@@ -134,6 +134,7 @@ hmi_server_setting {<br>
uint32_t workspace_background_layer_id;<br>
uint32_t workspace_layer_id;<br>
uint32_t panel_height;<br>
+ char *ivi_homescreen;<br>
};<br>
<br>
struct hmi_controller<br>
@@ -151,6 +152,10 @@ struct hmi_controller<br>
int32_t workspace_count;<br>
struct wl_array ui_widgets;<br>
int32_t is_initialized;<br>
+<br>
+ struct weston_compositor *compositor;<br>
+ struct weston_process process;<br>
+ struct wl_listener destroy_listener;<br>
};<br>
<br>
struct launcher_info<br>
@@ -830,6 +835,9 @@ hmi_server_setting_create(void)<br>
<br>
setting->panel_height = 70;<br>
<br>
+ weston_config_section_get_string(<br>
+ shellSection, "ivi-shell-user-interface", &setting->ivi_homescreen, NULL);<br>
+<br>
weston_config_destroy(config);<br>
<br>
return setting;<br>
@@ -1896,9 +1904,36 @@ bind_hmi_controller(struct wl_client *client,<br>
}<br>
<br>
static void<br>
-launch_hmi_client(void *data)<br>
+handle_hmi_client_process_sigchld(struct weston_process *proc, int status)<br>
+{<br>
+ proc->pid = 0;<br>
+}<br>
+<br>
+static void<br>
+hmi_client_destroy(struct wl_listener *listener, void *data)<br>
+{<br>
+ struct hmi_controller *hmi_ctrl =<br>
+ container_of(listener, struct hmi_controller, destroy_listener);<br>
+<br>
+ kill(hmi_ctrl->process.pid, SIGTERM);<br>
+ hmi_ctrl->process.pid = 0;<br>
+}<br>
+<br>
+static void<br>
+launch_hmi_client_process(void *data)<br>
{<br>
- /*Nothing to do here*/<br>
+ struct hmi_controller *hmi_ctrl =<br>
+ (struct hmi_controller *)data;<br>
+<br>
+ weston_client_launch(hmi_ctrl->compositor,<br>
+ &hmi_ctrl->process,<br>
+ hmi_ctrl->hmi_setting->ivi_homescreen,<br>
+ handle_hmi_client_process_sigchld);<br>
+<br>
+ hmi_ctrl->destroy_listener.notify = hmi_client_destroy;<br>
+ wl_signal_add(&hmi_ctrl->compositor->destroy_signal, &hmi_ctrl->destroy_listener);<br>
+<br>
+ free(hmi_ctrl->hmi_setting->ivi_homescreen);<br>
}<br>
<br>
/*****************************************************************************<br>
@@ -1910,6 +1945,7 @@ module_init(struct weston_compositor *ec,<br>
int *argc, char *argv[])<br>
{<br>
struct hmi_controller *hmi_ctrl = hmi_controller_create(ec);<br>
+ hmi_ctrl->compositor = ec;<br>
<br>
if (wl_global_create(ec->wl_display,<br>
&ivi_hmi_controller_interface, 1,<br>
@@ -1918,7 +1954,7 @@ module_init(struct weston_compositor *ec,<br>
}<br>
<br>
struct wl_event_loop *loop = wl_display_get_event_loop(ec->wl_display);<br>
- wl_event_loop_add_idle(loop, launch_hmi_client, ec);<br>
+ wl_event_loop_add_idle(loop, launch_hmi_client_process, hmi_ctrl);<br>
<br>
return 0;<br>
}<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br><div dir="ltr"><font>Regards,<br>
<br>
<i><b>Manuel BACHMANN</b><br>
Tizen Project<br>
VANNES-FR</i><br>
</font></div>
</div>