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