• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 DENSO CORPORATION
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "config.h"
25 
26 #include <sys/wait.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <linux/input.h>
33 #include <assert.h>
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <sys/mman.h>
37 #include <getopt.h>
38 #include <errno.h>
39 #include <wayland-cursor.h>
40 #include <wayland-client-protocol.h>
41 #include "shared/cairo-util.h"
42 #include <libweston/config-parser.h>
43 #include "shared/helpers.h"
44 #include "shared/os-compatibility.h"
45 #include "shared/xalloc.h"
46 #include <libweston/zalloc.h>
47 #include "shared/file-util.h"
48 #include "ivi-application-client-protocol.h"
49 #include "ivi-hmi-controller-client-protocol.h"
50 
51 /**
52  * A reference implementation how to use ivi-hmi-controller interface to
53  * interact with hmi-controller. This is launched from hmi-controller by using
54  * hmi_client_start and create a pthread.
55  *
56  * The basic flow is as followed,
57  * 1/ read configuration from weston.ini.
58  * 2/ draw png file to surface according to configuration of weston.ini
59  * 3/ set up UI by using ivi-hmi-controller protocol
60  * 4/ Enter event loop
61  * 5/ If a surface receives touch/pointer event, followings are invoked
62  *	according to type of event and surface
63  * 5-1/ If a surface to launch ivi_application receive touch up, it execs
64  *	  ivi-application configured in weston.ini.
65  * 5-2/ If a surface to switch layout mode receive touch up, it sends a request,
66  *	  ivi_hmi_controller_switch_mode, to hmi-controller.
67  * 5-3/ If a surface to show workspace having launchers, it sends a request,
68  *	  ivi_hmi_controller_home, to hmi-controller.
69  * 5-4/ If touch down events happens in workspace,
70  *	  ivi_hmi_controller_workspace_control is sent to slide workspace.
71  *	  When control finished, event: ivi_hmi_controller_workspace_end_control
72  *	  is received.
73  */
74 
75 /*****************************************************************************
76  *  structure, globals
77  ****************************************************************************/
78 enum cursor_type {
79 	CURSOR_BOTTOM_LEFT,
80 	CURSOR_BOTTOM_RIGHT,
81 	CURSOR_BOTTOM,
82 	CURSOR_DRAGGING,
83 	CURSOR_LEFT_PTR,
84 	CURSOR_LEFT,
85 	CURSOR_RIGHT,
86 	CURSOR_TOP_LEFT,
87 	CURSOR_TOP_RIGHT,
88 	CURSOR_TOP,
89 	CURSOR_IBEAM,
90 	CURSOR_HAND1,
91 	CURSOR_WATCH,
92 
93 	CURSOR_BLANK
94 };
95 struct wlContextCommon {
96 	struct wl_display		*wlDisplay;
97 	struct wl_registry		*wlRegistry;
98 	struct wl_compositor		*wlCompositor;
99 	struct wl_shm			*wlShm;
100 	uint32_t			formats;
101 	struct wl_seat			*wlSeat;
102 	struct wl_pointer		*wlPointer;
103 	struct wl_touch			*wlTouch;
104 	struct ivi_application		*iviApplication;
105 	struct ivi_hmi_controller	*hmiCtrl;
106 	struct hmi_homescreen_setting	*hmi_setting;
107 	struct wl_list			list_wlContextStruct;
108 	struct wl_surface		*enterSurface;
109 	int32_t				is_home_on;
110 	struct wl_cursor_theme		*cursor_theme;
111 	struct wl_cursor		**cursors;
112 	struct wl_surface		*pointer_surface;
113 	enum   cursor_type		current_cursor;
114 	uint32_t			enter_serial;
115 };
116 
117 struct wlContextStruct {
118 	struct wlContextCommon	*cmm;
119 	struct wl_surface	*wlSurface;
120 	struct wl_buffer	*wlBuffer;
121 	cairo_surface_t		*ctx_image;
122 	void			*data;
123 	uint32_t		id_surface;
124 	struct wl_list		link;
125 };
126 
127 struct
128 hmi_homescreen_srf {
129 	uint32_t	id;
130 	char		*filePath;
131 	uint32_t	color;
132 };
133 
134 struct
135 hmi_homescreen_workspace {
136 	struct wl_array	launcher_id_array;
137 	struct wl_list	link;
138 };
139 
140 struct
141 hmi_homescreen_launcher {
142 	uint32_t	icon_surface_id;
143 	uint32_t	workspace_id;
144 	char		*icon;
145 	char		*path;
146 	struct wl_list	link;
147 };
148 
149 struct
150 hmi_homescreen_setting {
151 	struct hmi_homescreen_srf background;
152 	struct hmi_homescreen_srf panel;
153 	struct hmi_homescreen_srf tiling;
154 	struct hmi_homescreen_srf sidebyside;
155 	struct hmi_homescreen_srf fullscreen;
156 	struct hmi_homescreen_srf random;
157 	struct hmi_homescreen_srf home;
158 	struct hmi_homescreen_srf workspace_background;
159 
160 	struct wl_list workspace_list;
161 	struct wl_list launcher_list;
162 
163 	char		*cursor_theme;
164 	int32_t		cursor_size;
165 	uint32_t	transition_duration;
166 	uint32_t	surface_id_offset;
167 	int32_t		screen_num;
168 };
169 
170 /*****************************************************************************
171  *  Event Handler
172  ****************************************************************************/
173 
174 static void
shm_format(void * data,struct wl_shm * pWlShm,uint32_t format)175 shm_format(void *data, struct wl_shm *pWlShm, uint32_t format)
176 {
177 	struct wlContextCommon *pCtx = data;
178 
179 	pCtx->formats |= (1 << format);
180 }
181 
182 static struct wl_shm_listener shm_listenter = {
183 	shm_format
184 };
185 
186 static int32_t
getIdOfWlSurface(struct wlContextCommon * pCtx,struct wl_surface * wlSurface)187 getIdOfWlSurface(struct wlContextCommon *pCtx, struct wl_surface *wlSurface)
188 {
189 	struct wlContextStruct *pWlCtxSt = NULL;
190 
191 	if (NULL == pCtx || NULL == wlSurface )
192 		return 0;
193 
194 	wl_list_for_each(pWlCtxSt, &pCtx->list_wlContextStruct, link) {
195 		if (pWlCtxSt->wlSurface == wlSurface)
196 			return pWlCtxSt->id_surface;
197 	}
198 
199 	return -1;
200 }
201 
202 static void
set_pointer_image(struct wlContextCommon * pCtx,uint32_t index)203 set_pointer_image(struct wlContextCommon *pCtx, uint32_t index)
204 {
205 	struct wl_cursor *cursor = NULL;
206 	struct wl_cursor_image *image = NULL;
207 	struct wl_buffer *buffer = NULL;
208 
209 	if (!pCtx->wlPointer || !pCtx->cursors)
210 		return;
211 
212 	if (CURSOR_BLANK == pCtx->current_cursor) {
213 		wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,
214 							  NULL, 0, 0);
215 		return;
216 	}
217 
218 	cursor = pCtx->cursors[pCtx->current_cursor];
219 	if (!cursor)
220 		return;
221 
222 	if (cursor->image_count <= index) {
223 		fprintf(stderr, "cursor index out of range\n");
224 		return;
225 	}
226 
227 	image = cursor->images[index];
228 	buffer = wl_cursor_image_get_buffer(image);
229 
230 	if (!buffer)
231 		return;
232 
233 	wl_pointer_set_cursor(pCtx->wlPointer, pCtx->enter_serial,
234 			      pCtx->pointer_surface,
235 			      image->hotspot_x, image->hotspot_y);
236 
237 	wl_surface_attach(pCtx->pointer_surface, buffer, 0, 0);
238 
239 	wl_surface_damage(pCtx->pointer_surface, 0, 0,
240 					  image->width, image->height);
241 
242 	wl_surface_commit(pCtx->pointer_surface);
243 }
244 
245 static void
PointerHandleEnter(void * data,struct wl_pointer * wlPointer,uint32_t serial,struct wl_surface * wlSurface,wl_fixed_t sx,wl_fixed_t sy)246 PointerHandleEnter(void *data, struct wl_pointer *wlPointer, uint32_t serial,
247 		   struct wl_surface *wlSurface, wl_fixed_t sx, wl_fixed_t sy)
248 {
249 	struct wlContextCommon *pCtx = data;
250 
251 	pCtx->enter_serial = serial;
252 	pCtx->enterSurface = wlSurface;
253 	set_pointer_image(pCtx, 0);
254 #ifdef _DEBUG
255 	printf("ENTER PointerHandleEnter: x(%d), y(%d)\n", sx, sy);
256 #endif
257 }
258 
259 static void
PointerHandleLeave(void * data,struct wl_pointer * wlPointer,uint32_t serial,struct wl_surface * wlSurface)260 PointerHandleLeave(void *data, struct wl_pointer *wlPointer, uint32_t serial,
261 		   struct wl_surface *wlSurface)
262 {
263 	struct wlContextCommon *pCtx = data;
264 
265 	pCtx->enterSurface = NULL;
266 
267 #ifdef _DEBUG
268 	printf("ENTER PointerHandleLeave: serial(%d)\n", serial);
269 #endif
270 }
271 
272 static void
PointerHandleMotion(void * data,struct wl_pointer * wlPointer,uint32_t time,wl_fixed_t sx,wl_fixed_t sy)273 PointerHandleMotion(void *data, struct wl_pointer *wlPointer, uint32_t time,
274 		    wl_fixed_t sx, wl_fixed_t sy)
275 {
276 #ifdef _DEBUG
277 	printf("ENTER PointerHandleMotion: x(%d), y(%d)\n", sx, sy);
278 #endif
279 }
280 
281 /**
282  * if a surface assigned as launcher receives touch-off event, invoking
283  * ivi-application which configured in weston.ini with path to binary.
284  */
285 extern char **environ; /*defied by libc */
286 
287 static pid_t
execute_process(char * path,char * argv[])288 execute_process(char *path, char *argv[])
289 {
290 	pid_t pid = fork();
291 	if (pid < 0)
292 		fprintf(stderr, "Failed to fork\n");
293 
294 	if (pid)
295 		return pid;
296 
297 	if (-1 == execve(path, argv, environ)) {
298 		fprintf(stderr, "Failed to execve %s\n", path);
299 		exit(1);
300 	}
301 
302 	return pid;
303 }
304 
305 static int32_t
launcher_button(uint32_t surfaceId,struct wl_list * launcher_list)306 launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
307 {
308 	struct hmi_homescreen_launcher *launcher = NULL;
309 
310 	wl_list_for_each(launcher, launcher_list, link) {
311 		char *argv[] = { NULL };
312 
313 		if (surfaceId != launcher->icon_surface_id)
314 			continue;
315 
316 		execute_process(launcher->path, argv);
317 
318 		return 1;
319 	}
320 
321 	return 0;
322 }
323 
324 /**
325  * is-method to identify a surface set as launcher in workspace or workspace
326  * itself. This is-method is used to decide whether request;
327  * ivi_hmi_controller_workspace_control is sent or not.
328  */
329 static int32_t
isWorkspaceSurface(uint32_t id,struct hmi_homescreen_setting * hmi_setting)330 isWorkspaceSurface(uint32_t id, struct hmi_homescreen_setting *hmi_setting)
331 {
332 	struct hmi_homescreen_launcher *launcher = NULL;
333 
334 	if (id == hmi_setting->workspace_background.id)
335 		return 1;
336 
337 	wl_list_for_each(launcher, &hmi_setting->launcher_list, link) {
338 		if (id == launcher->icon_surface_id)
339 			return 1;
340 	}
341 
342 	return 0;
343 }
344 
345 /**
346  * Decide which request is sent to hmi-controller
347  */
348 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)349 touch_up(struct ivi_hmi_controller *hmi_ctrl, uint32_t id_surface,
350 	 int32_t *is_home_on, struct hmi_homescreen_setting *hmi_setting)
351 {
352 	if (launcher_button(id_surface, &hmi_setting->launcher_list)) {
353 		*is_home_on = 0;
354 		ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
355 	} else if (id_surface == hmi_setting->tiling.id) {
356 		ivi_hmi_controller_switch_mode(hmi_ctrl,
357 				IVI_HMI_CONTROLLER_LAYOUT_MODE_TILING);
358 	} else if (id_surface == hmi_setting->sidebyside.id) {
359 		ivi_hmi_controller_switch_mode(hmi_ctrl,
360 				IVI_HMI_CONTROLLER_LAYOUT_MODE_SIDE_BY_SIDE);
361 	} else if (id_surface == hmi_setting->fullscreen.id) {
362 		ivi_hmi_controller_switch_mode(hmi_ctrl,
363 				IVI_HMI_CONTROLLER_LAYOUT_MODE_FULL_SCREEN);
364 	} else if (id_surface == hmi_setting->random.id) {
365 		ivi_hmi_controller_switch_mode(hmi_ctrl,
366 				IVI_HMI_CONTROLLER_LAYOUT_MODE_RANDOM);
367 	} else if (id_surface == hmi_setting->home.id) {
368 		*is_home_on = !(*is_home_on);
369 		if (*is_home_on) {
370 			ivi_hmi_controller_home(hmi_ctrl,
371 						IVI_HMI_CONTROLLER_HOME_ON);
372 		} else {
373 			ivi_hmi_controller_home(hmi_ctrl,
374 						IVI_HMI_CONTROLLER_HOME_OFF);
375 		}
376 	}
377 }
378 
379 /**
380  * Even handler of Pointer event. IVI system is usually manipulated by touch
381  * screen. However, some systems also have pointer device.
382  * Release is the same behavior as touch off
383  * Pressed is the same behavior as touch on
384  */
385 static void
PointerHandleButton(void * data,struct wl_pointer * wlPointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)386 PointerHandleButton(void *data, struct wl_pointer *wlPointer, uint32_t serial,
387 		    uint32_t time, uint32_t button, uint32_t state)
388 {
389 	struct wlContextCommon *pCtx = data;
390 	struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
391 	const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
392 
393 	if (BTN_RIGHT == button)
394 		return;
395 
396 	switch (state) {
397 	case WL_POINTER_BUTTON_STATE_RELEASED:
398 		touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on,
399 			 pCtx->hmi_setting);
400 		break;
401 
402 	case WL_POINTER_BUTTON_STATE_PRESSED:
403 
404 		if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {
405 			ivi_hmi_controller_workspace_control(hmi_ctrl,
406 							     pCtx->wlSeat,
407 							     serial);
408 		}
409 
410 		break;
411 	}
412 #ifdef _DEBUG
413 	printf("ENTER PointerHandleButton: button(%d), state(%d)\n",
414 	       button, state);
415 #endif
416 }
417 
418 static void
PointerHandleAxis(void * data,struct wl_pointer * wlPointer,uint32_t time,uint32_t axis,wl_fixed_t value)419 PointerHandleAxis(void *data, struct wl_pointer *wlPointer, uint32_t time,
420 		  uint32_t axis, wl_fixed_t value)
421 {
422 #ifdef _DEBUG
423 	printf("ENTER PointerHandleAxis: axis(%d), value(%d)\n", axis, value);
424 #endif
425 }
426 
427 static struct wl_pointer_listener pointer_listener = {
428 	PointerHandleEnter,
429 	PointerHandleLeave,
430 	PointerHandleMotion,
431 	PointerHandleButton,
432 	PointerHandleAxis
433 };
434 
435 /**
436  * Even handler of touch event
437  */
438 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)439 TouchHandleDown(void *data, struct wl_touch *wlTouch, uint32_t serial,
440 		uint32_t time, struct wl_surface *surface, int32_t id,
441 		wl_fixed_t x_w, wl_fixed_t y_w)
442 {
443 	struct wlContextCommon *pCtx = data;
444 	struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
445 	uint32_t id_surface = 0;
446 
447 	if (0 == id)
448 		pCtx->enterSurface = surface;
449 
450 	id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
451 
452 	/**
453 	 * When touch down happens on surfaces of workspace, ask
454 	 * hmi-controller to start control workspace to select page of
455 	 * workspace. After sending seat to hmi-controller by
456 	 * ivi_hmi_controller_workspace_control,
457 	 * hmi-controller-homescreen doesn't receive any event till
458 	 * hmi-controller sends back it.
459 	 */
460 	if (isWorkspaceSurface(id_surface, pCtx->hmi_setting)) {
461 		ivi_hmi_controller_workspace_control(hmi_ctrl, pCtx->wlSeat,
462 						     serial);
463 	}
464 }
465 
466 static void
TouchHandleUp(void * data,struct wl_touch * wlTouch,uint32_t serial,uint32_t time,int32_t id)467 TouchHandleUp(void *data, struct wl_touch *wlTouch, uint32_t serial,
468 	      uint32_t time, int32_t id)
469 {
470 	struct wlContextCommon *pCtx = data;
471 	struct ivi_hmi_controller *hmi_ctrl = pCtx->hmiCtrl;
472 
473 	const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
474 
475 	/**
476 	 * triggering event according to touch-up happening on which surface.
477 	 */
478 	if (id == 0){
479 		touch_up(hmi_ctrl, id_surface, &pCtx->is_home_on,
480 			 pCtx->hmi_setting);
481 	}
482 }
483 
484 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)485 TouchHandleMotion(void *data, struct wl_touch *wlTouch, uint32_t time,
486 		  int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
487 {
488 }
489 
490 static void
TouchHandleFrame(void * data,struct wl_touch * wlTouch)491 TouchHandleFrame(void *data, struct wl_touch *wlTouch)
492 {
493 }
494 
495 static void
TouchHandleCancel(void * data,struct wl_touch * wlTouch)496 TouchHandleCancel(void *data, struct wl_touch *wlTouch)
497 {
498 }
499 
500 static struct wl_touch_listener touch_listener = {
501 	TouchHandleDown,
502 	TouchHandleUp,
503 	TouchHandleMotion,
504 	TouchHandleFrame,
505 	TouchHandleCancel,
506 };
507 
508 /**
509  * Handler of capabilities
510  */
511 static void
seat_handle_capabilities(void * data,struct wl_seat * seat,uint32_t caps)512 seat_handle_capabilities(void *data, struct wl_seat *seat, uint32_t caps)
513 {
514 	struct wlContextCommon *p_wlCtx = (struct wlContextCommon*)data;
515 	struct wl_seat *wlSeat = p_wlCtx->wlSeat;
516 	struct wl_pointer *wlPointer = p_wlCtx->wlPointer;
517 	struct wl_touch *wlTouch = p_wlCtx->wlTouch;
518 
519 	if (p_wlCtx->hmi_setting->cursor_theme) {
520 		if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlPointer){
521 			wlPointer = wl_seat_get_pointer(wlSeat);
522 			wl_pointer_add_listener(wlPointer,
523 						&pointer_listener, data);
524 		} else
525 		if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlPointer){
526 			wl_pointer_destroy(wlPointer);
527 			wlPointer = NULL;
528 		}
529 		p_wlCtx->wlPointer = wlPointer;
530 	}
531 
532 	if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wlTouch){
533 		wlTouch = wl_seat_get_touch(wlSeat);
534 		wl_touch_add_listener(wlTouch, &touch_listener, data);
535 	} else
536 	if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wlTouch){
537 		wl_touch_destroy(wlTouch);
538 		wlTouch = NULL;
539 	}
540 	p_wlCtx->wlTouch = wlTouch;
541 }
542 
543 static struct wl_seat_listener seat_Listener = {
544 	seat_handle_capabilities,
545 };
546 
547 /**
548  * Registration of event
549  * This event is received when hmi-controller server finished controlling
550  * workspace.
551  */
552 static void
ivi_hmi_controller_workspace_end_control(void * data,struct ivi_hmi_controller * hmi_ctrl,int32_t is_controlled)553 ivi_hmi_controller_workspace_end_control(void *data,
554 					 struct ivi_hmi_controller *hmi_ctrl,
555 					 int32_t is_controlled)
556 {
557 	struct wlContextCommon *pCtx = data;
558 	const uint32_t id_surface = getIdOfWlSurface(pCtx, pCtx->enterSurface);
559 
560 	if (is_controlled)
561 		return;
562 
563 	/**
564 	 * During being controlled by hmi-controller, any input event is not
565 	 * notified. So when control ends with touch up, it invokes launcher
566 	 * if up event happens on a launcher surface.
567 	 *
568 	 */
569 	if (launcher_button(id_surface, &pCtx->hmi_setting->launcher_list)) {
570 		pCtx->is_home_on = 0;
571 		ivi_hmi_controller_home(hmi_ctrl, IVI_HMI_CONTROLLER_HOME_OFF);
572 	}
573 }
574 
575 static const struct ivi_hmi_controller_listener hmi_controller_listener = {
576 	ivi_hmi_controller_workspace_end_control
577 };
578 
579 /**
580  * Registration of interfaces
581  */
582 static void
registry_handle_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)583 registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
584 		       const char *interface, uint32_t version)
585 {
586 	struct wlContextCommon *p_wlCtx = (struct wlContextCommon*)data;
587 
588 	if (!strcmp(interface, "wl_compositor")) {
589 		p_wlCtx->wlCompositor =
590 			wl_registry_bind(registry, name,
591 					 &wl_compositor_interface, 1);
592 	} else if (!strcmp(interface, "wl_shm")) {
593 		p_wlCtx->wlShm =
594 			wl_registry_bind(registry, name, &wl_shm_interface, 1);
595 		wl_shm_add_listener(p_wlCtx->wlShm, &shm_listenter, p_wlCtx);
596 	} else if (!strcmp(interface, "wl_seat")) {
597 		/* XXX: should be handling multiple wl_seats */
598 		if (p_wlCtx->wlSeat)
599 			return;
600 
601 		p_wlCtx->wlSeat =
602 			wl_registry_bind(registry, name, &wl_seat_interface, 1);
603 		wl_seat_add_listener(p_wlCtx->wlSeat, &seat_Listener, data);
604 	} else if (!strcmp(interface, "ivi_application")) {
605 		p_wlCtx->iviApplication =
606 			wl_registry_bind(registry, name,
607 					 &ivi_application_interface, 1);
608 	} else if (!strcmp(interface, "ivi_hmi_controller")) {
609 		p_wlCtx->hmiCtrl =
610 			wl_registry_bind(registry, name,
611 					 &ivi_hmi_controller_interface, 1);
612 
613 		ivi_hmi_controller_add_listener(p_wlCtx->hmiCtrl,
614 				&hmi_controller_listener, p_wlCtx);
615 	} else if (!strcmp(interface, "wl_output")) {
616 		p_wlCtx->hmi_setting->screen_num++;
617 	}
618 }
619 
620 static void
registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t name)621 registry_handle_global_remove(void *data, struct wl_registry *registry,
622 			      uint32_t name)
623 {
624 }
625 
626 static const struct wl_registry_listener registry_listener = {
627 	registry_handle_global,
628 	registry_handle_global_remove
629 };
630 
631 static void
frame_listener_func(void * data,struct wl_callback * callback,uint32_t time)632 frame_listener_func(void *data, struct wl_callback *callback, uint32_t time)
633 {
634 	if (callback)
635 		wl_callback_destroy(callback);
636 }
637 
638 static const struct wl_callback_listener frame_listener = {
639 	frame_listener_func
640 };
641 
642 /*
643  * The following correspondences between file names and cursors was copied
644  * from: https://bugs.kde.org/attachment.cgi?id=67313
645  */
646 static const char *bottom_left_corners[] = {
647 	"bottom_left_corner",
648 	"sw-resize",
649 	"size_bdiag"
650 };
651 
652 static const char *bottom_right_corners[] = {
653 	"bottom_right_corner",
654 	"se-resize",
655 	"size_fdiag"
656 };
657 
658 static const char *bottom_sides[] = {
659 	"bottom_side",
660 	"s-resize",
661 	"size_ver"
662 };
663 
664 static const char *grabbings[] = {
665 	"grabbing",
666 	"closedhand",
667 	"208530c400c041818281048008011002"
668 };
669 
670 static const char *left_ptrs[] = {
671 	"left_ptr",
672 	"default",
673 	"top_left_arrow",
674 	"left-arrow"
675 };
676 
677 static const char *left_sides[] = {
678 	"left_side",
679 	"w-resize",
680 	"size_hor"
681 };
682 
683 static const char *right_sides[] = {
684 	"right_side",
685 	"e-resize",
686 	"size_hor"
687 };
688 
689 static const char *top_left_corners[] = {
690 	"top_left_corner",
691 	"nw-resize",
692 	"size_fdiag"
693 };
694 
695 static const char *top_right_corners[] = {
696 	"top_right_corner",
697 	"ne-resize",
698 	"size_bdiag"
699 };
700 
701 static const char *top_sides[] = {
702 	"top_side",
703 	"n-resize",
704 	"size_ver"
705 };
706 
707 static const char *xterms[] = {
708 	"xterm",
709 	"ibeam",
710 	"text"
711 };
712 
713 static const char *hand1s[] = {
714 	"hand1",
715 	"pointer",
716 	"pointing_hand",
717 	"e29285e634086352946a0e7090d73106"
718 };
719 
720 static const char *watches[] = {
721 	"watch",
722 	"wait",
723 	"0426c94ea35c87780ff01dc239897213"
724 };
725 
726 struct cursor_alternatives {
727 	const char **names;
728 	size_t count;
729 };
730 
731 static const struct cursor_alternatives cursors[] = {
732 	{ bottom_left_corners, ARRAY_LENGTH(bottom_left_corners) },
733 	{ bottom_right_corners, ARRAY_LENGTH(bottom_right_corners) },
734 	{ bottom_sides, ARRAY_LENGTH(bottom_sides) },
735 	{ grabbings, ARRAY_LENGTH(grabbings) },
736 	{ left_ptrs, ARRAY_LENGTH(left_ptrs) },
737 	{ left_sides, ARRAY_LENGTH(left_sides) },
738 	{ right_sides, ARRAY_LENGTH(right_sides) },
739 	{ top_left_corners, ARRAY_LENGTH(top_left_corners) },
740 	{ top_right_corners, ARRAY_LENGTH(top_right_corners) },
741 	{ top_sides, ARRAY_LENGTH(top_sides) },
742 	{ xterms, ARRAY_LENGTH(xterms) },
743 	{ hand1s, ARRAY_LENGTH(hand1s) },
744 	{ watches, ARRAY_LENGTH(watches) },
745 };
746 
747 static void
create_cursors(struct wlContextCommon * cmm)748 create_cursors(struct wlContextCommon *cmm)
749 {
750 	uint32_t i = 0;
751 	uint32_t j = 0;
752 	struct wl_cursor *cursor = NULL;
753 	char *cursor_theme = cmm->hmi_setting->cursor_theme;
754 	int32_t cursor_size = cmm->hmi_setting->cursor_size;
755 
756 	cmm->cursor_theme = wl_cursor_theme_load(cursor_theme, cursor_size,
757 						 cmm->wlShm);
758 
759 	cmm->cursors =
760 		xzalloc(ARRAY_LENGTH(cursors) * sizeof(cmm->cursors[0]));
761 
762 	for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
763 		cursor = NULL;
764 
765 		for (j = 0; !cursor && j < cursors[i].count; ++j) {
766 			cursor = wl_cursor_theme_get_cursor(
767 				cmm->cursor_theme, cursors[i].names[j]);
768 		}
769 
770 		if (!cursor) {
771 			fprintf(stderr, "could not load cursor '%s'\n",
772 					cursors[i].names[0]);
773 		}
774 
775 		cmm->cursors[i] = cursor;
776 	}
777 }
778 
779 static void
destroy_cursors(struct wlContextCommon * cmm)780 destroy_cursors(struct wlContextCommon *cmm)
781 {
782 	if (cmm->cursor_theme)
783 		wl_cursor_theme_destroy(cmm->cursor_theme);
784 
785 	free(cmm->cursors);
786 }
787 
788 /**
789  * Internal method to prepare parts of UI
790  */
791 static void
createShmBuffer(struct wlContextStruct * p_wlCtx)792 createShmBuffer(struct wlContextStruct *p_wlCtx)
793 {
794 	struct wl_shm_pool *pool;
795 
796 	int fd = -1;
797 	int size = 0;
798 	int width = 0;
799 	int height = 0;
800 	int stride = 0;
801 
802 	width  = cairo_image_surface_get_width(p_wlCtx->ctx_image);
803 	height = cairo_image_surface_get_height(p_wlCtx->ctx_image);
804 	stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);
805 
806 	size = stride * height;
807 
808 	fd = os_create_anonymous_file(size);
809 	if (fd < 0) {
810 		fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
811 			size, strerror(errno));
812 		return ;
813 	}
814 
815 	p_wlCtx->data =
816 		mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
817 
818 	if (MAP_FAILED == p_wlCtx->data) {
819 		fprintf(stderr, "mmap failed: %s\n", strerror(errno));
820 		close(fd);
821 		return;
822 	}
823 
824 	pool = wl_shm_create_pool(p_wlCtx->cmm->wlShm, fd, size);
825 	p_wlCtx->wlBuffer = wl_shm_pool_create_buffer(pool, 0,
826 						      width,
827 						      height,
828 						      stride,
829 						      WL_SHM_FORMAT_ARGB8888);
830 
831 	if (NULL == p_wlCtx->wlBuffer) {
832 		fprintf(stderr, "wl_shm_create_buffer failed: %s\n",
833 			strerror(errno));
834 		close(fd);
835 		return;
836 	}
837 
838 	wl_shm_pool_destroy(pool);
839 	close(fd);
840 }
841 
842 static void
destroyWLContextCommon(struct wlContextCommon * p_wlCtx)843 destroyWLContextCommon(struct wlContextCommon *p_wlCtx)
844 {
845 	destroy_cursors(p_wlCtx);
846 
847 	if (p_wlCtx->pointer_surface)
848 		wl_surface_destroy(p_wlCtx->pointer_surface);
849 
850 	if (p_wlCtx->wlCompositor)
851 		wl_compositor_destroy(p_wlCtx->wlCompositor);
852 }
853 
854 static void
destroyWLContextStruct(struct wlContextStruct * p_wlCtx)855 destroyWLContextStruct(struct wlContextStruct *p_wlCtx)
856 {
857 	if (p_wlCtx->wlSurface)
858 		wl_surface_destroy(p_wlCtx->wlSurface);
859 
860 	if (p_wlCtx->ctx_image) {
861 		cairo_surface_destroy(p_wlCtx->ctx_image);
862 		p_wlCtx->ctx_image = NULL;
863 	}
864 }
865 
866 static int
createSurface(struct wlContextStruct * p_wlCtx)867 createSurface(struct wlContextStruct *p_wlCtx)
868 {
869 	p_wlCtx->wlSurface =
870 		wl_compositor_create_surface(p_wlCtx->cmm->wlCompositor);
871 	if (NULL == p_wlCtx->wlSurface) {
872 		printf("Error: wl_compositor_create_surface failed.\n");
873 		destroyWLContextCommon(p_wlCtx->cmm);
874 		abort();
875 	}
876 
877 	return 0;
878 }
879 
880 static void
drawImage(struct wlContextStruct * p_wlCtx)881 drawImage(struct wlContextStruct *p_wlCtx)
882 {
883 	struct wl_callback *callback;
884 
885 	int width = 0;
886 	int height = 0;
887 	int stride = 0;
888 	void *data = NULL;
889 
890 	width = cairo_image_surface_get_width(p_wlCtx->ctx_image);
891 	height = cairo_image_surface_get_height(p_wlCtx->ctx_image);
892 	stride = cairo_image_surface_get_stride(p_wlCtx->ctx_image);
893 	data = cairo_image_surface_get_data(p_wlCtx->ctx_image);
894 
895 	memcpy(p_wlCtx->data, data, stride * height);
896 
897 	wl_surface_attach(p_wlCtx->wlSurface, p_wlCtx->wlBuffer, 0, 0);
898 	wl_surface_damage(p_wlCtx->wlSurface, 0, 0, width, height);
899 
900 	callback = wl_surface_frame(p_wlCtx->wlSurface);
901 	wl_callback_add_listener(callback, &frame_listener, NULL);
902 
903 	wl_surface_commit(p_wlCtx->wlSurface);
904 }
905 
906 static void
create_ivisurface(struct wlContextStruct * p_wlCtx,uint32_t id_surface,cairo_surface_t * surface)907 create_ivisurface(struct wlContextStruct *p_wlCtx,
908 				  uint32_t id_surface,
909 				  cairo_surface_t *surface)
910 {
911 	struct ivi_surface *ivisurf = NULL;
912 
913 	p_wlCtx->ctx_image = surface;
914 
915 	p_wlCtx->id_surface = id_surface;
916 	wl_list_init(&p_wlCtx->link);
917 	wl_list_insert(&p_wlCtx->cmm->list_wlContextStruct, &p_wlCtx->link);
918 
919 	createSurface(p_wlCtx);
920 	createShmBuffer(p_wlCtx);
921 
922 	ivisurf = ivi_application_surface_create(p_wlCtx->cmm->iviApplication,
923 						 id_surface,
924 						 p_wlCtx->wlSurface);
925 	if (ivisurf == NULL) {
926 		fprintf(stderr, "Failed to create ivi_client_surface\n");
927 		return;
928 	}
929 
930 	drawImage(p_wlCtx);
931 }
932 
933 static void
create_ivisurfaceFromFile(struct wlContextStruct * p_wlCtx,uint32_t id_surface,const char * imageFile)934 create_ivisurfaceFromFile(struct wlContextStruct *p_wlCtx,
935 			  uint32_t id_surface,
936 			  const char *imageFile)
937 {
938 	cairo_surface_t *surface = load_cairo_surface(imageFile);
939 
940 	if (NULL == surface) {
941 		fprintf(stderr, "Failed to load_cairo_surface %s\n", imageFile);
942 		return;
943 	}
944 
945 	create_ivisurface(p_wlCtx, id_surface, surface);
946 }
947 
948 static void
set_hex_color(cairo_t * cr,uint32_t color)949 set_hex_color(cairo_t *cr, uint32_t color)
950 {
951 	cairo_set_source_rgba(cr,
952 		((color >> 16) & 0xff) / 255.0,
953 		((color >>  8) & 0xff) / 255.0,
954 		((color >>  0) & 0xff) / 255.0,
955 		((color >> 24) & 0xff) / 255.0);
956 }
957 
958 static void
create_ivisurfaceFromColor(struct wlContextStruct * p_wlCtx,uint32_t id_surface,uint32_t width,uint32_t height,uint32_t color)959 create_ivisurfaceFromColor(struct wlContextStruct *p_wlCtx,
960 			   uint32_t id_surface,
961 			   uint32_t width, uint32_t height,
962 			   uint32_t color)
963 {
964 	cairo_surface_t *surface = NULL;
965 	cairo_t *cr = NULL;
966 
967 	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
968 					     width, height);
969 
970 	cr = cairo_create(surface);
971 	cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
972 	cairo_rectangle(cr, 0, 0, width, height);
973 	set_hex_color(cr, color);
974 	cairo_fill(cr);
975 	cairo_destroy(cr);
976 
977 	create_ivisurface(p_wlCtx, id_surface, surface);
978 }
979 
980 static void
UI_ready(struct ivi_hmi_controller * controller)981 UI_ready(struct ivi_hmi_controller *controller)
982 {
983 	ivi_hmi_controller_UI_ready(controller);
984 }
985 
986 /**
987  * Internal method to set up UI by using ivi-hmi-controller
988  */
989 static void
create_background(struct wlContextStruct * p_wlCtx,const uint32_t id_surface,const char * imageFile)990 create_background(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
991 		  const char *imageFile)
992 {
993 	create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
994 }
995 
996 static void
create_panel(struct wlContextStruct * p_wlCtx,const uint32_t id_surface,const char * imageFile)997 create_panel(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
998 	     const char *imageFile)
999 {
1000 	create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
1001 }
1002 
1003 static void
create_button(struct wlContextStruct * p_wlCtx,const uint32_t id_surface,const char * imageFile,uint32_t number)1004 create_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
1005 	      const char *imageFile, uint32_t number)
1006 {
1007 	create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
1008 }
1009 
1010 static void
create_home_button(struct wlContextStruct * p_wlCtx,const uint32_t id_surface,const char * imageFile)1011 create_home_button(struct wlContextStruct *p_wlCtx, const uint32_t id_surface,
1012 		   const char *imageFile)
1013 {
1014 	create_ivisurfaceFromFile(p_wlCtx, id_surface, imageFile);
1015 }
1016 
1017 static void
create_workspace_background(struct wlContextStruct * p_wlCtx,struct hmi_homescreen_srf * srf)1018 create_workspace_background(struct wlContextStruct *p_wlCtx,
1019 			    struct hmi_homescreen_srf *srf)
1020 {
1021 	create_ivisurfaceFromColor(p_wlCtx, srf->id, 1, 1, srf->color);
1022 }
1023 
1024 static void
create_launchers(struct wlContextCommon * cmm,struct wl_list * launcher_list)1025 create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
1026 {
1027 	struct hmi_homescreen_launcher **launchers;
1028 	struct hmi_homescreen_launcher *launcher = NULL;
1029 
1030 	int launcher_count = wl_list_length(launcher_list);
1031 	int ii = 0;
1032 	int start = 0;
1033 
1034 	if (0 == launcher_count)
1035 		return;
1036 
1037 	launchers = xzalloc(launcher_count * sizeof(*launchers));
1038 
1039 	wl_list_for_each(launcher, launcher_list, link) {
1040 		launchers[ii] = launcher;
1041 		ii++;
1042 	}
1043 
1044 	for (ii = 0; ii < launcher_count; ii++) {
1045 		int jj = 0;
1046 
1047 		if (ii != launcher_count - 1 &&
1048 		    launchers[ii]->workspace_id ==
1049 		    launchers[ii + 1]->workspace_id)
1050 			continue;
1051 
1052 		for (jj = start; jj <= ii; jj++) {
1053 			struct wlContextStruct *p_wlCtx;
1054 
1055 			p_wlCtx = xzalloc(sizeof(*p_wlCtx));
1056 			p_wlCtx->cmm = cmm;
1057 			create_ivisurfaceFromFile(p_wlCtx,
1058 						  launchers[jj]->icon_surface_id,
1059 						  launchers[jj]->icon);
1060 		}
1061 
1062 		start = ii + 1;
1063 	}
1064 
1065 	free(launchers);
1066 }
1067 
1068 /**
1069  * Internal method to read out weston.ini to get configuration
1070  */
1071 static struct hmi_homescreen_setting *
hmi_homescreen_setting_create(void)1072 hmi_homescreen_setting_create(void)
1073 {
1074 	const char *config_file;
1075 	struct weston_config *config = NULL;
1076 	struct weston_config_section *shellSection = NULL;
1077 	struct hmi_homescreen_setting *setting = xzalloc(sizeof(*setting));
1078 	struct weston_config_section *section = NULL;
1079 	const char *name = NULL;
1080 	uint32_t workspace_layer_id;
1081 	uint32_t icon_surface_id = 0;
1082 	char *filename;
1083 
1084 	wl_list_init(&setting->workspace_list);
1085 	wl_list_init(&setting->launcher_list);
1086 
1087 	config_file = weston_config_get_name_from_env();
1088 	config = weston_config_parse(config_file);
1089 
1090 	shellSection =
1091 		weston_config_get_section(config, "ivi-shell", NULL, NULL);
1092 
1093 	weston_config_section_get_string(
1094 		shellSection, "cursor-theme", &setting->cursor_theme, NULL);
1095 
1096 	weston_config_section_get_int(
1097 		shellSection, "cursor-size", &setting->cursor_size, 32);
1098 
1099 	weston_config_section_get_uint(
1100 		shellSection, "workspace-layer-id", &workspace_layer_id, 3000);
1101 
1102 	filename = file_name_with_datadir("background.png");
1103 	weston_config_section_get_string(
1104 		shellSection, "background-image", &setting->background.filePath,
1105 		filename);
1106 	free(filename);
1107 
1108 	weston_config_section_get_uint(
1109 		shellSection, "background-id", &setting->background.id, 1001);
1110 
1111 	filename = file_name_with_datadir("panel.png");
1112 	weston_config_section_get_string(
1113 		shellSection, "panel-image", &setting->panel.filePath,
1114 		filename);
1115 	free(filename);
1116 
1117 	weston_config_section_get_uint(
1118 		shellSection, "panel-id", &setting->panel.id, 1002);
1119 
1120 	filename = file_name_with_datadir("tiling.png");
1121 	weston_config_section_get_string(
1122 		shellSection, "tiling-image", &setting->tiling.filePath,
1123 		filename);
1124 	free(filename);
1125 
1126 	weston_config_section_get_uint(
1127 		shellSection, "tiling-id", &setting->tiling.id, 1003);
1128 
1129 	filename = file_name_with_datadir("sidebyside.png");
1130 	weston_config_section_get_string(
1131 		shellSection, "sidebyside-image", &setting->sidebyside.filePath,
1132 		filename);
1133 	free(filename);
1134 
1135 	weston_config_section_get_uint(
1136 		shellSection, "sidebyside-id", &setting->sidebyside.id, 1004);
1137 
1138 	filename = file_name_with_datadir("fullscreen.png");
1139 	weston_config_section_get_string(
1140 		shellSection, "fullscreen-image", &setting->fullscreen.filePath,
1141 		filename);
1142 	free(filename);
1143 
1144 	weston_config_section_get_uint(
1145 		shellSection, "fullscreen-id", &setting->fullscreen.id, 1005);
1146 
1147 	filename = file_name_with_datadir("random.png");
1148 	weston_config_section_get_string(
1149 		shellSection, "random-image", &setting->random.filePath,
1150 		filename);
1151 	free(filename);
1152 
1153 	weston_config_section_get_uint(
1154 		shellSection, "random-id", &setting->random.id, 1006);
1155 
1156 	filename = file_name_with_datadir("home.png");
1157 	weston_config_section_get_string(
1158 		shellSection, "home-image", &setting->home.filePath,
1159 		filename);
1160 	free(filename);
1161 
1162 	weston_config_section_get_uint(
1163 		shellSection, "home-id", &setting->home.id, 1007);
1164 
1165 	weston_config_section_get_color(
1166 		shellSection, "workspace-background-color",
1167 		&setting->workspace_background.color, 0x99000000);
1168 
1169 	weston_config_section_get_uint(
1170 		shellSection, "workspace-background-id",
1171 		&setting->workspace_background.id, 2001);
1172 
1173 	weston_config_section_get_uint(
1174 		shellSection, "surface-id-offset", &setting->surface_id_offset, 10);
1175 
1176 	icon_surface_id = workspace_layer_id + 1;
1177 
1178 	while (weston_config_next_section(config, &section, &name)) {
1179 		struct hmi_homescreen_launcher *launcher;
1180 
1181 		if (strcmp(name, "ivi-launcher") != 0)
1182 			continue;
1183 
1184 		launcher = xzalloc(sizeof(*launcher));
1185 		wl_list_init(&launcher->link);
1186 
1187 		weston_config_section_get_string(section, "icon",
1188 						 &launcher->icon, NULL);
1189 		weston_config_section_get_string(section, "path",
1190 						 &launcher->path, NULL);
1191 		weston_config_section_get_uint(section, "workspace-id",
1192 					       &launcher->workspace_id, 0);
1193 		weston_config_section_get_uint(section, "icon-id",
1194 					       &launcher->icon_surface_id,
1195 					       icon_surface_id);
1196 		icon_surface_id++;
1197 
1198 		wl_list_insert(setting->launcher_list.prev, &launcher->link);
1199 	}
1200 
1201 	weston_config_destroy(config);
1202 	return setting;
1203 }
1204 
1205 /**
1206  * Main thread
1207  *
1208  * The basic flow are as followed,
1209  * 1/ read configuration from weston.ini by hmi_homescreen_setting_create
1210  * 2/ draw png file to surface according to configuration of weston.ini and
1211  *	set up UI by using ivi-hmi-controller protocol by each create_* method
1212  */
main(int argc,char ** argv)1213 int main(int argc, char **argv)
1214 {
1215 	struct wlContextCommon wlCtxCommon;
1216 	struct wlContextStruct *wlCtx_BackGround;
1217 	struct wlContextStruct *wlCtx_Panel;
1218 	struct wlContextStruct wlCtx_Button_1;
1219 	struct wlContextStruct wlCtx_Button_2;
1220 	struct wlContextStruct wlCtx_Button_3;
1221 	struct wlContextStruct wlCtx_Button_4;
1222 	struct wlContextStruct wlCtx_HomeButton;
1223 	struct wlContextStruct wlCtx_WorkSpaceBackGround;
1224 	struct wl_list launcher_wlCtxList;
1225 	int ret = 0;
1226 	struct hmi_homescreen_setting *hmi_setting;
1227 	struct wlContextStruct *pWlCtxSt = NULL;
1228 	int i = 0;
1229 
1230 	hmi_setting = hmi_homescreen_setting_create();
1231 
1232 	memset(&wlCtxCommon, 0x00, sizeof(wlCtxCommon));
1233 	memset(&wlCtx_Button_1,   0x00, sizeof(wlCtx_Button_1));
1234 	memset(&wlCtx_Button_2,   0x00, sizeof(wlCtx_Button_2));
1235 	memset(&wlCtx_Button_3,   0x00, sizeof(wlCtx_Button_3));
1236 	memset(&wlCtx_Button_4,   0x00, sizeof(wlCtx_Button_4));
1237 	memset(&wlCtx_HomeButton, 0x00, sizeof(wlCtx_HomeButton));
1238 	memset(&wlCtx_WorkSpaceBackGround, 0x00,
1239 	       sizeof(wlCtx_WorkSpaceBackGround));
1240 	wl_list_init(&launcher_wlCtxList);
1241 	wl_list_init(&wlCtxCommon.list_wlContextStruct);
1242 
1243 	wlCtxCommon.hmi_setting = hmi_setting;
1244 
1245 	wlCtxCommon.wlDisplay = wl_display_connect(NULL);
1246 	if (NULL == wlCtxCommon.wlDisplay) {
1247 		printf("Error: wl_display_connect failed.\n");
1248 		return -1;
1249 	}
1250 
1251 	/* get wl_registry */
1252 	wlCtxCommon.formats = 0;
1253 	wlCtxCommon.wlRegistry = wl_display_get_registry(wlCtxCommon.wlDisplay);
1254 	wl_registry_add_listener(wlCtxCommon.wlRegistry,
1255 				 &registry_listener, &wlCtxCommon);
1256 	wl_display_roundtrip(wlCtxCommon.wlDisplay);
1257 
1258 	if (wlCtxCommon.wlShm == NULL) {
1259 		fprintf(stderr, "No wl_shm global\n");
1260 		exit(1);
1261 	}
1262 
1263 	wl_display_roundtrip(wlCtxCommon.wlDisplay);
1264 
1265 	if (!(wlCtxCommon.formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
1266 		fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
1267 		exit(1);
1268 	}
1269 
1270 	wlCtx_BackGround = xzalloc(hmi_setting->screen_num * sizeof(struct wlContextStruct));
1271 	wlCtx_Panel= xzalloc(hmi_setting->screen_num * sizeof(struct wlContextStruct));
1272 
1273 	if (wlCtxCommon.hmi_setting->cursor_theme) {
1274 		create_cursors(&wlCtxCommon);
1275 
1276 		wlCtxCommon.pointer_surface =
1277 			wl_compositor_create_surface(wlCtxCommon.wlCompositor);
1278 
1279 		wlCtxCommon.current_cursor = CURSOR_LEFT_PTR;
1280 	}
1281 
1282 	wlCtx_Button_1.cmm   = &wlCtxCommon;
1283 	wlCtx_Button_2.cmm   = &wlCtxCommon;
1284 	wlCtx_Button_3.cmm   = &wlCtxCommon;
1285 	wlCtx_Button_4.cmm   = &wlCtxCommon;
1286 	wlCtx_HomeButton.cmm = &wlCtxCommon;
1287 	wlCtx_WorkSpaceBackGround.cmm = &wlCtxCommon;
1288 
1289 	/* create desktop widgets */
1290 	for (i = 0; i < hmi_setting->screen_num; i++) {
1291 		wlCtx_BackGround[i].cmm = &wlCtxCommon;
1292 		create_background(&wlCtx_BackGround[i],
1293 				  hmi_setting->background.id +
1294 					(i * hmi_setting->surface_id_offset),
1295 				  hmi_setting->background.filePath);
1296 
1297 		wlCtx_Panel[i].cmm = &wlCtxCommon;
1298 		create_panel(&wlCtx_Panel[i],
1299 			     hmi_setting->panel.id + (i * hmi_setting->surface_id_offset),
1300 			     hmi_setting->panel.filePath);
1301 	}
1302 
1303 	create_button(&wlCtx_Button_1, hmi_setting->tiling.id,
1304 		      hmi_setting->tiling.filePath, 0);
1305 
1306 	create_button(&wlCtx_Button_2, hmi_setting->sidebyside.id,
1307 		      hmi_setting->sidebyside.filePath, 1);
1308 
1309 	create_button(&wlCtx_Button_3, hmi_setting->fullscreen.id,
1310 		      hmi_setting->fullscreen.filePath, 2);
1311 
1312 	create_button(&wlCtx_Button_4, hmi_setting->random.id,
1313 		      hmi_setting->random.filePath, 3);
1314 
1315 	create_workspace_background(&wlCtx_WorkSpaceBackGround,
1316 				    &hmi_setting->workspace_background);
1317 
1318 	create_launchers(&wlCtxCommon, &hmi_setting->launcher_list);
1319 
1320 	create_home_button(&wlCtx_HomeButton, hmi_setting->home.id,
1321 			   hmi_setting->home.filePath);
1322 
1323 	UI_ready(wlCtxCommon.hmiCtrl);
1324 
1325 	while (ret != -1)
1326 		ret = wl_display_dispatch(wlCtxCommon.wlDisplay);
1327 
1328 	wl_list_for_each(pWlCtxSt, &wlCtxCommon.list_wlContextStruct, link) {
1329 		destroyWLContextStruct(pWlCtxSt);
1330 	}
1331 
1332 	free(wlCtx_BackGround);
1333 	free(wlCtx_Panel);
1334 
1335 	destroyWLContextCommon(&wlCtxCommon);
1336 
1337 	return 0;
1338 }
1339